Commit 41029b88 by Hans Boehm Committed by Tom Tromey

finalize.c: - Accomodate finalization requests for static objects.

2001-04-04  Hans Boehm  <hans_boehm@hp.com>

	* finalize.c:
	- Accomodate finalization requests for static objects.
	  (Will be required by hash synchronization.  May be needed
	  in some configurations now.)

	* gc_priv.h:
	- Define MIN_WORDS.  All allocation requests are rounded
	  up to at least this size.  Removes a subtle assumption that
	  Java objects have a 2 word header.

	* gcconfig.h:
	- Adjust Linux/IA64 configuration for non-ancient kernels.
	  (Necessary fix for IA64.)

	* linux_threads.c:
	- Fix syntax error in currently unused code.  Will be needed
	  for Linux/PA-RISC.

	* malloc.c:
	- Handle MIN_WORDS.

	* misc.c:
	- Handle MIN_WORDS.
	- Change stack cleaning code to typically clear about one tenth
	  the memory it used to in the threads configuration.  Occasionally
	  still clear more.  (This is really a fix for a long-standing
	  and fairly significant performance bug with threads.)

	* os_dep.c:
	- Fix the code for finding the beginning of the data segment under
	  Linux.  I believe this is necessary for some IA64 Linux
	  distributions.  It will also helo other platforms, though those
	  may additionally require a gcconfig.h adjustment.  (This basically
	  works around the absence of a data_start or __data_start
	  definition in glibc.)

	* test.c:
	- Handle rounding due to MIN_WORDS.

