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
This commit is contained in:
parent
48f9396dd6
commit
41029b884a
10 changed files with 133 additions and 28 deletions
|
@ -1,3 +1,44 @@
|
|||
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>
|
||||
|
||||
* Makefile.am (gctest_LDFLAGS): Use -shared-libgcc.
|
||||
|
|
|
@ -324,6 +324,7 @@ finalization_mark_proc * mp;
|
|||
struct finalizable_object * curr_fo, * prev_fo;
|
||||
int index;
|
||||
struct finalizable_object *new_fo;
|
||||
hdr *hhdr;
|
||||
DCL_LOCK_STATE;
|
||||
|
||||
# ifdef THREADS
|
||||
|
@ -402,6 +403,19 @@ finalization_mark_proc * mp;
|
|||
# endif
|
||||
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
|
||||
new_fo = (struct finalizable_object *)
|
||||
GC_generic_malloc_inner(sizeof(struct finalizable_object),NORMAL);
|
||||
|
@ -413,7 +427,7 @@ finalization_mark_proc * mp;
|
|||
new_fo -> fo_hidden_base = (word)HIDE_POINTER(base);
|
||||
new_fo -> fo_fn = fn;
|
||||
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;
|
||||
fo_set_next(new_fo, fo_head[index]);
|
||||
GC_fo_entries++;
|
||||
|
|
|
@ -890,6 +890,18 @@ extern GC_warn_proc GC_current_warn_proc;
|
|||
# define SMALL_OBJ(bytes) ((bytes) <= WORDS_TO_BYTES(MAXOBJSZ))
|
||||
# define ADD_SLOP(bytes) (bytes)
|
||||
# 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 @@
|
|||
# define CPP_WORDSZ 64
|
||||
/* This should really be done through /proc, but that */
|
||||
/* 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 */
|
||||
/* backing store. There is probably a better way to */
|
||||
/* get that, too ... */
|
||||
# define BACKING_STORE_BASE ((ptr_t) 0x9fffffff80000000l)
|
||||
/* backing store. There should be a better way to get */
|
||||
/* this: */
|
||||
# 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
|
||||
# define SEARCH_FOR_DATA_START
|
||||
# define DATASTART GC_data_start
|
||||
|
|
|
@ -267,7 +267,6 @@ DCL_LOCK_STATE;
|
|||
} else {
|
||||
*opp = obj_link(op);
|
||||
GC_words_allocd += lw;
|
||||
FASTUNLOCK();
|
||||
}
|
||||
*(void **)op = ptr_to_struct_containing_descr;
|
||||
UNLOCK();
|
||||
|
|
|
@ -611,7 +611,7 @@ void * GC_start_routine(void * arg)
|
|||
/* Needs to be plausible, since an asynchronous stack mark */
|
||||
/* should not crash. */
|
||||
# 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;
|
||||
# endif
|
||||
/* This is dubious, since we may be more than a page into the stack, */
|
||||
|
|
|
@ -52,7 +52,7 @@ register ptr_t *opp;
|
|||
lw = GC_size_map[lb];
|
||||
# else
|
||||
lw = ALIGNED_WORDS(lb);
|
||||
if (lw == 0) lw = 1;
|
||||
if (lw == 0) lw = MIN_WORDS;
|
||||
# endif
|
||||
opp = &(kind -> ok_freelist[lw]);
|
||||
if( (op = *opp) == 0 ) {
|
||||
|
|
|
@ -107,13 +107,17 @@ extern signed_word GC_mem_found;
|
|||
{
|
||||
register unsigned i;
|
||||
|
||||
/* Map size 0 to 1. This avoids problems at lower levels. */
|
||||
GC_size_map[0] = 1;
|
||||
/* Map size 0 to something bigger. */
|
||||
/* This avoids problems at lower levels. */
|
||||
/* One word objects don't have to be 2 word aligned. */
|
||||
for (i = 1; i < sizeof(word); i++) {
|
||||
GC_size_map[i] = 1;
|
||||
for (i = 0; i < sizeof(word); i++) {
|
||||
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++) {
|
||||
# ifdef ALIGN_DOUBLE
|
||||
GC_size_map[i] = (ROUNDED_UP_WORDS(i) + 1) & (~1);
|
||||
|
@ -202,10 +206,10 @@ extern signed_word GC_mem_found;
|
|||
*/
|
||||
word GC_stack_last_cleared = 0; /* GC_no when we last did this */
|
||||
# ifdef THREADS
|
||||
# define CLEAR_SIZE 2048
|
||||
# else
|
||||
# define CLEAR_SIZE 213
|
||||
# define BIG_CLEAR_SIZE 2048 /* Clear this much now and then. */
|
||||
# define SMALL_CLEAR_SIZE 256 /* Clear this much every time. */
|
||||
# endif
|
||||
# define CLEAR_SIZE 213 /* Granularity for GC_clear_stack_inner */
|
||||
# define DEGRADE_RATE 50
|
||||
|
||||
word GC_min_sp; /* Coolest stack pointer value from which we've */
|
||||
|
@ -262,10 +266,12 @@ ptr_t arg;
|
|||
{
|
||||
register word sp = (word)GC_approx_sp(); /* Hotter than actual sp */
|
||||
# ifdef THREADS
|
||||
word dummy[CLEAR_SIZE];
|
||||
# else
|
||||
register word limit;
|
||||
word dummy[SMALL_CLEAR_SIZE];
|
||||
unsigned random_no = 0; /* Should be more random than it is ... */
|
||||
/* Used to occasionally clear a bigger */
|
||||
/* chunk. */
|
||||
# endif
|
||||
register word limit;
|
||||
|
||||
# define SLOP 400
|
||||
/* Extra bytes we clear every time. This clears our own */
|
||||
|
@ -283,7 +289,14 @@ ptr_t arg;
|
|||
/* thus more junk remains accessible, thus the heap gets */
|
||||
/* larger ... */
|
||||
# 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
|
||||
if (GC_gc_no > GC_stack_last_cleared) {
|
||||
/* Start things over, so we clear the entire stack again */
|
||||
|
|
|
@ -144,20 +144,37 @@
|
|||
#endif
|
||||
|
||||
#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 */
|
||||
/* used to be handled differently as well, but the rules changed */
|
||||
/* for recent Linux versions. This seems to be the easiest way to */
|
||||
/* 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()
|
||||
{
|
||||
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
|
||||
|
||||
|
|
|
@ -958,17 +958,17 @@ void run_one_test()
|
|||
"This test program is not designed for leak detection mode\n");
|
||||
(void)GC_printf0("Expect lots of problems.\n");
|
||||
# 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) {
|
||||
(void)GC_printf0("GC_size produced unexpected results\n");
|
||||
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");
|
||||
FAIL;
|
||||
}
|
||||
if (GC_size(GC_malloc_uncollectable(0)) != 4
|
||||
&& GC_size(GC_malloc_uncollectable(0)) != 8) {
|
||||
if (GC_size(GC_malloc_uncollectable(0)) != MIN_WORDS * sizeof(GC_word)) {
|
||||
(void)GC_printf0("GC_malloc_uncollectable(0) failed\n");
|
||||
FAIL;
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue