Mercurial > hg > xemacs-beta
comparison src/alloc.c @ 404:2f8bb876ab1d r21-2-32
Import from CVS: tag r21-2-32
author | cvs |
---|---|
date | Mon, 13 Aug 2007 11:16:07 +0200 |
parents | a86b2b5e0111 |
children | b8cc9ab3f761 |
comparison
equal
deleted
inserted
replaced
403:9f011ab08d48 | 404:2f8bb876ab1d |
---|---|
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. Portable dumper. | 39 og: Killed the purespace. Portable dumper (moved to dumper.c) |
40 */ | 40 */ |
41 | 41 |
42 #include <config.h> | 42 #include <config.h> |
43 #include "lisp.h" | 43 #include "lisp.h" |
44 | 44 |
45 #include "alloc.h" | |
45 #include "backtrace.h" | 46 #include "backtrace.h" |
46 #include "buffer.h" | 47 #include "buffer.h" |
47 #include "bytecode.h" | 48 #include "bytecode.h" |
48 #include "chartab.h" | 49 #include "chartab.h" |
49 #include "device.h" | 50 #include "device.h" |
54 #include "glyphs.h" | 55 #include "glyphs.h" |
55 #include "opaque.h" | 56 #include "opaque.h" |
56 #include "redisplay.h" | 57 #include "redisplay.h" |
57 #include "specifier.h" | 58 #include "specifier.h" |
58 #include "sysfile.h" | 59 #include "sysfile.h" |
60 #include "sysdep.h" | |
59 #include "window.h" | 61 #include "window.h" |
60 #include "console-stream.h" | 62 #include "console-stream.h" |
61 | 63 |
62 #ifdef DOUG_LEA_MALLOC | 64 #ifdef DOUG_LEA_MALLOC |
63 #include <malloc.h> | 65 #include <malloc.h> |
64 #endif | 66 #endif |
65 | 67 |
66 #ifdef HAVE_MMAP | |
67 #include <unistd.h> | |
68 #include <sys/mman.h> | |
69 #endif | |
70 | |
71 #ifdef PDUMP | 68 #ifdef PDUMP |
72 typedef struct | 69 #include "dumper.h" |
73 { | |
74 const struct lrecord_description *desc; | |
75 int count; | |
76 } pdump_reloc_table; | |
77 | |
78 static char *pdump_rt_list = 0; | |
79 #endif | 70 #endif |
80 | 71 |
81 EXFUN (Fgarbage_collect, 0); | 72 EXFUN (Fgarbage_collect, 0); |
82 | 73 |
83 #if 0 /* this is _way_ too slow to be part of the standard debug options */ | 74 #if 0 /* this is _way_ too slow to be part of the standard debug options */ |
391 (! implementation->basic_p) | 382 (! implementation->basic_p) |
392 && | 383 && |
393 (! (implementation->hash == NULL && implementation->equal != NULL))); | 384 (! (implementation->hash == NULL && implementation->equal != NULL))); |
394 | 385 |
395 lcheader = (struct lcrecord_header *) allocate_lisp_storage (size); | 386 lcheader = (struct lcrecord_header *) allocate_lisp_storage (size); |
396 set_lheader_implementation (&(lcheader->lheader), implementation); | 387 set_lheader_implementation (&lcheader->lheader, implementation); |
397 lcheader->next = all_lcrecords; | 388 lcheader->next = all_lcrecords; |
398 #if 1 /* mly prefers to see small ID numbers */ | 389 #if 1 /* mly prefers to see small ID numbers */ |
399 lcheader->uid = lrecord_uid_counter++; | 390 lcheader->uid = lrecord_uid_counter++; |
400 #else /* jwz prefers to see real addrs */ | 391 #else /* jwz prefers to see real addrs */ |
401 lcheader->uid = (int) &lcheader; | 392 lcheader->uid = (int) &lcheader; |
655 try to set aside another reserve in case we run out once more. | 646 try to set aside another reserve in case we run out once more. |
656 | 647 |
657 This is called when a relocatable block is freed in ralloc.c. */ | 648 This is called when a relocatable block is freed in ralloc.c. */ |
658 void refill_memory_reserve (void); | 649 void refill_memory_reserve (void); |
659 void | 650 void |
660 refill_memory_reserve () | 651 refill_memory_reserve (void) |
661 { | 652 { |
662 if (breathing_space == 0) | 653 if (breathing_space == 0) |
663 breathing_space = (char *) malloc (4096 - MALLOC_OVERHEAD); | 654 breathing_space = (char *) malloc (4096 - MALLOC_OVERHEAD); |
664 } | 655 } |
665 #endif | 656 #endif |
794 # define INVALID_POINTER_VALUE 0xFFFFFFFFFFFFFFFF | 785 # define INVALID_POINTER_VALUE 0xFFFFFFFFFFFFFFFF |
795 #else | 786 #else |
796 You have some weird system and need to supply a reasonable value here. | 787 You have some weird system and need to supply a reasonable value here. |
797 #endif | 788 #endif |
798 | 789 |
790 /* The construct (* (void **) (ptr)) would cause aliasing problems | |
791 with modern optimizing compilers like `gcc -O3 -fstrict-aliasing'. | |
792 But `char *' can legally alias any pointer. Hence this union trick. */ | |
793 typedef union { char c; void *p; } *aliasing_voidpp; | |
794 #define ALIASING_VOIDPP_DEREFERENCE(ptr) \ | |
795 (((aliasing_voidpp) (ptr))->p) | |
799 #define FREE_STRUCT_P(ptr) \ | 796 #define FREE_STRUCT_P(ptr) \ |
800 (* (void **) ptr == (void *) INVALID_POINTER_VALUE) | 797 (ALIASING_VOIDPP_DEREFERENCE (ptr) == (void *) INVALID_POINTER_VALUE) |
801 #define MARK_STRUCT_AS_FREE(ptr) \ | 798 #define MARK_STRUCT_AS_FREE(ptr) \ |
802 (* (void **) ptr = (void *) INVALID_POINTER_VALUE) | 799 (ALIASING_VOIDPP_DEREFERENCE (ptr) = (void *) INVALID_POINTER_VALUE) |
803 #define MARK_STRUCT_AS_NOT_FREE(ptr) \ | 800 #define MARK_STRUCT_AS_NOT_FREE(ptr) \ |
804 (* (void **) ptr = 0) | 801 (ALIASING_VOIDPP_DEREFERENCE (ptr) = 0) |
805 | 802 |
806 #ifdef ERROR_CHECK_GC | 803 #ifdef ERROR_CHECK_GC |
807 | 804 |
808 #define PUT_FIXED_TYPE_ON_FREE_LIST(type, structtype, ptr) \ | 805 #define PUT_FIXED_TYPE_ON_FREE_LIST(type, structtype, ptr) \ |
809 do { if (type##_free_list_tail) \ | 806 do { if (type##_free_list_tail) \ |
921 /* This cannot GC. */ | 918 /* This cannot GC. */ |
922 Lisp_Object val; | 919 Lisp_Object val; |
923 Lisp_Cons *c; | 920 Lisp_Cons *c; |
924 | 921 |
925 ALLOCATE_FIXED_TYPE (cons, Lisp_Cons, c); | 922 ALLOCATE_FIXED_TYPE (cons, Lisp_Cons, c); |
926 set_lheader_implementation (&(c->lheader), &lrecord_cons); | 923 set_lheader_implementation (&c->lheader, &lrecord_cons); |
927 XSETCONS (val, c); | 924 XSETCONS (val, c); |
928 c->car = car; | 925 c->car = car; |
929 c->cdr = cdr; | 926 c->cdr = cdr; |
930 return val; | 927 return val; |
931 } | 928 } |
938 { | 935 { |
939 Lisp_Object val; | 936 Lisp_Object val; |
940 Lisp_Cons *c; | 937 Lisp_Cons *c; |
941 | 938 |
942 NOSEEUM_ALLOCATE_FIXED_TYPE (cons, Lisp_Cons, c); | 939 NOSEEUM_ALLOCATE_FIXED_TYPE (cons, Lisp_Cons, c); |
943 set_lheader_implementation (&(c->lheader), &lrecord_cons); | 940 set_lheader_implementation (&c->lheader, &lrecord_cons); |
944 XSETCONS (val, c); | 941 XSETCONS (val, c); |
945 XCAR (val) = car; | 942 XCAR (val) = car; |
946 XCDR (val) = cdr; | 943 XCDR (val) = cdr; |
947 return val; | 944 return val; |
948 } | 945 } |
1055 | 1052 |
1056 /* Avoid dump-time `uninitialized memory read' purify warnings. */ | 1053 /* Avoid dump-time `uninitialized memory read' purify warnings. */ |
1057 if (sizeof (struct lrecord_header) + sizeof (double) != sizeof (*f)) | 1054 if (sizeof (struct lrecord_header) + sizeof (double) != sizeof (*f)) |
1058 xzero (*f); | 1055 xzero (*f); |
1059 | 1056 |
1060 set_lheader_implementation (&(f->lheader), &lrecord_float); | 1057 set_lheader_implementation (&f->lheader, &lrecord_float); |
1061 float_data (f) = float_value; | 1058 float_data (f) = float_value; |
1062 XSETFLOAT (val, f); | 1059 XSETFLOAT (val, f); |
1063 return val; | 1060 return val; |
1064 } | 1061 } |
1065 | 1062 |
1295 make_bit_vector_internal (size_t sizei) | 1292 make_bit_vector_internal (size_t sizei) |
1296 { | 1293 { |
1297 size_t num_longs = BIT_VECTOR_LONG_STORAGE (sizei); | 1294 size_t num_longs = BIT_VECTOR_LONG_STORAGE (sizei); |
1298 size_t sizem = offsetof (Lisp_Bit_Vector, bits[num_longs]); | 1295 size_t sizem = offsetof (Lisp_Bit_Vector, bits[num_longs]); |
1299 Lisp_Bit_Vector *p = (Lisp_Bit_Vector *) allocate_lisp_storage (sizem); | 1296 Lisp_Bit_Vector *p = (Lisp_Bit_Vector *) allocate_lisp_storage (sizem); |
1300 set_lheader_implementation (&(p->lheader), &lrecord_bit_vector); | 1297 set_lheader_implementation (&p->lheader, &lrecord_bit_vector); |
1301 | 1298 |
1302 INCREMENT_CONS_COUNTER (sizem, "bit-vector"); | 1299 INCREMENT_CONS_COUNTER (sizem, "bit-vector"); |
1303 | 1300 |
1304 bit_vector_length (p) = sizei; | 1301 bit_vector_length (p) = sizei; |
1305 bit_vector_next (p) = all_bit_vectors; | 1302 bit_vector_next (p) = all_bit_vectors; |
1399 { | 1396 { |
1400 Lisp_Compiled_Function *f; | 1397 Lisp_Compiled_Function *f; |
1401 Lisp_Object fun; | 1398 Lisp_Object fun; |
1402 | 1399 |
1403 ALLOCATE_FIXED_TYPE (compiled_function, Lisp_Compiled_Function, f); | 1400 ALLOCATE_FIXED_TYPE (compiled_function, Lisp_Compiled_Function, f); |
1404 set_lheader_implementation (&(f->lheader), &lrecord_compiled_function); | 1401 set_lheader_implementation (&f->lheader, &lrecord_compiled_function); |
1405 | 1402 |
1406 f->stack_depth = 0; | 1403 f->stack_depth = 0; |
1407 f->specpdl_depth = 0; | 1404 f->specpdl_depth = 0; |
1408 f->flags.documentationp = 0; | 1405 f->flags.documentationp = 0; |
1409 f->flags.interactivep = 0; | 1406 f->flags.interactivep = 0; |
1483 if (!NILP (constants)) | 1480 if (!NILP (constants)) |
1484 CHECK_VECTOR (constants); | 1481 CHECK_VECTOR (constants); |
1485 f->constants = constants; | 1482 f->constants = constants; |
1486 | 1483 |
1487 CHECK_NATNUM (stack_depth); | 1484 CHECK_NATNUM (stack_depth); |
1488 f->stack_depth = XINT (stack_depth); | 1485 f->stack_depth = (unsigned short) XINT (stack_depth); |
1489 | 1486 |
1490 #ifdef COMPILED_FUNCTION_ANNOTATION_HACK | 1487 #ifdef COMPILED_FUNCTION_ANNOTATION_HACK |
1491 if (!NILP (Vcurrent_compiled_function_annotation)) | 1488 if (!NILP (Vcurrent_compiled_function_annotation)) |
1492 f->annotated = Fcopy (Vcurrent_compiled_function_annotation); | 1489 f->annotated = Fcopy (Vcurrent_compiled_function_annotation); |
1493 else if (!NILP (Vload_file_name_internal_the_purecopy)) | 1490 else if (!NILP (Vload_file_name_internal_the_purecopy)) |
1546 Lisp_Symbol *p; | 1543 Lisp_Symbol *p; |
1547 | 1544 |
1548 CHECK_STRING (name); | 1545 CHECK_STRING (name); |
1549 | 1546 |
1550 ALLOCATE_FIXED_TYPE (symbol, Lisp_Symbol, p); | 1547 ALLOCATE_FIXED_TYPE (symbol, Lisp_Symbol, p); |
1551 set_lheader_implementation (&(p->lheader), &lrecord_symbol); | 1548 set_lheader_implementation (&p->lheader, &lrecord_symbol); |
1552 p->name = XSTRING (name); | 1549 p->name = XSTRING (name); |
1553 p->plist = Qnil; | 1550 p->plist = Qnil; |
1554 p->value = Qunbound; | 1551 p->value = Qunbound; |
1555 p->function = Qunbound; | 1552 p->function = Qunbound; |
1556 symbol_next (p) = 0; | 1553 symbol_next (p) = 0; |
1570 allocate_extent (void) | 1567 allocate_extent (void) |
1571 { | 1568 { |
1572 struct extent *e; | 1569 struct extent *e; |
1573 | 1570 |
1574 ALLOCATE_FIXED_TYPE (extent, struct extent, e); | 1571 ALLOCATE_FIXED_TYPE (extent, struct extent, e); |
1575 set_lheader_implementation (&(e->lheader), &lrecord_extent); | 1572 set_lheader_implementation (&e->lheader, &lrecord_extent); |
1576 extent_object (e) = Qnil; | 1573 extent_object (e) = Qnil; |
1577 set_extent_start (e, -1); | 1574 set_extent_start (e, -1); |
1578 set_extent_end (e, -1); | 1575 set_extent_end (e, -1); |
1579 e->plist = Qnil; | 1576 e->plist = Qnil; |
1580 | 1577 |
1600 { | 1597 { |
1601 Lisp_Object val; | 1598 Lisp_Object val; |
1602 Lisp_Event *e; | 1599 Lisp_Event *e; |
1603 | 1600 |
1604 ALLOCATE_FIXED_TYPE (event, Lisp_Event, e); | 1601 ALLOCATE_FIXED_TYPE (event, Lisp_Event, e); |
1605 set_lheader_implementation (&(e->lheader), &lrecord_event); | 1602 set_lheader_implementation (&e->lheader, &lrecord_event); |
1606 | 1603 |
1607 XSETEVENT (val, e); | 1604 XSETEVENT (val, e); |
1608 return val; | 1605 return val; |
1609 } | 1606 } |
1610 | 1607 |
1623 { | 1620 { |
1624 Lisp_Object val; | 1621 Lisp_Object val; |
1625 Lisp_Marker *p; | 1622 Lisp_Marker *p; |
1626 | 1623 |
1627 ALLOCATE_FIXED_TYPE (marker, Lisp_Marker, p); | 1624 ALLOCATE_FIXED_TYPE (marker, Lisp_Marker, p); |
1628 set_lheader_implementation (&(p->lheader), &lrecord_marker); | 1625 set_lheader_implementation (&p->lheader, &lrecord_marker); |
1629 p->buffer = 0; | 1626 p->buffer = 0; |
1630 p->memind = 0; | 1627 p->memind = 0; |
1631 marker_next (p) = 0; | 1628 marker_next (p) = 0; |
1632 marker_prev (p) = 0; | 1629 marker_prev (p) = 0; |
1633 p->insertion_type = 0; | 1630 p->insertion_type = 0; |
1640 { | 1637 { |
1641 Lisp_Object val; | 1638 Lisp_Object val; |
1642 Lisp_Marker *p; | 1639 Lisp_Marker *p; |
1643 | 1640 |
1644 NOSEEUM_ALLOCATE_FIXED_TYPE (marker, Lisp_Marker, p); | 1641 NOSEEUM_ALLOCATE_FIXED_TYPE (marker, Lisp_Marker, p); |
1645 set_lheader_implementation (&(p->lheader), &lrecord_marker); | 1642 set_lheader_implementation (&p->lheader, &lrecord_marker); |
1646 p->buffer = 0; | 1643 p->buffer = 0; |
1647 p->memind = 0; | 1644 p->memind = 0; |
1648 marker_next (p) = 0; | 1645 marker_next (p) = 0; |
1649 marker_prev (p) = 0; | 1646 marker_prev (p) = 0; |
1650 p->insertion_type = 0; | 1647 p->insertion_type = 0; |
1860 | 1857 |
1861 assert (length >= 0 && fullsize > 0); | 1858 assert (length >= 0 && fullsize > 0); |
1862 | 1859 |
1863 /* Allocate the string header */ | 1860 /* Allocate the string header */ |
1864 ALLOCATE_FIXED_TYPE (string, Lisp_String, s); | 1861 ALLOCATE_FIXED_TYPE (string, Lisp_String, s); |
1865 set_lheader_implementation (&(s->lheader), &lrecord_string); | 1862 set_lheader_implementation (&s->lheader, &lrecord_string); |
1866 | 1863 |
1867 set_string_data (s, BIG_STRING_FULLSIZE_P (fullsize) | 1864 set_string_data (s, BIG_STRING_FULLSIZE_P (fullsize) |
1868 ? xnew_array (Bufbyte, length + 1) | 1865 ? xnew_array (Bufbyte, length + 1) |
1869 : allocate_string_chars_struct (s, fullsize)->chars); | 1866 : allocate_string_chars_struct (s, fullsize)->chars); |
1870 | 1867 |
2164 bytecount_to_charcount (contents, length); /* Just for the assertions */ | 2161 bytecount_to_charcount (contents, length); /* Just for the assertions */ |
2165 #endif | 2162 #endif |
2166 | 2163 |
2167 /* Allocate the string header */ | 2164 /* Allocate the string header */ |
2168 ALLOCATE_FIXED_TYPE (string, Lisp_String, s); | 2165 ALLOCATE_FIXED_TYPE (string, Lisp_String, s); |
2169 set_lheader_implementation (&(s->lheader), &lrecord_string); | 2166 set_lheader_implementation (&s->lheader, &lrecord_string); |
2170 SET_C_READONLY_RECORD_HEADER (&s->lheader); | 2167 SET_C_READONLY_RECORD_HEADER (&s->lheader); |
2171 s->plist = Qnil; | 2168 s->plist = Qnil; |
2172 set_string_data (s, (Bufbyte *)contents); | 2169 set_string_data (s, (Bufbyte *)contents); |
2173 set_string_length (s, length); | 2170 set_string_length (s, length); |
2174 | 2171 |
2346 | 2343 |
2347 /************************************************************************/ | 2344 /************************************************************************/ |
2348 /* Garbage Collection */ | 2345 /* Garbage Collection */ |
2349 /************************************************************************/ | 2346 /************************************************************************/ |
2350 | 2347 |
2351 /* This will be used more extensively In The Future */ | |
2352 static int last_lrecord_type_index_assigned; | |
2353 | |
2354 /* All the built-in lisp object types are enumerated in `enum lrecord_type'. | 2348 /* All the built-in lisp object types are enumerated in `enum lrecord_type'. |
2355 Additional ones may be defined by a module (none yet). We leave some | 2349 Additional ones may be defined by a module (none yet). We leave some |
2356 room in `lrecord_implementations_table' for such new lisp object types. */ | 2350 room in `lrecord_implementations_table' for such new lisp object types. */ |
2357 #define MODULE_DEFINABLE_TYPE_COUNT 32 | 2351 #define MODULE_DEFINABLE_TYPE_COUNT 32 |
2358 const struct lrecord_implementation *lrecord_implementations_table[lrecord_type_count + MODULE_DEFINABLE_TYPE_COUNT]; | 2352 const struct lrecord_implementation *lrecord_implementations_table[lrecord_type_count + MODULE_DEFINABLE_TYPE_COUNT]; |
2370 #ifdef HAVE_SHLIB | 2364 #ifdef HAVE_SHLIB |
2371 #define NSTATICS 4000 | 2365 #define NSTATICS 4000 |
2372 #else | 2366 #else |
2373 #define NSTATICS 2000 | 2367 #define NSTATICS 2000 |
2374 #endif | 2368 #endif |
2375 /* Not "static" because of linker lossage on some systems */ | 2369 |
2376 Lisp_Object *staticvec[NSTATICS] | 2370 /* Not "static" because used by dumper.c */ |
2377 /* Force it into data space! */ | 2371 Lisp_Object *staticvec[NSTATICS]; |
2378 = {0}; | 2372 int staticidx; |
2379 static int staticidx; | |
2380 | 2373 |
2381 /* Put an entry in staticvec, pointing at the variable whose address is given | 2374 /* Put an entry in staticvec, pointing at the variable whose address is given |
2382 */ | 2375 */ |
2383 void | 2376 void |
2384 staticpro (Lisp_Object *varaddress) | 2377 staticpro (Lisp_Object *varaddress) |
2385 { | 2378 { |
2386 if (staticidx >= countof (staticvec)) | 2379 /* #### This is now a dubious assert() since this routine may be called */ |
2387 /* #### This is now a dubious abort() since this routine may be called */ | 2380 /* by Lisp attempting to load a DLL. */ |
2388 /* by Lisp attempting to load a DLL. */ | 2381 assert (staticidx < countof (staticvec)); |
2389 abort (); | |
2390 staticvec[staticidx++] = varaddress; | 2382 staticvec[staticidx++] = varaddress; |
2391 } | 2383 } |
2392 | 2384 |
2393 /* Not "static" because of linker lossage on some systems */ | 2385 |
2394 Lisp_Object *staticvec_nodump[200] | 2386 Lisp_Object *staticvec_nodump[200]; |
2395 /* Force it into data space! */ | 2387 int staticidx_nodump; |
2396 = {0}; | |
2397 static int staticidx_nodump; | |
2398 | 2388 |
2399 /* Put an entry in staticvec_nodump, pointing at the variable whose address is given | 2389 /* Put an entry in staticvec_nodump, pointing at the variable whose address is given |
2400 */ | 2390 */ |
2401 void | 2391 void |
2402 staticpro_nodump (Lisp_Object *varaddress) | 2392 staticpro_nodump (Lisp_Object *varaddress) |
2403 { | 2393 { |
2404 if (staticidx_nodump >= countof (staticvec_nodump)) | 2394 /* #### This is now a dubious assert() since this routine may be called */ |
2405 /* #### This is now a dubious abort() since this routine may be called */ | 2395 /* by Lisp attempting to load a DLL. */ |
2406 /* by Lisp attempting to load a DLL. */ | 2396 assert (staticidx_nodump < countof (staticvec_nodump)); |
2407 abort (); | |
2408 staticvec_nodump[staticidx_nodump++] = varaddress; | 2397 staticvec_nodump[staticidx_nodump++] = varaddress; |
2409 } | 2398 } |
2410 | 2399 |
2411 /* Not "static" because of linker lossage on some systems */ | 2400 |
2412 struct | 2401 struct pdump_dumpstructinfo dumpstructvec[200]; |
2413 { | 2402 int dumpstructidx; |
2414 void *data; | |
2415 const struct struct_description *desc; | |
2416 } dumpstructvec[200]; | |
2417 | |
2418 static int dumpstructidx; | |
2419 | 2403 |
2420 /* Put an entry in dumpstructvec, pointing at the variable whose address is given | 2404 /* Put an entry in dumpstructvec, pointing at the variable whose address is given |
2421 */ | 2405 */ |
2422 void | 2406 void |
2423 dumpstruct (void *varaddress, const struct struct_description *desc) | 2407 dumpstruct (void *varaddress, const struct struct_description *desc) |
2424 { | 2408 { |
2425 if (dumpstructidx >= countof (dumpstructvec)) | 2409 assert (dumpstructidx < countof (dumpstructvec)); |
2426 abort (); | |
2427 dumpstructvec[dumpstructidx].data = varaddress; | 2410 dumpstructvec[dumpstructidx].data = varaddress; |
2428 dumpstructvec[dumpstructidx].desc = desc; | 2411 dumpstructvec[dumpstructidx].desc = desc; |
2429 dumpstructidx++; | 2412 dumpstructidx++; |
2430 } | 2413 } |
2431 | 2414 |
2432 /* Not "static" because of linker lossage on some systems */ | 2415 struct pdump_dumpopaqueinfo dumpopaquevec[250]; |
2433 struct dumpopaque_info | 2416 int dumpopaqueidx; |
2434 { | |
2435 void *data; | |
2436 size_t size; | |
2437 } dumpopaquevec[200]; | |
2438 | |
2439 static int dumpopaqueidx; | |
2440 | 2417 |
2441 /* Put an entry in dumpopaquevec, pointing at the variable whose address is given | 2418 /* Put an entry in dumpopaquevec, pointing at the variable whose address is given |
2442 */ | 2419 */ |
2443 void | 2420 void |
2444 dumpopaque (void *varaddress, size_t size) | 2421 dumpopaque (void *varaddress, size_t size) |
2445 { | 2422 { |
2446 if (dumpopaqueidx >= countof (dumpopaquevec)) | 2423 assert (dumpopaqueidx < countof (dumpopaquevec)); |
2447 abort (); | 2424 |
2448 dumpopaquevec[dumpopaqueidx].data = varaddress; | 2425 dumpopaquevec[dumpopaqueidx].data = varaddress; |
2449 dumpopaquevec[dumpopaqueidx].size = size; | 2426 dumpopaquevec[dumpopaqueidx].size = size; |
2450 dumpopaqueidx++; | 2427 dumpopaqueidx++; |
2451 } | 2428 } |
2452 | 2429 |
2453 Lisp_Object *pdump_wirevec[50]; | 2430 Lisp_Object *pdump_wirevec[50]; |
2454 static int pdump_wireidx; | 2431 int pdump_wireidx; |
2455 | 2432 |
2456 /* Put an entry in pdump_wirevec, pointing at the variable whose address is given | 2433 /* Put an entry in pdump_wirevec, pointing at the variable whose address is given |
2457 */ | 2434 */ |
2458 void | 2435 void |
2459 pdump_wire (Lisp_Object *varaddress) | 2436 pdump_wire (Lisp_Object *varaddress) |
2460 { | 2437 { |
2461 if (pdump_wireidx >= countof (pdump_wirevec)) | 2438 assert (pdump_wireidx < countof (pdump_wirevec)); |
2462 abort (); | |
2463 pdump_wirevec[pdump_wireidx++] = varaddress; | 2439 pdump_wirevec[pdump_wireidx++] = varaddress; |
2464 } | 2440 } |
2465 | 2441 |
2466 | 2442 |
2467 Lisp_Object *pdump_wirevec_list[50]; | 2443 Lisp_Object *pdump_wirevec_list[50]; |
2468 static int pdump_wireidx_list; | 2444 int pdump_wireidx_list; |
2469 | 2445 |
2470 /* Put an entry in pdump_wirevec_list, pointing at the variable whose address is given | 2446 /* Put an entry in pdump_wirevec_list, pointing at the variable whose address is given |
2471 */ | 2447 */ |
2472 void | 2448 void |
2473 pdump_wire_list (Lisp_Object *varaddress) | 2449 pdump_wire_list (Lisp_Object *varaddress) |
2474 { | 2450 { |
2475 if (pdump_wireidx_list >= countof (pdump_wirevec_list)) | 2451 assert (pdump_wireidx_list < countof (pdump_wirevec_list)); |
2476 abort (); | |
2477 pdump_wirevec_list[pdump_wireidx_list++] = varaddress; | 2452 pdump_wirevec_list[pdump_wireidx_list++] = varaddress; |
2478 } | 2453 } |
2479 | 2454 |
2480 #ifdef ERROR_CHECK_GC | 2455 #ifdef ERROR_CHECK_GC |
2481 #define GC_CHECK_LHEADER_INVARIANTS(lheader) do { \ | 2456 #define GC_CHECK_LHEADER_INVARIANTS(lheader) do { \ |
2482 struct lrecord_header * GCLI_lh = (lheader); \ | 2457 struct lrecord_header * GCLI_lh = (lheader); \ |
2483 assert (GCLI_lh != 0); \ | 2458 assert (GCLI_lh != 0); \ |
2484 assert (GCLI_lh->type <= last_lrecord_type_index_assigned); \ | 2459 assert (GCLI_lh->type < lrecord_type_count); \ |
2485 assert (! C_READONLY_RECORD_HEADER_P (GCLI_lh) || \ | 2460 assert (! C_READONLY_RECORD_HEADER_P (GCLI_lh) || \ |
2486 (MARKED_RECORD_HEADER_P (GCLI_lh) && \ | 2461 (MARKED_RECORD_HEADER_P (GCLI_lh) && \ |
2487 LISP_READONLY_RECORD_HEADER_P (GCLI_lh))); \ | 2462 LISP_READONLY_RECORD_HEADER_P (GCLI_lh))); \ |
2488 } while (0) | 2463 } while (0) |
2489 #else | 2464 #else |
3073 assert (!(FREE_STRUCT_P (string))); | 3048 assert (!(FREE_STRUCT_P (string))); |
3074 | 3049 |
3075 size = string_length (string); | 3050 size = string_length (string); |
3076 fullsize = STRING_FULLSIZE (size); | 3051 fullsize = STRING_FULLSIZE (size); |
3077 | 3052 |
3078 if (BIG_STRING_FULLSIZE_P (fullsize)) | 3053 gc_checking_assert (! BIG_STRING_FULLSIZE_P (fullsize)); |
3079 abort (); | |
3080 | 3054 |
3081 /* Just skip it if it isn't marked. */ | 3055 /* Just skip it if it isn't marked. */ |
3082 if (! MARKED_RECORD_HEADER_P (&(string->lheader))) | 3056 if (! MARKED_RECORD_HEADER_P (&(string->lheader))) |
3083 { | 3057 { |
3084 from_pos += fullsize; | 3058 from_pos += fullsize; |
3136 static void | 3110 static void |
3137 debug_string_purity_print (Lisp_String *p) | 3111 debug_string_purity_print (Lisp_String *p) |
3138 { | 3112 { |
3139 Charcount i; | 3113 Charcount i; |
3140 Charcount s = string_char_length (p); | 3114 Charcount s = string_char_length (p); |
3141 putc ('\"', stderr); | 3115 stderr_out ("\""); |
3142 for (i = 0; i < s; i++) | 3116 for (i = 0; i < s; i++) |
3143 { | 3117 { |
3144 Emchar ch = string_char (p, i); | 3118 Emchar ch = string_char (p, i); |
3145 if (ch < 32 || ch >= 126) | 3119 if (ch < 32 || ch >= 126) |
3146 stderr_out ("\\%03o", ch); | 3120 stderr_out ("\\%03o", ch); |
3264 sweep_markers (); | 3238 sweep_markers (); |
3265 | 3239 |
3266 sweep_events (); | 3240 sweep_events (); |
3267 | 3241 |
3268 #ifdef PDUMP | 3242 #ifdef PDUMP |
3269 /* Unmark all dumped objects */ | 3243 pdump_objects_unmark (); |
3270 { | |
3271 int i; | |
3272 char *p = pdump_rt_list; | |
3273 if (p) | |
3274 for (;;) | |
3275 { | |
3276 pdump_reloc_table *rt = (pdump_reloc_table *)p; | |
3277 p += sizeof (pdump_reloc_table); | |
3278 if (rt->desc) | |
3279 { | |
3280 for (i=0; i<rt->count; i++) | |
3281 { | |
3282 struct lrecord_header *lh = * (struct lrecord_header **) p; | |
3283 if (! C_READONLY_RECORD_HEADER_P (lh)) | |
3284 UNMARK_RECORD_HEADER (lh); | |
3285 p += sizeof (EMACS_INT); | |
3286 } | |
3287 } else | |
3288 break; | |
3289 } | |
3290 } | |
3291 #endif | 3244 #endif |
3292 } | 3245 } |
3293 | 3246 |
3294 /* Clearing for disksave. */ | 3247 /* Clearing for disksave. */ |
3295 | 3248 |
3650 int i; | 3603 int i; |
3651 int gc_count_vector_total_size = 0; | 3604 int gc_count_vector_total_size = 0; |
3652 | 3605 |
3653 garbage_collect_1 (); | 3606 garbage_collect_1 (); |
3654 | 3607 |
3655 for (i = 0; i <= last_lrecord_type_index_assigned; i++) | 3608 for (i = 0; i < lrecord_type_count; i++) |
3656 { | 3609 { |
3657 if (lcrecord_stats[i].bytes_in_use != 0 | 3610 if (lcrecord_stats[i].bytes_in_use != 0 |
3658 || lcrecord_stats[i].bytes_freed != 0 | 3611 || lcrecord_stats[i].bytes_freed != 0 |
3659 || lcrecord_stats[i].instances_on_free_list != 0) | 3612 || lcrecord_stats[i].instances_on_free_list != 0) |
3660 { | 3613 { |
3991 void | 3944 void |
3992 init_alloc_once_early (void) | 3945 init_alloc_once_early (void) |
3993 { | 3946 { |
3994 reinit_alloc_once_early (); | 3947 reinit_alloc_once_early (); |
3995 | 3948 |
3996 last_lrecord_type_index_assigned = lrecord_type_count - 1; | |
3997 | |
3998 { | 3949 { |
3999 int i; | 3950 int i; |
4000 for (i = 0; i < countof (lrecord_implementations_table); i++) | 3951 for (i = 0; i < countof (lrecord_implementations_table); i++) |
4001 lrecord_implementations_table[i] = 0; | 3952 lrecord_implementations_table[i] = 0; |
4002 } | 3953 } |
4133 void | 4084 void |
4134 complex_vars_of_alloc (void) | 4085 complex_vars_of_alloc (void) |
4135 { | 4086 { |
4136 Vgc_pointer_glyph = Fmake_glyph_internal (Qpointer); | 4087 Vgc_pointer_glyph = Fmake_glyph_internal (Qpointer); |
4137 } | 4088 } |
4138 | |
4139 | |
4140 #ifdef PDUMP | |
4141 | |
4142 /* The structure of the file | |
4143 * | |
4144 * 0 - header | |
4145 * 256 - dumped objects | |
4146 * stab_offset - nb_staticpro*(Lisp_Object *) from staticvec | |
4147 * - nb_staticpro*(relocated Lisp_Object) pointed to by staticpro | |
4148 * - nb_structdmp*pair(void *, adr) for pointers to structures | |
4149 * - lrecord_implementations_table[] | |
4150 * - relocation table | |
4151 * - wired variable address/value couples with the count preceding the list | |
4152 */ | |
4153 typedef struct | |
4154 { | |
4155 char signature[8]; | |
4156 EMACS_UINT stab_offset; | |
4157 EMACS_UINT reloc_address; | |
4158 int nb_staticpro; | |
4159 int nb_structdmp; | |
4160 int nb_opaquedmp; | |
4161 int last_type; | |
4162 } dump_header; | |
4163 | |
4164 char *pdump_start, *pdump_end; | |
4165 | |
4166 static const unsigned char align_table[256] = | |
4167 { | |
4168 8, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, | |
4169 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, | |
4170 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, | |
4171 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, | |
4172 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, | |
4173 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, | |
4174 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, | |
4175 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, | |
4176 7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, | |
4177 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, | |
4178 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, | |
4179 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, | |
4180 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, | |
4181 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, | |
4182 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, | |
4183 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0 | |
4184 }; | |
4185 | |
4186 typedef struct pdump_entry_list_elmt | |
4187 { | |
4188 struct pdump_entry_list_elmt *next; | |
4189 const void *obj; | |
4190 size_t size; | |
4191 int count; | |
4192 int is_lrecord; | |
4193 EMACS_INT save_offset; | |
4194 } pdump_entry_list_elmt; | |
4195 | |
4196 typedef struct | |
4197 { | |
4198 pdump_entry_list_elmt *first; | |
4199 int align; | |
4200 int count; | |
4201 } pdump_entry_list; | |
4202 | |
4203 typedef struct pdump_struct_list_elmt | |
4204 { | |
4205 pdump_entry_list list; | |
4206 const struct struct_description *sdesc; | |
4207 } pdump_struct_list_elmt; | |
4208 | |
4209 typedef struct | |
4210 { | |
4211 pdump_struct_list_elmt *list; | |
4212 int count; | |
4213 int size; | |
4214 } pdump_struct_list; | |
4215 | |
4216 static pdump_entry_list pdump_object_table[256]; | |
4217 static pdump_entry_list pdump_opaque_data_list; | |
4218 static pdump_struct_list pdump_struct_table; | |
4219 static pdump_entry_list_elmt *pdump_qnil; | |
4220 | |
4221 static int pdump_alert_undump_object[256]; | |
4222 | |
4223 static unsigned long cur_offset; | |
4224 static size_t max_size; | |
4225 static int pdump_fd; | |
4226 static void *pdump_buf; | |
4227 | |
4228 #define PDUMP_HASHSIZE 200001 | |
4229 | |
4230 static pdump_entry_list_elmt **pdump_hash; | |
4231 | |
4232 /* Since most pointers are eight bytes aligned, the >>3 allows for a better hash */ | |
4233 static int | |
4234 pdump_make_hash (const void *obj) | |
4235 { | |
4236 return ((unsigned long)(obj)>>3) % PDUMP_HASHSIZE; | |
4237 } | |
4238 | |
4239 static pdump_entry_list_elmt * | |
4240 pdump_get_entry (const void *obj) | |
4241 { | |
4242 int pos = pdump_make_hash (obj); | |
4243 pdump_entry_list_elmt *e; | |
4244 | |
4245 assert (obj != 0); | |
4246 | |
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 = xnew (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 = (pdump_struct_list_elmt *) | |
4311 xrealloc (pdump_struct_table.list, | |
4312 pdump_struct_table.size * sizeof (pdump_struct_list_elmt)); | |
4313 } | |
4314 pdump_struct_table.list[pdump_struct_table.count].list.first = 0; | |
4315 pdump_struct_table.list[pdump_struct_table.count].list.align = 8; | |
4316 pdump_struct_table.list[pdump_struct_table.count].list.count = 0; | |
4317 pdump_struct_table.list[pdump_struct_table.count].sdesc = sdesc; | |
4318 | |
4319 return &pdump_struct_table.list[pdump_struct_table.count++].list; | |
4320 } | |
4321 | |
4322 static struct | |
4323 { | |
4324 struct lrecord_header *obj; | |
4325 int position; | |
4326 int offset; | |
4327 } backtrace[65536]; | |
4328 | |
4329 static int depth; | |
4330 | |
4331 static void pdump_backtrace (void) | |
4332 { | |
4333 int i; | |
4334 fprintf (stderr, "pdump backtrace :\n"); | |
4335 for (i=0;i<depth;i++) | |
4336 { | |
4337 if (!backtrace[i].obj) | |
4338 fprintf (stderr, " - ind. (%d, %d)\n", backtrace[i].position, backtrace[i].offset); | |
4339 else | |
4340 { | |
4341 fprintf (stderr, " - %s (%d, %d)\n", | |
4342 LHEADER_IMPLEMENTATION (backtrace[i].obj)->name, | |
4343 backtrace[i].position, | |
4344 backtrace[i].offset); | |
4345 } | |
4346 } | |
4347 } | |
4348 | |
4349 static void pdump_register_object (Lisp_Object obj); | |
4350 static void pdump_register_struct (const void *data, const struct struct_description *sdesc, int count); | |
4351 | |
4352 static EMACS_INT | |
4353 pdump_get_indirect_count (EMACS_INT code, const struct lrecord_description *idesc, const void *idata) | |
4354 { | |
4355 EMACS_INT count; | |
4356 const void *irdata; | |
4357 | |
4358 int line = XD_INDIRECT_VAL (code); | |
4359 int delta = XD_INDIRECT_DELTA (code); | |
4360 | |
4361 irdata = ((char *)idata) + idesc[line].offset; | |
4362 switch (idesc[line].type) | |
4363 { | |
4364 case XD_SIZE_T: | |
4365 count = *(size_t *)irdata; | |
4366 break; | |
4367 case XD_INT: | |
4368 count = *(int *)irdata; | |
4369 break; | |
4370 case XD_LONG: | |
4371 count = *(long *)irdata; | |
4372 break; | |
4373 case XD_BYTECOUNT: | |
4374 count = *(Bytecount *)irdata; | |
4375 break; | |
4376 default: | |
4377 fprintf (stderr, "Unsupported count type : %d (line = %d, code=%ld)\n", idesc[line].type, line, (long)code); | |
4378 pdump_backtrace (); | |
4379 abort (); | |
4380 } | |
4381 count += delta; | |
4382 return count; | |
4383 } | |
4384 | |
4385 static void | |
4386 pdump_register_sub (const void *data, const struct lrecord_description *desc, int me) | |
4387 { | |
4388 int pos; | |
4389 | |
4390 restart: | |
4391 for (pos = 0; desc[pos].type != XD_END; pos++) | |
4392 { | |
4393 const void *rdata = (const char *)data + desc[pos].offset; | |
4394 | |
4395 backtrace[me].position = pos; | |
4396 backtrace[me].offset = desc[pos].offset; | |
4397 | |
4398 switch (desc[pos].type) | |
4399 { | |
4400 case XD_SPECIFIER_END: | |
4401 pos = 0; | |
4402 desc = ((const Lisp_Specifier *)data)->methods->extra_description; | |
4403 goto restart; | |
4404 case XD_SIZE_T: | |
4405 case XD_INT: | |
4406 case XD_LONG: | |
4407 case XD_BYTECOUNT: | |
4408 case XD_LO_RESET_NIL: | |
4409 case XD_INT_RESET: | |
4410 case XD_LO_LINK: | |
4411 break; | |
4412 case XD_OPAQUE_DATA_PTR: | |
4413 { | |
4414 EMACS_INT count = desc[pos].data1; | |
4415 if (XD_IS_INDIRECT (count)) | |
4416 count = pdump_get_indirect_count (count, desc, data); | |
4417 | |
4418 pdump_add_entry (&pdump_opaque_data_list, | |
4419 *(void **)rdata, | |
4420 count, | |
4421 1, | |
4422 0); | |
4423 break; | |
4424 } | |
4425 case XD_C_STRING: | |
4426 { | |
4427 const char *str = *(const char **)rdata; | |
4428 if (str) | |
4429 pdump_add_entry (&pdump_opaque_data_list, str, strlen (str)+1, 1, 0); | |
4430 break; | |
4431 } | |
4432 case XD_DOC_STRING: | |
4433 { | |
4434 const char *str = *(const char **)rdata; | |
4435 if ((EMACS_INT)str > 0) | |
4436 pdump_add_entry (&pdump_opaque_data_list, str, strlen (str)+1, 1, 0); | |
4437 break; | |
4438 } | |
4439 case XD_LISP_OBJECT: | |
4440 { | |
4441 const Lisp_Object *pobj = (const Lisp_Object *)rdata; | |
4442 | |
4443 assert (desc[pos].data1 == 0); | |
4444 | |
4445 backtrace[me].offset = (const char *)pobj - (const char *)data; | |
4446 pdump_register_object (*pobj); | |
4447 break; | |
4448 } | |
4449 case XD_LISP_OBJECT_ARRAY: | |
4450 { | |
4451 int i; | |
4452 EMACS_INT count = desc[pos].data1; | |
4453 if (XD_IS_INDIRECT (count)) | |
4454 count = pdump_get_indirect_count (count, desc, data); | |
4455 | |
4456 for (i = 0; i < count; i++) | |
4457 { | |
4458 const Lisp_Object *pobj = ((const Lisp_Object *)rdata) + i; | |
4459 Lisp_Object dobj = *pobj; | |
4460 | |
4461 backtrace[me].offset = (const char *)pobj - (const char *)data; | |
4462 pdump_register_object (dobj); | |
4463 } | |
4464 break; | |
4465 } | |
4466 case XD_STRUCT_PTR: | |
4467 { | |
4468 EMACS_INT count = desc[pos].data1; | |
4469 const struct struct_description *sdesc = desc[pos].data2; | |
4470 const char *dobj = *(const char **)rdata; | |
4471 if (dobj) | |
4472 { | |
4473 if (XD_IS_INDIRECT (count)) | |
4474 count = pdump_get_indirect_count (count, desc, data); | |
4475 | |
4476 pdump_register_struct (dobj, sdesc, count); | |
4477 } | |
4478 break; | |
4479 } | |
4480 default: | |
4481 fprintf (stderr, "Unsupported dump type : %d\n", desc[pos].type); | |
4482 pdump_backtrace (); | |
4483 abort (); | |
4484 }; | |
4485 } | |
4486 } | |
4487 | |
4488 static void | |
4489 pdump_register_object (Lisp_Object obj) | |
4490 { | |
4491 struct lrecord_header *objh; | |
4492 | |
4493 if (!POINTER_TYPE_P (XTYPE (obj))) | |
4494 return; | |
4495 | |
4496 objh = XRECORD_LHEADER (obj); | |
4497 if (!objh) | |
4498 return; | |
4499 | |
4500 if (pdump_get_entry (objh)) | |
4501 return; | |
4502 | |
4503 if (LHEADER_IMPLEMENTATION (objh)->description) | |
4504 { | |
4505 int me = depth++; | |
4506 if (me>65536) | |
4507 { | |
4508 fprintf (stderr, "Backtrace overflow, loop ?\n"); | |
4509 abort (); | |
4510 } | |
4511 backtrace[me].obj = objh; | |
4512 backtrace[me].position = 0; | |
4513 backtrace[me].offset = 0; | |
4514 | |
4515 pdump_add_entry (pdump_object_table + objh->type, | |
4516 objh, | |
4517 LHEADER_IMPLEMENTATION (objh)->static_size ? | |
4518 LHEADER_IMPLEMENTATION (objh)->static_size : | |
4519 LHEADER_IMPLEMENTATION (objh)->size_in_bytes_method (objh), | |
4520 1, | |
4521 1); | |
4522 pdump_register_sub (objh, | |
4523 LHEADER_IMPLEMENTATION (objh)->description, | |
4524 me); | |
4525 --depth; | |
4526 } | |
4527 else | |
4528 { | |
4529 pdump_alert_undump_object[objh->type]++; | |
4530 fprintf (stderr, "Undumpable object type : %s\n", LHEADER_IMPLEMENTATION (objh)->name); | |
4531 pdump_backtrace (); | |
4532 } | |
4533 } | |
4534 | |
4535 static void | |
4536 pdump_register_struct (const void *data, const struct struct_description *sdesc, int count) | |
4537 { | |
4538 if (data && !pdump_get_entry (data)) | |
4539 { | |
4540 int me = depth++; | |
4541 int i; | |
4542 if (me>65536) | |
4543 { | |
4544 fprintf (stderr, "Backtrace overflow, loop ?\n"); | |
4545 abort (); | |
4546 } | |
4547 backtrace[me].obj = 0; | |
4548 backtrace[me].position = 0; | |
4549 backtrace[me].offset = 0; | |
4550 | |
4551 pdump_add_entry (pdump_get_entry_list (sdesc), | |
4552 data, | |
4553 sdesc->size, | |
4554 count, | |
4555 0); | |
4556 for (i=0; i<count; i++) | |
4557 { | |
4558 pdump_register_sub (((char *)data) + sdesc->size*i, | |
4559 sdesc->description, | |
4560 me); | |
4561 } | |
4562 --depth; | |
4563 } | |
4564 } | |
4565 | |
4566 static void | |
4567 pdump_dump_data (pdump_entry_list_elmt *elmt, const struct lrecord_description *desc) | |
4568 { | |
4569 size_t size = elmt->size; | |
4570 int count = elmt->count; | |
4571 if (desc) | |
4572 { | |
4573 int pos, i; | |
4574 memcpy (pdump_buf, elmt->obj, size*count); | |
4575 | |
4576 for (i=0; i<count; i++) | |
4577 { | |
4578 char *cur = ((char *)pdump_buf) + i*size; | |
4579 restart: | |
4580 for (pos = 0; desc[pos].type != XD_END; pos++) | |
4581 { | |
4582 void *rdata = cur + desc[pos].offset; | |
4583 switch (desc[pos].type) | |
4584 { | |
4585 case XD_SPECIFIER_END: | |
4586 desc = ((const Lisp_Specifier *)(elmt->obj))->methods->extra_description; | |
4587 goto restart; | |
4588 case XD_SIZE_T: | |
4589 case XD_INT: | |
4590 case XD_LONG: | |
4591 case XD_BYTECOUNT: | |
4592 break; | |
4593 case XD_LO_RESET_NIL: | |
4594 { | |
4595 EMACS_INT count = desc[pos].data1; | |
4596 int i; | |
4597 if (XD_IS_INDIRECT (count)) | |
4598 count = pdump_get_indirect_count (count, desc, elmt->obj); | |
4599 for (i=0; i<count; i++) | |
4600 ((EMACS_INT *)rdata)[i] = pdump_qnil->save_offset; | |
4601 break; | |
4602 } | |
4603 case XD_INT_RESET: | |
4604 { | |
4605 EMACS_INT val = desc[pos].data1; | |
4606 if (XD_IS_INDIRECT (val)) | |
4607 val = pdump_get_indirect_count (val, desc, elmt->obj); | |
4608 *(int *)rdata = val; | |
4609 break; | |
4610 } | |
4611 case XD_OPAQUE_DATA_PTR: | |
4612 case XD_C_STRING: | |
4613 case XD_STRUCT_PTR: | |
4614 { | |
4615 void *ptr = *(void **)rdata; | |
4616 if (ptr) | |
4617 *(EMACS_INT *)rdata = pdump_get_entry (ptr)->save_offset; | |
4618 break; | |
4619 } | |
4620 case XD_LO_LINK: | |
4621 { | |
4622 Lisp_Object obj = *(Lisp_Object *)rdata; | |
4623 pdump_entry_list_elmt *elmt1; | |
4624 for (;;) | |
4625 { | |
4626 elmt1 = pdump_get_entry (XRECORD_LHEADER (obj)); | |
4627 if (elmt1) | |
4628 break; | |
4629 obj = *(Lisp_Object *)(desc[pos].offset + (char *)(XRECORD_LHEADER (obj))); | |
4630 } | |
4631 *(EMACS_INT *)rdata = elmt1->save_offset; | |
4632 break; | |
4633 } | |
4634 case XD_LISP_OBJECT: | |
4635 { | |
4636 Lisp_Object *pobj = (Lisp_Object *) rdata; | |
4637 | |
4638 assert (desc[pos].data1 == 0); | |
4639 | |
4640 if (POINTER_TYPE_P (XTYPE (*pobj)) && XRECORD_LHEADER (*pobj)) | |
4641 *(EMACS_INT *)pobj = | |
4642 pdump_get_entry (XRECORD_LHEADER (*pobj))->save_offset; | |
4643 break; | |
4644 } | |
4645 case XD_LISP_OBJECT_ARRAY: | |
4646 { | |
4647 EMACS_INT count = desc[pos].data1; | |
4648 int i; | |
4649 if (XD_IS_INDIRECT (count)) | |
4650 count = pdump_get_indirect_count (count, desc, elmt->obj); | |
4651 | |
4652 for (i=0; i<count; i++) | |
4653 { | |
4654 Lisp_Object *pobj = ((Lisp_Object *)rdata) + i; | |
4655 if (POINTER_TYPE_P (XTYPE (*pobj)) && XRECORD_LHEADER (*pobj)) | |
4656 *(EMACS_INT *)pobj = | |
4657 pdump_get_entry (XRECORD_LHEADER (*pobj))->save_offset; | |
4658 } | |
4659 break; | |
4660 } | |
4661 case XD_DOC_STRING: | |
4662 { | |
4663 EMACS_INT str = *(EMACS_INT *)rdata; | |
4664 if (str > 0) | |
4665 *(EMACS_INT *)rdata = pdump_get_entry ((void *)str)->save_offset; | |
4666 break; | |
4667 } | |
4668 default: | |
4669 fprintf (stderr, "Unsupported dump type : %d\n", desc[pos].type); | |
4670 abort (); | |
4671 }; | |
4672 } | |
4673 } | |
4674 } | |
4675 write (pdump_fd, desc ? pdump_buf : elmt->obj, size*count); | |
4676 if (elmt->is_lrecord && ((size*count) & 3)) | |
4677 write (pdump_fd, "\0\0\0", 4-((size*count) & 3)); | |
4678 } | |
4679 | |
4680 static void | |
4681 pdump_reloc_one (void *data, EMACS_INT delta, const struct lrecord_description *desc) | |
4682 { | |
4683 int pos; | |
4684 | |
4685 restart: | |
4686 for (pos = 0; desc[pos].type != XD_END; pos++) | |
4687 { | |
4688 void *rdata = (char *)data + desc[pos].offset; | |
4689 switch (desc[pos].type) | |
4690 { | |
4691 case XD_SPECIFIER_END: | |
4692 pos = 0; | |
4693 desc = ((const Lisp_Specifier *)data)->methods->extra_description; | |
4694 goto restart; | |
4695 case XD_SIZE_T: | |
4696 case XD_INT: | |
4697 case XD_LONG: | |
4698 case XD_BYTECOUNT: | |
4699 case XD_INT_RESET: | |
4700 break; | |
4701 case XD_OPAQUE_DATA_PTR: | |
4702 case XD_C_STRING: | |
4703 case XD_STRUCT_PTR: | |
4704 case XD_LO_LINK: | |
4705 { | |
4706 EMACS_INT ptr = *(EMACS_INT *)rdata; | |
4707 if (ptr) | |
4708 *(EMACS_INT *)rdata = ptr+delta; | |
4709 break; | |
4710 } | |
4711 case XD_LISP_OBJECT: | |
4712 { | |
4713 Lisp_Object *pobj = (Lisp_Object *) rdata; | |
4714 | |
4715 assert (desc[pos].data1 == 0); | |
4716 | |
4717 if (POINTER_TYPE_P (XTYPE (*pobj)) | |
4718 && ! EQ (*pobj, Qnull_pointer)) | |
4719 XSETOBJ (*pobj, XTYPE (*pobj), (char *) XPNTR (*pobj) + delta); | |
4720 | |
4721 break; | |
4722 } | |
4723 case XD_LISP_OBJECT_ARRAY: | |
4724 case XD_LO_RESET_NIL: | |
4725 { | |
4726 EMACS_INT count = desc[pos].data1; | |
4727 int i; | |
4728 if (XD_IS_INDIRECT (count)) | |
4729 count = pdump_get_indirect_count (count, desc, data); | |
4730 | |
4731 for (i=0; i<count; i++) | |
4732 { | |
4733 Lisp_Object *pobj = (Lisp_Object *) rdata + i; | |
4734 | |
4735 if (POINTER_TYPE_P (XTYPE (*pobj)) | |
4736 && ! EQ (*pobj, Qnull_pointer)) | |
4737 XSETOBJ (*pobj, XTYPE (*pobj), (char *) XPNTR (*pobj) + delta); | |
4738 } | |
4739 break; | |
4740 } | |
4741 case XD_DOC_STRING: | |
4742 { | |
4743 EMACS_INT str = *(EMACS_INT *)rdata; | |
4744 if (str > 0) | |
4745 *(EMACS_INT *)rdata = str + delta; | |
4746 break; | |
4747 } | |
4748 default: | |
4749 fprintf (stderr, "Unsupported dump type : %d\n", desc[pos].type); | |
4750 abort (); | |
4751 }; | |
4752 } | |
4753 } | |
4754 | |
4755 static void | |
4756 pdump_allocate_offset (pdump_entry_list_elmt *elmt, const struct lrecord_description *desc) | |
4757 { | |
4758 size_t size = (elmt->is_lrecord ? (elmt->size + 3) & ~3 : elmt->size)*elmt->count; | |
4759 elmt->save_offset = cur_offset; | |
4760 if (size>max_size) | |
4761 max_size = size; | |
4762 cur_offset += size; | |
4763 } | |
4764 | |
4765 static void | |
4766 pdump_scan_by_alignment (void (*f)(pdump_entry_list_elmt *, const struct lrecord_description *)) | |
4767 { | |
4768 int align, i; | |
4769 const struct lrecord_description *idesc; | |
4770 pdump_entry_list_elmt *elmt; | |
4771 for (align=8; align>=0; align--) | |
4772 { | |
4773 for (i=0; i<=last_lrecord_type_index_assigned; i++) | |
4774 if (pdump_object_table[i].align == align) | |
4775 { | |
4776 elmt = pdump_object_table[i].first; | |
4777 if (!elmt) | |
4778 continue; | |
4779 idesc = lrecord_implementations_table[i]->description; | |
4780 while (elmt) | |
4781 { | |
4782 f (elmt, idesc); | |
4783 elmt = elmt->next; | |
4784 } | |
4785 } | |
4786 | |
4787 for (i=0; i<pdump_struct_table.count; i++) | |
4788 if (pdump_struct_table.list[i].list.align == align) | |
4789 { | |
4790 elmt = pdump_struct_table.list[i].list.first; | |
4791 idesc = pdump_struct_table.list[i].sdesc->description; | |
4792 while (elmt) | |
4793 { | |
4794 f (elmt, idesc); | |
4795 elmt = elmt->next; | |
4796 } | |
4797 } | |
4798 | |
4799 elmt = pdump_opaque_data_list.first; | |
4800 while (elmt) | |
4801 { | |
4802 if (align_table[elmt->size & 255] == align) | |
4803 f (elmt, 0); | |
4804 elmt = elmt->next; | |
4805 } | |
4806 } | |
4807 } | |
4808 | |
4809 static void | |
4810 pdump_dump_staticvec (void) | |
4811 { | |
4812 EMACS_INT *reloc = xnew_array (EMACS_INT, staticidx); | |
4813 int i; | |
4814 write (pdump_fd, staticvec, staticidx*sizeof (Lisp_Object *)); | |
4815 | |
4816 for (i=0; i<staticidx; i++) | |
4817 { | |
4818 Lisp_Object obj = *staticvec[i]; | |
4819 if (POINTER_TYPE_P (XTYPE (obj))) | |
4820 reloc[i] = pdump_get_entry (XRECORD_LHEADER (obj))->save_offset; | |
4821 else | |
4822 reloc[i] = *(EMACS_INT *)(staticvec[i]); | |
4823 } | |
4824 write (pdump_fd, reloc, staticidx*sizeof (Lisp_Object)); | |
4825 free (reloc); | |
4826 } | |
4827 | |
4828 static void | |
4829 pdump_dump_structvec (void) | |
4830 { | |
4831 int i; | |
4832 for (i=0; i<dumpstructidx; i++) | |
4833 { | |
4834 EMACS_INT adr; | |
4835 write (pdump_fd, &(dumpstructvec[i].data), sizeof (void *)); | |
4836 adr = pdump_get_entry (*(void **)(dumpstructvec[i].data))->save_offset; | |
4837 write (pdump_fd, &adr, sizeof (adr)); | |
4838 } | |
4839 } | |
4840 | |
4841 static void | |
4842 pdump_dump_opaquevec (void) | |
4843 { | |
4844 int i; | |
4845 for (i=0; i<dumpopaqueidx; i++) | |
4846 { | |
4847 write (pdump_fd, &(dumpopaquevec[i]), sizeof (dumpopaquevec[i])); | |
4848 write (pdump_fd, dumpopaquevec[i].data, dumpopaquevec[i].size); | |
4849 } | |
4850 } | |
4851 | |
4852 static void | |
4853 pdump_dump_itable (void) | |
4854 { | |
4855 write (pdump_fd, lrecord_implementations_table, sizeof (lrecord_implementations_table)); | |
4856 } | |
4857 | |
4858 static void | |
4859 pdump_dump_rtables (void) | |
4860 { | |
4861 int i, j; | |
4862 pdump_entry_list_elmt *elmt; | |
4863 pdump_reloc_table rt; | |
4864 | |
4865 for (i=0; i<=last_lrecord_type_index_assigned; i++) | |
4866 { | |
4867 elmt = pdump_object_table[i].first; | |
4868 if (!elmt) | |
4869 continue; | |
4870 rt.desc = lrecord_implementations_table[i]->description; | |
4871 rt.count = pdump_object_table[i].count; | |
4872 write (pdump_fd, &rt, sizeof (rt)); | |
4873 while (elmt) | |
4874 { | |
4875 EMACS_INT rdata = pdump_get_entry (elmt->obj)->save_offset; | |
4876 write (pdump_fd, &rdata, sizeof (rdata)); | |
4877 elmt = elmt->next; | |
4878 } | |
4879 } | |
4880 | |
4881 rt.desc = 0; | |
4882 rt.count = 0; | |
4883 write (pdump_fd, &rt, sizeof (rt)); | |
4884 | |
4885 for (i=0; i<pdump_struct_table.count; i++) | |
4886 { | |
4887 elmt = pdump_struct_table.list[i].list.first; | |
4888 rt.desc = pdump_struct_table.list[i].sdesc->description; | |
4889 rt.count = pdump_struct_table.list[i].list.count; | |
4890 write (pdump_fd, &rt, sizeof (rt)); | |
4891 while (elmt) | |
4892 { | |
4893 EMACS_INT rdata = pdump_get_entry (elmt->obj)->save_offset; | |
4894 for (j=0; j<elmt->count; j++) | |
4895 { | |
4896 write (pdump_fd, &rdata, sizeof (rdata)); | |
4897 rdata += elmt->size; | |
4898 } | |
4899 elmt = elmt->next; | |
4900 } | |
4901 } | |
4902 rt.desc = 0; | |
4903 rt.count = 0; | |
4904 write (pdump_fd, &rt, sizeof (rt)); | |
4905 } | |
4906 | |
4907 static void | |
4908 pdump_dump_wired (void) | |
4909 { | |
4910 EMACS_INT count = pdump_wireidx + pdump_wireidx_list; | |
4911 int i; | |
4912 | |
4913 write (pdump_fd, &count, sizeof (count)); | |
4914 | |
4915 for (i=0; i<pdump_wireidx; i++) | |
4916 { | |
4917 EMACS_INT obj = pdump_get_entry (XRECORD_LHEADER (*(pdump_wirevec[i])))->save_offset; | |
4918 write (pdump_fd, &pdump_wirevec[i], sizeof (pdump_wirevec[i])); | |
4919 write (pdump_fd, &obj, sizeof (obj)); | |
4920 } | |
4921 | |
4922 for (i=0; i<pdump_wireidx_list; i++) | |
4923 { | |
4924 Lisp_Object obj = *(pdump_wirevec_list[i]); | |
4925 pdump_entry_list_elmt *elmt; | |
4926 EMACS_INT res; | |
4927 | |
4928 for (;;) | |
4929 { | |
4930 const struct lrecord_description *desc; | |
4931 int pos; | |
4932 elmt = pdump_get_entry (XRECORD_LHEADER (obj)); | |
4933 if (elmt) | |
4934 break; | |
4935 desc = XRECORD_LHEADER_IMPLEMENTATION (obj)->description; | |
4936 for (pos = 0; desc[pos].type != XD_LO_LINK; pos++) | |
4937 if (desc[pos].type == XD_END) | |
4938 abort (); | |
4939 | |
4940 obj = *(Lisp_Object *)(desc[pos].offset + (char *)(XRECORD_LHEADER (obj))); | |
4941 } | |
4942 res = elmt->save_offset; | |
4943 | |
4944 write (pdump_fd, &pdump_wirevec_list[i], sizeof (pdump_wirevec_list[i])); | |
4945 write (pdump_fd, &res, sizeof (res)); | |
4946 } | |
4947 } | |
4948 | |
4949 void | |
4950 pdump (void) | |
4951 { | |
4952 int i; | |
4953 Lisp_Object t_console, t_device, t_frame; | |
4954 int none; | |
4955 dump_header hd; | |
4956 | |
4957 /* These appear in a DEFVAR_LISP, which does a staticpro() */ | |
4958 t_console = Vterminal_console; | |
4959 t_frame = Vterminal_frame; | |
4960 t_device = Vterminal_device; | |
4961 | |
4962 Vterminal_console = Qnil; | |
4963 Vterminal_frame = Qnil; | |
4964 Vterminal_device = Qnil; | |
4965 | |
4966 pdump_hash = xnew_array_and_zero (pdump_entry_list_elmt *, PDUMP_HASHSIZE); | |
4967 | |
4968 for (i=0; i<=last_lrecord_type_index_assigned; i++) | |
4969 { | |
4970 pdump_object_table[i].first = 0; | |
4971 pdump_object_table[i].align = 8; | |
4972 pdump_object_table[i].count = 0; | |
4973 pdump_alert_undump_object[i] = 0; | |
4974 } | |
4975 pdump_struct_table.count = 0; | |
4976 pdump_struct_table.size = -1; | |
4977 | |
4978 pdump_opaque_data_list.first = 0; | |
4979 pdump_opaque_data_list.align = 8; | |
4980 pdump_opaque_data_list.count = 0; | |
4981 depth = 0; | |
4982 | |
4983 for (i=0; i<staticidx; i++) | |
4984 pdump_register_object (*staticvec[i]); | |
4985 for (i=0; i<pdump_wireidx; i++) | |
4986 pdump_register_object (*pdump_wirevec[i]); | |
4987 | |
4988 none = 1; | |
4989 for (i=0; i<=last_lrecord_type_index_assigned; i++) | |
4990 if (pdump_alert_undump_object[i]) | |
4991 { | |
4992 if (none) | |
4993 printf ("Undumpable types list :\n"); | |
4994 none = 0; | |
4995 printf (" - %s (%d)\n", lrecord_implementations_table[i]->name, pdump_alert_undump_object[i]); | |
4996 } | |
4997 if (!none) | |
4998 return; | |
4999 | |
5000 for (i=0; i<dumpstructidx; i++) | |
5001 pdump_register_struct (*(void **)(dumpstructvec[i].data), dumpstructvec[i].desc, 1); | |
5002 | |
5003 memcpy (hd.signature, "XEmacsDP", 8); | |
5004 hd.reloc_address = 0; | |
5005 hd.nb_staticpro = staticidx; | |
5006 hd.nb_structdmp = dumpstructidx; | |
5007 hd.nb_opaquedmp = dumpopaqueidx; | |
5008 hd.last_type = last_lrecord_type_index_assigned; | |
5009 | |
5010 cur_offset = 256; | |
5011 max_size = 0; | |
5012 | |
5013 pdump_scan_by_alignment (pdump_allocate_offset); | |
5014 pdump_qnil = pdump_get_entry (XRECORD_LHEADER (Qnil)); | |
5015 | |
5016 pdump_buf = xmalloc (max_size); | |
5017 /* Avoid use of the `open' macro. We want the real function. */ | |
5018 #undef open | |
5019 pdump_fd = open ("xemacs.dmp", | |
5020 O_WRONLY | O_CREAT | O_TRUNC | OPEN_BINARY, 0666); | |
5021 hd.stab_offset = (cur_offset + 3) & ~3; | |
5022 | |
5023 write (pdump_fd, &hd, sizeof (hd)); | |
5024 lseek (pdump_fd, 256, SEEK_SET); | |
5025 | |
5026 pdump_scan_by_alignment (pdump_dump_data); | |
5027 | |
5028 lseek (pdump_fd, hd.stab_offset, SEEK_SET); | |
5029 | |
5030 pdump_dump_staticvec (); | |
5031 pdump_dump_structvec (); | |
5032 pdump_dump_opaquevec (); | |
5033 pdump_dump_itable (); | |
5034 pdump_dump_rtables (); | |
5035 pdump_dump_wired (); | |
5036 | |
5037 close (pdump_fd); | |
5038 free (pdump_buf); | |
5039 | |
5040 free (pdump_hash); | |
5041 | |
5042 Vterminal_console = t_console; | |
5043 Vterminal_frame = t_frame; | |
5044 Vterminal_device = t_device; | |
5045 } | |
5046 | |
5047 int | |
5048 pdump_load (void) | |
5049 { | |
5050 size_t length; | |
5051 int i; | |
5052 char *p; | |
5053 EMACS_INT delta; | |
5054 EMACS_INT count; | |
5055 | |
5056 #define PDUMP_READ(p, type) (p = (char*) (((type *) p) + 1), *((type *) p - 1)) | |
5057 | |
5058 pdump_start = pdump_end = 0; | |
5059 | |
5060 pdump_fd = open ("xemacs.dmp", O_RDONLY | OPEN_BINARY); | |
5061 if (pdump_fd<0) | |
5062 return 0; | |
5063 | |
5064 length = lseek (pdump_fd, 0, SEEK_END); | |
5065 lseek (pdump_fd, 0, SEEK_SET); | |
5066 | |
5067 #ifdef HAVE_MMAP | |
5068 pdump_start = (char *) mmap (0, length, PROT_READ|PROT_WRITE, MAP_PRIVATE, pdump_fd, 0); | |
5069 if (pdump_start == MAP_FAILED) | |
5070 pdump_start = 0; | |
5071 #endif | |
5072 | |
5073 if (!pdump_start) | |
5074 { | |
5075 pdump_start = (char *)((((unsigned long)(xmalloc(length+255))) + 255) & ~255); | |
5076 read (pdump_fd, pdump_start, length); | |
5077 } | |
5078 | |
5079 close (pdump_fd); | |
5080 | |
5081 pdump_end = pdump_start + length; | |
5082 | |
5083 staticidx = ((dump_header *)(pdump_start))->nb_staticpro; | |
5084 last_lrecord_type_index_assigned = ((dump_header *)pdump_start)->last_type; | |
5085 delta = ((EMACS_INT)pdump_start) - ((dump_header *)pdump_start)->reloc_address; | |
5086 p = pdump_start + ((dump_header *)pdump_start)->stab_offset; | |
5087 | |
5088 /* Put back the staticvec in place */ | |
5089 memcpy (staticvec, p, staticidx*sizeof (Lisp_Object *)); | |
5090 p += staticidx*sizeof (Lisp_Object *); | |
5091 for (i=0; i<staticidx; i++) | |
5092 { | |
5093 Lisp_Object obj = PDUMP_READ (p, Lisp_Object); | |
5094 if (POINTER_TYPE_P (XTYPE (obj))) | |
5095 XSETOBJ (obj, XTYPE (obj), (char *) XPNTR (obj) + delta); | |
5096 *staticvec[i] = obj; | |
5097 } | |
5098 | |
5099 /* Put back the dumpstructs */ | |
5100 for (i=0; i<((dump_header *)pdump_start)->nb_structdmp; i++) | |
5101 { | |
5102 void **adr = PDUMP_READ (p, void **); | |
5103 *adr = (void *) (PDUMP_READ (p, char *) + delta); | |
5104 } | |
5105 | |
5106 /* Put back the opaques */ | |
5107 for (i=0; i<((dump_header *)pdump_start)->nb_opaquedmp; i++) | |
5108 { | |
5109 struct dumpopaque_info di = PDUMP_READ (p, struct dumpopaque_info); | |
5110 memcpy (di.data, p, di.size); | |
5111 p += di.size; | |
5112 } | |
5113 | |
5114 /* Put back the lrecord_implementations_table */ | |
5115 memcpy (lrecord_implementations_table, p, sizeof (lrecord_implementations_table)); | |
5116 p += sizeof (lrecord_implementations_table); | |
5117 | |
5118 /* Reinitialize lrecord_markers from lrecord_implementations_table */ | |
5119 for (i=0; i < countof (lrecord_implementations_table); i++) | |
5120 if (lrecord_implementations_table[i]) | |
5121 lrecord_markers[i] = lrecord_implementations_table[i]->marker; | |
5122 | |
5123 /* Do the relocations */ | |
5124 pdump_rt_list = p; | |
5125 count = 2; | |
5126 for (;;) | |
5127 { | |
5128 pdump_reloc_table rt = PDUMP_READ (p, pdump_reloc_table); | |
5129 if (rt.desc) | |
5130 { | |
5131 for (i=0; i < rt.count; i++) | |
5132 { | |
5133 char *adr = delta + *(char **)p; | |
5134 *(char **)p = adr; | |
5135 pdump_reloc_one (adr, delta, rt.desc); | |
5136 p += sizeof (char *); | |
5137 } | |
5138 } else | |
5139 if (!(--count)) | |
5140 break; | |
5141 } | |
5142 | |
5143 /* Put the pdump_wire variables in place */ | |
5144 count = PDUMP_READ (p, EMACS_INT); | |
5145 | |
5146 for (i=0; i<count; i++) | |
5147 { | |
5148 Lisp_Object *var = PDUMP_READ (p, Lisp_Object *); | |
5149 Lisp_Object obj = PDUMP_READ (p, Lisp_Object); | |
5150 | |
5151 if (POINTER_TYPE_P (XTYPE (obj))) | |
5152 XSETOBJ (obj, XTYPE (obj), (char *) XPNTR (obj) + delta); | |
5153 | |
5154 *var = obj; | |
5155 } | |
5156 | |
5157 /* Final cleanups */ | |
5158 /* reorganize hash tables */ | |
5159 p = pdump_rt_list; | |
5160 for (;;) | |
5161 { | |
5162 pdump_reloc_table rt = PDUMP_READ (p, pdump_reloc_table); | |
5163 if (!rt.desc) | |
5164 break; | |
5165 if (rt.desc == hash_table_description) | |
5166 { | |
5167 for (i=0; i < rt.count; i++) | |
5168 pdump_reorganize_hash_table (PDUMP_READ (p, Lisp_Object)); | |
5169 break; | |
5170 } else | |
5171 p += sizeof (Lisp_Object) * rt.count; | |
5172 } | |
5173 | |
5174 /* Put back noninteractive1 to its real value */ | |
5175 noninteractive1 = noninteractive; | |
5176 | |
5177 return 1; | |
5178 } | |
5179 | |
5180 #endif /* PDUMP */ | |
5181 |