From-SVN: r41102
parent 48f9396d
2001-04-04 Hans Boehm <hans_boehm@hp.com>
* finalize.c:
- Accomodate finalization requests for static objects.
(Will be required by hash synchronization. May be needed
in some configurations now.)
* gc_priv.h:
- Define MIN_WORDS. All allocation requests are rounded
up to at least this size. Removes a subtle assumption that
Java objects have a 2 word header.
* gcconfig.h:
- Adjust Linux/IA64 configuration for non-ancient kernels.
(Necessary fix for IA64.)
* linux_threads.c:
- Fix syntax error in currently unused code. Will be needed
for Linux/PA-RISC.
* malloc.c:
- Handle MIN_WORDS.
* misc.c:
- Handle MIN_WORDS.
- Change stack cleaning code to typically clear about one tenth
the memory it used to in the threads configuration. Occasionally
still clear more. (This is really a fix for a long-standing
and fairly significant performance bug with threads.)
* os_dep.c:
- Fix the code for finding the beginning of the data segment under
Linux. I believe this is necessary for some IA64 Linux
distributions. It will also helo other platforms, though those
may additionally require a gcconfig.h adjustment. (This basically
works around the absence of a data_start or __data_start
definition in glibc.)
* test.c:
- Handle rounding due to MIN_WORDS.
2001-03-22 Tom Tromey <tromey@redhat.com> 2001-03-22 Tom Tromey <tromey@redhat.com>
* Makefile.am (gctest_LDFLAGS): Use -shared-libgcc. * Makefile.am (gctest_LDFLAGS): Use -shared-libgcc.
......
...@@ -324,6 +324,7 @@ finalization_mark_proc * mp; ...@@ -324,6 +324,7 @@ finalization_mark_proc * mp;
struct finalizable_object * curr_fo, * prev_fo; struct finalizable_object * curr_fo, * prev_fo;
int index; int index;
struct finalizable_object *new_fo; struct finalizable_object *new_fo;
hdr *hhdr;
DCL_LOCK_STATE; DCL_LOCK_STATE;
# ifdef THREADS # ifdef THREADS
...@@ -402,6 +403,19 @@ finalization_mark_proc * mp; ...@@ -402,6 +403,19 @@ finalization_mark_proc * mp;
# endif # endif
return; return;
} }
GET_HDR(base, hhdr);
if (0 == hhdr) {
/* We won't collect it, hence finalizer wouldn't be run. */
/* This is changed for gcj, but it will be in version 6.0 of the */
/* standard collector distribution. It costs virtually nothing */
/* here, but it's expensive to check in the hash synchronization */
/* code, where it matters. -HB */
# ifdef THREADS
UNLOCK();
ENABLE_SIGNALS();
# endif
return;
}
# ifdef THREADS # ifdef THREADS
new_fo = (struct finalizable_object *) new_fo = (struct finalizable_object *)
GC_generic_malloc_inner(sizeof(struct finalizable_object),NORMAL); GC_generic_malloc_inner(sizeof(struct finalizable_object),NORMAL);
...@@ -413,7 +427,7 @@ finalization_mark_proc * mp; ...@@ -413,7 +427,7 @@ finalization_mark_proc * mp;
new_fo -> fo_hidden_base = (word)HIDE_POINTER(base); new_fo -> fo_hidden_base = (word)HIDE_POINTER(base);
new_fo -> fo_fn = fn; new_fo -> fo_fn = fn;
new_fo -> fo_client_data = (ptr_t)cd; new_fo -> fo_client_data = (ptr_t)cd;
new_fo -> fo_object_size = GC_size(base); new_fo -> fo_object_size = hhdr -> hb_sz;
new_fo -> fo_mark_proc = mp; new_fo -> fo_mark_proc = mp;
fo_set_next(new_fo, fo_head[index]); fo_set_next(new_fo, fo_head[index]);
GC_fo_entries++; GC_fo_entries++;
......
...@@ -890,6 +890,18 @@ extern GC_warn_proc GC_current_warn_proc; ...@@ -890,6 +890,18 @@ extern GC_warn_proc GC_current_warn_proc;
# define SMALL_OBJ(bytes) ((bytes) <= WORDS_TO_BYTES(MAXOBJSZ)) # define SMALL_OBJ(bytes) ((bytes) <= WORDS_TO_BYTES(MAXOBJSZ))
# define ADD_SLOP(bytes) (bytes) # define ADD_SLOP(bytes) (bytes)
# endif # endif
# ifndef MIN_WORDS
/* MIN_WORDS is the size of the smallest allocated object. */
/* 1 and 2 are the only valid values. */
/* 2 must be used if: */
/* - GC_gcj_malloc can be used for objects of requested */
/* size smaller than 2 words */
# if defined(GC_GCJ_SUPPORT)
# define MIN_WORDS 2 /* Smallest allocated object. */
# else
# define MIN_WORDS 1
# endif
# endif
/* /*
......
...@@ -1116,11 +1116,20 @@ ...@@ -1116,11 +1116,20 @@
# define CPP_WORDSZ 64 # define CPP_WORDSZ 64
/* This should really be done through /proc, but that */ /* This should really be done through /proc, but that */
/* requires we run on an IA64 kernel. */ /* requires we run on an IA64 kernel. */
# define STACKBOTTOM ((ptr_t) 0xa000000000000000l) /* The following works on NUE and older kernels: */
/* # define STACKBOTTOM ((ptr_t) 0xa000000000000000l) */
/* This does not work on NUE: */
# define LINUX_STACKBOTTOM
/* We also need the base address of the register stack */ /* We also need the base address of the register stack */
/* backing store. There is probably a better way to */ /* backing store. There should be a better way to get */
/* get that, too ... */ /* this: */
# define BACKING_STORE_BASE ((ptr_t) 0x9fffffff80000000l) # define APPROX_BS_BASE ((word)GC_stackbottom-0x80000000)
/* We round to the next multiple of 1 MB, to compensate */
/* for the fact that the stack base is displaced by */
/* the environment, etc. */
# define BACKING_STORE_BASE \
(ptr_t)((APPROX_BS_BASE + 0xfffff) & ~0xfffff)
# if 1 # if 1
# define SEARCH_FOR_DATA_START # define SEARCH_FOR_DATA_START
# define DATASTART GC_data_start # define DATASTART GC_data_start
......
...@@ -267,7 +267,6 @@ DCL_LOCK_STATE; ...@@ -267,7 +267,6 @@ DCL_LOCK_STATE;
} else { } else {
*opp = obj_link(op); *opp = obj_link(op);
GC_words_allocd += lw; GC_words_allocd += lw;
FASTUNLOCK();
} }
*(void **)op = ptr_to_struct_containing_descr; *(void **)op = ptr_to_struct_containing_descr;
UNLOCK(); UNLOCK();
......
...@@ -611,7 +611,7 @@ void * GC_start_routine(void * arg) ...@@ -611,7 +611,7 @@ void * GC_start_routine(void * arg)
/* Needs to be plausible, since an asynchronous stack mark */ /* Needs to be plausible, since an asynchronous stack mark */
/* should not crash. */ /* should not crash. */
# else # else
me -> stack_end = (ptr_t)(((word)(&dummy) & ~(GC_page_size - 1)); me -> stack_end = (ptr_t)((word)(&dummy) & ~(GC_page_size - 1));
me -> stack_ptr = me -> stack_end + 0x10; me -> stack_ptr = me -> stack_end + 0x10;
# endif # endif
/* This is dubious, since we may be more than a page into the stack, */ /* This is dubious, since we may be more than a page into the stack, */
......
...@@ -52,7 +52,7 @@ register ptr_t *opp; ...@@ -52,7 +52,7 @@ register ptr_t *opp;
lw = GC_size_map[lb]; lw = GC_size_map[lb];
# else # else
lw = ALIGNED_WORDS(lb); lw = ALIGNED_WORDS(lb);
if (lw == 0) lw = 1; if (lw == 0) lw = MIN_WORDS;
# endif # endif
opp = &(kind -> ok_freelist[lw]); opp = &(kind -> ok_freelist[lw]);
if( (op = *opp) == 0 ) { if( (op = *opp) == 0 ) {
......
...@@ -107,13 +107,17 @@ extern signed_word GC_mem_found; ...@@ -107,13 +107,17 @@ extern signed_word GC_mem_found;
{ {
register unsigned i; register unsigned i;
/* Map size 0 to 1. This avoids problems at lower levels. */ /* Map size 0 to something bigger. */
GC_size_map[0] = 1; /* This avoids problems at lower levels. */
/* One word objects don't have to be 2 word aligned. */ /* One word objects don't have to be 2 word aligned. */
for (i = 1; i < sizeof(word); i++) { for (i = 0; i < sizeof(word); i++) {
GC_size_map[i] = 1; GC_size_map[i] = MIN_WORDS;
} }
GC_size_map[sizeof(word)] = ROUNDED_UP_WORDS(sizeof(word)); # if MIN_WORDS > 1
GC_size_map[sizeof(word)] = MIN_WORDS;
# else
GC_size_map[sizeof(word)] = ROUNDED_UP_WORDS(sizeof(word));
# endif
for (i = sizeof(word) + 1; i <= 8 * sizeof(word); i++) { for (i = sizeof(word) + 1; i <= 8 * sizeof(word); i++) {
# ifdef ALIGN_DOUBLE # ifdef ALIGN_DOUBLE
GC_size_map[i] = (ROUNDED_UP_WORDS(i) + 1) & (~1); GC_size_map[i] = (ROUNDED_UP_WORDS(i) + 1) & (~1);
...@@ -202,10 +206,10 @@ extern signed_word GC_mem_found; ...@@ -202,10 +206,10 @@ extern signed_word GC_mem_found;
*/ */
word GC_stack_last_cleared = 0; /* GC_no when we last did this */ word GC_stack_last_cleared = 0; /* GC_no when we last did this */
# ifdef THREADS # ifdef THREADS
# define CLEAR_SIZE 2048 # define BIG_CLEAR_SIZE 2048 /* Clear this much now and then. */
# else # define SMALL_CLEAR_SIZE 256 /* Clear this much every time. */
# define CLEAR_SIZE 213
# endif # endif
# define CLEAR_SIZE 213 /* Granularity for GC_clear_stack_inner */
# define DEGRADE_RATE 50 # define DEGRADE_RATE 50
word GC_min_sp; /* Coolest stack pointer value from which we've */ word GC_min_sp; /* Coolest stack pointer value from which we've */
...@@ -262,10 +266,12 @@ ptr_t arg; ...@@ -262,10 +266,12 @@ ptr_t arg;
{ {
register word sp = (word)GC_approx_sp(); /* Hotter than actual sp */ register word sp = (word)GC_approx_sp(); /* Hotter than actual sp */
# ifdef THREADS # ifdef THREADS
word dummy[CLEAR_SIZE]; word dummy[SMALL_CLEAR_SIZE];
# else unsigned random_no = 0; /* Should be more random than it is ... */
register word limit; /* Used to occasionally clear a bigger */
/* chunk. */
# endif # endif
register word limit;
# define SLOP 400 # define SLOP 400
/* Extra bytes we clear every time. This clears our own */ /* Extra bytes we clear every time. This clears our own */
...@@ -283,7 +289,14 @@ ptr_t arg; ...@@ -283,7 +289,14 @@ ptr_t arg;
/* thus more junk remains accessible, thus the heap gets */ /* thus more junk remains accessible, thus the heap gets */
/* larger ... */ /* larger ... */
# ifdef THREADS # ifdef THREADS
BZERO(dummy, CLEAR_SIZE*sizeof(word)); if (++random_no % 13 == 0) {
limit = sp;
MAKE_HOTTER(limit, BIG_CLEAR_SIZE*sizeof(word));
return GC_lear_stack_inner(arg, limit);
} else {
BZERO(dummy, SMALL_CLEAR_SIZE*sizeof(word));
return arg;
}
# else # else
if (GC_gc_no > GC_stack_last_cleared) { if (GC_gc_no > GC_stack_last_cleared) {
/* Start things over, so we clear the entire stack again */ /* Start things over, so we clear the entire stack again */
......
...@@ -144,20 +144,37 @@ ...@@ -144,20 +144,37 @@
#endif #endif
#if defined(SEARCH_FOR_DATA_START) #if defined(SEARCH_FOR_DATA_START)
/* The following doesn't work if the GC is in a dynamic library. */
/* The I386 case can be handled without a search. The Alpha case */ /* The I386 case can be handled without a search. The Alpha case */
/* used to be handled differently as well, but the rules changed */ /* used to be handled differently as well, but the rules changed */
/* for recent Linux versions. This seems to be the easiest way to */ /* for recent Linux versions. This seems to be the easiest way to */
/* cover all versions. */ /* cover all versions. */
ptr_t GC_data_start;
extern char * GC_copyright[]; /* Any data symbol would do. */ # ifdef LINUX
# pragma weak __data_start
extern int __data_start;
# pragma weak data_start
extern int data_start;
# endif /* LINUX */
extern int _end;
ptr_t GC_data_start;
void GC_init_linux_data_start() void GC_init_linux_data_start()
{ {
extern ptr_t GC_find_limit(); extern ptr_t GC_find_limit();
GC_data_start = GC_find_limit((ptr_t)GC_copyright, FALSE); # ifdef LINUX
/* Try the easy approaches first: */
if (&__data_start != 0) {
GC_data_start = (ptr_t)(&__data_start);
return;
}
if (&data_start != 0) {
GC_data_start = (ptr_t)(&data_start);
return;
}
# endif /* LINUX */
GC_data_start = GC_find_limit((ptr_t)(&_end), FALSE);
} }
#endif #endif
......
...@@ -958,17 +958,17 @@ void run_one_test() ...@@ -958,17 +958,17 @@ void run_one_test()
"This test program is not designed for leak detection mode\n"); "This test program is not designed for leak detection mode\n");
(void)GC_printf0("Expect lots of problems.\n"); (void)GC_printf0("Expect lots of problems.\n");
# endif # endif
if (GC_size(GC_malloc(7)) != 8 if (GC_size(GC_malloc(7)) != 8 &&
GC_size(GC_malloc(7)) != MIN_WORDS * sizeof(GC_word)
|| GC_size(GC_malloc(15)) != 16) { || GC_size(GC_malloc(15)) != 16) {
(void)GC_printf0("GC_size produced unexpected results\n"); (void)GC_printf0("GC_size produced unexpected results\n");
FAIL; FAIL;
} }
if (GC_size(GC_malloc(0)) != 4 && GC_size(GC_malloc(0)) != 8) { if (GC_size(GC_malloc(0)) != MIN_WORDS * sizeof(GC_word)) {
(void)GC_printf0("GC_malloc(0) failed\n"); (void)GC_printf0("GC_malloc(0) failed\n");
FAIL; FAIL;
} }
if (GC_size(GC_malloc_uncollectable(0)) != 4 if (GC_size(GC_malloc_uncollectable(0)) != MIN_WORDS * sizeof(GC_word)) {
&& GC_size(GC_malloc_uncollectable(0)) != 8) {
(void)GC_printf0("GC_malloc_uncollectable(0) failed\n"); (void)GC_printf0("GC_malloc_uncollectable(0) failed\n");
FAIL; FAIL;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment