comparison src/gc.c @ 3263:d674024a8674

[xemacs-hg @ 2006-02-27 16:29:00 by crestani] - Introduce a fancy asynchronous finalization strategy on C level. - Merge the code conditioned on MC_ALLOC into the code conditioned on NEW_GC. - Remove the possibility to free objects manually outside garbage collections when the new collector is enabled.
author crestani
date Mon, 27 Feb 2006 16:29:29 +0000
parents 141c2920ea48
children a0de8be91f1b
comparison
equal deleted inserted replaced
3262:79d41cfd8e6b 3263:d674024a8674
630 return MAX_ALIGN_SIZE (max_offset + size_at_max); 630 return MAX_ALIGN_SIZE (max_offset + size_at_max);
631 } 631 }
632 } 632 }
633 #endif /* defined (USE_KKCC) || defined (PDUMP) */ 633 #endif /* defined (USE_KKCC) || defined (PDUMP) */
634 634
635 #ifdef MC_ALLOC 635 #ifdef NEW_GC
636 #define GC_CHECK_NOT_FREE(lheader) \ 636 #define GC_CHECK_NOT_FREE(lheader) \
637 gc_checking_assert (! LRECORD_FREE_P (lheader)); 637 gc_checking_assert (! LRECORD_FREE_P (lheader));
638 #else /* MC_ALLOC */ 638 #else /* not NEW_GC */
639 #define GC_CHECK_NOT_FREE(lheader) \ 639 #define GC_CHECK_NOT_FREE(lheader) \
640 gc_checking_assert (! LRECORD_FREE_P (lheader)); \ 640 gc_checking_assert (! LRECORD_FREE_P (lheader)); \
641 gc_checking_assert (LHEADER_IMPLEMENTATION (lheader)->basic_p || \ 641 gc_checking_assert (LHEADER_IMPLEMENTATION (lheader)->basic_p || \
642 ! ((struct old_lcrecord_header *) lheader)->free) 642 ! ((struct old_lcrecord_header *) lheader)->free)
643 #endif /* MC_ALLOC */ 643 #endif /* not NEW_GC */
644 644
645 #ifdef USE_KKCC 645 #ifdef USE_KKCC
646 /* The following functions implement the new mark algorithm. 646 /* The following functions implement the new mark algorithm.
647 They mark objects according to their descriptions. They 647 They mark objects according to their descriptions. They
648 are modeled on the corresponding pdumper procedures. */ 648 are modeled on the corresponding pdumper procedures. */
1145 Lisp_Objects have the same representation), XD_LISP_OBJECT 1145 Lisp_Objects have the same representation), XD_LISP_OBJECT
1146 can be used for untagged pointers. They might be NULL, 1146 can be used for untagged pointers. They might be NULL,
1147 though. */ 1147 though. */
1148 if (EQ (*stored_obj, Qnull_pointer)) 1148 if (EQ (*stored_obj, Qnull_pointer))
1149 break; 1149 break;
1150 #ifdef MC_ALLOC 1150 #ifdef NEW_GC
1151 mark_object_maybe_checking_free (*stored_obj, 0, level, pos); 1151 mark_object_maybe_checking_free (*stored_obj, 0, level, pos);
1152 #else /* not MC_ALLOC */ 1152 #else /* not NEW_GC */
1153 mark_object_maybe_checking_free 1153 mark_object_maybe_checking_free
1154 (*stored_obj, (desc1->flags) & XD_FLAG_FREE_LISP_OBJECT, 1154 (*stored_obj, (desc1->flags) & XD_FLAG_FREE_LISP_OBJECT,
1155 level, pos); 1155 level, pos);
1156 #endif /* not MC_ALLOC */ 1156 #endif /* not NEW_GC */
1157 break; 1157 break;
1158 } 1158 }
1159 case XD_LISP_OBJECT_ARRAY: 1159 case XD_LISP_OBJECT_ARRAY:
1160 { 1160 {
1161 int i; 1161 int i;
1167 const Lisp_Object *stored_obj = 1167 const Lisp_Object *stored_obj =
1168 (const Lisp_Object *) rdata + i; 1168 (const Lisp_Object *) rdata + i;
1169 1169
1170 if (EQ (*stored_obj, Qnull_pointer)) 1170 if (EQ (*stored_obj, Qnull_pointer))
1171 break; 1171 break;
1172 #ifdef MC_ALLOC 1172 #ifdef NEW_GC
1173 mark_object_maybe_checking_free 1173 mark_object_maybe_checking_free
1174 (*stored_obj, 0, level, pos); 1174 (*stored_obj, 0, level, pos);
1175 #else /* not MC_ALLOC */ 1175 #else /* not NEW_GC */
1176 mark_object_maybe_checking_free 1176 mark_object_maybe_checking_free
1177 (*stored_obj, (desc1->flags) & XD_FLAG_FREE_LISP_OBJECT, 1177 (*stored_obj, (desc1->flags) & XD_FLAG_FREE_LISP_OBJECT,
1178 level, pos); 1178 level, pos);
1179 #endif /* not MC_ALLOC */ 1179 #endif /* not NEW_GC */
1180 } 1180 }
1181 break; 1181 break;
1182 } 1182 }
1183 #ifdef NEW_GC 1183 #ifdef NEW_GC
1184 case XD_LISP_OBJECT_BLOCK_PTR: 1184 case XD_LISP_OBJECT_BLOCK_PTR:
1390 1390
1391 Dynarr_reset (post_gc_actions); 1391 Dynarr_reset (post_gc_actions);
1392 } 1392 }
1393 } 1393 }
1394 1394
1395 #ifdef NEW_GC
1396 /* Asynchronous finalization. */
1397 typedef struct finalize_elem
1398 {
1399 Lisp_Object obj;
1400 struct finalize_elem *next;
1401 } finalize_elem;
1402
1403 finalize_elem *Vall_finalizable_objs;
1404 Lisp_Object Vfinalizers_to_run;
1405
1406 void
1407 add_finalizable_obj (Lisp_Object obj)
1408 {
1409 finalize_elem *next = Vall_finalizable_objs;
1410 Vall_finalizable_objs =
1411 (finalize_elem *) xmalloc_and_zero (sizeof (finalize_elem));
1412 Vall_finalizable_objs->obj = obj;
1413 Vall_finalizable_objs->next = next;
1414 }
1415
1416 void
1417 register_for_finalization (void)
1418 {
1419 finalize_elem *rest = Vall_finalizable_objs;
1420
1421 if (!rest)
1422 return;
1423
1424 while (!marked_p (rest->obj))
1425 {
1426 finalize_elem *temp = rest;
1427 Vfinalizers_to_run = Fcons (rest->obj, Vfinalizers_to_run);
1428 Vall_finalizable_objs = rest->next;
1429 xfree (temp, finalize_elem *);
1430 rest = Vall_finalizable_objs;
1431 }
1432
1433 while (rest->next)
1434 {
1435 if (LRECORDP (rest->next->obj)
1436 && !marked_p (rest->next->obj))
1437 {
1438 finalize_elem *temp = rest->next;
1439 Vfinalizers_to_run = Fcons (rest->next->obj, Vfinalizers_to_run);
1440 rest->next = rest->next->next;
1441 xfree (temp, finalize_elem *);
1442 }
1443 else
1444 {
1445 rest = rest->next;
1446 }
1447 }
1448 /* Keep objects alive that need to be finalized by marking
1449 Vfinalizers_to_run transitively. */
1450 kkcc_gc_stack_push_lisp_object (Vfinalizers_to_run, 0, -1);
1451 kkcc_marking (0);
1452 }
1453
1454 void
1455 run_finalizers (void)
1456 {
1457 Lisp_Object rest;
1458 for (rest = Vfinalizers_to_run; !NILP (rest); rest = XCDR (rest))
1459 {
1460 MC_ALLOC_CALL_FINALIZER (XPNTR (XCAR (rest)));
1461 }
1462 Vfinalizers_to_run = Qnil;
1463 }
1464 #endif /* not NEW_GC */
1395 1465
1396 1466
1397 /************************************************************************/ 1467 /************************************************************************/
1398 /* Garbage Collection */ 1468 /* Garbage Collection */
1399 /************************************************************************/ 1469 /************************************************************************/
1512 /***** Now we actually start the garbage collection. */ 1582 /***** Now we actually start the garbage collection. */
1513 1583
1514 gc_in_progress = 1; 1584 gc_in_progress = 1;
1515 #ifndef NEW_GC 1585 #ifndef NEW_GC
1516 inhibit_non_essential_conversion_operations = 1; 1586 inhibit_non_essential_conversion_operations = 1;
1517 #endif /* NEW_GC */ 1587 #endif /* not NEW_GC */
1518 1588
1519 #if MAX_SAVE_STACK > 0 1589 #if MAX_SAVE_STACK > 0
1520 1590
1521 /* Save a copy of the contents of the stack, for debugging. */ 1591 /* Save a copy of the contents of the stack, for debugging. */
1522 if (!purify_flag) 1592 if (!purify_flag)
1594 mark_object (**p++); 1664 mark_object (**p++);
1595 else 1665 else
1596 **p++; 1666 **p++;
1597 } 1667 }
1598 1668
1599 #ifdef MC_ALLOC 1669 #ifdef NEW_GC
1600 { /* mcpro () */ 1670 { /* mcpro () */
1601 Lisp_Object *p = Dynarr_begin (mcpros); 1671 Lisp_Object *p = Dynarr_begin (mcpros);
1602 Elemcount count; 1672 Elemcount count;
1603 for (count = Dynarr_length (mcpros); count; count--) 1673 for (count = Dynarr_length (mcpros); count; count--)
1604 mark_object (*p++); 1674 mark_object (*p++);
1605 } 1675 }
1606 #endif /* MC_ALLOC */ 1676 #endif /* NEW_GC */
1607 1677
1608 { /* GCPRO() */ 1678 { /* GCPRO() */
1609 struct gcpro *tail; 1679 struct gcpro *tail;
1610 int i; 1680 int i;
1611 for (tail = gcprolist; tail; tail = tail->next) 1681 for (tail = gcprolist; tail; tail = tail->next)
1706 #ifdef NEW_GC 1776 #ifdef NEW_GC
1707 void 1777 void
1708 gc_finalize (void) 1778 gc_finalize (void)
1709 { 1779 {
1710 GC_SET_PHASE (FINALIZE); 1780 GC_SET_PHASE (FINALIZE);
1711 mc_finalize (); 1781 register_for_finalization ();
1712 } 1782 }
1713 1783
1714 void 1784 void
1715 gc_sweep (void) 1785 gc_sweep (void)
1716 { 1786 {
1767 } 1837 }
1768 } 1838 }
1769 } 1839 }
1770 } 1840 }
1771 1841
1772 #ifndef MC_ALLOC 1842 #ifndef NEW_GC
1773 if (!breathing_space) 1843 if (!breathing_space)
1774 { 1844 {
1775 breathing_space = malloc (4096 - MALLOC_OVERHEAD); 1845 breathing_space = malloc (4096 - MALLOC_OVERHEAD);
1776 } 1846 }
1777 #endif /* not MC_ALLOC */ 1847 #endif /* not NEW_GC */
1778 1848
1779 need_to_signal_post_gc = 1; 1849 need_to_signal_post_gc = 1;
1780 funcall_allocation_flag = 1; 1850 funcall_allocation_flag = 1;
1781 1851
1782 PROFILE_RECORD_EXITING_SECTION (QSin_garbage_collection); 1852 PROFILE_RECORD_EXITING_SECTION (QSin_garbage_collection);
1885 case MARK: 1955 case MARK:
1886 if (!KKCC_GC_STACK_EMPTY) 1956 if (!KKCC_GC_STACK_EMPTY)
1887 if (!gc_resume_mark (incremental)) 1957 if (!gc_resume_mark (incremental))
1888 return; /* suspend gc */ 1958 return; /* suspend gc */
1889 gc_finish_mark (); 1959 gc_finish_mark ();
1960 case FINISH_MARK:
1961 gc_finalize ();
1890 kkcc_gc_stack_free (); 1962 kkcc_gc_stack_free ();
1891 #ifdef DEBUG_XEMACS 1963 #ifdef DEBUG_XEMACS
1892 kkcc_bt_free (); 1964 kkcc_bt_free ();
1893 #endif 1965 #endif
1894 case FINISH_MARK:
1895 gc_finalize ();
1896 case FINALIZE: 1966 case FINALIZE:
1897 gc_sweep (); 1967 gc_sweep ();
1898 case SWEEP: 1968 case SWEEP:
1899 gc_finish (); 1969 gc_finish ();
1900 case FINISH_GC: 1970 case FINISH_GC:
2021 gc_cons_percentage = 40; /* #### what is optimal? */ 2091 gc_cons_percentage = 40; /* #### what is optimal? */
2022 total_gc_usage_set = 0; 2092 total_gc_usage_set = 0;
2023 #ifdef NEW_GC 2093 #ifdef NEW_GC
2024 gc_cons_incremental_threshold = GC_CONS_INCREMENTAL_THRESHOLD; 2094 gc_cons_incremental_threshold = GC_CONS_INCREMENTAL_THRESHOLD;
2025 gc_incremental_traversal_threshold = GC_INCREMENTAL_TRAVERSAL_THRESHOLD; 2095 gc_incremental_traversal_threshold = GC_INCREMENTAL_TRAVERSAL_THRESHOLD;
2026 #endif /* not NEW_GC */ 2096 #endif /* NEW_GC */
2027 } 2097 }
2028 2098
2029 void 2099 void
2030 init_gc_early (void) 2100 init_gc_early (void)
2031 { 2101 {
2102 #ifdef NEW_GC
2103 /* Reset the finalizers_to_run list after pdump_load. */
2104 Vfinalizers_to_run = Qnil;
2105 #endif /* NEW_GC */
2032 } 2106 }
2033 2107
2034 void 2108 void
2035 reinit_gc_early (void) 2109 reinit_gc_early (void)
2036 { 2110 {
2172 DEFVAR_BOOL ("allow-incremental-gc", &allow_incremental_gc /* 2246 DEFVAR_BOOL ("allow-incremental-gc", &allow_incremental_gc /*
2173 *Non-nil means to allow incremental garbage collection. Nil prevents 2247 *Non-nil means to allow incremental garbage collection. Nil prevents
2174 *incremental garbage collection, the garbage collector then only does 2248 *incremental garbage collection, the garbage collector then only does
2175 *full collects (even if (gc-incremental) is called). 2249 *full collects (even if (gc-incremental) is called).
2176 */ ); 2250 */ );
2251
2252 Vfinalizers_to_run = Qnil;
2253 staticpro_nodump (&Vfinalizers_to_run);
2177 #endif /* NEW_GC */ 2254 #endif /* NEW_GC */
2178 } 2255 }
2179 2256
2180 void 2257 void
2181 complex_vars_of_gc (void) 2258 complex_vars_of_gc (void)