Mercurial > hg > xemacs-beta
comparison src/alloc.c @ 183:e121b013d1f0 r20-3b18
Import from CVS: tag r20-3b18
author | cvs |
---|---|
date | Mon, 13 Aug 2007 09:54:23 +0200 |
parents | 6075d714658b |
children | 3d6bfa290dbd |
comparison
equal
deleted
inserted
replaced
182:f07455f06202 | 183:e121b013d1f0 |
---|---|
90 consing_since_gc += __sz__; \ | 90 consing_since_gc += __sz__; \ |
91 cadillac_record_backtrace (2, __sz__); \ | 91 cadillac_record_backtrace (2, __sz__); \ |
92 } while (0) | 92 } while (0) |
93 #else | 93 #else |
94 #define INCREMENT_CONS_COUNTER_1(size) (consing_since_gc += (size)) | 94 #define INCREMENT_CONS_COUNTER_1(size) (consing_since_gc += (size)) |
95 #endif | 95 #endif /* EMACS_BTL */ |
96 | 96 |
97 #define debug_allocation_backtrace() \ | 97 #define debug_allocation_backtrace() \ |
98 do { \ | 98 do { \ |
99 if (debug_allocation_backtrace_length > 0) \ | 99 if (debug_allocation_backtrace_length > 0) \ |
100 debug_short_backtrace (debug_allocation_backtrace_length); \ | 100 debug_short_backtrace (debug_allocation_backtrace_length); \ |
240 static int purecopying_for_bytecode; | 240 static int purecopying_for_bytecode; |
241 | 241 |
242 static int pure_sizeof (Lisp_Object /*, int recurse */); | 242 static int pure_sizeof (Lisp_Object /*, int recurse */); |
243 | 243 |
244 /* Keep statistics on how much of what is in purespace */ | 244 /* Keep statistics on how much of what is in purespace */ |
245 struct purestat | 245 static struct purestat |
246 { | 246 { |
247 int nobjects; | 247 int nobjects; |
248 int nbytes; | 248 int nbytes; |
249 CONST char *name; | 249 CONST char *name; |
250 }; | 250 } |
251 | 251 purestat_cons = {0, 0, "cons cells"}, |
252 #define FMH(s,n) static struct purestat s = { 0, 0, n } | 252 purestat_float = {0, 0, "float objects"}, |
253 FMH (purestat_cons, "cons cells:"); | 253 purestat_string_pname = {0, 0, "symbol-name strings"}, |
254 FMH (purestat_float, "float objects:"); | 254 purestat_bytecode = {0, 0, "compiled-function objects"}, |
255 FMH (purestat_string_pname, "symbol-name strings:"); | 255 purestat_string_bytecodes = {0, 0, "byte-code strings"}, |
256 FMH (purestat_bytecode, "compiled-function objects:"); | 256 purestat_vector_bytecode_constants = {0, 0, "byte-constant vectors"}, |
257 FMH (purestat_string_bytecodes, "byte-code strings:"); | 257 purestat_string_interactive = {0, 0, "interactive strings"}, |
258 FMH (purestat_vector_bytecode_constants, "byte-constant vectors:"); | |
259 FMH (purestat_string_interactive, "interactive strings:"); | |
260 #ifdef I18N3 | 258 #ifdef I18N3 |
261 FMH (purestat_string_domain, "domain strings:"); | 259 purestat_string_domain = {0, 0, "domain strings"}, |
262 #endif | 260 #endif |
263 FMH (purestat_string_documentation, "documentation strings:"); | 261 purestat_string_documentation = {0, 0, "documentation strings"}, |
264 FMH (purestat_string_other_function, "other function strings:"); | 262 purestat_string_other_function = {0, 0, "other function strings"}, |
265 FMH (purestat_vector_other, "other vectors:"); | 263 purestat_vector_other = {0, 0, "other vectors"}, |
266 FMH (purestat_string_other, "other strings:"); | 264 purestat_string_other = {0, 0, "other strings"}, |
267 FMH (purestat_string_all, "all strings:"); | 265 purestat_string_all = {0, 0, "all strings"}, |
268 FMH (purestat_vector_all, "all vectors:"); | 266 purestat_vector_all = {0, 0, "all vectors"}; |
269 | 267 |
270 static struct purestat *purestats[] = | 268 static struct purestat *purestats[] = |
271 { | 269 { |
272 &purestat_cons, | 270 &purestat_cons, |
273 &purestat_float, | 271 &purestat_float, |
285 &purestat_string_other, | 283 &purestat_string_other, |
286 0, | 284 0, |
287 &purestat_string_all, | 285 &purestat_string_all, |
288 &purestat_vector_all | 286 &purestat_vector_all |
289 }; | 287 }; |
290 #undef FMH | |
291 | 288 |
292 static void | 289 static void |
293 bump_purestat (struct purestat *purestat, int nbytes) | 290 bump_purestat (struct purestat *purestat, int nbytes) |
294 { | 291 { |
295 if (pure_lossage) return; | 292 if (pure_lossage) return; |
317 static void *breathing_space; | 314 static void *breathing_space; |
318 | 315 |
319 void | 316 void |
320 release_breathing_space (void) | 317 release_breathing_space (void) |
321 { | 318 { |
322 if (breathing_space) | 319 if (breathing_space) |
323 { | 320 { |
324 void *tmp = breathing_space; | 321 void *tmp = breathing_space; |
325 breathing_space = 0; | 322 breathing_space = 0; |
326 xfree (tmp); | 323 xfree (tmp); |
327 } | 324 } |
421 /* Unbelievably, calling free() on 0xDEADBEEF doesn't cause an | 418 /* Unbelievably, calling free() on 0xDEADBEEF doesn't cause an |
422 error until much later on for many system mallocs, such as | 419 error until much later on for many system mallocs, such as |
423 the one that comes with Solaris 2.3. FMH!! */ | 420 the one that comes with Solaris 2.3. FMH!! */ |
424 assert (block != (void *) 0xDEADBEEF); | 421 assert (block != (void *) 0xDEADBEEF); |
425 assert (block); | 422 assert (block); |
426 #endif | 423 #endif /* ERROR_CHECK_MALLOC */ |
427 free (block); | 424 free (block); |
428 } | 425 } |
429 | 426 |
430 #if INTBITS == 32 | 427 #if INTBITS == 32 |
431 # define FOUR_BYTE_TYPE unsigned int | 428 # define FOUR_BYTE_TYPE unsigned int |
449 deadbeef_memory (void *ptr, unsigned long size) | 446 deadbeef_memory (void *ptr, unsigned long size) |
450 { | 447 { |
451 unsigned long long_length = size / sizeof (FOUR_BYTE_TYPE); | 448 unsigned long long_length = size / sizeof (FOUR_BYTE_TYPE); |
452 unsigned long i; | 449 unsigned long i; |
453 unsigned long bytes_left_over = size - sizeof (FOUR_BYTE_TYPE) * long_length; | 450 unsigned long bytes_left_over = size - sizeof (FOUR_BYTE_TYPE) * long_length; |
454 | 451 |
455 for (i = 0; i < long_length; i++) | 452 for (i = 0; i < long_length; i++) |
456 ((FOUR_BYTE_TYPE *) ptr)[i] = 0xdeadbeef; | 453 ((FOUR_BYTE_TYPE *) ptr)[i] = 0xdeadbeef; |
457 for (i = i; i < bytes_left_over; i++) | 454 for (i = i; i < bytes_left_over; i++) |
458 ((unsigned char *) ptr + long_length)[i] = deadbeef_as_char[i]; | 455 ((unsigned char *) ptr + long_length)[i] = deadbeef_as_char[i]; |
459 } | 456 } |
460 | 457 |
461 #else | 458 #else /* !ERROR_CHECK_GC */ |
459 | |
462 | 460 |
463 #define deadbeef_memory(ptr, size) | 461 #define deadbeef_memory(ptr, size) |
464 | 462 |
465 #endif | 463 #endif /* !ERROR_CHECK_GC */ |
466 | 464 |
467 #ifdef xstrdup | 465 #ifdef xstrdup |
468 #undef xstrdup | 466 #undef xstrdup |
469 #endif | 467 #endif |
470 | 468 |
516 do { (((lheader)->implementation)--); } while (0) | 514 do { (((lheader)->implementation)--); } while (0) |
517 | 515 |
518 | 516 |
519 /* lrecords are chained together through their "next.v" field. | 517 /* lrecords are chained together through their "next.v" field. |
520 * After doing the mark phase, the GC will walk this linked | 518 * After doing the mark phase, the GC will walk this linked |
521 * list and free any record which hasn't been marked | 519 * list and free any record which hasn't been marked |
522 */ | 520 */ |
523 static struct lcrecord_header *all_lcrecords; | 521 static struct lcrecord_header *all_lcrecords; |
524 | 522 |
525 void * | 523 void * |
526 alloc_lcrecord (int size, CONST struct lrecord_implementation *implementation) | 524 alloc_lcrecord (int size, CONST struct lrecord_implementation *implementation) |
598 { | 596 { |
599 if (header->lheader.implementation->finalizer && !header->free) | 597 if (header->lheader.implementation->finalizer && !header->free) |
600 ((header->lheader.implementation->finalizer) (header, 1)); | 598 ((header->lheader.implementation->finalizer) (header, 1)); |
601 } | 599 } |
602 } | 600 } |
603 | 601 |
604 | 602 |
605 /* This must not be called -- it just serves as for EQ test | 603 /* This must not be called -- it just serves as for EQ test |
606 * If lheader->implementation->finalizer is this_marks_a_marked_record, | 604 * If lheader->implementation->finalizer is this_marks_a_marked_record, |
607 * then lrecord has been marked by the GC sweeper | 605 * then lrecord has been marked by the GC sweeper |
608 * header->implementation is put back to its correct value by | 606 * header->implementation is put back to its correct value by |
675 make more sense) are malloc()ed separately and not stored in | 673 make more sense) are malloc()ed separately and not stored in |
676 string_chars_blocks. Furthermore, no one string stretches across | 674 string_chars_blocks. Furthermore, no one string stretches across |
677 two string_chars_blocks. | 675 two string_chars_blocks. |
678 | 676 |
679 Vectors are each malloc()ed separately, similar to lcrecords. | 677 Vectors are each malloc()ed separately, similar to lcrecords. |
680 | 678 |
681 In the following discussion, we use conses, but it applies equally | 679 In the following discussion, we use conses, but it applies equally |
682 well to the other fixed-size types. | 680 well to the other fixed-size types. |
683 | 681 |
684 We store cons cells inside of cons_blocks, allocating a new | 682 We store cons cells inside of cons_blocks, allocating a new |
685 cons_block with malloc() whenever necessary. Cons cells reclaimed | 683 cons_block with malloc() whenever necessary. Cons cells reclaimed |
791 #elif defined (rcheck) | 789 #elif defined (rcheck) |
792 #define MALLOC_OVERHEAD 20 | 790 #define MALLOC_OVERHEAD 20 |
793 #else | 791 #else |
794 #define MALLOC_OVERHEAD 8 | 792 #define MALLOC_OVERHEAD 8 |
795 #endif | 793 #endif |
796 #endif | 794 #endif /* MALLOC_OVERHEAD */ |
797 | 795 |
798 #ifdef ALLOC_NO_POOLS | 796 #ifdef ALLOC_NO_POOLS |
799 # define TYPE_ALLOC_SIZE(type, structtype) 1 | 797 # define TYPE_ALLOC_SIZE(type, structtype) 1 |
800 #else | 798 #else |
801 # define TYPE_ALLOC_SIZE(type, structtype) \ | 799 # define TYPE_ALLOC_SIZE(type, structtype) \ |
802 ((2048 - MALLOC_OVERHEAD - sizeof (struct type##_block *)) \ | 800 ((2048 - MALLOC_OVERHEAD - sizeof (struct type##_block *)) \ |
803 / sizeof (structtype)) | 801 / sizeof (structtype)) |
804 #endif | 802 #endif /* ALLOC_NO_POOLS */ |
805 | 803 |
806 #define DECLARE_FIXED_TYPE_ALLOC(type, structtype) \ | 804 #define DECLARE_FIXED_TYPE_ALLOC(type, structtype) \ |
807 \ | 805 \ |
808 struct type##_block \ | 806 struct type##_block \ |
809 { \ | 807 { \ |
871 else \ | 869 else \ |
872 ALLOCATE_FIXED_TYPE_FROM_BLOCK (type, result); \ | 870 ALLOCATE_FIXED_TYPE_FROM_BLOCK (type, result); \ |
873 MARK_STRUCT_AS_NOT_FREE (result); \ | 871 MARK_STRUCT_AS_NOT_FREE (result); \ |
874 } while (0) | 872 } while (0) |
875 | 873 |
876 #else | 874 #else /* !ERROR_CHECK_GC */ |
877 | 875 |
878 #define ALLOCATE_FIXED_TYPE_1(type, structtype, result) \ | 876 #define ALLOCATE_FIXED_TYPE_1(type, structtype, result) \ |
879 do \ | 877 do \ |
880 { \ | 878 { \ |
881 if (type##_free_list) \ | 879 if (type##_free_list) \ |
887 else \ | 885 else \ |
888 ALLOCATE_FIXED_TYPE_FROM_BLOCK (type, result); \ | 886 ALLOCATE_FIXED_TYPE_FROM_BLOCK (type, result); \ |
889 MARK_STRUCT_AS_NOT_FREE (result); \ | 887 MARK_STRUCT_AS_NOT_FREE (result); \ |
890 } while (0) | 888 } while (0) |
891 | 889 |
892 #endif | 890 #endif /* !ERROR_CHECK_GC */ |
893 | 891 |
894 #define ALLOCATE_FIXED_TYPE(type, structtype, result) \ | 892 #define ALLOCATE_FIXED_TYPE(type, structtype, result) \ |
895 do \ | 893 do \ |
896 { \ | 894 { \ |
897 ALLOCATE_FIXED_TYPE_1 (type, structtype, result); \ | 895 ALLOCATE_FIXED_TYPE_1 (type, structtype, result); \ |
913 be a pointer, and the pointer will be misaligned. | 911 be a pointer, and the pointer will be misaligned. |
914 | 912 |
915 Even if Emacs is run on some weirdo system that allows and allocates | 913 Even if Emacs is run on some weirdo system that allows and allocates |
916 byte-aligned pointers, this pointer is at the very top of the address | 914 byte-aligned pointers, this pointer is at the very top of the address |
917 space and so it's almost inconceivable that it could ever be valid. */ | 915 space and so it's almost inconceivable that it could ever be valid. */ |
918 | 916 |
919 #if INTBITS == 32 | 917 #if INTBITS == 32 |
920 # define INVALID_POINTER_VALUE 0xFFFFFFFF | 918 # define INVALID_POINTER_VALUE 0xFFFFFFFF |
921 #elif INTBITS == 48 | 919 #elif INTBITS == 48 |
922 # define INVALID_POINTER_VALUE 0xFFFFFFFFFFFF | 920 # define INVALID_POINTER_VALUE 0xFFFFFFFFFFFF |
923 #elif INTBITS == 64 | 921 #elif INTBITS == 64 |
952 else \ | 950 else \ |
953 type##_free_list = ptr; \ | 951 type##_free_list = ptr; \ |
954 type##_free_list_tail = ptr; \ | 952 type##_free_list_tail = ptr; \ |
955 } while (0) | 953 } while (0) |
956 | 954 |
957 #else | 955 #else /* !ERROR_CHECK_GC */ |
958 | 956 |
959 #define PUT_FIXED_TYPE_ON_FREE_LIST(type, structtype, ptr) \ | 957 #define PUT_FIXED_TYPE_ON_FREE_LIST(type, structtype, ptr) \ |
960 do { * (structtype **) ((char *) ptr + sizeof (void *)) = \ | 958 do { * (structtype **) ((char *) ptr + sizeof (void *)) = \ |
961 type##_free_list; \ | 959 type##_free_list; \ |
962 type##_free_list = ptr; \ | 960 type##_free_list = ptr; \ |
963 } while (0) | 961 } while (0) |
964 | 962 |
965 #endif | 963 #endif /* !ERROR_CHECK_GC */ |
966 | 964 |
967 /* TYPE and STRUCTTYPE are the same as in ALLOCATE_FIXED_TYPE(). */ | 965 /* TYPE and STRUCTTYPE are the same as in ALLOCATE_FIXED_TYPE(). */ |
968 | 966 |
969 #define FREE_FIXED_TYPE(type, structtype, ptr) \ | 967 #define FREE_FIXED_TYPE(type, structtype, ptr) \ |
970 do { structtype *_weird_ = (ptr); \ | 968 do { structtype *_weird_ = (ptr); \ |
987 #define FREE_FIXED_TYPE_WHEN_NOT_IN_GC(type, structtype, ptr) \ | 985 #define FREE_FIXED_TYPE_WHEN_NOT_IN_GC(type, structtype, ptr) \ |
988 do { FREE_FIXED_TYPE (type, structtype, ptr); \ | 986 do { FREE_FIXED_TYPE (type, structtype, ptr); \ |
989 DECREMENT_CONS_COUNTER (sizeof (structtype)); \ | 987 DECREMENT_CONS_COUNTER (sizeof (structtype)); \ |
990 gc_count_num_##type##_freelist++; \ | 988 gc_count_num_##type##_freelist++; \ |
991 } while (0) | 989 } while (0) |
992 | 990 |
993 | 991 |
994 | 992 |
995 /**********************************************************************/ | 993 /**********************************************************************/ |
996 /* Cons allocation */ | 994 /* Cons allocation */ |
997 /**********************************************************************/ | 995 /**********************************************************************/ |
1524 the objects are sitting on Vload_force_doc_string_list, which | 1522 the objects are sitting on Vload_force_doc_string_list, which |
1525 is staticpro'd, so we're OK. */ | 1523 is staticpro'd, so we're OK. */ |
1526 int purecopy_instructions = 1; | 1524 int purecopy_instructions = 1; |
1527 | 1525 |
1528 if (nargs > 6) | 1526 if (nargs > 6) |
1529 return Fsignal (Qwrong_number_of_arguments, | 1527 return Fsignal (Qwrong_number_of_arguments, |
1530 list2 (intern ("make-byte-code"), make_int (nargs))); | 1528 list2 (intern ("make-byte-code"), make_int (nargs))); |
1531 | 1529 |
1532 CHECK_LIST (arglist); | 1530 CHECK_LIST (arglist); |
1533 /* instructions is a string or a cons (string . int) for a | 1531 /* instructions is a string or a cons (string . int) for a |
1534 lazy-loaded function. */ | 1532 lazy-loaded function. */ |
1587 if (STRINGP (interactive)) | 1585 if (STRINGP (interactive)) |
1588 bump_purestat (&purestat_string_interactive, | 1586 bump_purestat (&purestat_string_interactive, |
1589 pure_sizeof (interactive)); | 1587 pure_sizeof (interactive)); |
1590 #endif /* PURESTAT */ | 1588 #endif /* PURESTAT */ |
1591 } | 1589 } |
1592 | 1590 |
1593 { | 1591 { |
1594 int docp = !NILP (doc_string); | 1592 int docp = !NILP (doc_string); |
1595 int intp = !UNBOUNDP (interactive); | 1593 int intp = !UNBOUNDP (interactive); |
1596 #ifdef I18N3 | 1594 #ifdef I18N3 |
1597 int domp = !NILP (Vfile_domain); | 1595 int domp = !NILP (Vfile_domain); |
1619 Vload_file_name_internal_the_purecopy = | 1617 Vload_file_name_internal_the_purecopy = |
1620 Fpurecopy (Ffile_name_nondirectory (Vload_file_name_internal)); | 1618 Fpurecopy (Ffile_name_nondirectory (Vload_file_name_internal)); |
1621 b->annotated = Vload_file_name_internal_the_purecopy; | 1619 b->annotated = Vload_file_name_internal_the_purecopy; |
1622 UNGCPRO; | 1620 UNGCPRO; |
1623 } | 1621 } |
1624 #endif | 1622 #endif /* COMPILED_FUNCTION_ANNOTATION_HACK */ |
1625 | 1623 |
1626 #ifdef I18N3 | 1624 #ifdef I18N3 |
1627 if (docp && intp && domp) | 1625 if (docp && intp && domp) |
1628 b->doc_and_interactive = (((purify_flag) ? pure_cons : Fcons) | 1626 b->doc_and_interactive = (((purify_flag) ? pure_cons : Fcons) |
1629 (doc_string, | 1627 (doc_string, |
1733 set_lheader_implementation (&(e->lheader), lrecord_event); | 1731 set_lheader_implementation (&(e->lheader), lrecord_event); |
1734 | 1732 |
1735 XSETEVENT (val, e); | 1733 XSETEVENT (val, e); |
1736 return val; | 1734 return val; |
1737 } | 1735 } |
1738 | 1736 |
1739 | 1737 |
1740 /**********************************************************************/ | 1738 /**********************************************************************/ |
1741 /* Marker allocation */ | 1739 /* Marker allocation */ |
1742 /**********************************************************************/ | 1740 /**********************************************************************/ |
1743 | 1741 |
1783 | 1781 |
1784 /**********************************************************************/ | 1782 /**********************************************************************/ |
1785 /* String allocation */ | 1783 /* String allocation */ |
1786 /**********************************************************************/ | 1784 /**********************************************************************/ |
1787 | 1785 |
1788 /* The data for "short" strings generally resides inside of structs of type | 1786 /* The data for "short" strings generally resides inside of structs of type |
1789 string_chars_block. The Lisp_String structure is allocated just like any | 1787 string_chars_block. The Lisp_String structure is allocated just like any |
1790 other Lisp object (except for vectors), and these are freelisted when | 1788 other Lisp object (except for vectors), and these are freelisted when |
1791 they get garbage collected. The data for short strings get compacted, | 1789 they get garbage collected. The data for short strings get compacted, |
1792 but the data for large strings do not. | 1790 but the data for large strings do not. |
1793 | 1791 |
1794 Previously Lisp_String structures were relocated, but this caused a lot | 1792 Previously Lisp_String structures were relocated, but this caused a lot |
1795 of bus-errors because the C code didn't include enough GCPRO's for | 1793 of bus-errors because the C code didn't include enough GCPRO's for |
1796 strings (since EVERY REFERENCE to a short string needed to be GCPRO'd so | 1794 strings (since EVERY REFERENCE to a short string needed to be GCPRO'd so |
1797 that the reference would get relocated). | 1795 that the reference would get relocated). |
1850 }; | 1848 }; |
1851 | 1849 |
1852 static void | 1850 static void |
1853 init_string_chars_alloc (void) | 1851 init_string_chars_alloc (void) |
1854 { | 1852 { |
1855 first_string_chars_block = | 1853 first_string_chars_block = |
1856 (struct string_chars_block *) xmalloc (sizeof (struct string_chars_block)); | 1854 (struct string_chars_block *) xmalloc (sizeof (struct string_chars_block)); |
1857 first_string_chars_block->prev = 0; | 1855 first_string_chars_block->prev = 0; |
1858 first_string_chars_block->next = 0; | 1856 first_string_chars_block->next = 0; |
1859 first_string_chars_block->pos = 0; | 1857 first_string_chars_block->pos = 0; |
1860 current_string_chars_block = first_string_chars_block; | 1858 current_string_chars_block = first_string_chars_block; |
1882 current_string_chars_block->pos += fullsize; | 1880 current_string_chars_block->pos += fullsize; |
1883 } | 1881 } |
1884 else | 1882 else |
1885 { | 1883 { |
1886 /* Make a new current string chars block */ | 1884 /* Make a new current string chars block */ |
1887 struct string_chars_block *new | 1885 struct string_chars_block *new |
1888 = (struct string_chars_block *) | 1886 = (struct string_chars_block *) |
1889 xmalloc (sizeof (struct string_chars_block)); | 1887 xmalloc (sizeof (struct string_chars_block)); |
1890 | 1888 |
1891 current_string_chars_block->next = new; | 1889 current_string_chars_block->next = new; |
1892 new->prev = current_string_chars_block; | 1890 new->prev = current_string_chars_block; |
1893 new->next = 0; | 1891 new->next = 0; |
1894 current_string_chars_block = new; | 1892 current_string_chars_block = new; |
1895 new->pos = fullsize; | 1893 new->pos = fullsize; |
1921 s_chars = allocate_string_chars_struct (s, fullsize); | 1919 s_chars = allocate_string_chars_struct (s, fullsize); |
1922 | 1920 |
1923 set_string_data (s, &(s_chars->chars[0])); | 1921 set_string_data (s, &(s_chars->chars[0])); |
1924 set_string_length (s, length); | 1922 set_string_length (s, length); |
1925 s->plist = Qnil; | 1923 s->plist = Qnil; |
1926 | 1924 |
1927 set_string_byte (s, length, 0); | 1925 set_string_byte (s, length, 0); |
1928 | 1926 |
1929 XSETSTRING (val, s); | 1927 XSETSTRING (val, s); |
1930 return val; | 1928 return val; |
1931 } | 1929 } |
1932 | 1930 |
1933 #ifdef VERIFY_STRING_CHARS_INTEGRITY | 1931 #ifdef VERIFY_STRING_CHARS_INTEGRITY |
1934 static void verify_string_chars_integrity (void); | 1932 static void verify_string_chars_integrity (void); |
1935 #endif | 1933 #endif |
1936 | 1934 |
1937 /* Resize the string S so that DELTA bytes can be inserted starting | 1935 /* Resize the string S so that DELTA bytes can be inserted starting |
1938 at POS. If DELTA < 0, it means deletion starting at POS. If | 1936 at POS. If DELTA < 0, it means deletion starting at POS. If |
1939 POS < 0, resize the string but don't copy any characters. Use | 1937 POS < 0, resize the string but don't copy any characters. Use |
1940 this if you're planning on completely overwriting the string. | 1938 this if you're planning on completely overwriting the string. |
1941 */ | 1939 */ |
1957 else | 1955 else |
1958 { | 1956 { |
1959 if (delta < 0) | 1957 if (delta < 0) |
1960 assert ((-delta) <= string_length (s)); | 1958 assert ((-delta) <= string_length (s)); |
1961 } | 1959 } |
1962 #endif | 1960 #endif /* ERROR_CHECK_BUFPOS */ |
1963 | 1961 |
1964 if (pos >= 0 && delta < 0) | 1962 if (pos >= 0 && delta < 0) |
1965 /* If DELTA < 0, the functions below will delete the characters | 1963 /* If DELTA < 0, the functions below will delete the characters |
1966 before POS. We want to delete characters *after* POS, however, | 1964 before POS. We want to delete characters *after* POS, however, |
1967 so convert this to the appropriate form. */ | 1965 so convert this to the appropriate form. */ |
1981 allocation size won't change (up or down; code somewhere | 1979 allocation size won't change (up or down; code somewhere |
1982 depends on there not being any unused allocation space, | 1980 depends on there not being any unused allocation space, |
1983 modulo any alignment constraints). */ | 1981 modulo any alignment constraints). */ |
1984 if (pos >= 0) | 1982 if (pos >= 0) |
1985 { | 1983 { |
1986 Bufbyte *addroff = pos + string_data (s); | 1984 Bufbyte *addroff = pos + string_data (s); |
1987 | 1985 |
1988 memmove (addroff + delta, addroff, | 1986 memmove (addroff + delta, addroff, |
1989 /* +1 due to zero-termination. */ | 1987 /* +1 due to zero-termination. */ |
1990 string_length (s) + 1 - pos); | 1988 string_length (s) + 1 - pos); |
1991 } | 1989 } |
2002 string could result in memory leakage. */ | 2000 string could result in memory leakage. */ |
2003 set_string_data (s, (Bufbyte *) xrealloc (string_data (s), | 2001 set_string_data (s, (Bufbyte *) xrealloc (string_data (s), |
2004 newfullsize)); | 2002 newfullsize)); |
2005 if (pos >= 0) | 2003 if (pos >= 0) |
2006 { | 2004 { |
2007 Bufbyte *addroff = pos + string_data (s); | 2005 Bufbyte *addroff = pos + string_data (s); |
2008 | 2006 |
2009 memmove (addroff + delta, addroff, | 2007 memmove (addroff + delta, addroff, |
2010 /* +1 due to zero-termination. */ | 2008 /* +1 due to zero-termination. */ |
2011 string_length (s) + 1 - pos); | 2009 string_length (s) + 1 - pos); |
2012 } | 2010 } |
2134 | 2132 |
2135 /* Make sure we find out about bad make_string's when they happen */ | 2133 /* Make sure we find out about bad make_string's when they happen */ |
2136 #if defined (ERROR_CHECK_BUFPOS) && defined (MULE) | 2134 #if defined (ERROR_CHECK_BUFPOS) && defined (MULE) |
2137 bytecount_to_charcount (contents, length); /* Just for the assertions */ | 2135 bytecount_to_charcount (contents, length); /* Just for the assertions */ |
2138 #endif | 2136 #endif |
2139 | 2137 |
2140 val = make_uninit_string (length); | 2138 val = make_uninit_string (length); |
2141 memcpy (XSTRING_DATA (val), contents, length); | 2139 memcpy (XSTRING_DATA (val), contents, length); |
2142 return val; | 2140 return val; |
2143 } | 2141 } |
2144 | 2142 |
2257 #endif /* ERROR_CHECK_GC */ | 2255 #endif /* ERROR_CHECK_GC */ |
2258 | 2256 |
2259 MARK_RECORD_HEADER (lheader); | 2257 MARK_RECORD_HEADER (lheader); |
2260 chain = free_header->chain; | 2258 chain = free_header->chain; |
2261 } | 2259 } |
2262 | 2260 |
2263 return Qnil; | 2261 return Qnil; |
2264 } | 2262 } |
2265 | 2263 |
2266 Lisp_Object | 2264 Lisp_Object |
2267 make_lcrecord_list (int size, | 2265 make_lcrecord_list (int size, |
2303 /* The type of the lcrecord must be right. */ | 2301 /* The type of the lcrecord must be right. */ |
2304 assert (implementation == list->implementation); | 2302 assert (implementation == list->implementation); |
2305 /* So must the size. */ | 2303 /* So must the size. */ |
2306 assert (implementation->static_size == 0 | 2304 assert (implementation->static_size == 0 |
2307 || implementation->static_size == list->size); | 2305 || implementation->static_size == list->size); |
2308 #endif | 2306 #endif /* ERROR_CHECK_GC */ |
2309 list->free = free_header->chain; | 2307 list->free = free_header->chain; |
2310 free_header->lcheader.free = 0; | 2308 free_header->lcheader.free = 0; |
2311 return val; | 2309 return val; |
2312 } | 2310 } |
2313 else | 2311 else |
2337 if (implementation->size_in_bytes_method) | 2335 if (implementation->size_in_bytes_method) |
2338 assert (((implementation->size_in_bytes_method) (lheader)) | 2336 assert (((implementation->size_in_bytes_method) (lheader)) |
2339 == list->size); | 2337 == list->size); |
2340 else | 2338 else |
2341 assert (implementation->static_size == list->size); | 2339 assert (implementation->static_size == list->size); |
2342 #endif | 2340 #endif /* ERROR_CHECK_GC */ |
2343 | 2341 |
2344 if (implementation->finalizer) | 2342 if (implementation->finalizer) |
2345 ((implementation->finalizer) (lheader, 0)); | 2343 ((implementation->finalizer) (lheader, 0)); |
2346 free_header->chain = list->free; | 2344 free_header->chain = list->free; |
2347 free_header->lcheader.free = 1; | 2345 free_header->lcheader.free = 1; |
2359 make_pure_string (CONST Bufbyte *data, Bytecount length, | 2357 make_pure_string (CONST Bufbyte *data, Bytecount length, |
2360 Lisp_Object plist, int no_need_to_copy_data) | 2358 Lisp_Object plist, int no_need_to_copy_data) |
2361 { | 2359 { |
2362 Lisp_Object new; | 2360 Lisp_Object new; |
2363 struct Lisp_String *s; | 2361 struct Lisp_String *s; |
2364 int size = (sizeof (struct Lisp_String) + ((no_need_to_copy_data) | 2362 int size = (sizeof (struct Lisp_String) + ((no_need_to_copy_data) |
2365 ? 0 | 2363 ? 0 |
2366 /* + 1 for terminating 0 */ | 2364 /* + 1 for terminating 0 */ |
2367 : (length + 1))); | 2365 : (length + 1))); |
2368 size = ALIGN_SIZE (size, ALIGNOF (Lisp_Object)); | 2366 size = ALIGN_SIZE (size, ALIGNOF (Lisp_Object)); |
2369 | 2367 |
2370 if (symbols_initialized && !pure_lossage) | 2368 if (symbols_initialized && !pure_lossage) |
2400 | 2398 |
2401 #ifdef PURESTAT | 2399 #ifdef PURESTAT |
2402 bump_purestat (&purestat_string_all, size); | 2400 bump_purestat (&purestat_string_all, size); |
2403 if (purecopying_for_bytecode) | 2401 if (purecopying_for_bytecode) |
2404 bump_purestat (&purestat_string_other_function, size); | 2402 bump_purestat (&purestat_string_other_function, size); |
2405 #endif | 2403 #endif /* PURESTAT */ |
2406 | 2404 |
2407 /* Do this after the official "completion" of the purecopying. */ | 2405 /* Do this after the official "completion" of the purecopying. */ |
2408 s->plist = Fpurecopy (plist); | 2406 s->plist = Fpurecopy (plist); |
2409 | 2407 |
2410 XSETSTRING (new, s); | 2408 XSETSTRING (new, s); |
2480 that the `double' slot in it is supposed to be aligned to; this | 2478 that the `double' slot in it is supposed to be aligned to; this |
2481 should be ok because presumably there is padding in the layout | 2479 should be ok because presumably there is padding in the layout |
2482 of the struct to account for this. | 2480 of the struct to account for this. |
2483 */ | 2481 */ |
2484 int alignment = sizeof (float_data (f)); | 2482 int alignment = sizeof (float_data (f)); |
2485 #endif | 2483 #endif /* !GNUC */ |
2486 char *p = ((char *) PUREBEG + pureptr); | 2484 char *p = ((char *) PUREBEG + pureptr); |
2487 | 2485 |
2488 p = (char *) (((unsigned EMACS_INT) p + alignment - 1) & - alignment); | 2486 p = (char *) (((unsigned EMACS_INT) p + alignment - 1) & - alignment); |
2489 pureptr = p - (char *) PUREBEG; | 2487 pureptr = p - (char *) PUREBEG; |
2490 } | 2488 } |
2541 | 2539 |
2542 set_lheader_implementation (header, implementation); | 2540 set_lheader_implementation (header, implementation); |
2543 header->next = 0; | 2541 header->next = 0; |
2544 return header; | 2542 return header; |
2545 } | 2543 } |
2546 #endif | 2544 #endif /* unused */ |
2547 | 2545 |
2548 | 2546 |
2549 | 2547 |
2550 DEFUN ("purecopy", Fpurecopy, 1, 1, 0, /* | 2548 DEFUN ("purecopy", Fpurecopy, 1, 1, 0, /* |
2551 Make a copy of OBJECT in pure storage. | 2549 Make a copy of OBJECT in pure storage. |
2610 } | 2608 } |
2611 | 2609 |
2612 | 2610 |
2613 | 2611 |
2614 static void | 2612 static void |
2615 PURESIZE_h(long int puresize) | 2613 puresize_adjust_h (long int puresize) |
2616 { | 2614 { |
2617 int fd; | 2615 FILE *stream = fopen ("puresize-adjust.h", "w"); |
2618 char *PURESIZE_h_file = "puresize_adjust.h"; | 2616 |
2619 char *WARNING = "/* This file is generated by XEmacs, DO NOT MODIFY!!! */\n"; | 2617 if (stream == NULL) |
2620 char define_PURESIZE[256]; | 2618 report_file_error ("Opening puresize adjustment file", |
2621 | 2619 Fcons (build_string ("puresize-adjust.h"), Qnil)); |
2622 if ((fd = open(PURESIZE_h_file, O_WRONLY|O_CREAT|O_TRUNC, 0666)) < 0) { | 2620 |
2623 report_file_error("Can't write PURESIZE_ADJUSTMENT", | 2621 fprintf (stream, |
2624 Fcons(build_ext_string(PURESIZE_h_file, FORMAT_FILENAME), | 2622 "/*\tDo not edit this file!\n" |
2625 Qnil)); | 2623 "\tAutomatically generated by XEmacs */\n" |
2626 } | 2624 "# define PURESIZE_ADJUSTMENT (%ld)\n", |
2627 | 2625 puresize - RAW_PURESIZE); |
2628 write(fd, WARNING, strlen(WARNING)); | 2626 fclose (stream); |
2629 sprintf(define_PURESIZE, "# define PURESIZE_ADJUSTMENT (%ld)\n", | |
2630 puresize - RAW_PURESIZE); | |
2631 write(fd, define_PURESIZE, strlen(define_PURESIZE)); | |
2632 close(fd); | |
2633 } | 2627 } |
2634 | 2628 |
2635 void | 2629 void |
2636 report_pure_usage (int report_impurities, | 2630 report_pure_usage (int report_impurities, |
2637 int die_if_pure_storage_exceeded) | 2631 int die_if_pure_storage_exceeded) |
2639 int rc = 0; | 2633 int rc = 0; |
2640 | 2634 |
2641 if (pure_lossage) | 2635 if (pure_lossage) |
2642 { | 2636 { |
2643 message ("\n****\tPure Lisp storage exhausted!\n" | 2637 message ("\n****\tPure Lisp storage exhausted!\n" |
2644 "\tPurespace usage: %ld of %ld\n" | 2638 "\tPurespace usage: %ld of %ld\n" |
2645 "****", | 2639 "****", |
2646 get_PURESIZE()+pure_lossage, (long) get_PURESIZE()); | 2640 get_PURESIZE()+pure_lossage, (long) get_PURESIZE()); |
2647 if (die_if_pure_storage_exceeded) { | 2641 if (die_if_pure_storage_exceeded) { |
2648 PURESIZE_h(get_PURESIZE() + pure_lossage); | 2642 puresize_adjust_h (get_PURESIZE() + pure_lossage); |
2649 rc = -1; | 2643 rc = -1; |
2650 } | 2644 } |
2651 } | 2645 } |
2652 else | 2646 else |
2653 { | 2647 { |
2658 pureptr, (long) get_PURESIZE(), | 2652 pureptr, (long) get_PURESIZE(), |
2659 (int) (pureptr / (get_PURESIZE() / 100.0) + 0.5)); | 2653 (int) (pureptr / (get_PURESIZE() / 100.0) + 0.5)); |
2660 if (lost > 2) { | 2654 if (lost > 2) { |
2661 sprintf (buf + strlen (buf), " -- %dk wasted", lost); | 2655 sprintf (buf + strlen (buf), " -- %dk wasted", lost); |
2662 if (die_if_pure_storage_exceeded) { | 2656 if (die_if_pure_storage_exceeded) { |
2663 PURESIZE_h(pureptr + 16); | 2657 puresize_adjust_h (pureptr + 16); |
2664 rc = -1; | 2658 rc = -1; |
2665 } | 2659 } |
2666 } | 2660 } |
2667 | 2661 |
2668 strcat (buf, ")."); | 2662 strcat (buf, ")."); |
2669 message ("%s", buf); | 2663 message ("%s", buf); |
2670 } | 2664 } |
2671 | 2665 |
2672 #ifdef PURESTAT | 2666 #ifdef PURESTAT |
2667 | |
2668 purestat_vector_other.nbytes = | |
2669 purestat_vector_all.nbytes - | |
2670 purestat_vector_bytecode_constants.nbytes; | |
2671 purestat_vector_other.nobjects = | |
2672 purestat_vector_all.nobjects - | |
2673 purestat_vector_bytecode_constants.nobjects; | |
2674 | |
2675 purestat_string_other.nbytes = | |
2676 purestat_string_all.nbytes - | |
2677 (purestat_string_pname.nbytes + | |
2678 purestat_string_bytecodes.nbytes + | |
2679 purestat_string_interactive.nbytes + | |
2680 purestat_string_documentation.nbytes + | |
2681 #ifdef I18N3 | |
2682 purestat_string_domain.nbytes + | |
2683 #endif | |
2684 purestat_string_other_function.nbytes); | |
2685 | |
2686 purestat_string_other.nobjects = | |
2687 purestat_string_all.nobjects - | |
2688 (purestat_string_pname.nobjects + | |
2689 purestat_string_bytecodes.nobjects + | |
2690 purestat_string_interactive.nobjects + | |
2691 purestat_string_documentation.nobjects + | |
2692 #ifdef I18N3 | |
2693 purestat_string_domain.nobjects + | |
2694 #endif | |
2695 purestat_string_other_function.nobjects); | |
2696 | |
2697 message (" %-26s Total Bytes", ""); | |
2698 | |
2673 { | 2699 { |
2674 int iii; | 2700 int j; |
2675 | 2701 |
2676 purestat_vector_other.nbytes = | 2702 for (j = 0; j < countof (purestats); j++) |
2677 purestat_vector_all.nbytes - purestat_vector_bytecode_constants.nbytes; | 2703 if (!purestats[j]) |
2678 purestat_vector_other.nobjects = | |
2679 purestat_vector_all.nobjects - | |
2680 purestat_vector_bytecode_constants.nobjects; | |
2681 | |
2682 purestat_string_other.nbytes = | |
2683 purestat_string_all.nbytes - (purestat_string_pname.nbytes + | |
2684 purestat_string_bytecodes.nbytes + | |
2685 purestat_string_interactive.nbytes + | |
2686 purestat_string_documentation.nbytes + | |
2687 #ifdef I18N3 | |
2688 purestat_string_domain.nbytes + | |
2689 #endif | |
2690 purestat_string_other_function.nbytes); | |
2691 purestat_string_other.nobjects = | |
2692 purestat_string_all.nobjects - (purestat_string_pname.nobjects + | |
2693 purestat_string_bytecodes.nobjects + | |
2694 purestat_string_interactive.nobjects + | |
2695 purestat_string_documentation.nobjects + | |
2696 #ifdef I18N3 | |
2697 purestat_string_domain.nobjects + | |
2698 #endif | |
2699 purestat_string_other_function.nobjects); | |
2700 | |
2701 message (" %-24stotal: bytes:", ""); | |
2702 | |
2703 for (iii = 0; iii < countof (purestats); iii++) | |
2704 if (!purestats[iii]) | |
2705 clear_message (); | 2704 clear_message (); |
2706 else | 2705 else |
2707 message (" %-24s%5d %7d %2d%%", | 2706 { |
2708 purestats[iii]->name, | 2707 char buf [100]; |
2709 purestats[iii]->nobjects, | 2708 sprintf(buf, "%s:", purestats[j]->name); |
2710 purestats[iii]->nbytes, | 2709 message (" %-26s %5d %7d %2d%%", |
2711 (int) (purestats[iii]->nbytes / (pureptr / 100.0) + 0.5)); | 2710 buf, |
2711 purestats[j]->nobjects, | |
2712 purestats[j]->nbytes, | |
2713 (int) (purestats[j]->nbytes / (pureptr / 100.0) + 0.5)); | |
2714 } | |
2712 } | 2715 } |
2713 #endif /* PURESTAT */ | 2716 #endif /* PURESTAT */ |
2714 | 2717 |
2715 | 2718 |
2716 if (report_impurities) | 2719 if (report_impurities) |
2730 char *s = buf; | 2733 char *s = buf; |
2731 memcpy (buf, string_data (XSYMBOL (Fcar (tem))->name), | 2734 memcpy (buf, string_data (XSYMBOL (Fcar (tem))->name), |
2732 string_length (XSYMBOL (Fcar (tem))->name) + 1); | 2735 string_length (XSYMBOL (Fcar (tem))->name) + 1); |
2733 while (*s++) if (*s == '-') *s = ' '; | 2736 while (*s++) if (*s == '-') *s = ' '; |
2734 s--; *s++ = ':'; *s = 0; | 2737 s--; *s++ = ':'; *s = 0; |
2735 message (" %-32s%6d", buf, total); | 2738 message (" %-33s %6d", buf, total); |
2736 } | 2739 } |
2737 tem = Fcdr (Fcdr (tem)); | 2740 tem = Fcdr (Fcdr (tem)); |
2738 } | 2741 } |
2739 else /* WTF?! */ | 2742 else /* WTF?! */ |
2740 { | 2743 { |
2746 garbage_collect_1 (); /* GC garbage_collect's garbage */ | 2749 garbage_collect_1 (); /* GC garbage_collect's garbage */ |
2747 } | 2750 } |
2748 clear_message (); | 2751 clear_message (); |
2749 | 2752 |
2750 if (rc < 0) { | 2753 if (rc < 0) { |
2751 (void)unlink("SATISFIED"); | 2754 unlink("SATISFIED"); |
2752 /* Current build process on NT does */ | 2755 /* Current build process on NT does */ |
2753 /* not know how to restart itself. */ | 2756 /* not know how to restart itself. */ |
2754 /* --marcpa */ | 2757 /* --marcpa */ |
2755 #ifndef WINDOWSNT | 2758 #ifndef WINDOWSNT |
2756 fatal ("Pure size adjusted, Don't Panic! I will restart the `make'"); | 2759 fatal ("Pure size adjusted, Don't Panic! I will restart the `make'"); |
2757 #endif | 2760 #endif |
2758 } else if (pure_lossage && die_if_pure_storage_exceeded) { | 2761 } else if (pure_lossage && die_if_pure_storage_exceeded) { |
2759 fatal ("Pure storage exhausted"); | 2762 fatal ("Pure storage exhausted"); |
2786 } | 2789 } |
2787 | 2790 |
2788 | 2791 |
2789 /* Mark reference to a Lisp_Object. If the object referred to has not been | 2792 /* Mark reference to a Lisp_Object. If the object referred to has not been |
2790 seen yet, recursively mark all the references contained in it. */ | 2793 seen yet, recursively mark all the references contained in it. */ |
2791 | 2794 |
2792 static void | 2795 static void |
2793 mark_object (Lisp_Object obj) | 2796 mark_object (Lisp_Object obj) |
2794 { | 2797 { |
2795 tail_recurse: | 2798 tail_recurse: |
2796 | 2799 |
2938 mark_object (rest); | 2941 mark_object (rest); |
2939 } | 2942 } |
2940 | 2943 |
2941 | 2944 |
2942 #ifdef PURESTAT | 2945 #ifdef PURESTAT |
2943 /* Simpler than mark-object, because pure structure can't | 2946 /* Simpler than mark-object, because pure structure can't |
2944 have any circularities | 2947 have any circularities */ |
2945 */ | |
2946 | 2948 |
2947 #if 0 /* unused */ | 2949 #if 0 /* unused */ |
2948 static int idiot_c_doesnt_have_closures; | 2950 static int idiot_c_doesnt_have_closures; |
2949 static void | 2951 static void |
2950 idiot_c (Lisp_Object obj) | 2952 idiot_c (Lisp_Object obj) |
2976 int size = string_length (ptr); | 2978 int size = string_length (ptr); |
2977 | 2979 |
2978 if (string_data (ptr) != | 2980 if (string_data (ptr) != |
2979 (unsigned char *) ptr + sizeof (struct Lisp_String)) | 2981 (unsigned char *) ptr + sizeof (struct Lisp_String)) |
2980 { | 2982 { |
2981 /* string-data not allocated contiguously. | 2983 /* string-data not allocated contiguously. |
2982 Probably (better be!!) a pointer constant "C" data. */ | 2984 Probably (better be!!) a pointer constant "C" data. */ |
2983 size = sizeof (struct Lisp_String); | 2985 size = sizeof (struct Lisp_String); |
2984 } | 2986 } |
2985 else | 2987 else |
2986 { | 2988 { |
2999 total += (sizeof (struct Lisp_Vector) | 3001 total += (sizeof (struct Lisp_Vector) |
3000 + (len - 1) * sizeof (Lisp_Object)); | 3002 + (len - 1) * sizeof (Lisp_Object)); |
3001 #if 0 /* unused */ | 3003 #if 0 /* unused */ |
3002 if (!recurse) | 3004 if (!recurse) |
3003 break; | 3005 break; |
3004 { | 3006 { |
3005 int i; | 3007 int i; |
3006 for (i = 0; i < len - 1; i++) | 3008 for (i = 0; i < len - 1; i++) |
3007 total += pure_sizeof (ptr->contents[i], 1); | 3009 total += pure_sizeof (ptr->contents[i], 1); |
3008 } | 3010 } |
3009 if (len > 0) | 3011 if (len > 0) |
3036 | 3038 |
3037 idiot_c_doesnt_have_closures = 0; | 3039 idiot_c_doesnt_have_closures = 0; |
3038 obj = ((implementation->marker) (obj, idiot_c)); | 3040 obj = ((implementation->marker) (obj, idiot_c)); |
3039 total += idiot_c_doesnt_have_closures; | 3041 total += idiot_c_doesnt_have_closures; |
3040 idiot_c_doesnt_have_closures = old; | 3042 idiot_c_doesnt_have_closures = old; |
3041 | 3043 |
3042 if (!NILP (obj)) goto tail_recurse; | 3044 if (!NILP (obj)) goto tail_recurse; |
3043 } | 3045 } |
3044 #endif /* unused */ | 3046 #endif /* unused */ |
3045 } | 3047 } |
3046 break; | 3048 break; |
3227 *used = num_used; | 3229 *used = num_used; |
3228 /* *total = total_size; */ | 3230 /* *total = total_size; */ |
3229 } | 3231 } |
3230 | 3232 |
3231 static void | 3233 static void |
3232 sweep_vectors_1 (Lisp_Object *prev, | 3234 sweep_vectors_1 (Lisp_Object *prev, |
3233 int *used, int *total, int *storage) | 3235 int *used, int *total, int *storage) |
3234 { | 3236 { |
3235 Lisp_Object vector; | 3237 Lisp_Object vector; |
3236 int num_used = 0; | 3238 int num_used = 0; |
3237 int total_size = 0; | 3239 int total_size = 0; |
3265 *total = total_size; | 3267 *total = total_size; |
3266 *storage = total_storage; | 3268 *storage = total_storage; |
3267 } | 3269 } |
3268 | 3270 |
3269 static void | 3271 static void |
3270 sweep_bit_vectors_1 (Lisp_Object *prev, | 3272 sweep_bit_vectors_1 (Lisp_Object *prev, |
3271 int *used, int *total, int *storage) | 3273 int *used, int *total, int *storage) |
3272 { | 3274 { |
3273 Lisp_Object bit_vector; | 3275 Lisp_Object bit_vector; |
3274 int num_used = 0; | 3276 int num_used = 0; |
3275 int total_size = 0; | 3277 int total_size = 0; |
3352 \ | 3354 \ |
3353 gc_count_num_##typename##_in_use = num_used; \ | 3355 gc_count_num_##typename##_in_use = num_used; \ |
3354 gc_count_num_##typename##_freelist = num_free; \ | 3356 gc_count_num_##typename##_freelist = num_free; \ |
3355 } while (0) | 3357 } while (0) |
3356 | 3358 |
3357 #else | 3359 #else /* !ERROR_CHECK_GC */ |
3358 | 3360 |
3359 #define SWEEP_FIXED_TYPE_BLOCK(typename, obj_type) \ | 3361 #define SWEEP_FIXED_TYPE_BLOCK(typename, obj_type) \ |
3360 do { \ | 3362 do { \ |
3361 struct typename##_block *_frob_current; \ | 3363 struct typename##_block *_frob_current; \ |
3362 struct typename##_block **_frob_prev; \ | 3364 struct typename##_block **_frob_prev; \ |
3427 \ | 3429 \ |
3428 gc_count_num_##typename##_in_use = num_used; \ | 3430 gc_count_num_##typename##_in_use = num_used; \ |
3429 gc_count_num_##typename##_freelist = num_free; \ | 3431 gc_count_num_##typename##_freelist = num_free; \ |
3430 } while (0) | 3432 } while (0) |
3431 | 3433 |
3432 #endif | 3434 #endif /* !ERROR_CHECK_GC */ |
3433 | 3435 |
3434 | 3436 |
3435 | 3437 |
3436 | 3438 |
3437 static void | 3439 static void |
3455 a chain pointer to the next cons on the list, which has cleverly | 3457 a chain pointer to the next cons on the list, which has cleverly |
3456 had all its 0's and 1's inverted. This allows for a quick | 3458 had all its 0's and 1's inverted. This allows for a quick |
3457 check to make sure we're not freeing something already freed. */ | 3459 check to make sure we're not freeing something already freed. */ |
3458 if (POINTER_TYPE_P (XTYPE (ptr->car))) | 3460 if (POINTER_TYPE_P (XTYPE (ptr->car))) |
3459 ASSERT_VALID_POINTER (XPNTR (ptr->car)); | 3461 ASSERT_VALID_POINTER (XPNTR (ptr->car)); |
3460 #endif | 3462 #endif /* ERROR_CHECK_GC */ |
3463 | |
3461 #ifndef ALLOC_NO_POOLS | 3464 #ifndef ALLOC_NO_POOLS |
3462 FREE_FIXED_TYPE_WHEN_NOT_IN_GC (cons, struct Lisp_Cons, ptr); | 3465 FREE_FIXED_TYPE_WHEN_NOT_IN_GC (cons, struct Lisp_Cons, ptr); |
3463 #endif /* ALLOC_NO_POOLS */ | 3466 #endif /* ALLOC_NO_POOLS */ |
3464 } | 3467 } |
3465 | 3468 |
3581 #ifdef ERROR_CHECK_GC | 3584 #ifdef ERROR_CHECK_GC |
3582 /* Perhaps this will catch freeing an already-freed marker. */ | 3585 /* Perhaps this will catch freeing an already-freed marker. */ |
3583 Lisp_Object temmy; | 3586 Lisp_Object temmy; |
3584 XSETMARKER (temmy, ptr); | 3587 XSETMARKER (temmy, ptr); |
3585 assert (GC_MARKERP (temmy)); | 3588 assert (GC_MARKERP (temmy)); |
3586 #endif | 3589 #endif /* ERROR_CHECK_GC */ |
3590 | |
3587 #ifndef ALLOC_NO_POOLS | 3591 #ifndef ALLOC_NO_POOLS |
3588 FREE_FIXED_TYPE_WHEN_NOT_IN_GC (marker, struct Lisp_Marker, ptr); | 3592 FREE_FIXED_TYPE_WHEN_NOT_IN_GC (marker, struct Lisp_Marker, ptr); |
3589 #endif /* ALLOC_NO_POOLS */ | 3593 #endif /* ALLOC_NO_POOLS */ |
3590 } | 3594 } |
3591 | 3595 |
3605 { | 3609 { |
3606 int pos = 0; | 3610 int pos = 0; |
3607 /* POS is the index of the next string in the block. */ | 3611 /* POS is the index of the next string in the block. */ |
3608 while (pos < sb->pos) | 3612 while (pos < sb->pos) |
3609 { | 3613 { |
3610 struct string_chars *s_chars = | 3614 struct string_chars *s_chars = |
3611 (struct string_chars *) &(sb->string_chars[pos]); | 3615 (struct string_chars *) &(sb->string_chars[pos]); |
3612 struct Lisp_String *string; | 3616 struct Lisp_String *string; |
3613 int size; | 3617 int size; |
3614 int fullsize; | 3618 int fullsize; |
3615 | 3619 |
3655 { | 3659 { |
3656 int from_pos = 0; | 3660 int from_pos = 0; |
3657 /* FROM_POS is the index of the next string in the block. */ | 3661 /* FROM_POS is the index of the next string in the block. */ |
3658 while (from_pos < from_sb->pos) | 3662 while (from_pos < from_sb->pos) |
3659 { | 3663 { |
3660 struct string_chars *from_s_chars = | 3664 struct string_chars *from_s_chars = |
3661 (struct string_chars *) &(from_sb->string_chars[from_pos]); | 3665 (struct string_chars *) &(from_sb->string_chars[from_pos]); |
3662 struct string_chars *to_s_chars; | 3666 struct string_chars *to_s_chars; |
3663 struct Lisp_String *string; | 3667 struct Lisp_String *string; |
3664 int size; | 3668 int size; |
3665 int fullsize; | 3669 int fullsize; |
3704 { | 3708 { |
3705 to_sb->pos = to_pos; | 3709 to_sb->pos = to_pos; |
3706 to_sb = to_sb->next; | 3710 to_sb = to_sb->next; |
3707 to_pos = 0; | 3711 to_pos = 0; |
3708 } | 3712 } |
3709 | 3713 |
3710 /* Compute new address of this string | 3714 /* Compute new address of this string |
3711 and update TO_POS for the space being used. */ | 3715 and update TO_POS for the space being used. */ |
3712 to_s_chars = (struct string_chars *) &(to_sb->string_chars[to_pos]); | 3716 to_s_chars = (struct string_chars *) &(to_sb->string_chars[to_pos]); |
3713 | 3717 |
3714 /* Copy the string_chars to the new place. */ | 3718 /* Copy the string_chars to the new place. */ |
3715 if (from_s_chars != to_s_chars) | 3719 if (from_s_chars != to_s_chars) |
3716 memmove (to_s_chars, from_s_chars, fullsize); | 3720 memmove (to_s_chars, from_s_chars, fullsize); |
3717 | 3721 |
3718 /* Relocate FROM_S_CHARS's reference */ | 3722 /* Relocate FROM_S_CHARS's reference */ |
3719 set_string_data (string, &(to_s_chars->chars[0])); | 3723 set_string_data (string, &(to_s_chars->chars[0])); |
3720 | 3724 |
3721 from_pos += fullsize; | 3725 from_pos += fullsize; |
3722 to_pos += fullsize; | 3726 to_pos += fullsize; |
3723 } | 3727 } |
3724 } | 3728 } |
3725 | 3729 |
3726 /* Set current to the last string chars block still used and | 3730 /* Set current to the last string chars block still used and |
3727 free any that follow. */ | 3731 free any that follow. */ |
3728 { | 3732 { |
3729 struct string_chars_block *victim; | 3733 struct string_chars_block *victim; |
3730 | 3734 |
3731 for (victim = to_sb->next; victim; ) | 3735 for (victim = to_sb->next; victim; ) |
3760 else | 3764 else |
3761 stderr_out ("%c", ch); | 3765 stderr_out ("%c", ch); |
3762 } | 3766 } |
3763 stderr_out ("\"\n"); | 3767 stderr_out ("\"\n"); |
3764 } | 3768 } |
3765 #endif | 3769 #endif /* 1 */ |
3766 | 3770 |
3767 | 3771 |
3768 static void | 3772 static void |
3769 sweep_strings (void) | 3773 sweep_strings (void) |
3770 { | 3774 { |
4169 char *msg = (STRINGP (Vgc_message) | 4173 char *msg = (STRINGP (Vgc_message) |
4170 ? GETTEXT ((char *) XSTRING_DATA (Vgc_message)) | 4174 ? GETTEXT ((char *) XSTRING_DATA (Vgc_message)) |
4171 : 0); | 4175 : 0); |
4172 | 4176 |
4173 /* Show "...done" only if the echo area would otherwise be empty. */ | 4177 /* Show "...done" only if the echo area would otherwise be empty. */ |
4174 if (NILP (clear_echo_area (selected_frame (), | 4178 if (NILP (clear_echo_area (selected_frame (), |
4175 Qgarbage_collecting, 0))) | 4179 Qgarbage_collecting, 0))) |
4176 { | 4180 { |
4177 Lisp_Object args[2], whole_msg; | 4181 Lisp_Object args[2], whole_msg; |
4178 args[0] = build_string (msg ? msg : | 4182 args[0] = build_string (msg ? msg : |
4179 GETTEXT ((CONST char *) | 4183 GETTEXT ((CONST char *) |
4204 of the garbage collector by noting that PC is between &garbage_collect_1 | 4208 of the garbage collector by noting that PC is between &garbage_collect_1 |
4205 and &BTL_after_garbage_collect_1_stub. So this fn must be right here. | 4209 and &BTL_after_garbage_collect_1_stub. So this fn must be right here. |
4206 There's not any other way to know the address of the end of a function. | 4210 There's not any other way to know the address of the end of a function. |
4207 */ | 4211 */ |
4208 void BTL_after_garbage_collect_1_stub () { abort (); } | 4212 void BTL_after_garbage_collect_1_stub () { abort (); } |
4209 #endif | 4213 #endif /* EMACS_BTL */ |
4210 | 4214 |
4211 /* Debugging aids. */ | 4215 /* Debugging aids. */ |
4212 | 4216 |
4213 static Lisp_Object | 4217 static Lisp_Object |
4214 gc_plist_hack (CONST char *name, int value, Lisp_Object tail) | 4218 gc_plist_hack (CONST char *name, int value, Lisp_Object tail) |
4230 DEFUN ("garbage-collect", Fgarbage_collect, 0, 0, "", /* | 4234 DEFUN ("garbage-collect", Fgarbage_collect, 0, 0, "", /* |
4231 Reclaim storage for Lisp objects no longer needed. | 4235 Reclaim storage for Lisp objects no longer needed. |
4232 Returns info on amount of space in use: | 4236 Returns info on amount of space in use: |
4233 ((USED-CONSES . FREE-CONSES) (USED-SYMS . FREE-SYMS) | 4237 ((USED-CONSES . FREE-CONSES) (USED-SYMS . FREE-SYMS) |
4234 (USED-MARKERS . FREE-MARKERS) USED-STRING-CHARS USED-VECTOR-SLOTS | 4238 (USED-MARKERS . FREE-MARKERS) USED-STRING-CHARS USED-VECTOR-SLOTS |
4235 PLIST) | 4239 PLIST) |
4236 where `PLIST' is a list of alternating keyword/value pairs providing | 4240 where `PLIST' is a list of alternating keyword/value pairs providing |
4237 more detailed information. | 4241 more detailed information. |
4238 Garbage collection happens automatically if you cons more than | 4242 Garbage collection happens automatically if you cons more than |
4239 `gc-cons-threshold' bytes of Lisp data since previous garbage collection. | 4243 `gc-cons-threshold' bytes of Lisp data since previous garbage collection. |
4240 */ | 4244 */ |
4251 | 4255 |
4252 garbage_collect_1 (); | 4256 garbage_collect_1 (); |
4253 | 4257 |
4254 for (i = 0; i < last_lrecord_type_index_assigned; i++) | 4258 for (i = 0; i < last_lrecord_type_index_assigned; i++) |
4255 { | 4259 { |
4256 if (lcrecord_stats[i].bytes_in_use != 0 | 4260 if (lcrecord_stats[i].bytes_in_use != 0 |
4257 || lcrecord_stats[i].bytes_freed != 0 | 4261 || lcrecord_stats[i].bytes_freed != 0 |
4258 || lcrecord_stats[i].instances_on_free_list != 0) | 4262 || lcrecord_stats[i].instances_on_free_list != 0) |
4259 { | 4263 { |
4260 char buf [255]; | 4264 char buf [255]; |
4261 CONST char *name = lrecord_implementations_table[i]->name; | 4265 CONST char *name = lrecord_implementations_table[i]->name; |
4297 HACK_O_MATIC (float, "float-storage", pl); | 4301 HACK_O_MATIC (float, "float-storage", pl); |
4298 pl = gc_plist_hack ("floats-free", gc_count_num_float_freelist, pl); | 4302 pl = gc_plist_hack ("floats-free", gc_count_num_float_freelist, pl); |
4299 pl = gc_plist_hack ("floats-used", gc_count_num_float_in_use, pl); | 4303 pl = gc_plist_hack ("floats-used", gc_count_num_float_in_use, pl); |
4300 #endif /* LISP_FLOAT_TYPE */ | 4304 #endif /* LISP_FLOAT_TYPE */ |
4301 HACK_O_MATIC (string, "string-header-storage", pl); | 4305 HACK_O_MATIC (string, "string-header-storage", pl); |
4302 pl = gc_plist_hack ("long-strings-total-length", | 4306 pl = gc_plist_hack ("long-strings-total-length", |
4303 gc_count_string_total_size | 4307 gc_count_string_total_size |
4304 - gc_count_short_string_total_size, pl); | 4308 - gc_count_short_string_total_size, pl); |
4305 HACK_O_MATIC (string_chars, "short-string-storage", pl); | 4309 HACK_O_MATIC (string_chars, "short-string-storage", pl); |
4306 pl = gc_plist_hack ("short-strings-total-length", | 4310 pl = gc_plist_hack ("short-strings-total-length", |
4307 gc_count_short_string_total_size, pl); | 4311 gc_count_short_string_total_size, pl); |
4308 pl = gc_plist_hack ("strings-free", gc_count_num_string_freelist, pl); | 4312 pl = gc_plist_hack ("strings-free", gc_count_num_string_freelist, pl); |
4309 pl = gc_plist_hack ("long-strings-used", | 4313 pl = gc_plist_hack ("long-strings-used", |
4310 gc_count_num_string_in_use | 4314 gc_count_num_string_in_use |
4311 - gc_count_num_short_string_in_use, pl); | 4315 - gc_count_num_short_string_in_use, pl); |
4312 pl = gc_plist_hack ("short-strings-used", | 4316 pl = gc_plist_hack ("short-strings-used", |
4313 gc_count_num_short_string_in_use, pl); | 4317 gc_count_num_short_string_in_use, pl); |
4314 | 4318 |
4315 HACK_O_MATIC (compiled_function, "compiled-function-storage", pl); | 4319 HACK_O_MATIC (compiled_function, "compiled-function-storage", pl); |
4316 pl = gc_plist_hack ("compiled-functions-free", | 4320 pl = gc_plist_hack ("compiled-functions-free", |
4317 gc_count_num_compiled_function_freelist, pl); | 4321 gc_count_num_compiled_function_freelist, pl); |
4318 pl = gc_plist_hack ("compiled-functions-used", | 4322 pl = gc_plist_hack ("compiled-functions-used", |
4319 gc_count_num_compiled_function_in_use, pl); | 4323 gc_count_num_compiled_function_in_use, pl); |
4320 | 4324 |
4321 pl = gc_plist_hack ("vector-storage", gc_count_vector_storage, pl); | 4325 pl = gc_plist_hack ("vector-storage", gc_count_vector_storage, pl); |
4322 pl = gc_plist_hack ("vectors-total-length", | 4326 pl = gc_plist_hack ("vectors-total-length", |
4323 gc_count_vector_total_size, pl); | 4327 gc_count_vector_total_size, pl); |
4324 pl = gc_plist_hack ("vectors-used", gc_count_num_vector_used, pl); | 4328 pl = gc_plist_hack ("vectors-used", gc_count_num_vector_used, pl); |
4325 | 4329 |
4326 pl = gc_plist_hack ("bit-vector-storage", gc_count_bit_vector_storage, pl); | 4330 pl = gc_plist_hack ("bit-vector-storage", gc_count_bit_vector_storage, pl); |
4327 pl = gc_plist_hack ("bit-vectors-total-length", | 4331 pl = gc_plist_hack ("bit-vectors-total-length", |
4328 gc_count_bit_vector_total_size, pl); | 4332 gc_count_bit_vector_total_size, pl); |
4329 pl = gc_plist_hack ("bit-vectors-used", gc_count_num_bit_vector_used, pl); | 4333 pl = gc_plist_hack ("bit-vectors-used", gc_count_num_bit_vector_used, pl); |
4330 | 4334 |
4331 HACK_O_MATIC (symbol, "symbol-storage", pl); | 4335 HACK_O_MATIC (symbol, "symbol-storage", pl); |
4332 pl = gc_plist_hack ("symbols-free", gc_count_num_symbol_freelist, pl); | 4336 pl = gc_plist_hack ("symbols-free", gc_count_num_symbol_freelist, pl); |
4359 */ | 4363 */ |
4360 ()) | 4364 ()) |
4361 { | 4365 { |
4362 return make_int (consing_since_gc); | 4366 return make_int (consing_since_gc); |
4363 } | 4367 } |
4364 | 4368 |
4365 DEFUN ("memory-limit", Fmemory_limit, 0, 0, "", /* | 4369 DEFUN ("memory-limit", Fmemory_limit, 0, 0, "", /* |
4366 Return the address of the last byte Emacs has allocated, divided by 1024. | 4370 Return the address of the last byte Emacs has allocated, divided by 1024. |
4367 This may be helpful in debugging Emacs's memory usage. | 4371 This may be helpful in debugging Emacs's memory usage. |
4368 The value is divided by 1024 to make sure it will fit in a lisp integer. | 4372 The value is divided by 1024 to make sure it will fit in a lisp integer. |
4369 */ | 4373 */ |
4382 (WINDOWP (obj) && !WINDOW_LIVE_P (XWINDOW (obj))) || | 4386 (WINDOWP (obj) && !WINDOW_LIVE_P (XWINDOW (obj))) || |
4383 (DEVICEP (obj) && !DEVICE_LIVE_P (XDEVICE (obj))) || | 4387 (DEVICEP (obj) && !DEVICE_LIVE_P (XDEVICE (obj))) || |
4384 (CONSOLEP (obj) && !CONSOLE_LIVE_P (XCONSOLE (obj))) || | 4388 (CONSOLEP (obj) && !CONSOLE_LIVE_P (XCONSOLE (obj))) || |
4385 (EVENTP (obj) && !EVENT_LIVE_P (XEVENT (obj))) || | 4389 (EVENTP (obj) && !EVENT_LIVE_P (XEVENT (obj))) || |
4386 (EXTENTP (obj) && !EXTENT_LIVE_P (XEXTENT (obj)))); | 4390 (EXTENTP (obj) && !EXTENT_LIVE_P (XEXTENT (obj)))); |
4387 | 4391 |
4388 } | 4392 } |
4389 | 4393 |
4390 #ifdef MEMORY_USAGE_STATS | 4394 #ifdef MEMORY_USAGE_STATS |
4391 | 4395 |
4392 /* Attempt to determine the actual amount of space that is used for | 4396 /* Attempt to determine the actual amount of space that is used for |
4537 if (! purestats[iii]) continue; | 4541 if (! purestats[iii]) continue; |
4538 purestats[iii]->nobjects = 0; | 4542 purestats[iii]->nobjects = 0; |
4539 purestats[iii]->nbytes = 0; | 4543 purestats[iii]->nbytes = 0; |
4540 } | 4544 } |
4541 purecopying_for_bytecode = 0; | 4545 purecopying_for_bytecode = 0; |
4542 #endif | 4546 #endif /* PURESTAT */ |
4543 | 4547 |
4544 last_lrecord_type_index_assigned = -1; | 4548 last_lrecord_type_index_assigned = -1; |
4545 for (iii = 0; iii < countof (lrecord_implementations_table); iii++) | 4549 for (iii = 0; iii < countof (lrecord_implementations_table); iii++) |
4546 { | 4550 { |
4547 lrecord_implementations_table[iii] = 0; | 4551 lrecord_implementations_table[iii] = 0; |
4548 } | 4552 } |
4549 | 4553 |
4550 symbols_initialized = 0; | 4554 symbols_initialized = 0; |
4551 | 4555 |
4552 gc_generation_number[0] = 0; | 4556 gc_generation_number[0] = 0; |
4553 /* purify_flag 1 is correct even if CANNOT_DUMP. | 4557 /* purify_flag 1 is correct even if CANNOT_DUMP. |
4554 * loadup.el will set to nil at end. */ | 4558 * loadup.el will set to nil at end. */ |
4555 purify_flag = 1; | 4559 purify_flag = 1; |
4556 pureptr = 0; | 4560 pureptr = 0; |
4599 ERROR_ME_NOT. | 4603 ERROR_ME_NOT. |
4600 really_unlikely_name_to_have_accidentally_in_a_non_errb_structure = 42; | 4604 really_unlikely_name_to_have_accidentally_in_a_non_errb_structure = 42; |
4601 ERROR_ME_WARN. | 4605 ERROR_ME_WARN. |
4602 really_unlikely_name_to_have_accidentally_in_a_non_errb_structure = | 4606 really_unlikely_name_to_have_accidentally_in_a_non_errb_structure = |
4603 3333632; | 4607 3333632; |
4604 #endif | 4608 #endif /* ERROR_CHECK_TYPECHECK */ |
4605 } | 4609 } |
4606 | 4610 |
4607 void | 4611 void |
4608 reinit_alloc (void) | 4612 reinit_alloc (void) |
4609 { | 4613 { |