Mercurial > hg > xemacs-beta
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) |