Skip to content
This repository
Browse code

gc4.14 tarball import

  • Loading branch information...
commit c63ec8250de446bca83601966c918d37ad120a83 1 parent e9faf69
Ivan Maidanski authored
15 Makefile
@@ -254,6 +254,19 @@ liblinuxgc.so: $(OBJS) dyn_load.o
254 254 gcc -shared -o liblinuxgc.so $(OBJS) dyn_load.o -lo
255 255 ln liblinuxgc.so libgc.so
256 256
  257 +# Alternative Linux rule. This is preferable, but is likely to break the
  258 +# Makefile for some non-linux platforms.
  259 +# LIBOBJS= $(patsubst %.o, %.lo, $(OBJS))
  260 +#
  261 +#.SUFFIXES: .lo $(SUFFIXES)
  262 +#
  263 +#.c.lo:
  264 +# $(CC) $(CFLAGS) $(CPPFLAGS) -fPIC -c $< -o $@
  265 +#
  266 +# liblinuxgc.so: $(LIBOBJS) dyn_load.lo
  267 +# gcc -shared -Wl,-soname=libgc.so.0 -o libgc.so.0 $(LIBOBJS) dyn_load.lo
  268 +# touch liblinuxgc.so
  269 +
257 270 mach_dep.o: $(srcdir)/mach_dep.c $(srcdir)/mips_sgi_mach_dep.s $(srcdir)/mips_ultrix_mach_dep.s $(srcdir)/rs6000_mach_dep.s $(UTILS)
258 271 rm -f mach_dep.o
259 272 ./if_mach MIPS IRIX5 $(AS) -o mach_dep.o $(srcdir)/mips_sgi_mach_dep.s
@@ -369,7 +382,7 @@ gc.tar.gz: gc.tar
369 382 gzip gc.tar
370 383
371 384 lint: $(CSRCS) test.c
372   - lint -DLINT $(CSRCS) test.c | egrep -v "possible pointer alignment problem|abort|exit|sbrk|mprotect|syscall"
  385 + lint -DLINT $(CSRCS) test.c | egrep -v "possible pointer alignment problem|abort|exit|sbrk|mprotect|syscall|change in ANSI|improper alignment"
373 386
374 387 # BTL: added to test shared library version of collector.
375 388 # Currently works only under SunOS5. Requires GC_INIT call from statically
37 README
@@ -11,7 +11,7 @@ Permission to modify the code and to distribute modified code is granted,
11 11 provided the above notices are retained, and a notice that the code was
12 12 modified is included with the above copyright notice.
13 13
14   -This is version 4.14alpha1 of a conservative garbage collector for C and C++.
  14 +This is version 4.14 of a conservative garbage collector for C and C++.
15 15
16 16 You might find a more recent version of this at
17 17
@@ -22,7 +22,14 @@ HISTORY -
22 22 Early versions of this collector were developed as a part of research
23 23 projects supported in part by the National Science Foundation
24 24 and the Defense Advance Research Projects Agency.
25   -Much of the code was rewritten by Hans-J. Boehm at Xerox PARC.
  25 +Much of the code was rewritten by Hans-J. Boehm at Xerox PARC
  26 +and is now maintained by him at SGI (boehm@sgi.com).
  27 +
  28 +Some other contributors:
  29 +
  30 +More recent contributors are mentioned in the modification history at the
  31 +end of this file. My apologies for any omissions.
  32 +
26 33 The SPARC specific code was contributed by Mark Weiser
27 34 (weiser@parc.xerox.com). The Encore Multimax modifications were supplied by
28 35 Kevin Kenny (kenny@m.cs.uiuc.edu). The adaptation to the RT is largely due
@@ -59,8 +66,7 @@ made it into the released version of the collector, yet.)
59 66 (Blame for misinstallation of these modifications goes to the first author,
60 67 however.)
61 68
62   -Credits for some more recent modifications are given in the modification
63   -history at the end of this file.
  69 +OVERVIEW
64 70
65 71 This is intended to be a general purpose, garbage collecting storage
66 72 allocator. The algorithms used are described in:
@@ -89,7 +95,7 @@ of the ACM SIGPLAN '96 Conference on Programming Language Design and
89 95 Implementation.
90 96
91 97 (Both are also available from
92   -http://reality.sgi.com/employees/boehm_mti/papers/, among other places.)
  98 +http://reality.sgi.com/boehm/papers/, among other places.)
93 99
94 100 Unlike the collector described in the second reference, this collector
95 101 operates either with the mutator stopped during the entire collection
@@ -606,7 +612,7 @@ reclaimed. Exclusive-or'ing forward and backward links in a list
606 612 doesn't cut it.
607 613 Some C optimizers may lose the last undisguised pointer to a memory
608 614 object as a consequence of clever optimizations. This has almost
609   -never been observed in practice. Send mail to boehm@mti.sgi.com
  615 +never been observed in practice. Send mail to boehm@sgi.com
610 616 for suggestions on how to fix your compiler.
611 617 This is not a real-time collector. In the standard configuration,
612 618 percentage of time required for collection should be constant across
@@ -615,7 +621,7 @@ heap sizes. But collection pauses will increase for larger heaps.
615 621 per MB of accessible memory that needs to be scanned. Your mileage
616 622 may vary.) The incremental/generational collection facility helps,
617 623 but is portable only if "stubborn" allocation is used.
618   - Please address bug reports to boehm@mti.sgi.com. If you are
  624 + Please address bug reports to boehm@sgi.com. If you are
