Mercurial > hg > xemacs-beta
comparison src/alloc.c @ 424:11054d720c21 r21-2-20
Import from CVS: tag r21-2-20
author | cvs |
---|---|
date | Mon, 13 Aug 2007 11:26:11 +0200 |
parents | 41dbb7a9d5f2 |
children |
comparison
equal
deleted
inserted
replaced
423:28d9c139be4c | 424:11054d720c21 |
---|---|
34 and various changes for Mule, for 19.12. | 34 and various changes for Mule, for 19.12. |
35 Added bit vectors for 19.13. | 35 Added bit vectors for 19.13. |
36 Added lcrecord lists for 19.14. | 36 Added lcrecord lists for 19.14. |
37 slb: Lots of work on the purification and dump time code. | 37 slb: Lots of work on the purification and dump time code. |
38 Synched Doug Lea malloc support from Emacs 20.2. | 38 Synched Doug Lea malloc support from Emacs 20.2. |
39 og: Killed the purespace. | 39 og: Killed the purespace. Portable dumper. |
40 */ | 40 */ |
41 | 41 |
42 #include <config.h> | 42 #include <config.h> |
43 #include "lisp.h" | 43 #include "lisp.h" |
44 | 44 |
55 #include "opaque.h" | 55 #include "opaque.h" |
56 #include "redisplay.h" | 56 #include "redisplay.h" |
57 #include "specifier.h" | 57 #include "specifier.h" |
58 #include "sysfile.h" | 58 #include "sysfile.h" |
59 #include "window.h" | 59 #include "window.h" |
60 #include "console-stream.h" | |
60 | 61 |
61 #ifdef DOUG_LEA_MALLOC | 62 #ifdef DOUG_LEA_MALLOC |
62 #include <malloc.h> | 63 #include <malloc.h> |
64 #endif | |
65 | |
66 #ifdef HAVE_MMAP | |
67 #include <unistd.h> | |
68 #include <sys/mman.h> | |
69 #endif | |
70 | |
71 #ifdef PDUMP | |
72 typedef struct | |
73 { | |
74 const struct lrecord_description *desc; | |
75 int count; | |
76 } pdump_reloc_table; | |
77 | |
78 static char *pdump_rt_list = 0; | |
63 #endif | 79 #endif |
64 | 80 |
65 EXFUN (Fgarbage_collect, 0); | 81 EXFUN (Fgarbage_collect, 0); |
66 | 82 |
67 /* Return the true size of a struct with a variable-length array field. */ | 83 /* Return the true size of a struct with a variable-length array field. */ |
181 #endif | 197 #endif |
182 | 198 |
183 int | 199 int |
184 c_readonly (Lisp_Object obj) | 200 c_readonly (Lisp_Object obj) |
185 { | 201 { |
186 return POINTER_TYPE_P (XGCTYPE (obj)) && C_READONLY (obj); | 202 return POINTER_TYPE_P (XTYPE (obj)) && C_READONLY (obj); |
187 } | 203 } |
188 | 204 |
189 int | 205 int |
190 lisp_readonly (Lisp_Object obj) | 206 lisp_readonly (Lisp_Object obj) |
191 { | 207 { |
192 return POINTER_TYPE_P (XGCTYPE (obj)) && LISP_READONLY (obj); | 208 return POINTER_TYPE_P (XTYPE (obj)) && LISP_READONLY (obj); |
193 } | 209 } |
194 | 210 |
195 | 211 |
196 /* Maximum amount of C stack to save when a GC happens. */ | 212 /* Maximum amount of C stack to save when a GC happens. */ |
197 | 213 |
357 { | 373 { |
358 int len = strlen (str) + 1; /* for stupid terminating 0 */ | 374 int len = strlen (str) + 1; /* for stupid terminating 0 */ |
359 | 375 |
360 void *val = xmalloc (len); | 376 void *val = xmalloc (len); |
361 if (val == 0) return 0; | 377 if (val == 0) return 0; |
362 memcpy (val, str, len); | 378 return (char *) memcpy (val, str, len); |
363 return (char *) val; | |
364 } | 379 } |
365 | 380 |
366 #ifdef NEED_STRDUP | 381 #ifdef NEED_STRDUP |
367 char * | 382 char * |
368 strdup (CONST char *s) | 383 strdup (CONST char *s) |
373 | 388 |
374 | 389 |
375 static void * | 390 static void * |
376 allocate_lisp_storage (size_t size) | 391 allocate_lisp_storage (size_t size) |
377 { | 392 { |
378 void *p = xmalloc (size); | 393 return xmalloc (size); |
379 return p; | |
380 } | 394 } |
381 | 395 |
382 | 396 |
383 /* lrecords are chained together through their "next.v" field. | 397 /* lrecords are chained together through their "next.v" field. |
384 * After doing the mark phase, the GC will walk this linked | 398 * After doing the mark phase, the GC will walk this linked |
463 ((LHEADER_IMPLEMENTATION(&header->lheader)->finalizer) | 477 ((LHEADER_IMPLEMENTATION(&header->lheader)->finalizer) |
464 (header, 1)); | 478 (header, 1)); |
465 } | 479 } |
466 } | 480 } |
467 | 481 |
468 | |
469 /* This must not be called -- it just serves as for EQ test | |
470 * If lheader->implementation->finalizer is this_marks_a_marked_record, | |
471 * then lrecord has been marked by the GC sweeper | |
472 * header->implementation is put back to its correct value by | |
473 * sweep_records */ | |
474 void | |
475 this_marks_a_marked_record (void *dummy0, int dummy1) | |
476 { | |
477 abort (); | |
478 } | |
479 | |
480 /* Semi-kludge -- lrecord_symbol_value_forward objects get stuck | 482 /* Semi-kludge -- lrecord_symbol_value_forward objects get stuck |
481 in CONST space and you get SEGV's if you attempt to mark them. | 483 in CONST space and you get SEGV's if you attempt to mark them. |
482 This sits in lheader->implementation->marker. */ | 484 This sits in lheader->implementation->marker. */ |
483 | 485 |
484 Lisp_Object | 486 Lisp_Object |
485 this_one_is_unmarkable (Lisp_Object obj, void (*markobj) (Lisp_Object)) | 487 this_one_is_unmarkable (Lisp_Object obj) |
486 { | 488 { |
487 abort (); | 489 abort (); |
488 return Qnil; | 490 return Qnil; |
489 } | |
490 | |
491 /* XGCTYPE for records */ | |
492 int | |
493 gc_record_type_p (Lisp_Object frob, CONST struct lrecord_implementation *type) | |
494 { | |
495 CONST struct lrecord_implementation *imp; | |
496 | |
497 if (XGCTYPE (frob) != Lisp_Type_Record) | |
498 return 0; | |
499 | |
500 imp = XRECORD_LHEADER_IMPLEMENTATION (frob); | |
501 return imp == type; | |
502 } | 491 } |
503 | 492 |
504 | 493 |
505 /************************************************************************/ | 494 /************************************************************************/ |
506 /* Debugger support */ | 495 /* Debugger support */ |
941 /* conses are used and freed so often that we set this really high */ | 930 /* conses are used and freed so often that we set this really high */ |
942 /* #define MINIMUM_ALLOWED_FIXED_TYPE_CELLS_cons 20000 */ | 931 /* #define MINIMUM_ALLOWED_FIXED_TYPE_CELLS_cons 20000 */ |
943 #define MINIMUM_ALLOWED_FIXED_TYPE_CELLS_cons 2000 | 932 #define MINIMUM_ALLOWED_FIXED_TYPE_CELLS_cons 2000 |
944 | 933 |
945 static Lisp_Object | 934 static Lisp_Object |
946 mark_cons (Lisp_Object obj, void (*markobj) (Lisp_Object)) | 935 mark_cons (Lisp_Object obj) |
947 { | 936 { |
948 if (GC_NILP (XCDR (obj))) | 937 if (NILP (XCDR (obj))) |
949 return XCAR (obj); | 938 return XCAR (obj); |
950 | 939 |
951 markobj (XCAR (obj)); | 940 mark_object (XCAR (obj)); |
952 return XCDR (obj); | 941 return XCDR (obj); |
953 } | 942 } |
954 | 943 |
955 static int | 944 static int |
956 cons_equal (Lisp_Object ob1, Lisp_Object ob2, int depth) | 945 cons_equal (Lisp_Object ob1, Lisp_Object ob2, int depth) |
1094 { | 1083 { |
1095 CHECK_NATNUM (length); | 1084 CHECK_NATNUM (length); |
1096 | 1085 |
1097 { | 1086 { |
1098 Lisp_Object val = Qnil; | 1087 Lisp_Object val = Qnil; |
1099 int size = XINT (length); | 1088 size_t size = XINT (length); |
1100 | 1089 |
1101 while (size-- > 0) | 1090 while (size--) |
1102 val = Fcons (init, val); | 1091 val = Fcons (init, val); |
1103 return val; | 1092 return val; |
1104 } | 1093 } |
1105 } | 1094 } |
1106 | 1095 |
1133 /************************************************************************/ | 1122 /************************************************************************/ |
1134 /* Vector allocation */ | 1123 /* Vector allocation */ |
1135 /************************************************************************/ | 1124 /************************************************************************/ |
1136 | 1125 |
1137 static Lisp_Object | 1126 static Lisp_Object |
1138 mark_vector (Lisp_Object obj, void (*markobj) (Lisp_Object)) | 1127 mark_vector (Lisp_Object obj) |
1139 { | 1128 { |
1140 Lisp_Vector *ptr = XVECTOR (obj); | 1129 Lisp_Vector *ptr = XVECTOR (obj); |
1141 int len = vector_length (ptr); | 1130 int len = vector_length (ptr); |
1142 int i; | 1131 int i; |
1143 | 1132 |
1144 for (i = 0; i < len - 1; i++) | 1133 for (i = 0; i < len - 1; i++) |
1145 markobj (ptr->contents[i]); | 1134 mark_object (ptr->contents[i]); |
1146 return (len > 0) ? ptr->contents[len - 1] : Qnil; | 1135 return (len > 0) ? ptr->contents[len - 1] : Qnil; |
1147 } | 1136 } |
1148 | 1137 |
1149 static size_t | 1138 static size_t |
1150 size_vector (CONST void *lheader) | 1139 size_vector (CONST void *lheader) |
1170 return 1; | 1159 return 1; |
1171 } | 1160 } |
1172 | 1161 |
1173 static const struct lrecord_description vector_description[] = { | 1162 static const struct lrecord_description vector_description[] = { |
1174 { XD_LONG, offsetof(struct Lisp_Vector, size) }, | 1163 { XD_LONG, offsetof(struct Lisp_Vector, size) }, |
1175 { XD_LISP_OBJECT, offsetof(struct Lisp_Vector, contents), XD_INDIRECT(0) } | 1164 { XD_LISP_OBJECT, offsetof(struct Lisp_Vector, contents), XD_INDIRECT(0, 0) }, |
1165 { XD_END } | |
1176 }; | 1166 }; |
1177 | 1167 |
1178 DEFINE_LRECORD_SEQUENCE_IMPLEMENTATION("vector", vector, | 1168 DEFINE_LRECORD_SEQUENCE_IMPLEMENTATION("vector", vector, |
1179 mark_vector, print_vector, 0, | 1169 mark_vector, print_vector, 0, |
1180 vector_equal, | 1170 vector_equal, |
1543 if (!NILP (constants)) | 1533 if (!NILP (constants)) |
1544 CHECK_VECTOR (constants); | 1534 CHECK_VECTOR (constants); |
1545 f->constants = constants; | 1535 f->constants = constants; |
1546 | 1536 |
1547 CHECK_NATNUM (stack_depth); | 1537 CHECK_NATNUM (stack_depth); |
1548 f->stack_depth = XINT (stack_depth); | 1538 f->stack_depth = XINT (stack_depth); |
1549 | 1539 |
1550 #ifdef COMPILED_FUNCTION_ANNOTATION_HACK | 1540 #ifdef COMPILED_FUNCTION_ANNOTATION_HACK |
1551 if (!NILP (Vcurrent_compiled_function_annotation)) | 1541 if (!NILP (Vcurrent_compiled_function_annotation)) |
1552 f->annotated = Fcopy (Vcurrent_compiled_function_annotation); | 1542 f->annotated = Fcopy (Vcurrent_compiled_function_annotation); |
1553 else if (!NILP (Vload_file_name_internal_the_purecopy)) | 1543 else if (!NILP (Vload_file_name_internal_the_purecopy)) |
1555 else if (!NILP (Vload_file_name_internal)) | 1545 else if (!NILP (Vload_file_name_internal)) |
1556 { | 1546 { |
1557 struct gcpro gcpro1; | 1547 struct gcpro gcpro1; |
1558 GCPRO1 (fun); /* don't let fun get reaped */ | 1548 GCPRO1 (fun); /* don't let fun get reaped */ |
1559 Vload_file_name_internal_the_purecopy = | 1549 Vload_file_name_internal_the_purecopy = |
1560 Fpurecopy (Ffile_name_nondirectory (Vload_file_name_internal)); | 1550 Ffile_name_nondirectory (Vload_file_name_internal); |
1561 f->annotated = Vload_file_name_internal_the_purecopy; | 1551 f->annotated = Vload_file_name_internal_the_purecopy; |
1562 UNGCPRO; | 1552 UNGCPRO; |
1563 } | 1553 } |
1564 #endif /* COMPILED_FUNCTION_ANNOTATION_HACK */ | 1554 #endif /* COMPILED_FUNCTION_ANNOTATION_HACK */ |
1565 | 1555 |
1734 /* strings are used and freed quite often */ | 1724 /* strings are used and freed quite often */ |
1735 /* #define MINIMUM_ALLOWED_FIXED_TYPE_CELLS_string 10000 */ | 1725 /* #define MINIMUM_ALLOWED_FIXED_TYPE_CELLS_string 10000 */ |
1736 #define MINIMUM_ALLOWED_FIXED_TYPE_CELLS_string 1000 | 1726 #define MINIMUM_ALLOWED_FIXED_TYPE_CELLS_string 1000 |
1737 | 1727 |
1738 static Lisp_Object | 1728 static Lisp_Object |
1739 mark_string (Lisp_Object obj, void (*markobj) (Lisp_Object)) | 1729 mark_string (Lisp_Object obj) |
1740 { | 1730 { |
1741 struct Lisp_String *ptr = XSTRING (obj); | 1731 struct Lisp_String *ptr = XSTRING (obj); |
1742 | 1732 |
1743 if (GC_CONSP (ptr->plist) && GC_EXTENT_INFOP (XCAR (ptr->plist))) | 1733 if (CONSP (ptr->plist) && EXTENT_INFOP (XCAR (ptr->plist))) |
1744 flush_cached_extent_info (XCAR (ptr->plist)); | 1734 flush_cached_extent_info (XCAR (ptr->plist)); |
1745 return ptr->plist; | 1735 return ptr->plist; |
1746 } | 1736 } |
1747 | 1737 |
1748 static int | 1738 static int |
1752 return (((len = XSTRING_LENGTH (obj1)) == XSTRING_LENGTH (obj2)) && | 1742 return (((len = XSTRING_LENGTH (obj1)) == XSTRING_LENGTH (obj2)) && |
1753 !memcmp (XSTRING_DATA (obj1), XSTRING_DATA (obj2), len)); | 1743 !memcmp (XSTRING_DATA (obj1), XSTRING_DATA (obj2), len)); |
1754 } | 1744 } |
1755 | 1745 |
1756 static const struct lrecord_description string_description[] = { | 1746 static const struct lrecord_description string_description[] = { |
1757 { XD_STRING_DATA, offsetof(Lisp_String, data) }, | 1747 { XD_BYTECOUNT, offsetof(Lisp_String, size) }, |
1758 { XD_LISP_OBJECT, offsetof(Lisp_String, plist), 1 }, | 1748 { XD_OPAQUE_DATA_PTR, offsetof(Lisp_String, data), XD_INDIRECT(0, 1) }, |
1749 { XD_LISP_OBJECT, offsetof(Lisp_String, plist), 1 }, | |
1759 { XD_END } | 1750 { XD_END } |
1760 }; | 1751 }; |
1761 | 1752 |
1762 DEFINE_BASIC_LRECORD_IMPLEMENTATION ("string", string, | 1753 DEFINE_BASIC_LRECORD_IMPLEMENTATION ("string", string, |
1763 mark_string, print_string, | 1754 mark_string, print_string, |
1789 /* Contents of string_chars_block->string_chars are interleaved | 1780 /* Contents of string_chars_block->string_chars are interleaved |
1790 string_chars structures (see below) and the actual string data */ | 1781 string_chars structures (see below) and the actual string data */ |
1791 unsigned char string_chars[STRING_CHARS_BLOCK_SIZE]; | 1782 unsigned char string_chars[STRING_CHARS_BLOCK_SIZE]; |
1792 }; | 1783 }; |
1793 | 1784 |
1794 struct string_chars_block *first_string_chars_block; | 1785 static struct string_chars_block *first_string_chars_block; |
1795 struct string_chars_block *current_string_chars_block; | 1786 static struct string_chars_block *current_string_chars_block; |
1796 | 1787 |
1797 /* If SIZE is the length of a string, this returns how many bytes | 1788 /* If SIZE is the length of a string, this returns how many bytes |
1798 * the string occupies in string_chars_block->string_chars | 1789 * the string occupies in string_chars_block->string_chars |
1799 * (including alignment padding). | 1790 * (including alignment padding). |
1800 */ | 1791 */ |
2077 if (len == 1) | 2068 if (len == 1) |
2078 /* Optimize the single-byte case */ | 2069 /* Optimize the single-byte case */ |
2079 memset (XSTRING_DATA (val), XCHAR (init), XSTRING_LENGTH (val)); | 2070 memset (XSTRING_DATA (val), XCHAR (init), XSTRING_LENGTH (val)); |
2080 else | 2071 else |
2081 { | 2072 { |
2082 int i; | 2073 size_t i; |
2083 Bufbyte *ptr = XSTRING_DATA (val); | 2074 Bufbyte *ptr = XSTRING_DATA (val); |
2084 | 2075 |
2085 for (i = XINT (length); i; i--) | 2076 for (i = XINT (length); i; i--) |
2086 { | 2077 { |
2087 Bufbyte *init_ptr = init_str; | 2078 Bufbyte *init_ptr = init_str; |
2200 It is similar to the Blocktype class. | 2191 It is similar to the Blocktype class. |
2201 | 2192 |
2202 It works like this: | 2193 It works like this: |
2203 | 2194 |
2204 1) Create an lcrecord-list object using make_lcrecord_list(). | 2195 1) Create an lcrecord-list object using make_lcrecord_list(). |
2205 This is often done at initialization. Remember to staticpro | 2196 This is often done at initialization. Remember to staticpro_nodump |
2206 this object! The arguments to make_lcrecord_list() are the | 2197 this object! The arguments to make_lcrecord_list() are the |
2207 same as would be passed to alloc_lcrecord(). | 2198 same as would be passed to alloc_lcrecord(). |
2208 2) Instead of calling alloc_lcrecord(), call allocate_managed_lcrecord() | 2199 2) Instead of calling alloc_lcrecord(), call allocate_managed_lcrecord() |
2209 and pass the lcrecord-list earlier created. | 2200 and pass the lcrecord-list earlier created. |
2210 3) When done with the lcrecord, call free_managed_lcrecord(). | 2201 3) When done with the lcrecord, call free_managed_lcrecord(). |
2221 at the time that free_managed_lcrecord() is called. | 2212 at the time that free_managed_lcrecord() is called. |
2222 | 2213 |
2223 */ | 2214 */ |
2224 | 2215 |
2225 static Lisp_Object | 2216 static Lisp_Object |
2226 mark_lcrecord_list (Lisp_Object obj, void (*markobj) (Lisp_Object)) | 2217 mark_lcrecord_list (Lisp_Object obj) |
2227 { | 2218 { |
2228 struct lcrecord_list *list = XLCRECORD_LIST (obj); | 2219 struct lcrecord_list *list = XLCRECORD_LIST (obj); |
2229 Lisp_Object chain = list->free; | 2220 Lisp_Object chain = list->free; |
2230 | 2221 |
2231 while (!NILP (chain)) | 2222 while (!NILP (chain)) |
2374 | 2365 |
2375 struct gcpro *gcprolist; | 2366 struct gcpro *gcprolist; |
2376 | 2367 |
2377 /* 415 used Mly 29-Jun-93 */ | 2368 /* 415 used Mly 29-Jun-93 */ |
2378 /* 1327 used slb 28-Feb-98 */ | 2369 /* 1327 used slb 28-Feb-98 */ |
2370 /* 1328 used og 03-Oct-99 (moving slowly, heh?) */ | |
2379 #ifdef HAVE_SHLIB | 2371 #ifdef HAVE_SHLIB |
2380 #define NSTATICS 4000 | 2372 #define NSTATICS 4000 |
2381 #else | 2373 #else |
2382 #define NSTATICS 2000 | 2374 #define NSTATICS 2000 |
2383 #endif | 2375 #endif |
2397 /* by Lisp attempting to load a DLL. */ | 2389 /* by Lisp attempting to load a DLL. */ |
2398 abort (); | 2390 abort (); |
2399 staticvec[staticidx++] = varaddress; | 2391 staticvec[staticidx++] = varaddress; |
2400 } | 2392 } |
2401 | 2393 |
2394 /* Not "static" because of linker lossage on some systems */ | |
2395 Lisp_Object *staticvec_nodump[200] | |
2396 /* Force it into data space! */ | |
2397 = {0}; | |
2398 static int staticidx_nodump; | |
2399 | |
2400 /* Put an entry in staticvec_nodump, pointing at the variable whose address is given | |
2401 */ | |
2402 void | |
2403 staticpro_nodump (Lisp_Object *varaddress) | |
2404 { | |
2405 if (staticidx_nodump >= countof (staticvec_nodump)) | |
2406 /* #### This is now a dubious abort() since this routine may be called */ | |
2407 /* by Lisp attempting to load a DLL. */ | |
2408 abort (); | |
2409 staticvec_nodump[staticidx_nodump++] = varaddress; | |
2410 } | |
2411 | |
2412 /* Not "static" because of linker lossage on some systems */ | |
2413 struct { | |
2414 void *data; | |
2415 const struct struct_description *desc; | |
2416 } dumpstructvec[200]; | |
2417 | |
2418 static int dumpstructidx; | |
2419 | |
2420 /* Put an entry in dumpstructvec, pointing at the variable whose address is given | |
2421 */ | |
2422 void | |
2423 dumpstruct (void *varaddress, const struct struct_description *desc) | |
2424 { | |
2425 if (dumpstructidx >= countof (dumpstructvec)) | |
2426 abort (); | |
2427 dumpstructvec[dumpstructidx].data = varaddress; | |
2428 dumpstructvec[dumpstructidx].desc = desc; | |
2429 dumpstructidx++; | |
2430 } | |
2431 | |
2432 Lisp_Object *pdump_wirevec[50]; | |
2433 static int pdump_wireidx; | |
2434 | |
2435 /* Put an entry in pdump_wirevec, pointing at the variable whose address is given | |
2436 */ | |
2437 void | |
2438 pdump_wire (Lisp_Object *varaddress) | |
2439 { | |
2440 if (pdump_wireidx >= countof (pdump_wirevec)) | |
2441 abort (); | |
2442 pdump_wirevec[pdump_wireidx++] = varaddress; | |
2443 } | |
2444 | |
2445 | |
2446 Lisp_Object *pdump_wirevec_list[50]; | |
2447 static int pdump_wireidx_list; | |
2448 | |
2449 /* Put an entry in pdump_wirevec_list, pointing at the variable whose address is given | |
2450 */ | |
2451 void | |
2452 pdump_wire_list (Lisp_Object *varaddress) | |
2453 { | |
2454 if (pdump_wireidx_list >= countof (pdump_wirevec_list)) | |
2455 abort (); | |
2456 pdump_wirevec_list[pdump_wireidx_list++] = varaddress; | |
2457 } | |
2458 | |
2402 | 2459 |
2403 /* Mark reference to a Lisp_Object. If the object referred to has not been | 2460 /* Mark reference to a Lisp_Object. If the object referred to has not been |
2404 seen yet, recursively mark all the references contained in it. */ | 2461 seen yet, recursively mark all the references contained in it. */ |
2405 | 2462 |
2406 static void | 2463 void |
2407 mark_object (Lisp_Object obj) | 2464 mark_object (Lisp_Object obj) |
2408 { | 2465 { |
2409 tail_recurse: | 2466 tail_recurse: |
2410 | 2467 |
2411 #ifdef ERROR_CHECK_GC | 2468 #ifdef ERROR_CHECK_GC |
2412 assert (! (GC_EQ (obj, Qnull_pointer))); | 2469 assert (! (EQ (obj, Qnull_pointer))); |
2413 #endif | 2470 #endif |
2414 /* Checks we used to perform */ | 2471 /* Checks we used to perform */ |
2415 /* if (EQ (obj, Qnull_pointer)) return; */ | 2472 /* if (EQ (obj, Qnull_pointer)) return; */ |
2416 /* if (!POINTER_TYPE_P (XGCTYPE (obj))) return; */ | 2473 /* if (!POINTER_TYPE_P (XGCTYPE (obj))) return; */ |
2417 /* if (PURIFIED (XPNTR (obj))) return; */ | 2474 /* if (PURIFIED (XPNTR (obj))) return; */ |
2418 | 2475 |
2419 if (XGCTYPE (obj) == Lisp_Type_Record) | 2476 if (XTYPE (obj) == Lisp_Type_Record) |
2420 { | 2477 { |
2421 struct lrecord_header *lheader = XRECORD_LHEADER (obj); | 2478 struct lrecord_header *lheader = XRECORD_LHEADER (obj); |
2422 #if defined (ERROR_CHECK_GC) | 2479 #if defined (ERROR_CHECK_GC) |
2423 assert (lheader->type <= last_lrecord_type_index_assigned); | 2480 assert (lheader->type <= last_lrecord_type_index_assigned); |
2424 #endif | 2481 #endif |
2435 if (!implementation->basic_p) | 2492 if (!implementation->basic_p) |
2436 assert (! ((struct lcrecord_header *) lheader)->free); | 2493 assert (! ((struct lcrecord_header *) lheader)->free); |
2437 #endif | 2494 #endif |
2438 if (implementation->marker) | 2495 if (implementation->marker) |
2439 { | 2496 { |
2440 obj = implementation->marker (obj, mark_object); | 2497 obj = implementation->marker (obj); |
2441 if (!GC_NILP (obj)) goto tail_recurse; | 2498 if (!NILP (obj)) goto tail_recurse; |
2442 } | 2499 } |
2443 } | 2500 } |
2444 } | 2501 } |
2445 } | 2502 } |
2446 | 2503 |
2909 { | 2966 { |
2910 #ifdef ERROR_CHECK_GC | 2967 #ifdef ERROR_CHECK_GC |
2911 /* Perhaps this will catch freeing an already-freed marker. */ | 2968 /* Perhaps this will catch freeing an already-freed marker. */ |
2912 Lisp_Object temmy; | 2969 Lisp_Object temmy; |
2913 XSETMARKER (temmy, ptr); | 2970 XSETMARKER (temmy, ptr); |
2914 assert (GC_MARKERP (temmy)); | 2971 assert (MARKERP (temmy)); |
2915 #endif /* ERROR_CHECK_GC */ | 2972 #endif /* ERROR_CHECK_GC */ |
2916 | 2973 |
2917 #ifndef ALLOC_NO_POOLS | 2974 #ifndef ALLOC_NO_POOLS |
2918 FREE_FIXED_TYPE_WHEN_NOT_IN_GC (marker, struct Lisp_Marker, ptr); | 2975 FREE_FIXED_TYPE_WHEN_NOT_IN_GC (marker, struct Lisp_Marker, ptr); |
2919 #endif /* ALLOC_NO_POOLS */ | 2976 #endif /* ALLOC_NO_POOLS */ |
3122 gc_count_short_string_total_size = num_small_bytes; | 3179 gc_count_short_string_total_size = num_small_bytes; |
3123 } | 3180 } |
3124 | 3181 |
3125 | 3182 |
3126 /* I hate duplicating all this crap! */ | 3183 /* I hate duplicating all this crap! */ |
3127 static int | 3184 int |
3128 marked_p (Lisp_Object obj) | 3185 marked_p (Lisp_Object obj) |
3129 { | 3186 { |
3130 #ifdef ERROR_CHECK_GC | 3187 #ifdef ERROR_CHECK_GC |
3131 assert (! (GC_EQ (obj, Qnull_pointer))); | 3188 assert (! (EQ (obj, Qnull_pointer))); |
3132 #endif | 3189 #endif |
3133 /* Checks we used to perform. */ | 3190 /* Checks we used to perform. */ |
3134 /* if (EQ (obj, Qnull_pointer)) return 1; */ | 3191 /* if (EQ (obj, Qnull_pointer)) return 1; */ |
3135 /* if (!POINTER_TYPE_P (XGCTYPE (obj))) return 1; */ | 3192 /* if (!POINTER_TYPE_P (XGCTYPE (obj))) return 1; */ |
3136 /* if (PURIFIED (XPNTR (obj))) return 1; */ | 3193 /* if (PURIFIED (XPNTR (obj))) return 1; */ |
3137 | 3194 |
3138 if (XGCTYPE (obj) == Lisp_Type_Record) | 3195 if (XTYPE (obj) == Lisp_Type_Record) |
3139 { | 3196 { |
3140 struct lrecord_header *lheader = XRECORD_LHEADER (obj); | 3197 struct lrecord_header *lheader = XRECORD_LHEADER (obj); |
3141 #if defined (ERROR_CHECK_GC) | 3198 #if defined (ERROR_CHECK_GC) |
3142 assert (lheader->type <= last_lrecord_type_index_assigned); | 3199 assert (lheader->type <= last_lrecord_type_index_assigned); |
3143 #endif | 3200 #endif |
3203 Dechain each one first from the buffer into which it points. */ | 3260 Dechain each one first from the buffer into which it points. */ |
3204 sweep_markers (); | 3261 sweep_markers (); |
3205 | 3262 |
3206 sweep_events (); | 3263 sweep_events (); |
3207 | 3264 |
3265 #ifdef PDUMP | |
3266 /* Unmark all dumped objects */ | |
3267 { | |
3268 int i; | |
3269 char *p = pdump_rt_list; | |
3270 if(p) | |
3271 for(;;) | |
3272 { | |
3273 pdump_reloc_table *rt = (pdump_reloc_table *)p; | |
3274 p += sizeof (pdump_reloc_table); | |
3275 if (rt->desc) { | |
3276 for (i=0; i<rt->count; i++) | |
3277 { | |
3278 UNMARK_RECORD_HEADER ((struct lrecord_header *)(*(EMACS_INT *)p)); | |
3279 p += sizeof (EMACS_INT); | |
3280 } | |
3281 } else | |
3282 break; | |
3283 } | |
3284 } | |
3285 #endif | |
3208 } | 3286 } |
3209 | 3287 |
3210 /* Clearing for disksave. */ | 3288 /* Clearing for disksave. */ |
3211 | 3289 |
3212 void | 3290 void |
3404 | 3482 |
3405 { /* staticpro() */ | 3483 { /* staticpro() */ |
3406 int i; | 3484 int i; |
3407 for (i = 0; i < staticidx; i++) | 3485 for (i = 0; i < staticidx; i++) |
3408 mark_object (*(staticvec[i])); | 3486 mark_object (*(staticvec[i])); |
3487 for (i = 0; i < staticidx_nodump; i++) | |
3488 mark_object (*(staticvec_nodump[i])); | |
3409 } | 3489 } |
3410 | 3490 |
3411 { /* GCPRO() */ | 3491 { /* GCPRO() */ |
3412 struct gcpro *tail; | 3492 struct gcpro *tail; |
3413 int i; | 3493 int i; |
3448 for (i = 0; i < nargs; i++) | 3528 for (i = 0; i < nargs; i++) |
3449 mark_object (backlist->args[i]); | 3529 mark_object (backlist->args[i]); |
3450 } | 3530 } |
3451 } | 3531 } |
3452 | 3532 |
3453 mark_redisplay (mark_object); | 3533 mark_redisplay (); |
3454 mark_profiling_info (mark_object); | 3534 mark_profiling_info (); |
3455 | 3535 |
3456 /* OK, now do the after-mark stuff. This is for things that | 3536 /* OK, now do the after-mark stuff. This is for things that |
3457 are only marked when something else is marked (e.g. weak hash tables). | 3537 are only marked when something else is marked (e.g. weak hash tables). |
3458 There may be complex dependencies between such objects -- e.g. | 3538 There may be complex dependencies between such objects -- e.g. |
3459 a weak hash table might be unmarked, but after processing a later | 3539 a weak hash table might be unmarked, but after processing a later |
3460 weak hash table, the former one might get marked. So we have to | 3540 weak hash table, the former one might get marked. So we have to |
3461 iterate until nothing more gets marked. */ | 3541 iterate until nothing more gets marked. */ |
3462 | 3542 |
3463 while (finish_marking_weak_hash_tables (marked_p, mark_object) > 0 || | 3543 while (finish_marking_weak_hash_tables () > 0 || |
3464 finish_marking_weak_lists (marked_p, mark_object) > 0) | 3544 finish_marking_weak_lists () > 0) |
3465 ; | 3545 ; |
3466 | 3546 |
3467 /* And prune (this needs to be called after everything else has been | 3547 /* And prune (this needs to be called after everything else has been |
3468 marked and before we do any sweeping). */ | 3548 marked and before we do any sweeping). */ |
3469 /* #### this is somewhat ad-hoc and should probably be an object | 3549 /* #### this is somewhat ad-hoc and should probably be an object |
3470 method */ | 3550 method */ |
3471 prune_weak_hash_tables (marked_p); | 3551 prune_weak_hash_tables (); |
3472 prune_weak_lists (marked_p); | 3552 prune_weak_lists (); |
3473 prune_specifiers (marked_p); | 3553 prune_specifiers (); |
3474 prune_syntax_tables (marked_p); | 3554 prune_syntax_tables (); |
3475 | 3555 |
3476 gc_sweep (); | 3556 gc_sweep (); |
3477 | 3557 |
3478 consing_since_gc = 0; | 3558 consing_since_gc = 0; |
3479 #ifndef DEBUG_XEMACS | 3559 #ifndef DEBUG_XEMACS |
3563 int i; | 3643 int i; |
3564 int gc_count_vector_total_size = 0; | 3644 int gc_count_vector_total_size = 0; |
3565 | 3645 |
3566 garbage_collect_1 (); | 3646 garbage_collect_1 (); |
3567 | 3647 |
3568 for (i = 0; i < last_lrecord_type_index_assigned; i++) | 3648 for (i = 0; i <= last_lrecord_type_index_assigned; i++) |
3569 { | 3649 { |
3570 if (lcrecord_stats[i].bytes_in_use != 0 | 3650 if (lcrecord_stats[i].bytes_in_use != 0 |
3571 || lcrecord_stats[i].bytes_freed != 0 | 3651 || lcrecord_stats[i].bytes_freed != 0 |
3572 || lcrecord_stats[i].instances_on_free_list != 0) | 3652 || lcrecord_stats[i].instances_on_free_list != 0) |
3573 { | 3653 { |
3837 #endif /* MEMORY_USAGE_STATS */ | 3917 #endif /* MEMORY_USAGE_STATS */ |
3838 | 3918 |
3839 | 3919 |
3840 /* Initialization */ | 3920 /* Initialization */ |
3841 void | 3921 void |
3842 init_alloc_once_early (void) | 3922 reinit_alloc_once_early (void) |
3843 { | 3923 { |
3844 int iii; | |
3845 | |
3846 last_lrecord_type_index_assigned = -1; | |
3847 for (iii = 0; iii < countof (lrecord_implementations_table); iii++) | |
3848 { | |
3849 lrecord_implementations_table[iii] = 0; | |
3850 } | |
3851 | |
3852 /* | |
3853 * All the staticly | |
3854 * defined subr lrecords were initialized with lheader->type == 0. | |
3855 * See subr_lheader_initializer in lisp.h. Force type index 0 to be | |
3856 * assigned to lrecord_subr so that those predefined indexes match | |
3857 * reality. | |
3858 */ | |
3859 lrecord_type_index (&lrecord_subr); | |
3860 assert (*(lrecord_subr.lrecord_type_index) == 0); | |
3861 /* | |
3862 * The same is true for symbol_value_forward objects, except the | |
3863 * type is 1. | |
3864 */ | |
3865 lrecord_type_index (&lrecord_symbol_value_forward); | |
3866 assert (*(lrecord_symbol_value_forward.lrecord_type_index) == 1); | |
3867 | |
3868 gc_generation_number[0] = 0; | 3924 gc_generation_number[0] = 0; |
3869 /* purify_flag 1 is correct even if CANNOT_DUMP. | 3925 /* purify_flag 1 is correct even if CANNOT_DUMP. |
3870 * loadup.el will set to nil at end. */ | 3926 * loadup.el will set to nil at end. */ |
3871 purify_flag = 1; | 3927 purify_flag = 1; |
3872 breathing_space = 0; | 3928 breathing_space = 0; |
3892 init_marker_alloc (); | 3948 init_marker_alloc (); |
3893 init_extent_alloc (); | 3949 init_extent_alloc (); |
3894 init_event_alloc (); | 3950 init_event_alloc (); |
3895 | 3951 |
3896 ignore_malloc_warnings = 0; | 3952 ignore_malloc_warnings = 0; |
3897 staticidx = 0; | 3953 |
3954 staticidx_nodump = 0; | |
3955 dumpstructidx = 0; | |
3956 pdump_wireidx = 0; | |
3957 | |
3898 consing_since_gc = 0; | 3958 consing_since_gc = 0; |
3899 #if 1 | 3959 #if 1 |
3900 gc_cons_threshold = 500000; /* XEmacs change */ | 3960 gc_cons_threshold = 500000; /* XEmacs change */ |
3901 #else | 3961 #else |
3902 gc_cons_threshold = 15000; /* debugging */ | 3962 gc_cons_threshold = 15000; /* debugging */ |
3919 really_unlikely_name_to_have_accidentally_in_a_non_errb_structure = 42; | 3979 really_unlikely_name_to_have_accidentally_in_a_non_errb_structure = 42; |
3920 ERROR_ME_WARN. | 3980 ERROR_ME_WARN. |
3921 really_unlikely_name_to_have_accidentally_in_a_non_errb_structure = | 3981 really_unlikely_name_to_have_accidentally_in_a_non_errb_structure = |
3922 3333632; | 3982 3333632; |
3923 #endif /* ERROR_CHECK_TYPECHECK */ | 3983 #endif /* ERROR_CHECK_TYPECHECK */ |
3984 } | |
3985 | |
3986 void | |
3987 init_alloc_once_early (void) | |
3988 { | |
3989 int iii; | |
3990 | |
3991 reinit_alloc_once_early (); | |
3992 | |
3993 last_lrecord_type_index_assigned = -1; | |
3994 for (iii = 0; iii < countof (lrecord_implementations_table); iii++) | |
3995 { | |
3996 lrecord_implementations_table[iii] = 0; | |
3997 } | |
3998 | |
3999 /* | |
4000 * All the staticly | |
4001 * defined subr lrecords were initialized with lheader->type == 0. | |
4002 * See subr_lheader_initializer in lisp.h. Force type index 0 to be | |
4003 * assigned to lrecord_subr so that those predefined indexes match | |
4004 * reality. | |
4005 */ | |
4006 lrecord_type_index (&lrecord_subr); | |
4007 assert (*(lrecord_subr.lrecord_type_index) == 0); | |
4008 /* | |
4009 * The same is true for symbol_value_forward objects, except the | |
4010 * type is 1. | |
4011 */ | |
4012 lrecord_type_index (&lrecord_symbol_value_forward); | |
4013 assert (*(lrecord_symbol_value_forward.lrecord_type_index) == 1); | |
4014 | |
4015 staticidx = 0; | |
3924 } | 4016 } |
3925 | 4017 |
3926 int pure_bytes_used = 0; | 4018 int pure_bytes_used = 0; |
3927 | 4019 |
3928 void | 4020 void |
4028 This is printed in the echo area. If the selected frame is on a | 4120 This is printed in the echo area. If the selected frame is on a |
4029 window system and `gc-pointer-glyph' specifies a value (i.e. a pointer | 4121 window system and `gc-pointer-glyph' specifies a value (i.e. a pointer |
4030 image instance) in the domain of the selected frame, the mouse pointer | 4122 image instance) in the domain of the selected frame, the mouse pointer |
4031 will change instead of this message being printed. | 4123 will change instead of this message being printed. |
4032 */ ); | 4124 */ ); |
4033 Vgc_message = make_string_nocopy ((CONST Bufbyte *) gc_default_message, | 4125 Vgc_message = build_string (gc_default_message); |
4034 countof (gc_default_message) - 1); | |
4035 | 4126 |
4036 DEFVAR_LISP ("gc-pointer-glyph", &Vgc_pointer_glyph /* | 4127 DEFVAR_LISP ("gc-pointer-glyph", &Vgc_pointer_glyph /* |
4037 Pointer glyph used to indicate that a garbage collection is in progress. | 4128 Pointer glyph used to indicate that a garbage collection is in progress. |
4038 If the selected window is on a window system and this glyph specifies a | 4129 If the selected window is on a window system and this glyph specifies a |
4039 value (i.e. a pointer image instance) in the domain of the selected | 4130 value (i.e. a pointer image instance) in the domain of the selected |
4046 void | 4137 void |
4047 complex_vars_of_alloc (void) | 4138 complex_vars_of_alloc (void) |
4048 { | 4139 { |
4049 Vgc_pointer_glyph = Fmake_glyph_internal (Qpointer); | 4140 Vgc_pointer_glyph = Fmake_glyph_internal (Qpointer); |
4050 } | 4141 } |
4142 | |
4143 | |
4144 #ifdef PDUMP | |
4145 | |
4146 /* The structure of the file | |
4147 * | |
4148 * 0 - header | |
4149 * 256 - dumped objects | |
4150 * stab_offset - nb_staticpro*(Lisp_Object *) from staticvec | |
4151 * - nb_staticpro*(relocated Lisp_Object) pointed to by staticpro | |
4152 * - nb_structdmp*pair(void *, adr) for pointers to structures | |
4153 * - lrecord_implementations_table[] | |
4154 * - relocation table | |
4155 * - wired variable address/value couples with the count preceding the list | |
4156 */ | |
4157 typedef struct | |
4158 { | |
4159 char signature[8]; | |
4160 EMACS_UINT stab_offset; | |
4161 EMACS_UINT reloc_address; | |
4162 int nb_staticpro; | |
4163 int nb_structdmp; | |
4164 int last_type; | |
4165 } dump_header; | |
4166 | |
4167 char *pdump_start, *pdump_end; | |
4168 | |
4169 static const unsigned char align_table[256] = | |
4170 { | |
4171 8, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, | |
4172 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, | |
4173 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, | |
4174 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, | |
4175 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, | |
4176 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, | |
4177 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, | |
4178 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, | |
4179 7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, | |
4180 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, | |
4181 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, | |
4182 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, | |
4183 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, | |
4184 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, | |
4185 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, | |
4186 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0 | |
4187 }; | |
4188 | |
4189 typedef struct pdump_entry_list_elmt | |
4190 { | |
4191 struct pdump_entry_list_elmt *next; | |
4192 const void *obj; | |
4193 size_t size; | |
4194 int count; | |
4195 int is_lrecord; | |
4196 EMACS_INT save_offset; | |
4197 } pdump_entry_list_elmt; | |
4198 | |
4199 typedef struct | |
4200 { | |
4201 pdump_entry_list_elmt *first; | |
4202 int align; | |
4203 int count; | |
4204 } pdump_entry_list; | |
4205 | |
4206 typedef struct pdump_struct_list_elmt | |
4207 { | |
4208 pdump_entry_list list; | |
4209 const struct struct_description *sdesc; | |
4210 } pdump_struct_list_elmt; | |
4211 | |
4212 typedef struct | |
4213 { | |
4214 pdump_struct_list_elmt *list; | |
4215 int count; | |
4216 int size; | |
4217 } pdump_struct_list; | |
4218 | |
4219 static pdump_entry_list pdump_object_table[256]; | |
4220 static pdump_entry_list pdump_opaque_data_list; | |
4221 static pdump_struct_list pdump_struct_table; | |
4222 static pdump_entry_list_elmt *pdump_qnil; | |
4223 | |
4224 static int pdump_alert_undump_object[256]; | |
4225 | |
4226 static unsigned long cur_offset; | |
4227 static size_t max_size; | |
4228 static int pdump_fd; | |
4229 static void *pdump_buf; | |
4230 | |
4231 #define PDUMP_HASHSIZE 200001 | |
4232 | |
4233 static pdump_entry_list_elmt **pdump_hash; | |
4234 | |
4235 /* Since most pointers are eight bytes aligned, the >>3 allows for a better hash */ | |
4236 static int | |
4237 pdump_make_hash (const void *obj) | |
4238 { | |
4239 return ((unsigned long)(obj)>>3) % PDUMP_HASHSIZE; | |
4240 } | |
4241 | |
4242 static pdump_entry_list_elmt * | |
4243 pdump_get_entry (const void *obj) | |
4244 { | |
4245 int pos = pdump_make_hash(obj); | |
4246 pdump_entry_list_elmt *e; | |
4247 while ((e = pdump_hash[pos]) != 0) | |
4248 { | |
4249 if (e->obj == obj) | |
4250 return e; | |
4251 | |
4252 pos++; | |
4253 if (pos == PDUMP_HASHSIZE) | |
4254 pos = 0; | |
4255 } | |
4256 return 0; | |
4257 } | |
4258 | |
4259 static void | |
4260 pdump_add_entry (pdump_entry_list *list, const void *obj, size_t size, int count, int is_lrecord) | |
4261 { | |
4262 pdump_entry_list_elmt *e; | |
4263 int align; | |
4264 int pos = pdump_make_hash (obj); | |
4265 | |
4266 while ((e = pdump_hash[pos]) != 0) | |
4267 { | |
4268 if (e->obj == obj) | |
4269 return; | |
4270 | |
4271 pos++; | |
4272 if (pos == PDUMP_HASHSIZE) | |
4273 pos = 0; | |
4274 } | |
4275 | |
4276 e = malloc (sizeof (pdump_entry_list_elmt)); | |
4277 | |
4278 e->next = list->first; | |
4279 e->obj = obj; | |
4280 e->size = size; | |
4281 e->count = count; | |
4282 e->is_lrecord = is_lrecord; | |
4283 list->first = e; | |
4284 | |
4285 list->count += count; | |
4286 pdump_hash[pos] = e; | |
4287 | |
4288 align = align_table[size & 255]; | |
4289 if (align<2 && is_lrecord) | |
4290 align = 2; | |
4291 | |
4292 if(align < list->align) | |
4293 list->align = align; | |
4294 } | |
4295 | |
4296 static pdump_entry_list * | |
4297 pdump_get_entry_list(const struct struct_description *sdesc) | |
4298 { | |
4299 int i; | |
4300 for(i=0; i<pdump_struct_table.count; i++) | |
4301 if (pdump_struct_table.list[i].sdesc == sdesc) | |
4302 return &pdump_struct_table.list[i].list; | |
4303 | |
4304 if (pdump_struct_table.size <= pdump_struct_table.count) | |
4305 { | |
4306 if (pdump_struct_table.size == -1) | |
4307 pdump_struct_table.size = 10; | |
4308 else | |
4309 pdump_struct_table.size = pdump_struct_table.size * 2; | |
4310 pdump_struct_table.list = xrealloc (pdump_struct_table.list, | |
4311 pdump_struct_table.size*sizeof (pdump_struct_list_elmt)); | |
4312 } | |
4313 pdump_struct_table.list[pdump_struct_table.count].list.first = 0; | |
4314 pdump_struct_table.list[pdump_struct_table.count].list.align = 8; | |
4315 pdump_struct_table.list[pdump_struct_table.count].list.count = 0; | |
4316 pdump_struct_table.list[pdump_struct_table.count].sdesc = sdesc; | |
4317 | |
4318 return &pdump_struct_table.list[pdump_struct_table.count++].list; | |
4319 } | |
4320 | |
4321 static struct { | |
4322 Lisp_Object obj; | |
4323 int position; | |
4324 int offset; | |
4325 } backtrace[65536]; | |
4326 | |
4327 static int depth; | |
4328 | |
4329 static void pdump_backtrace (void) | |
4330 { | |
4331 int i; | |
4332 fprintf (stderr, "pdump backtrace :\n"); | |
4333 for (i=0;i<depth;i++) | |
4334 { | |
4335 if (!backtrace[i].obj) | |
4336 fprintf (stderr, " - ind. (%d, %d)\n", backtrace[i].position, backtrace[i].offset); | |
4337 else | |
4338 { | |
4339 fprintf (stderr, " - %s (%d, %d)\n", | |
4340 XRECORD_LHEADER_IMPLEMENTATION (backtrace[i].obj)->name, | |
4341 backtrace[i].position, | |
4342 backtrace[i].offset); | |
4343 } | |
4344 } | |
4345 } | |
4346 | |
4347 static void pdump_register_object (Lisp_Object obj); | |
4348 static void pdump_register_struct (const void *data, const struct struct_description *sdesc, int count); | |
4349 | |
4350 static EMACS_INT | |
4351 pdump_get_indirect_count (EMACS_INT code, const struct lrecord_description *idesc, const void *idata) | |
4352 { | |
4353 EMACS_INT count; | |
4354 const void *irdata; | |
4355 | |
4356 int line = XD_INDIRECT_VAL (code); | |
4357 int delta = XD_INDIRECT_DELTA (code); | |
4358 | |
4359 irdata = ((char *)idata) + idesc[line].offset; | |
4360 switch (idesc[line].type) { | |
4361 case XD_SIZE_T: | |
4362 count = *(size_t *)irdata; | |
4363 break; | |
4364 case XD_INT: | |
4365 count = *(int *)irdata; | |
4366 break; | |
4367 case XD_LONG: | |
4368 count = *(long *)irdata; | |
4369 break; | |
4370 case XD_BYTECOUNT: | |
4371 count = *(Bytecount *)irdata; | |
4372 break; | |
4373 default: | |
4374 fprintf (stderr, "Unsupported count type : %d (line = %d, code=%ld)\n", idesc[line].type, line, (long)code); | |
4375 pdump_backtrace (); | |
4376 abort (); | |
4377 } | |
4378 count += delta; | |
4379 return count; | |
4380 } | |
4381 | |
4382 static void | |
4383 pdump_register_sub (const void *data, const struct lrecord_description *desc, int me) | |
4384 { | |
4385 int pos; | |
4386 const void *rdata; | |
4387 | |
4388 restart: | |
4389 for (pos = 0; desc[pos].type != XD_END; pos++) | |
4390 { | |
4391 backtrace[me].position = pos; | |
4392 backtrace[me].offset = desc[pos].offset; | |
4393 | |
4394 rdata = ((const char *)data) + desc[pos].offset; | |
4395 switch(desc[pos].type) | |
4396 { | |
4397 case XD_SPECIFIER_END: | |
4398 pos = 0; | |
4399 desc = ((const struct Lisp_Specifier *)data)->methods->extra_description; | |
4400 goto restart; | |
4401 case XD_SIZE_T: | |
4402 case XD_INT: | |
4403 case XD_LONG: | |
4404 case XD_BYTECOUNT: | |
4405 case XD_LO_RESET_NIL: | |
4406 case XD_INT_RESET: | |
4407 case XD_LO_LINK: | |
4408 break; | |
4409 case XD_OPAQUE_DATA_PTR: | |
4410 { | |
4411 EMACS_INT count = desc[pos].data1; | |
4412 if (XD_IS_INDIRECT(count)) | |
4413 count = pdump_get_indirect_count (count, desc, data); | |
4414 | |
4415 pdump_add_entry (&pdump_opaque_data_list, | |
4416 *(void **)rdata, | |
4417 count, | |
4418 1, | |
4419 0); | |
4420 break; | |
4421 } | |
4422 case XD_C_STRING: | |
4423 { | |
4424 const char *str = *(const char **)rdata; | |
4425 if (str) | |
4426 pdump_add_entry (&pdump_opaque_data_list, str, strlen (str)+1, 1, 0); | |
4427 break; | |
4428 } | |
4429 case XD_DOC_STRING: | |
4430 { | |
4431 const char *str = *(const char **)rdata; | |
4432 if ((EMACS_INT)str > 0) | |
4433 pdump_add_entry (&pdump_opaque_data_list, str, strlen (str)+1, 1, 0); | |
4434 break; | |
4435 } | |
4436 case XD_LISP_OBJECT: | |
4437 { | |
4438 EMACS_INT count = desc[pos].data1; | |
4439 int i; | |
4440 if (XD_IS_INDIRECT (count)) | |
4441 count = pdump_get_indirect_count (count, desc, data); | |
4442 | |
4443 for(i=0;i<count;i++) { | |
4444 const Lisp_Object *pobj = ((const Lisp_Object *)rdata) + i; | |
4445 Lisp_Object dobj = *pobj; | |
4446 | |
4447 backtrace[me].offset = (const char *)pobj - (const char *)data; | |
4448 pdump_register_object (dobj); | |
4449 } | |
4450 break; | |
4451 } | |
4452 case XD_STRUCT_PTR: | |
4453 { | |
4454 EMACS_INT count = desc[pos].data1; | |
4455 const struct struct_description *sdesc = desc[pos].data2; | |
4456 const char *dobj = *(const char **)rdata; | |
4457 if (dobj) { | |
4458 if (XD_IS_INDIRECT (count)) | |
4459 count = pdump_get_indirect_count (count, desc, data); | |
4460 | |
4461 pdump_register_struct (dobj, sdesc, count); | |
4462 } | |
4463 break; | |
4464 } | |
4465 default: | |
4466 fprintf (stderr, "Unsupported dump type : %d\n", desc[pos].type); | |
4467 pdump_backtrace (); | |
4468 abort (); | |
4469 }; | |
4470 } | |
4471 } | |
4472 | |
4473 static void | |
4474 pdump_register_object (Lisp_Object obj) | |
4475 { | |
4476 if (!obj || | |
4477 !POINTER_TYPE_P (XTYPE (obj)) || | |
4478 pdump_get_entry (XRECORD_LHEADER (obj))) | |
4479 return; | |
4480 | |
4481 if (XRECORD_LHEADER_IMPLEMENTATION (obj)->description) | |
4482 { | |
4483 int me = depth++; | |
4484 if (me>65536) | |
4485 { | |
4486 fprintf (stderr, "Backtrace overflow, loop ?\n"); | |
4487 abort (); | |
4488 } | |
4489 backtrace[me].obj = obj; | |
4490 backtrace[me].position = 0; | |
4491 backtrace[me].offset = 0; | |
4492 | |
4493 pdump_add_entry (pdump_object_table + XRECORD_LHEADER (obj)->type, | |
4494 XRECORD_LHEADER (obj), | |
4495 XRECORD_LHEADER_IMPLEMENTATION (obj)->static_size ? | |
4496 XRECORD_LHEADER_IMPLEMENTATION (obj)->static_size : | |
4497 XRECORD_LHEADER_IMPLEMENTATION (obj)->size_in_bytes_method (XRECORD_LHEADER (obj)), | |
4498 1, | |
4499 1); | |
4500 pdump_register_sub (XRECORD_LHEADER (obj), | |
4501 XRECORD_LHEADER_IMPLEMENTATION (obj)->description, | |
4502 me); | |
4503 --depth; | |
4504 } | |
4505 else | |
4506 { | |
4507 pdump_alert_undump_object[XRECORD_LHEADER (obj)->type]++; | |
4508 fprintf (stderr, "Undumpable object type : %s\n", XRECORD_LHEADER_IMPLEMENTATION (obj)->name); | |
4509 pdump_backtrace (); | |
4510 } | |
4511 } | |
4512 | |
4513 static void | |
4514 pdump_register_struct (const void *data, const struct struct_description *sdesc, int count) | |
4515 { | |
4516 if (data && !pdump_get_entry (data)) | |
4517 { | |
4518 int me = depth++; | |
4519 int i; | |
4520 if (me>65536) | |
4521 { | |
4522 fprintf (stderr, "Backtrace overflow, loop ?\n"); | |
4523 abort (); | |
4524 } | |
4525 backtrace[me].obj = 0; | |
4526 backtrace[me].position = 0; | |
4527 backtrace[me].offset = 0; | |
4528 | |
4529 pdump_add_entry (pdump_get_entry_list (sdesc), | |
4530 data, | |
4531 sdesc->size, | |
4532 count, | |
4533 0); | |
4534 for (i=0; i<count; i++) | |
4535 { | |
4536 pdump_register_sub (((char *)data) + sdesc->size*i, | |
4537 sdesc->description, | |
4538 me); | |
4539 } | |
4540 --depth; | |
4541 } | |
4542 } | |
4543 | |
4544 static void | |
4545 pdump_dump_data (pdump_entry_list_elmt *elmt, const struct lrecord_description *desc) | |
4546 { | |
4547 size_t size = elmt->size; | |
4548 int count = elmt->count; | |
4549 if (desc) | |
4550 { | |
4551 int pos, i; | |
4552 void *rdata; | |
4553 memcpy (pdump_buf, elmt->obj, size*count); | |
4554 | |
4555 for (i=0; i<count; i++) | |
4556 { | |
4557 char *cur = ((char *)pdump_buf) + i*size; | |
4558 restart: | |
4559 for (pos = 0; desc[pos].type != XD_END; pos++) | |
4560 { | |
4561 rdata = cur + desc[pos].offset; | |
4562 switch (desc[pos].type) | |
4563 { | |
4564 case XD_SPECIFIER_END: | |
4565 pos = 0; | |
4566 desc = ((const struct Lisp_Specifier *)(elmt->obj))->methods->extra_description; | |
4567 goto restart; | |
4568 case XD_SIZE_T: | |
4569 case XD_INT: | |
4570 case XD_LONG: | |
4571 case XD_BYTECOUNT: | |
4572 break; | |
4573 case XD_LO_RESET_NIL: | |
4574 { | |
4575 EMACS_INT count = desc[pos].data1; | |
4576 int i; | |
4577 if (XD_IS_INDIRECT (count)) | |
4578 count = pdump_get_indirect_count (count, desc, elmt->obj); | |
4579 for (i=0; i<count; i++) | |
4580 ((EMACS_INT *)rdata)[i] = pdump_qnil->save_offset; | |
4581 break; | |
4582 } | |
4583 case XD_INT_RESET: | |
4584 { | |
4585 EMACS_INT val = desc[pos].data1; | |
4586 if (XD_IS_INDIRECT (val)) | |
4587 val = pdump_get_indirect_count (val, desc, elmt->obj); | |
4588 *(int *)rdata = val; | |
4589 break; | |
4590 } | |
4591 case XD_OPAQUE_DATA_PTR: | |
4592 case XD_C_STRING: | |
4593 case XD_STRUCT_PTR: | |
4594 { | |
4595 void *ptr = *(void **)rdata; | |
4596 if (ptr) | |
4597 *(EMACS_INT *)rdata = pdump_get_entry (ptr)->save_offset; | |
4598 break; | |
4599 } | |
4600 case XD_LO_LINK: | |
4601 { | |
4602 Lisp_Object obj = *(Lisp_Object *)rdata; | |
4603 pdump_entry_list_elmt *elmt1; | |
4604 for(;;) | |
4605 { | |
4606 elmt1 = pdump_get_entry (XRECORD_LHEADER(obj)); | |
4607 if (elmt1) | |
4608 break; | |
4609 obj = *(Lisp_Object *)(desc[pos].offset + (char *)(XRECORD_LHEADER (obj))); | |
4610 } | |
4611 *(EMACS_INT *)rdata = elmt1->save_offset; | |
4612 break; | |
4613 } | |
4614 case XD_LISP_OBJECT: | |
4615 { | |
4616 EMACS_INT count = desc[pos].data1; | |
4617 int i; | |
4618 if (XD_IS_INDIRECT (count)) | |
4619 count = pdump_get_indirect_count (count, desc, elmt->obj); | |
4620 | |
4621 for(i=0; i<count; i++) | |
4622 { | |
4623 Lisp_Object *pobj = ((Lisp_Object *)rdata) + i; | |
4624 Lisp_Object dobj = *pobj; | |
4625 if (dobj && POINTER_TYPE_P (XTYPE (dobj))) | |
4626 *pobj = pdump_get_entry (XRECORD_LHEADER (dobj))->save_offset; | |
4627 } | |
4628 break; | |
4629 } | |
4630 case XD_DOC_STRING: | |
4631 { | |
4632 EMACS_INT str = *(EMACS_INT *)rdata; | |
4633 if (str > 0) | |
4634 *(EMACS_INT *)rdata = pdump_get_entry ((void *)str)->save_offset; | |
4635 break; | |
4636 } | |
4637 default: | |
4638 fprintf (stderr, "Unsupported dump type : %d\n", desc[pos].type); | |
4639 abort (); | |
4640 }; | |
4641 } | |
4642 } | |
4643 } | |
4644 write (pdump_fd, desc ? pdump_buf : elmt->obj, size*count); | |
4645 if (elmt->is_lrecord && ((size*count) & 3)) | |
4646 write (pdump_fd, "\0\0\0", 4-((size*count) & 3)); | |
4647 } | |
4648 | |
4649 static void | |
4650 pdump_reloc_one (void *data, EMACS_INT delta, const struct lrecord_description *desc) | |
4651 { | |
4652 int pos; | |
4653 void *rdata; | |
4654 | |
4655 restart: | |
4656 for (pos = 0; desc[pos].type != XD_END; pos++) | |
4657 { | |
4658 rdata = ((char *)data) + desc[pos].offset; | |
4659 switch (desc[pos].type) { | |
4660 case XD_SPECIFIER_END: | |
4661 pos = 0; | |
4662 desc = ((const struct Lisp_Specifier *)data)->methods->extra_description; | |
4663 goto restart; | |
4664 case XD_SIZE_T: | |
4665 case XD_INT: | |
4666 case XD_LONG: | |
4667 case XD_BYTECOUNT: | |
4668 case XD_INT_RESET: | |
4669 break; | |
4670 case XD_OPAQUE_DATA_PTR: | |
4671 case XD_C_STRING: | |
4672 case XD_STRUCT_PTR: | |
4673 case XD_LO_LINK: | |
4674 { | |
4675 EMACS_INT ptr = *(EMACS_INT *)rdata; | |
4676 if (ptr) | |
4677 *(EMACS_INT *)rdata = ptr+delta; | |
4678 break; | |
4679 } | |
4680 case XD_LISP_OBJECT: | |
4681 case XD_LO_RESET_NIL: | |
4682 { | |
4683 EMACS_INT count = desc[pos].data1; | |
4684 int i; | |
4685 if (XD_IS_INDIRECT (count)) | |
4686 count = pdump_get_indirect_count (count, desc, data); | |
4687 | |
4688 for (i=0; i<count; i++) | |
4689 { | |
4690 Lisp_Object *pobj = ((Lisp_Object *)rdata) + i; | |
4691 Lisp_Object dobj = *pobj; | |
4692 if (dobj && POINTER_TYPE_P (XTYPE (dobj))) | |
4693 *pobj = dobj + delta; | |
4694 } | |
4695 break; | |
4696 } | |
4697 case XD_DOC_STRING: | |
4698 { | |
4699 EMACS_INT str = *(EMACS_INT *)rdata; | |
4700 if (str > 0) | |
4701 *(EMACS_INT *)rdata = str + delta; | |
4702 break; | |
4703 } | |
4704 default: | |
4705 fprintf (stderr, "Unsupported dump type : %d\n", desc[pos].type); | |
4706 abort (); | |
4707 }; | |
4708 } | |
4709 } | |
4710 | |
4711 static void | |
4712 pdump_allocate_offset (pdump_entry_list_elmt *elmt, const struct lrecord_description *desc) | |
4713 { | |
4714 size_t size = (elmt->is_lrecord ? (elmt->size + 3) & ~3 : elmt->size)*elmt->count; | |
4715 elmt->save_offset = cur_offset; | |
4716 if (size>max_size) | |
4717 max_size = size; | |
4718 cur_offset += size; | |
4719 } | |
4720 | |
4721 static void | |
4722 pdump_scan_by_alignement (void (*f)(pdump_entry_list_elmt *, const struct lrecord_description *)) | |
4723 { | |
4724 int align, i; | |
4725 const struct lrecord_description *idesc; | |
4726 pdump_entry_list_elmt *elmt; | |
4727 for (align=8; align>=0; align--) | |
4728 { | |
4729 for (i=0; i<=last_lrecord_type_index_assigned; i++) | |
4730 if (pdump_object_table[i].align == align) | |
4731 { | |
4732 elmt = pdump_object_table[i].first; | |
4733 if (!elmt) | |
4734 continue; | |
4735 idesc = lrecord_implementations_table[i]->description; | |
4736 while (elmt) | |
4737 { | |
4738 f (elmt, idesc); | |
4739 elmt = elmt->next; | |
4740 } | |
4741 } | |
4742 | |
4743 for (i=0; i<pdump_struct_table.count; i++) | |
4744 if (pdump_struct_table.list[i].list.align == align) { | |
4745 elmt = pdump_struct_table.list[i].list.first; | |
4746 idesc = pdump_struct_table.list[i].sdesc->description; | |
4747 while (elmt) | |
4748 { | |
4749 f (elmt, idesc); | |
4750 elmt = elmt->next; | |
4751 } | |
4752 } | |
4753 | |
4754 elmt = pdump_opaque_data_list.first; | |
4755 while (elmt) | |
4756 { | |
4757 if (align_table[elmt->size & 255] == align) | |
4758 f (elmt, 0); | |
4759 elmt = elmt->next; | |
4760 } | |
4761 } | |
4762 } | |
4763 | |
4764 static void | |
4765 pdump_dump_staticvec (void) | |
4766 { | |
4767 Lisp_Object *reloc = malloc (staticidx*sizeof (Lisp_Object)); | |
4768 int i; | |
4769 write (pdump_fd, staticvec, staticidx*sizeof (Lisp_Object *)); | |
4770 | |
4771 for(i=0; i<staticidx; i++) | |
4772 { | |
4773 Lisp_Object obj = *staticvec[i]; | |
4774 if (obj && POINTER_TYPE_P (XTYPE (obj))) | |
4775 reloc[i] = pdump_get_entry (XRECORD_LHEADER (obj))->save_offset; | |
4776 else | |
4777 reloc[i] = obj; | |
4778 } | |
4779 write (pdump_fd, reloc, staticidx*sizeof (Lisp_Object)); | |
4780 free (reloc); | |
4781 } | |
4782 | |
4783 static void | |
4784 pdump_dump_structvec (void) | |
4785 { | |
4786 int i; | |
4787 for (i=0; i<dumpstructidx; i++) | |
4788 { | |
4789 EMACS_INT adr; | |
4790 write (pdump_fd, &(dumpstructvec[i].data), sizeof (void *)); | |
4791 adr = pdump_get_entry (*(void **)(dumpstructvec[i].data))->save_offset; | |
4792 write (pdump_fd, &adr, sizeof (adr)); | |
4793 } | |
4794 } | |
4795 | |
4796 static void | |
4797 pdump_dump_itable (void) | |
4798 { | |
4799 write (pdump_fd, lrecord_implementations_table, sizeof (lrecord_implementations_table)); | |
4800 } | |
4801 | |
4802 static void | |
4803 pdump_dump_rtables (void) | |
4804 { | |
4805 int i, j; | |
4806 pdump_entry_list_elmt *elmt; | |
4807 pdump_reloc_table rt; | |
4808 | |
4809 for (i=0; i<=last_lrecord_type_index_assigned; i++) | |
4810 { | |
4811 elmt = pdump_object_table[i].first; | |
4812 if(!elmt) | |
4813 continue; | |
4814 rt.desc = lrecord_implementations_table[i]->description; | |
4815 rt.count = pdump_object_table[i].count; | |
4816 write (pdump_fd, &rt, sizeof (rt)); | |
4817 while (elmt) | |
4818 { | |
4819 EMACS_INT rdata = pdump_get_entry (XRECORD_LHEADER (elmt->obj))->save_offset; | |
4820 write (pdump_fd, &rdata, sizeof (rdata)); | |
4821 elmt = elmt->next; | |
4822 } | |
4823 } | |
4824 | |
4825 rt.desc = 0; | |
4826 rt.count = 0; | |
4827 write (pdump_fd, &rt, sizeof (rt)); | |
4828 | |
4829 for (i=0; i<pdump_struct_table.count; i++) | |
4830 { | |
4831 elmt = pdump_struct_table.list[i].list.first; | |
4832 rt.desc = pdump_struct_table.list[i].sdesc->description; | |
4833 rt.count = pdump_struct_table.list[i].list.count; | |
4834 write (pdump_fd, &rt, sizeof (rt)); | |
4835 while (elmt) | |
4836 { | |
4837 EMACS_INT rdata = pdump_get_entry (XRECORD_LHEADER (elmt->obj))->save_offset; | |
4838 for (j=0; j<elmt->count; j++) { | |
4839 write (pdump_fd, &rdata, sizeof (rdata)); | |
4840 rdata += elmt->size; | |
4841 } | |
4842 elmt = elmt->next; | |
4843 } | |
4844 } | |
4845 rt.desc = 0; | |
4846 rt.count = 0; | |
4847 write (pdump_fd, &rt, sizeof (rt)); | |
4848 } | |
4849 | |
4850 static void | |
4851 pdump_dump_wired (void) | |
4852 { | |
4853 EMACS_INT count = pdump_wireidx + pdump_wireidx_list; | |
4854 int i; | |
4855 | |
4856 write (pdump_fd, &count, sizeof (count)); | |
4857 | |
4858 for (i=0; i<pdump_wireidx; i++) | |
4859 { | |
4860 Lisp_Object obj = pdump_get_entry (XRECORD_LHEADER (*(pdump_wirevec[i])))->save_offset; | |
4861 write (pdump_fd, &pdump_wirevec[i], sizeof (pdump_wirevec[i])); | |
4862 write (pdump_fd, &obj, sizeof (obj)); | |
4863 } | |
4864 | |
4865 for (i=0; i<pdump_wireidx_list; i++) | |
4866 { | |
4867 Lisp_Object obj = *(pdump_wirevec_list[i]); | |
4868 pdump_entry_list_elmt *elmt; | |
4869 EMACS_INT res; | |
4870 | |
4871 for(;;) | |
4872 { | |
4873 const struct lrecord_description *desc; | |
4874 int pos; | |
4875 elmt = pdump_get_entry (XRECORD_LHEADER (obj)); | |
4876 if (elmt) | |
4877 break; | |
4878 desc = XRECORD_LHEADER_IMPLEMENTATION (obj)->description; | |
4879 for (pos = 0; desc[pos].type != XD_LO_LINK; pos++) | |
4880 if (desc[pos].type == XD_END) | |
4881 abort (); | |
4882 | |
4883 obj = *(Lisp_Object *)(desc[pos].offset + (char *)(XRECORD_LHEADER (obj))); | |
4884 } | |
4885 res = elmt->save_offset; | |
4886 | |
4887 write (pdump_fd, &pdump_wirevec_list[i], sizeof (pdump_wirevec_list[i])); | |
4888 write (pdump_fd, &res, sizeof (res)); | |
4889 } | |
4890 } | |
4891 | |
4892 void | |
4893 pdump (void) | |
4894 { | |
4895 int i; | |
4896 Lisp_Object t_console, t_device, t_frame; | |
4897 int none; | |
4898 dump_header hd; | |
4899 | |
4900 /* These appear in a DEFVAR_LISP, which does a staticpro() */ | |
4901 t_console = Vterminal_console; | |
4902 t_frame = Vterminal_frame; | |
4903 t_device = Vterminal_device; | |
4904 | |
4905 Vterminal_console = Qnil; | |
4906 Vterminal_frame = Qnil; | |
4907 Vterminal_device = Qnil; | |
4908 | |
4909 pdump_hash = malloc (PDUMP_HASHSIZE*sizeof (pdump_entry_list_elmt *)); | |
4910 memset (pdump_hash, 0, PDUMP_HASHSIZE*sizeof (pdump_entry_list_elmt *)); | |
4911 | |
4912 for (i=0; i<=last_lrecord_type_index_assigned; i++) | |
4913 { | |
4914 pdump_object_table[i].first = 0; | |
4915 pdump_object_table[i].align = 8; | |
4916 pdump_object_table[i].count = 0; | |
4917 pdump_alert_undump_object[i] = 0; | |
4918 } | |
4919 pdump_struct_table.count = 0; | |
4920 pdump_struct_table.size = -1; | |
4921 | |
4922 pdump_opaque_data_list.first = 0; | |
4923 pdump_opaque_data_list.align = 8; | |
4924 pdump_opaque_data_list.count = 0; | |
4925 depth = 0; | |
4926 | |
4927 for (i=0; i<staticidx; i++) | |
4928 pdump_register_object (*staticvec[i]); | |
4929 for (i=0; i<pdump_wireidx; i++) | |
4930 pdump_register_object (*pdump_wirevec[i]); | |
4931 | |
4932 none = 1; | |
4933 for(i=0;i<=last_lrecord_type_index_assigned;i++) | |
4934 if (pdump_alert_undump_object[i]) | |
4935 { | |
4936 if (none) | |
4937 printf ("Undumpable types list :\n"); | |
4938 none = 0; | |
4939 printf (" - %s (%d)\n", lrecord_implementations_table[i]->name, pdump_alert_undump_object[i]); | |
4940 } | |
4941 if (!none) | |
4942 return; | |
4943 | |
4944 for (i=0; i<dumpstructidx; i++) | |
4945 pdump_register_struct (*(void **)(dumpstructvec[i].data), dumpstructvec[i].desc, 1); | |
4946 | |
4947 memcpy (hd.signature, "XEmacsDP", 8); | |
4948 hd.reloc_address = 0; | |
4949 hd.nb_staticpro = staticidx; | |
4950 hd.nb_structdmp = dumpstructidx; | |
4951 hd.last_type = last_lrecord_type_index_assigned; | |
4952 | |
4953 cur_offset = 256; | |
4954 max_size = 0; | |
4955 | |
4956 pdump_scan_by_alignement (pdump_allocate_offset); | |
4957 pdump_qnil = pdump_get_entry (XRECORD_LHEADER (Qnil)); | |
4958 | |
4959 pdump_buf = malloc (max_size); | |
4960 pdump_fd = open ("xemacs.dmp", O_WRONLY|O_CREAT|O_TRUNC, 0666); | |
4961 hd.stab_offset = (cur_offset + 3) & ~3; | |
4962 | |
4963 write (pdump_fd, &hd, sizeof (hd)); | |
4964 lseek (pdump_fd, 256, SEEK_SET); | |
4965 | |
4966 pdump_scan_by_alignement (pdump_dump_data); | |
4967 | |
4968 lseek (pdump_fd, hd.stab_offset, SEEK_SET); | |
4969 | |
4970 pdump_dump_staticvec (); | |
4971 pdump_dump_structvec (); | |
4972 pdump_dump_itable (); | |
4973 pdump_dump_rtables (); | |
4974 pdump_dump_wired (); | |
4975 | |
4976 close (pdump_fd); | |
4977 free (pdump_buf); | |
4978 | |
4979 free (pdump_hash); | |
4980 | |
4981 Vterminal_console = t_console; | |
4982 Vterminal_frame = t_frame; | |
4983 Vterminal_device = t_device; | |
4984 } | |
4985 | |
4986 int | |
4987 pdump_load (void) | |
4988 { | |
4989 size_t length; | |
4990 int i; | |
4991 char *p; | |
4992 EMACS_INT delta; | |
4993 EMACS_INT count; | |
4994 | |
4995 pdump_start = pdump_end = 0; | |
4996 | |
4997 pdump_fd = open ("xemacs.dmp", O_RDONLY); | |
4998 if (pdump_fd<0) | |
4999 return 0; | |
5000 | |
5001 length = lseek (pdump_fd, 0, SEEK_END); | |
5002 lseek (pdump_fd, 0, SEEK_SET); | |
5003 | |
5004 #ifdef HAVE_MMAP | |
5005 pdump_start = mmap (0, length, PROT_READ|PROT_WRITE, MAP_PRIVATE, pdump_fd, 0); | |
5006 if (pdump_start == MAP_FAILED) | |
5007 pdump_start = 0; | |
5008 #endif | |
5009 | |
5010 if (!pdump_start) | |
5011 { | |
5012 pdump_start = (void *)((((unsigned long)(malloc(length+255))) + 255) & ~255); | |
5013 read(pdump_fd, pdump_start, length); | |
5014 } | |
5015 | |
5016 close (pdump_fd); | |
5017 | |
5018 pdump_end = pdump_start + length; | |
5019 | |
5020 staticidx = ((dump_header *)(pdump_start))->nb_staticpro; | |
5021 last_lrecord_type_index_assigned = ((dump_header *)(pdump_start))->last_type; | |
5022 delta = ((EMACS_INT)pdump_start) - ((dump_header *)pdump_start)->reloc_address; | |
5023 p = pdump_start + ((dump_header *)pdump_start)->stab_offset; | |
5024 | |
5025 /* Put back the staticvec in place */ | |
5026 memcpy (staticvec, p, staticidx*sizeof (Lisp_Object *)); | |
5027 p += staticidx*sizeof (Lisp_Object *); | |
5028 for (i=0; i<staticidx; i++) | |
5029 { | |
5030 Lisp_Object obj = *(Lisp_Object *)p; | |
5031 p += sizeof (Lisp_Object); | |
5032 if (obj && POINTER_TYPE_P (XTYPE (obj))) | |
5033 obj += delta; | |
5034 *staticvec[i] = obj; | |
5035 } | |
5036 | |
5037 /* Put back the dumpstructs */ | |
5038 for (i=0; i<((dump_header *)pdump_start)->nb_structdmp; i++) | |
5039 { | |
5040 void **adr = *(void **)p; | |
5041 p += sizeof (void *); | |
5042 *adr = (void *)((*(EMACS_INT *)p) + delta); | |
5043 p += sizeof (EMACS_INT); | |
5044 } | |
5045 | |
5046 /* Put back the lrecord_implementations_table */ | |
5047 memcpy (lrecord_implementations_table, p, sizeof (lrecord_implementations_table)); | |
5048 p += sizeof (lrecord_implementations_table); | |
5049 | |
5050 /* Give back their numbers to the lrecord implementations */ | |
5051 for (i=0; i<sizeof(lrecord_implementations_table)/sizeof(lrecord_implementations_table[0]); i++) | |
5052 if (lrecord_implementations_table[i]) | |
5053 { | |
5054 *(lrecord_implementations_table[i]->lrecord_type_index) = i; | |
5055 last_lrecord_type_index_assigned = i; | |
5056 } | |
5057 | |
5058 /* Do the relocations */ | |
5059 pdump_rt_list = p; | |
5060 count = 2; | |
5061 for(;;) | |
5062 { | |
5063 pdump_reloc_table *rt = (pdump_reloc_table *)p; | |
5064 p += sizeof (pdump_reloc_table); | |
5065 if (rt->desc) { | |
5066 for (i=0; i<rt->count; i++) | |
5067 { | |
5068 EMACS_INT adr = delta + *(EMACS_INT *)p; | |
5069 *(EMACS_INT *)p = adr; | |
5070 pdump_reloc_one ((void *)adr, delta, rt->desc); | |
5071 p += sizeof (EMACS_INT); | |
5072 } | |
5073 } else | |
5074 if(!(--count)) | |
5075 break; | |
5076 } | |
5077 | |
5078 /* Put the pdump_wire variables in place */ | |
5079 count = *(EMACS_INT *)p; | |
5080 p += sizeof(EMACS_INT); | |
5081 | |
5082 for (i=0; i<count; i++) | |
5083 { | |
5084 Lisp_Object *var, obj; | |
5085 var = *(Lisp_Object **)p; | |
5086 p += sizeof (Lisp_Object *); | |
5087 | |
5088 obj = *(Lisp_Object *)p; | |
5089 p += sizeof (Lisp_Object); | |
5090 | |
5091 if (obj && POINTER_TYPE_P (XTYPE (obj))) | |
5092 obj += delta; | |
5093 *var = obj; | |
5094 } | |
5095 | |
5096 /* Final cleanups */ | |
5097 /* reorganize hash tables */ | |
5098 p = pdump_rt_list; | |
5099 for(;;) | |
5100 { | |
5101 pdump_reloc_table *rt = (pdump_reloc_table *)p; | |
5102 p += sizeof (pdump_reloc_table); | |
5103 if (!rt->desc) | |
5104 break; | |
5105 if (rt->desc == hash_table_description) | |
5106 { | |
5107 for (i=0; i<rt->count; i++) | |
5108 { | |
5109 struct Lisp_Hash_Table *ht = XHASH_TABLE (*(EMACS_INT *)p); | |
5110 reorganize_hash_table (ht); | |
5111 p += sizeof (EMACS_INT); | |
5112 } | |
5113 break; | |
5114 } else | |
5115 p += sizeof (EMACS_INT)*rt->count; | |
5116 } | |
5117 return 1; | |
5118 } | |
5119 | |
5120 #endif |