619 625 contemplating a major addition, you might also send mail to ask whether
620 626 it's already been done (or whether we tried and discarded it).
621 627
@@ -1424,14 +1430,27 @@ Since 4.13:
1424 1430 after the relevant frame was overwritten, and the new save location
1425 1431 might be outside the scanned area. Fixed by more eager stack scanning.)
1426 1432 - PRINT_BLACK_LIST had some problems. A few source addresses were garbage.
1427   - - Removed a prototype in code that shouldn't assume prototype support.
1428 1433 - Replaced Makefile.dj and added -I flags to cord make targets.
1429 1434 (Thanks to Gary Leavens.)
1430 1435 - GC_try_to_collect was broken with the nonincremental collector.
1431 1436 - gc_cleanup destructors could pass the wrong address to
1432 1437 GC_register_finalizer_ignore_self in the presence of multiple
1433 1438 inheritance. (Thanks to Darrell Schiebel.)
1434   -
  1439 + - Changed PowerPC Linux stack finding code.
  1440 +
  1441 +Since 4.14alpha1
  1442 + - -DSMALL_CONFIG did not work reliably with large (> 4K) pages.
  1443 + Recycling the mark stack during expansion could result in a size
  1444 + zero heap segment, which confused things. (This was probably also an
  1445 + issue with the normal config and huge pages.)
  1446 + - Did more work to make sure that callee-save registers were scanned
  1447 + completely, even with the setjmp-based code. Added USE_GENERIC_PUSH_REGS
  1448 + macro to facilitate testing on machines I have access to.
  1449 + - Added code to explicitly push register contents for win32 threads.
  1450 + This seems to be necessary. (Thanks to Pierre de Rop.)
  1451 +
  1452 +Since 4.14alpha2
  1453 + - changed STACKBOTTOM for DJGPP (Thanks to Salvador Eduardo Tropea).
1435 1454
1436 1455 To do:
1437 1456 - Very large root set sizes (> 16 MB or so) could cause the collector
3  allchblk.c
@@ -164,7 +164,8 @@ unsigned char flags; /* IGNORE_OFF_PAGE or 0 */
164 164 if (size_avail != size_needed
165 165 && !GC_incremental
166 166 && (word)size_needed <= GC_max_hblk_size/2
167   - && GC_in_last_heap_sect(hbp) && GC_should_collect()) {
  167 + && GC_in_last_heap_sect((ptr_t)hbp)
  168 + && GC_should_collect()) {
168 169 continue;
169 170 }
170 171 # endif
5 alloc.c
@@ -344,7 +344,7 @@ int n;
344 344
345 345 if (GC_incremental && GC_collection_in_progress()) {
346 346 for (i = GC_deficit; i < GC_RATE*n; i++) {
347   - if (GC_mark_some()) {
  347 + if (GC_mark_some((ptr_t)0)) {
348 348 /* Need to finish a collection */
349 349 # ifdef SAVE_CALL_CHAIN
350 350 GC_save_callers(GC_last_stack);
@@ -393,6 +393,7 @@ GC_bool GC_stopped_mark(stop_func)
393 393 GC_stop_func stop_func;
394 394 {
395 395 register int i;
  396 + int dummy;
396 397 # ifdef PRINTSTATS
397 398 CLOCK_TYPE start_time, current_time;
398 399 # endif
@@ -423,7 +424,7 @@ GC_stop_func stop_func;
423 424 START_WORLD();
424 425 return(FALSE);
425 426 }
426   - if (GC_mark_some()) break;
  427 + if (GC_mark_some((ptr_t)(&dummy))) break;
427 428 }
428 429
429 430 GC_gc_no++;
1  cord/de.c
@@ -565,7 +565,6 @@ int argc;
565 565 char ** argv;
566 566 {
567 567 int c;
568   - CORD initial;
569 568
570 569 #if defined(MACINTOSH)
571 570 console_options.title = "\pDumb Editor";
1  cord/gc.h
@@ -268,6 +268,7 @@ GC_API void GC_gcollect GC_PROTO((void));
268 268 /* than normal pause times for incremental collection. However, */
269 269 /* aborted collections do no useful work; the next collection needs */
270 270 /* to start from the beginning. */
  271 +/* Return 0 if the collection was aborted, 1 if it succeeded. */
271 272 typedef int (* GC_stop_func) GC_PROTO((void));
272 273 GC_API int GC_try_to_collect GC_PROTO((GC_stop_func stop_func));
273 274
4 dbg_mlc.c
@@ -139,7 +139,7 @@ ptr_t p;
139 139 {
140 140 register oh * ohdr = (oh *)GC_base(p);
141 141
142   - GC_err_printf1("0x%lx (", (unsigned long)ohdr + sizeof(oh));
  142 + GC_err_printf1("0x%lx (", ((unsigned long)ohdr + sizeof(oh)));
143 143 GC_err_puts(ohdr -> oh_string);
144 144 GC_err_printf2(":%ld, sz=%ld)\n", (unsigned long)(ohdr -> oh_int),
145 145 (unsigned long)(ohdr -> oh_sz));
@@ -166,7 +166,7 @@ ptr_t p, clobbered_addr;
166 166 if (clobbered_addr <= (ptr_t)(&(ohdr -> oh_sz))
167 167 || ohdr -> oh_string == 0) {
168 168 GC_err_printf1("<smashed>, appr. sz = %ld)\n",
169   - GC_size((ptr_t)ohdr) - DEBUG_BYTES);
  169 + (GC_size((ptr_t)ohdr) - DEBUG_BYTES));
170 170 } else {
171 171 if (ohdr -> oh_string[0] == '\0') {
172 172 GC_err_puts("EMPTY(smashed?)");
7 dyn_load.c
@@ -350,6 +350,8 @@ void GC_register_dynamic_libraries()
350 350 #include <errno.h>
351 351
352 352 extern void * GC_roots_present();
  353 + /* The type is a lie, since the real type doesn't make sense here, */
  354 + /* and we only test for NULL. */
353 355
354 356 extern ptr_t GC_scratch_last_end_ptr; /* End of GC_scratch_alloc arena */
355 357
@@ -376,6 +378,8 @@ void GC_register_dynamic_libraries()
376 378
377 379 if (fd < 0) {
378 380 sprintf(buf, "/proc/%d", getpid());
  381 + /* The above generates a lint complaint, since pid_t varies. */
  382 + /* It's unclear how to improve this. */
379 383 fd = open(buf, O_RDONLY);
380 384 if (fd < 0) {
381 385 ABORT("/proc open failed");
@@ -388,7 +392,8 @@ void GC_register_dynamic_libraries()
388 392 if (needed_sz >= current_sz) {
389 393 current_sz = needed_sz * 2 + 1;
390 394 /* Expansion, plus room for 0 record */
391   - addr_map = (prmap_t *)GC_scratch_alloc(current_sz * sizeof(prmap_t));
  395 + addr_map = (prmap_t *)GC_scratch_alloc((word)
  396 + (current_sz * sizeof(prmap_t)));
392 397 }
393 398 if (ioctl(fd, PIOCMAP, addr_map) < 0) {
394 399 GC_err_printf4("fd = %d, errno = %d, needed_sz = %d, addr_map = 0x%X\n",
1  gc.h
@@ -268,6 +268,7 @@ GC_API void GC_gcollect GC_PROTO((void));
268 268 /* than normal pause times for incremental collection. However, */
269 269 /* aborted collections do no useful work; the next collection needs */
270 270 /* to start from the beginning. */
  271 +/* Return 0 if the collection was aborted, 1 if it succeeded. */
271 272 typedef int (* GC_stop_func) GC_PROTO((void));
272 273 GC_API int GC_try_to_collect GC_PROTO((GC_stop_func stop_func));
273 274
2  gc_mark.h
@@ -224,7 +224,7 @@ mse * GC_signal_mark_stack_overflow();
224 224 while (!GC_mark_stack_empty()) GC_mark_from_mark_stack(); \
225 225 if (GC_mark_state != MS_NONE) { \
226 226 GC_set_mark_bit(real_ptr); \
227   - while (!GC_mark_some()); \
  227 + while (!GC_mark_some((ptr_t)0)); \
228 228 } \
229 229 }
230 230
29 gc_priv.h
@@ -1323,7 +1323,8 @@ void GC_mark_from_mark_stack(); /* Mark from everything on the mark stack. */
1323 1323 /* Return after about one pages worth of */
1324 1324 /* work. */
1325 1325 GC_bool GC_mark_stack_empty();
1326   -GC_bool GC_mark_some(); /* Perform about one pages worth of marking */
  1326 +GC_bool GC_mark_some(/* cold_gc_frame */);
  1327 + /* Perform about one pages worth of marking */
1327 1328 /* work of whatever kind is needed. Returns */
1328 1329 /* quickly if no collection is in progress. */
1329 1330 /* Return TRUE if mark phase finished. */
@@ -1345,7 +1346,31 @@ void GC_push_dirty(/*b,t*/); /* Push all possibly changed */
1345 1346 /* on the third arg. */
1346 1347 void GC_push_all_stack(/*b,t*/); /* As above, but consider */
1347 1348 /* interior pointers as valid */
1348   -void GC_push_roots(/* GC_bool all */); /* Push all or dirty roots. */
  1349 +void GC_push_all_eager(/*b,t*/); /* Same as GC_push_all_stack, but */
  1350 + /* ensures that stack is scanned */
  1351 + /* immediately, not just scheduled */
  1352 + /* for scanning. */
  1353 +#ifndef THREADS
  1354 + void GC_push_all_stack_partially_eager(/* bottom, top, cold_gc_frame */);
  1355 + /* Similar to GC_push_all_eager, but only the */
  1356 + /* part hotter than cold_gc_frame is scanned */
  1357 + /* immediately. Needed to endure that callee- */
  1358 + /* save registers are not missed. */
  1359 +#else
  1360 + /* In the threads case, we push part of the current thread stack */
  1361 + /* with GC_push_all_eager when we push the registers. This gets the */
  1362 + /* callee-save registers that may disappear. The remainder of the */
  1363 + /* stacks are scheduled for scanning in *GC_push_other_roots, which */
  1364 + /* is thread-package-specific. */
  1365 +#endif
  1366 +void GC_push_current_stack(/* ptr_t cold_gc_frame */);
  1367 + /* Push enough of the current stack eagerly to */
  1368 + /* ensure that callee-save registers saved in */
  1369 + /* GC frames are scanned. */
  1370 + /* In the non-threads case, schedule entire */
  1371 + /* stack for scanning. */
  1372 +void GC_push_roots(/* GC_bool all, ptr_t cold_gc_frame */);
  1373 + /* Push all or dirty roots. */
1349 1374 extern void (*GC_push_other_roots)();
1350 1375 /* Push system or application specific roots */
1351 1376 /* onto the mark stack. In some environments */
34 gcconfig.h
@@ -38,6 +38,11 @@
38 38 # define HP
39 39 # define mach_type_known
40 40 # endif
  41 +# if defined(__OpenBSD__) && defined(m68k)
  42 +# define M68K
  43 +# define OPENBSD
  44 +# define mach_type_known
  45 +# endif
41 46 # if defined(__NetBSD__) && defined(m68k)
42 47 # define M68K
43 48 # define NETBSD
@@ -173,6 +178,11 @@
173 178 # define NEXT
174 179 # define mach_type_known
175 180 # endif
  181 +# if defined(__OpenBSD__) && defined(i386)
  182 +# define I386
  183 +# define OPENBSD
  184 +# define mach_type_known
  185 +# endif
176 186 # if defined(__FreeBSD__) && defined(i386)
177 187 # define I386
178 188 # define FREEBSD
@@ -377,6 +387,12 @@
377 387 # ifdef M68K
378 388 # define MACH_TYPE "M68K"
379 389 # define ALIGNMENT 2
  390 +# ifdef OPENBSD
  391 +# define OS_TYPE "OPENBSD"
  392 +# define HEURISTIC2
  393 + extern char etext;
  394 +# define DATASTART ((ptr_t)(&etext))
  395 +# endif
380 396 # ifdef NETBSD
381 397 # define OS_TYPE "NETBSD"
382 398 # define HEURISTIC2
@@ -724,11 +740,16 @@
724 740 # include "stubinfo.h"
725 741 extern int etext;
726 742 extern int _stklen;
  743 + extern int __djgpp_stack_limit;
727 744 # define DATASTART ((ptr_t)((((word) (&etext)) + 0x1ff) & ~0x1ff))
728   -# define STACKBOTTOM ((ptr_t)((word) _stubinfo + _stubinfo->size \
729   - + _stklen))
  745 +/* # define STACKBOTTOM ((ptr_t)((word) _stubinfo + _stubinfo->size \
  746 + + _stklen)) */
  747 +# define STACKBOTTOM ((ptr_t)((word) __djgpp_stack_limit + _stklen))
730 748 /* This may not be right. */
731 749 # endif
  750 +# ifdef OPENBSD
  751 +# define OS_TYPE "OPENBSD"
  752 +# endif
732 753 # ifdef FREEBSD
733 754 # define OS_TYPE "FREEBSD"
734 755 # define MPROTECT_VDB
@@ -742,7 +763,7 @@
742 763 # ifdef BSDI
743 764 # define OS_TYPE "BSDI"
744 765 # endif
745   -# if defined(FREEBSD) || defined(NETBSD) \
  766 +# if defined(OPENBSD) || defined(FREEBSD) || defined(NETBSD) \
746 767 || defined(THREE86BSD) || defined(BSDI)
747 768 # define HEURISTIC2
748 769 extern char etext;
@@ -877,7 +898,7 @@
877 898 /* Normally HEURISTIC2 is too conervative, since */
878 899 /* the text segment immediately follows the stack. */
879 900 /* Hence we give an upper pound. */
880   - extern __start;
  901 + extern int __start;
881 902 # define HEURISTIC2_LIMIT ((ptr_t)((word)(&__start) & ~(getpagesize()-1)))
882 903 # define CPP_WORDSZ 64
883 904 # define MPROTECT_VDB
@@ -1026,6 +1047,11 @@
1026 1047 # define THREADS
1027 1048 # endif
1028 1049
  1050 +# if defined(HP_PA) || defined(M88K) || defined(POWERPC) \
  1051 + || (defined(I386) && defined(OS2)) || defined(UTS4) || defined(LINT)
  1052 + /* Use setjmp based hack to mark from callee-save registers. */
  1053 +# define USE_GENERIC_PUSH_REGS
  1054 +# endif
1029 1055 # if defined(SPARC) && !defined(LINUX)
1030 1056 # define SAVE_CALL_CHAIN
1031 1057 # define ASM_CLEAR_CODE /* Stack clearing is crucial, and we */
2  headers.c
@@ -125,7 +125,7 @@ hdr * hhdr;
125 125
126 126 void GC_init_headers()
127 127 {
128   - register int i;
  128 + register unsigned i;
129 129
130 130 GC_all_nils = (bottom_index *)GC_scratch_alloc((word)sizeof(bottom_index));
131 131 BZERO(GC_all_nils, sizeof(bottom_index));
1  include/gc.h
@@ -268,6 +268,7 @@ GC_API void GC_gcollect GC_PROTO((void));
268 268 /* than normal pause times for incremental collection. However, */
269 269 /* aborted collections do no useful work; the next collection needs */
270 270 /* to start from the beginning. */
  271 +/* Return 0 if the collection was aborted, 1 if it succeeded. */
271 272 typedef int (* GC_stop_func) GC_PROTO((void));
272 273 GC_API int GC_try_to_collect GC_PROTO((GC_stop_func stop_func));
273 274
29 include/private/gc_priv.h
@@ -1323,7 +1323,8 @@ void GC_mark_from_mark_stack(); /* Mark from everything on the mark stack. */
1323 1323 /* Return after about one pages worth of */
1324 1324 /* work. */
1325 1325 GC_bool GC_mark_stack_empty();
1326   -GC_bool GC_mark_some(); /* Perform about one pages worth of marking */
  1326 +GC_bool GC_mark_some(/* cold_gc_frame */);
  1327 + /* Perform about one pages worth of marking */
1327 1328 /* work of whatever kind is needed. Returns */
1328 1329 /* quickly if no collection is in progress. */
1329 1330 /* Return TRUE if mark phase finished. */
@@ -1345,7 +1346,31 @@ void GC_push_dirty(/*b,t*/); /* Push all possibly changed */
1345 1346 /* on the third arg. */
1346 1347 void GC_push_all_stack(/*b,t*/); /* As above, but consider */
1347 1348 /* interior pointers as valid */
1348   -void GC_push_roots(/* GC_bool all */); /* Push all or dirty roots. */
  1349 +void GC_push_all_eager(/*b,t*/); /* Same as GC_push_all_stack, but */
  1350 + /* ensures that stack is scanned */
  1351 + /* immediately, not just scheduled */
  1352 + /* for scanning. */
  1353 +#ifndef THREADS
  1354 + void GC_push_all_stack_partially_eager(/* bottom, top, cold_gc_frame */);
  1355 + /* Similar to GC_push_all_eager, but only the */
  1356 + /* part hotter than cold_gc_frame is scanned */
  1357 + /* immediately. Needed to endure that callee- */
  1358 + /* save registers are not missed. */
  1359 +#else
  1360 + /* In the threads case, we push part of the current thread stack */
  1361 + /* with GC_push_all_eager when we push the registers. This gets the */
  1362 + /* callee-save registers that may disappear. The remainder of the */
  1363 + /* stacks are scheduled for scanning in *GC_push_other_roots, which */
  1364 + /* is thread-package-specific. */
  1365 +#endif
  1366 +void GC_push_current_stack(/* ptr_t cold_gc_frame */);
  1367 + /* Push enough of the current stack eagerly to */
  1368 + /* ensure that callee-save registers saved in */
  1369 + /* GC frames are scanned. */
  1370 + /* In the non-threads case, schedule entire */
  1371 + /* stack for scanning. */
  1372 +void GC_push_roots(/* GC_bool all, ptr_t cold_gc_frame */);
  1373 + /* Push all or dirty roots. */
1349 1374 extern void (*GC_push_other_roots)();
1350 1375 /* Push system or application specific roots */
1351 1376 /* onto the mark stack. In some environments */
34 include/private/gcconfig.h
@@ -38,6 +38,11 @@
38 38 # define HP
39 39 # define mach_type_known
40 40 # endif
  41 +# if defined(__OpenBSD__) && defined(m68k)
  42 +# define M68K
  43 +# define OPENBSD
  44 +# define mach_type_known
  45 +# endif
41 46 # if defined(__NetBSD__) && defined(m68k)
42 47 # define M68K
43 48 # define NETBSD
@@ -173,6 +178,11 @@
173 178 # define NEXT
174 179 # define mach_type_known
175 180 # endif
  181 +# if defined(__OpenBSD__) && defined(i386)
  182 +# define I386
  183 +# define OPENBSD
  184 +# define mach_type_known
  185 +# endif
176 186 # if defined(__FreeBSD__) && defined(i386)
177 187 # define I386
178 188 # define FREEBSD
@@ -377,6 +387,12 @@
377 387 # ifdef M68K
378 388 # define MACH_TYPE "M68K"
379 389 # define ALIGNMENT 2
  390 +# ifdef OPENBSD
  391 +# define OS_TYPE "OPENBSD"
  392 +# define HEURISTIC2
  393 + extern char etext;
  394 +# define DATASTART ((ptr_t)(&etext))
  395 +# endif
380 396 # ifdef NETBSD
381 397 # define OS_TYPE "NETBSD"
382 398 # define HEURISTIC2
@@ -724,11 +740,16 @@
724 740 # include "stubinfo.h"
725 741 extern int etext;
726 742 extern int _stklen;
  743 + extern int __djgpp_stack_limit;
727 744 # define DATASTART ((ptr_t)((((word) (&etext)) + 0x1ff) & ~0x1ff))
728   -# define STACKBOTTOM ((ptr_t)((word) _stubinfo + _stubinfo->size \
729   - + _stklen))
  745 +/* # define STACKBOTTOM ((ptr_t)((word) _stubinfo + _stubinfo->size \
  746 + + _stklen)) */
  747 +# define STACKBOTTOM ((ptr_t)((word) __djgpp_stack_limit + _stklen))
730 748 /* This may not be right. */
731 749 # endif
  750 +# ifdef OPENBSD
  751 +# define OS_TYPE "OPENBSD"
  752 +# endif
732 753 # ifdef FREEBSD
733 754 # define OS_TYPE "FREEBSD"
734 755 # define MPROTECT_VDB
@@ -742,7 +763,7 @@
742 763 # ifdef BSDI
743 764 # define OS_TYPE "BSDI"
744 765 # endif
745   -# if defined(FREEBSD) || defined(NETBSD) \
  766 +# if defined(OPENBSD) || defined(FREEBSD) || defined(NETBSD) \
746 767 || defined(THREE86BSD) || defined(BSDI)
747 768 # define HEURISTIC2
748 769 extern char etext;
@@ -877,7 +898,7 @@
877 898 /* Normally HEURISTIC2 is too conervative, since */
878 899 /* the text segment immediately follows the stack. */
879 900 /* Hence we give an upper pound. */
880   - extern __start;
  901 + extern int __start;
881 902 # define HEURISTIC2_LIMIT ((ptr_t)((word)(&__start) & ~(getpagesize()-1)))
882 903 # define CPP_WORDSZ 64
883 904 # define MPROTECT_VDB
@@ -1026,6 +1047,11 @@
1026 1047 # define THREADS
1027 1048 # endif
1028 1049
  1050 +# if defined(HP_PA) || defined(M88K) || defined(POWERPC) \
  1051 + || (defined(I386) && defined(OS2)) || defined(UTS4) || defined(LINT)
  1052 + /* Use setjmp based hack to mark from callee-save registers. */
  1053 +# define USE_GENERIC_PUSH_REGS
  1054 +# endif
1029 1055 # if defined(SPARC) && !defined(LINUX)
1030 1056 # define SAVE_CALL_CHAIN
1031 1057 # define ASM_CLEAR_CODE /* Stack clearing is crucial, and we */
32 mach_dep.c
@@ -64,6 +64,7 @@ asm static void PushMacRegisters()
64 64 /* on your architecture. Run the test_setjmp program to see whether */
65 65 /* there is any chance it will work. */
66 66
  67 +#ifndef USE_GENERIC_PUSH_REGS
67 68 void GC_push_regs()
68 69 {
69 70 # ifdef RT
@@ -309,7 +310,21 @@ void GC_push_regs()
309 310 # endif /* M68K/SYSV */
310 311
311 312
312   -# if defined(HP_PA) || defined(M88K) || defined(POWERPC) || (defined(I386) && (defined(OS2) || defined(USE_GENERIC))) || defined(UTS4)
  313 + /* other machines... */
  314 +# if !(defined M68K) && !(defined VAX) && !(defined RT)
  315 +# if !(defined SPARC) && !(defined I386) && !(defined NS32K)
  316 +# if !defined(POWERPC) && !defined(UTS4)
  317 + --> bad news <--
  318 +# endif
  319 +# endif
  320 +# endif
  321 +}
  322 +#endif /* !USE_GENERIC_PUSH_REGS */
  323 +
  324 +#if defined(USE_GENERIC_PUSH_REGS)
  325 +void GC_generic_push_regs(cold_gc_frame)
  326 +ptr_t cold_gc_frame;
  327 +{
313 328 /* Generic code */
314 329 /* The idea is due to Parag Patel at HP. */
315 330 /* We're not sure whether he would like */
@@ -329,21 +344,10 @@ void GC_push_regs()
329 344 # else
330 345 (void) _setjmp(regs);
331 346 # endif
332   - GC_push_all_stack((ptr_t)regs, lim);
  347 + GC_push_current_stack(cold_gc_frame);
333 348 }
334   -# endif
335   -
336   - /* other machines... */
337   -# if !(defined M68K) && !(defined VAX) && !(defined RT)
338   -# if !(defined SPARC) && !(defined I386) && !(defined NS32K)
339   -# if !defined(HP_PA) && !defined(M88K) && !defined(POWERPC)
340   -# if !defined(UTS4)
341   - --> bad news <--
342   -# endif
343   -# endif
344   -# endif
345   -# endif
346 349 }
  350 +#endif /* USE_GENERIC_PUSH_REGS */
347 351
348 352 /* On register window machines, we need a way to force registers into */
349 353 /* the stack. Return sp. */
4 mallocx.c
@@ -130,7 +130,7 @@ void GC_incr_mem_freed(size_t n)
130 130 ptr_t GC_generic_malloc_words_small(size_t lw, int k)
131 131 #else
132 132 ptr_t GC_generic_malloc_words_small(lw, k)
133   - register size_t lw;
  133 + register word lw;
134 134 register int k;
135 135 #endif
136 136 {
@@ -148,7 +148,7 @@ DCL_LOCK_STATE;
148 148 GC_init_inner();
149 149 }
150 150 if (kind -> ok_reclaim_list != 0 || GC_alloc_reclaim_list(kind)) {
151   - op = GC_clear_stack(GC_allocobj(lw, k));
  151 + op = GC_clear_stack(GC_allocobj((word)lw, k));
152 152 }
153 153 if (op == 0) {
154 154 UNLOCK();
62 mark.c
@@ -241,7 +241,12 @@ static void alloc_mark_stack();
241 241 /* Perform a small amount of marking. */
242 242 /* We try to touch roughly a page of memory. */
243 243 /* Return TRUE if we just finished a mark phase. */
244   -GC_bool GC_mark_some()
  244 +/* Cold_gc_frame is an address inside a GC frame that */
  245 +/* remains valid until all marking is complete. */
  246 +/* A zero value indicates that it's OK to miss some */
  247 +/* register values. */
  248 +GC_bool GC_mark_some(cold_gc_frame)
  249 +ptr_t cold_gc_frame;
245 250 {
246 251 switch(GC_mark_state) {
247 252 case MS_NONE:
@@ -259,7 +264,7 @@ GC_bool GC_mark_some()
259 264 GC_printf1("Marked from %lu dirty pages\n",
260 265 (unsigned long)GC_n_rescuing_pages);
261 266 # endif
262   - GC_push_roots(FALSE);
  267 + GC_push_roots(FALSE, cold_gc_frame);
263 268 GC_objects_are_marked = TRUE;
264 269 if (GC_mark_state != MS_INVALID) {
265 270 GC_mark_state = MS_ROOTS_PUSHED;
@@ -276,7 +281,7 @@ GC_bool GC_mark_some()
276 281 } else {
277 282 scan_ptr = GC_push_next_marked_uncollectable(scan_ptr);
278 283 if (scan_ptr == 0) {
279   - GC_push_roots(TRUE);
  284 + GC_push_roots(TRUE, cold_gc_frame);
280 285 GC_objects_are_marked = TRUE;
281 286 if (GC_mark_state != MS_INVALID) {
282 287 GC_mark_state = MS_ROOTS_PUSHED;
@@ -317,7 +322,7 @@ GC_bool GC_mark_some()
317 322 }
318 323 scan_ptr = GC_push_next_marked(scan_ptr);
319 324 if (scan_ptr == 0 && GC_mark_state == MS_PARTIALLY_INVALID) {
320   - GC_push_roots(TRUE);
  325 + GC_push_roots(TRUE, cold_gc_frame);
321 326 GC_objects_are_marked = TRUE;
322 327 if (GC_mark_state != MS_INVALID) {
323 328 GC_mark_state = MS_ROOTS_PUSHED;
@@ -516,13 +521,15 @@ word n;
516 521 if (GC_mark_stack_size != 0) {
517 522 if (new_stack != 0) {
518 523 word displ = (word)GC_mark_stack & (GC_page_size - 1);
519   - word size = GC_mark_stack_size * sizeof(struct ms_entry);
  524 + signed_word size = GC_mark_stack_size * sizeof(struct ms_entry);
520 525
521 526 /* Recycle old space */
522 527 if (0 != displ) displ = GC_page_size - displ;
523 528 size = (size - displ) & ~(GC_page_size - 1);
524   - GC_add_to_heap((struct hblk *)
525   - ((word)GC_mark_stack + displ), size);
  529 + if (size > 0) {
  530 + GC_add_to_heap((struct hblk *)
  531 + ((word)GC_mark_stack + displ), (word)size);
  532 + }
526 533 GC_mark_stack = new_stack;
527 534 GC_mark_stack_size = n;
528 535 # ifdef PRINTSTATS
@@ -819,37 +826,34 @@ ptr_t top;
819 826 # undef GC_least_plausible_heap_addr
820 827 }
821 828
  829 +#ifndef THREADS
822 830 /*
823 831 * A version of GC_push_all that treats all interior pointers as valid
824 832 * and scans part of the area immediately, to make sure that saved
825 833 * register values are not lost.
  834 + * Cold_gc_frame delimits the stack section that must be scanned
  835 + * eagerly. A zero value indicates that no eager scanning is needed.
826 836 */
827   -void GC_push_all_stack(bottom, top)
  837 +void GC_push_all_stack_partially_eager(bottom, top, cold_gc_frame)
828 838 ptr_t bottom;
829 839 ptr_t top;
  840 +ptr_t cold_gc_frame;
830 841 {
831 842 # ifdef ALL_INTERIOR_POINTERS
832 843 # define EAGER_BYTES 1024
833 844 /* Push the hot end of the stack eagerly, so that register values */
834 845 /* saved inside GC frames are marked before they disappear. */
835 846 /* The rest of the marking can be deferred until later. */
836   - ptr_t mid;
  847 + if (0 == cold_gc_frame) {
  848 + GC_push_all_stack(bottom, top);
  849 + return;
  850 + }
837 851 # ifdef STACK_GROWS_DOWN
838   - mid = bottom + 1024;
839   - if (mid < top) {
840   - GC_push_all_eager(bottom, mid);
841   - GC_push_all(mid - sizeof(ptr_t), top);
842   - } else {
843   - GC_push_all_eager(bottom, top);
844   - }
  852 + GC_push_all_eager(bottom, cold_gc_frame);
  853 + GC_push_all(cold_gc_frame - sizeof(ptr_t), top);
845 854 # else /* STACK_GROWS_UP */
846   - mid = top - 1024;
847   - if (mid > bottom) {
848   - GC_push_all_eager(mid, top);
849   - GC_push_all(bottom, mid + sizeof(ptr_t));
850   - } else {
851   - GC_push_all_eager(bottom, top);
852   - }
  855 + GC_push_all_eager(cold_gc_frame, top);
  856 + GC_push_all(bottom, cold_gc_frame + sizeof(ptr_t));
853 857 # endif /* STACK_GROWS_UP */
854 858 # else
855 859 GC_push_all_eager(bottom, top);
@@ -858,6 +862,18 @@ ptr_t top;
858 862 GC_add_trace_entry("GC_push_all_stack", bottom, top);
859 863 # endif
860 864 }
  865 +#endif /* !THREADS */
  866 +
  867 +void GC_push_all_stack(bottom, top)
  868 +ptr_t bottom;
  869 +ptr_t top;
  870 +{
  871 +# ifdef ALL_INTERIOR_POINTERS
  872 + GC_push_all(bottom, top);
  873 +# else
  874 + GC_push_all_eager(bottom, top);
  875 +# endif
  876 +}
861 877
862 878 #ifndef SMALL_CONFIG
863 879 /* Push all objects reachable from marked objects in the given block */
52 mark_rts.c
@@ -400,13 +400,44 @@ int all;
400 400 }
401 401
402 402 /*
  403 + * In the absence of threads, push the stack contents.
  404 + * In the presence of threads, push enough of the current stack
  405 + * to ensure that callee-save registers saved in collector frames have been
  406 + * seen.
  407 + */
  408 +void GC_push_current_stack(cold_gc_frame)
  409 +ptr_t cold_gc_frame;
  410 +{
  411 +# if defined(THREADS)
  412 + if (0 == cold_gc_frame) return;
  413 +# ifdef STACK_GROWS_DOWN
  414 + GC_push_all_eager(GC_approx_sp(), cold_gc_frame);
  415 +# else
  416 + GC_push_all_eager( cold_gc_frame, GC_approx_sp() );
  417 +# endif
  418 +# else
  419 +# ifdef STACK_GROWS_DOWN
  420 + GC_push_all_stack_partially_eager( GC_approx_sp(), GC_stackbottom,
  421 + cold_gc_frame );
  422 +# else
  423 + GC_push_all_stack_partially_eager( GC_stackbottom, GC_approx_sp(),
  424 + cold_gc_frame );
  425 +# endif
  426 +# endif /* !THREADS */
  427 +}
  428 +
  429 +/*
403 430 * Call the mark routines (GC_tl_push for a single pointer, GC_push_conditional
404 431 * on groups of pointers) on every top level accessible pointer.
405 432 * If all is FALSE, arrange to push only possibly altered values.
  433 + * Cold_gc_frame is an address inside a GC frame that
  434 + * remains valid until all marking is complete.
  435 + * A zero value indicates that it's OK to miss some
  436 + * register values.
406 437 */
407   -
408   -void GC_push_roots(all)
  438 +void GC_push_roots(all, cold_gc_frame)
409 439 GC_bool all;
  440 +ptr_t cold_gc_frame;
410 441 {
411 442 register int i;
412 443
@@ -414,7 +445,11 @@ GC_bool all;
414 445 * push registers - i.e., call GC_push_one(r) for each
415 446 * register contents r.
416 447 */
  448 +# ifdef USE_GENERIC_PUSH_REGS
  449 + GC_generic_push_regs(cold_gc_frame);
  450 +# else
417 451 GC_push_regs(); /* usually defined in machine_dep.c */
  452 +# endif
418 453
419 454 /*
420 455 * Next push static data. This must happen early on, since it's
@@ -436,13 +471,12 @@ GC_bool all;
436 471 /*
437 472 * Now traverse stacks.
438 473 */
439   -# ifndef THREADS
440   - /* Mark everything on the stack. */
441   -# ifdef STACK_GROWS_DOWN
442   - GC_push_all_stack( GC_approx_sp(), GC_stackbottom );
443   -# else
444   - GC_push_all_stack( GC_stackbottom, GC_approx_sp() );
445   -# endif
  474 +# if !defined(USE_GENERIC_PUSH_REGS)
  475 + GC_push_current_stack(cold_gc_frame);
  476 + /* IN the threads case, this only pushes collector frames. */
  477 + /* In the USE_GENERIC_PUSH_REGS case, this is done inside */
  478 + /* GC_push_regs, so that we catch callee-save registers saved */
  479 + /* inside the GC_push_regs frame. */
446 480 # endif
447 481 if (GC_push_other_roots != 0) (*GC_push_other_roots)();
448 482 /* In the threads case, this also pushes thread stacks. */
6 os_dep.c
@@ -31,7 +31,11 @@
31 31 /* make sure the former gets defined to be the latter if appropriate. */
32 32 # include <features.h>
33 33 # if 2 <= __GLIBC__
34   -# include <sigcontext.h>
  34 +# if 0 == __GLIBC_MINOR__
  35 + /* glibc 2.1 no longer has sigcontext.h. But signal.h */
  36 + /* has the right declaration for glibc 2.1. */
  37 +# include <sigcontext.h>
  38 +# endif /* 0 == __GLIBC_MINOR__ */
35 39 # else /* not 2 <= __GLIBC__ */
36 40 /* libc5 doesn't have <sigcontext.h>: go directly with the kernel */
37 41 /* one. Check LINUX_VERSION_CODE to see which we should reference. */
6 typd_mlc.c
@@ -632,7 +632,7 @@ ptr_t GC_clear_stack();
632 632 (GC_PTR)GC_clear_stack(GC_generic_malloc((word)lb, k))
633 633
634 634 #define GENERAL_MALLOC_IOP(lb,k) \
635   - (GC_PTR)GC_clear_stack(GC_generic_malloc_ignore_off_page((word)lb, k))
  635 + (GC_PTR)GC_clear_stack(GC_generic_malloc_ignore_off_page(lb, k))
636 636
637 637 #if defined(__STDC__) || defined(__cplusplus)
638 638 void * GC_malloc_explicitly_typed(size_t lb, GC_descr d)
@@ -702,7 +702,7 @@ DCL_LOCK_STATE;
702 702 FASTLOCK();
703 703 if( !FASTLOCK_SUCCEEDED() || (op = *opp) == 0 ) {
704 704 FASTUNLOCK();
705   - op = (ptr_t)GENERAL_MALLOC_IOP((word)lb, GC_explicit_kind);
  705 + op = (ptr_t)GENERAL_MALLOC_IOP(lb, GC_explicit_kind);
706 706 # ifdef MERGE_SIZES
707 707 lw = GC_size_map[lb]; /* May have been uninitialized. */
708 708 # endif
@@ -712,7 +712,7 @@ DCL_LOCK_STATE;
712 712 FASTUNLOCK();
713 713 }
714 714 } else {
715   - op = (ptr_t)GENERAL_MALLOC_IOP((word)lb, GC_explicit_kind);
  715 + op = (ptr_t)GENERAL_MALLOC_IOP(lb, GC_explicit_kind);
716 716 if (op != NULL)
717 717 lw = BYTES_TO_WORDS(GC_size(op));
718 718 }
2  version.h
... ... @@ -1,6 +1,6 @@
1 1 #define GC_VERSION_MAJOR 4
2 2 #define GC_VERSION_MINOR 14
3   -#define GC_ALPHA_VERSION 1
  3 +#define GC_ALPHA_VERSION GC_NOT_ALPHA
4 4
5 5 # define GC_NOT_ALPHA 0xff
6 6
6 win32_threads.c
@@ -91,6 +91,12 @@ void GC_push_all_stacks()
91 91 if (thread_table[i].context.Esp >= (DWORD)thread_table[i].stack
92 92 || thread_table[i].context.Esp < (DWORD)bottom)
93 93 ABORT("Thread stack pointer out of range");
  94 + GC_push_one ((word) thread_table[i].context.Edi);
  95 + GC_push_one ((word) thread_table[i].context.Esi);
  96 + GC_push_one ((word) thread_table[i].context.Ebx);
  97 + GC_push_one ((word) thread_table[i].context.Edx);
  98 + GC_push_one ((word) thread_table[i].context.Ecx);
  99 + GC_push_one ((word) thread_table[i].context.Eax);
94 100 GC_push_all_stack(thread_table[i].context.Esp, thread_table[i].stack);
95 101 }
96 102 }

0 comments on commit c63ec82

Please sign in to comment.
Something went wrong with that request. Please try again.