From f68db211d8eb42b9b822911462c3e89765ddd2a1 Mon Sep 17 00:00:00 2001 From: Ivan Maidanski Date: Mon, 10 Jun 2024 21:48:04 +0300 Subject: [PATCH] Define GC_uintptr_t unconditionally in gc.h Issue #627 (bdwgc). * cord/cordprnt.c (CORD_vsprintf): Compare len (instead of res) to buf; cast len and buf values to GC_uintptr_t instead of casting res to word and then to char*. * cord/cordxtra.c (CORD_nul_func, CORD_chars, refill_cache, CORD_lf_func): Cast between pointer and char thru GC_uintptr_t instead of word. * include/private/dbg_mlc.h (MARKED_FOR_FINALIZATION, MARKED_FROM_REGISTER, NOT_MARKED): Likewise. * cord/tests/cordtest.c (test_fn, test_cord_x1, test_cord_x2): Likewise. * dbg_mlc.c (GC_has_other_debug_info, GC_store_debug_info_inner, GC_check_annotated_obj): Cast body, sz to GC_uintptr_t (instead of word); cast base/ohdr to GC_uintptr_t* instead of word*. * dbg_mlc.c (GC_print_backtrace): Remove out label; adjust indentation. * dbg_mlc.c (GET_OH_LINENUM): Add missing parentheses. * include/gc/gc.h (GC_PRE_INCR3, GC_POST_INCR3): Likewise. * dbg_mlc.c [!SHORT_DBG_HDRS] (GC_print_smashed_obj): Rename clobbered_addr argument to clobbered; reformat comment. * dbg_mlc.c (GC_FREED_MEM_MARKER): Move definition to dbg_mlc.h. * dbg_mlc.c (GC_debug_free): Cast sz and GC_size(base) to GC_uintptr_t; cast p to GC_uintptr_t* instead of word*. * dbg_mlc.c (GC_check_leaked): Cast base to GC_uintptr_t* instead of word*. * include/private/dbg_mlc.h [(KEEP_BACK_PTRS || MAKE_BACK_GRAPH) && !(PARALLEL_MARK || KEEP_BACK_PTRS)] (GC_HAS_DEBUG_INFO): Likewise. * dbg_mlc.c (GC_debug_invoke_finalizer): Change "fns" to "function" in comment. * dbg_mlc.c (store_old, GC_debug_register_finalizer, GC_debug_register_finalizer_no_order, GC_debug_register_finalizer_unreachable, GC_debug_register_finalizer_ignore_self): Store NULL (instead of 0) to *ocd. * gc.man (.TH): Update date. * gc.man (GC_set_warn_proc): Change arg type from GC_word to GC_uintptr_t. * include/gc/gc.h (GC_warn_proc, GC_ignore_warn_proc): Likewise. * misc.c (GC_default_warn_proc, GC_ignore_warn_proc): Likewise. * tests/cpp.cc (warn_proc): Likewise. * gcj_mlc.c (GC_gcj_fake_mark_proc, GC_init_gcj_malloc): Rename FUNCPTR_IS_WORD to FUNCPTR_IS_DATAPTR. * include/private/gc_priv.h (FUNCPTR_IS_WORD): Likewise. * misc.c [!CPPCHECK] (GC_init): Likewise. * pthread_support.c [GC_PTHREADS && !SN_TARGET_ORBIS && !SN_TARGET_PSP2 && DEBUG_THREADS] (GC_start_rtn_prepare_thread): Likewise. * include/gc/gc.h (GC_uintptr_t): Define unconditionally; move definition to the beginning of the file. * include/gc/gc.h (GC_general_register_disappearing_link, GC_malloc_many): Refine comment. * include/private/gc_priv.h (GC_PUSH_ALL_SYM): Likewise. * include/gc/gc.h (GC_hidden_pointer): Change type from GC_word to GC_uintptr_t. * include/private/gc_priv.h (GC_funcptr_uint): Likewise. * include/private/dbg_mlc.h (GC_FREED_MEM_MARKER, START_FLAG, END_FLAG): Cast to GC_uintptr_t instead of word. * include/private/dbg_mlc.h [ALIGNMENT==1] (HIDE_BACK_PTR): Likewise. * include/private/dbg_mlc.h (oh): Remove oh_dummy field; make oh_back_ptr and oh_bg_ptr field either present both or not; refine comment. * include/private/dbg_mlc.h [!SHORT_DBG_HDRS] (oh.oh_sz, oh.oh_sf): Change type from word to GC_uintptr_t. * include/private/gc_priv.h (GC_ASSERT): Move definition upper (to be right after include gc_locks.h). * include/private/gc_priv.h (WARN): Cast arg to GC_uintptr_t instead of word. * include/private/gc_priv.h (WARN_PRIdPTR): Change comment to TODO item. * mallocx.c [_FORTIFY_SOURCE && __GNUC__ && !__clang__] (GC_realloc): Change type of cleared_p local variable from word to GC_uintptr_t; reformat comment. * mallocx.c [!_FORTIFY_SOURCE || !__GNUC__ || __clang__] (GC_realloc): Define cleared_p as a macro (and undefine it at the end of function). * misc.c [!CPPCHECK] (GC_init): Change ptr_t to ptrdiff_t in comparison to sizeof word. * misc.c [!CPPCHECK && FUNCPTR_IS_DATAPTR] (GC_init): Change word to ptr_t in comparison to sizeof GC_funcptr_uint. * misc.c [!CPPCHECK] (GC_init): Add assertion that size of GC_uintptr_t matches size of ptr_t. * pthread_support.c [E2K] (GC_record_stack_base, GC_set_stackbottom): Cast sb->reg_base to GC_uintptr_t instead of ADDR() usage. * pthread_support.c [E2K] (GC_get_my_stackbottom): Cast crtn->ps_ofs to GC_uintptr_t instead of word; add comment. * tests/cpp.cc (Disguise): Change type or result from GC_word to GC_uintptr_t. * tests/cpp.cc (Undisguise): Rename i argument to v and change its type from GC_word to GC_uintptr_t. * tests/cpp.cc (main): Change type of as, bs local variables from GC_word[] to GC_uintptr_t[]. * tests/cpp.cc (INT_TO_SEXPR, SEXPR_TO_INT): Rename argument; cast thru GC_uintptr_t instead of GC_word. * tests/cpp.cc [TEST_WITH_SYSTEM_MALLOC] (reverse): Cast TEST_WITH_SYSTEM_MALLOC() result to GC_word. * tests/cpp.cc (reverse_test_inner, finalizer, mktree): Cast between pointer and int thru GC_uintptr_t instead GC_word. * thread_local_alloc.c (return_freelists, GC_init_thread_local): Likewise. * tests/cpp.cc (warn_proc): Rename argument from p to arg; remove cast of arg to unsigned long. --- cord/cordprnt.c | 2 +- cord/cordxtra.c | 16 +- cord/tests/cordtest.c | 8 +- dbg_mlc.c | 410 +++++++++++++++++++------------------- gc.man | 4 +- gcj_mlc.c | 9 +- include/gc/gc.h | 43 ++-- include/private/dbg_mlc.h | 52 ++--- include/private/gc_priv.h | 58 +++--- mallocx.c | 11 +- misc.c | 11 +- pthread_support.c | 9 +- tests/cpp.cc | 10 +- tests/gctest.c | 17 +- thread_local_alloc.c | 6 +- 15 files changed, 333 insertions(+), 333 deletions(-) diff --git a/cord/cordprnt.c b/cord/cordprnt.c index c7c80facb..feda6f517 100644 --- a/cord/cordprnt.c +++ b/cord/cordprnt.c @@ -375,7 +375,7 @@ int CORD_vsprintf(CORD * out, CORD format, va_list args) va_end(vsprintf_args); # endif len = (unsigned)res; - if ((char *)(GC_word)res == buf) { + if ((GC_uintptr_t)len == (GC_uintptr_t)buf) { /* old style vsprintf */ len = strlen(buf); } else if (res < 0) { diff --git a/cord/cordxtra.c b/cord/cordxtra.c index 963445ac5..bac3acd4a 100644 --- a/cord/cordxtra.c +++ b/cord/cordxtra.c @@ -435,12 +435,13 @@ void CORD_ec_append_cord(CORD_ec x, CORD s) static char CORD_nul_func(size_t i, void * client_data) { (void)i; - return (char)(GC_word)client_data; + return (char)(GC_uintptr_t)client_data; } CORD CORD_chars(char c, size_t i) { - return CORD_from_fn(CORD_nul_func, (void *)(GC_word)(unsigned char)c, i); + return CORD_from_fn(CORD_nul_func, + (void *)(GC_uintptr_t)(unsigned char)c, i); } CORD CORD_from_file_eager(FILE * f) @@ -537,10 +538,11 @@ static void * GC_CALLBACK refill_cache(void * client_data) # else state -> lf_cache[line_no] = new_cache; # endif - GC_END_STUBBORN_CHANGE((/* no volatile */ void *) - (GC_word)(state -> lf_cache + line_no)); + GC_END_STUBBORN_CHANGE((/* no volatile */ cache_line *) + &(state -> lf_cache[line_no])); state -> lf_current = line_start + LINE_SZ; - return (void *)((GC_word)new_cache->data[MOD_LINE_SZ(file_pos)]); + return (void *)(GC_uintptr_t) + ((unsigned char)(new_cache -> data[MOD_LINE_SZ(file_pos)])); } #ifndef CORD_USE_GCC_ATOMIC @@ -565,7 +567,7 @@ static char CORD_lf_func(size_t i, void * client_data) get_cache_line, (void *)cl_addr); # else cl = (cache_line *)GC_call_with_reader_lock(get_cache_line, - (void *)cl_addr, 0); + (/* no volatile */ void *)cl_addr, 0); # endif if (NULL == cl || cl -> tag != DIV_LINE_SZ(i)) { /* Cache miss */ @@ -575,7 +577,7 @@ static char CORD_lf_func(size_t i, void * client_data) rd.file_pos = i; rd.new_cache = GC_NEW_ATOMIC(cache_line); if (NULL == rd.new_cache) OUT_OF_MEMORY; - return (char)((GC_word)GC_call_with_alloc_lock(refill_cache, &rd)); + return (char)(GC_uintptr_t)GC_call_with_alloc_lock(refill_cache, &rd); } return cl -> data[MOD_LINE_SZ(i)]; } diff --git a/cord/tests/cordtest.c b/cord/tests/cordtest.c index 7ed8762a4..a5a20db7d 100644 --- a/cord/tests/cordtest.c +++ b/cord/tests/cordtest.c @@ -48,7 +48,7 @@ static int count; static int test_fn(char c, void * client_data) { - if (client_data != (void *)(GC_word)13) + if ((GC_uintptr_t)client_data != 13U) ABORT("bad client data"); if (count < CORD_ITER_CNT + 1) { if ((count & 1) == 0) { @@ -84,7 +84,7 @@ static void test_cord_x1(CORD x) count = 0; if (CORD_iter5(x, CORD_ITER_CNT - 1, test_fn, CORD_NO_FN, - (void *)(GC_word)13) == 0) { + (void *)(GC_uintptr_t)13) == 0) { ABORT("CORD_iter5 failed"); } if (count != CORD_ITER_CNT + 2) ABORT("CORD_iter5 failed"); @@ -92,7 +92,7 @@ static void test_cord_x1(CORD x) count = 0; CORD_set_pos(p, x, CORD_ITER_CNT - 1); while (CORD_pos_valid(p)) { - (void)test_fn(CORD_pos_fetch(p), (void *)(GC_word)13); + (void)test_fn(CORD_pos_fetch(p), (void *)(GC_uintptr_t)13); CORD_next(p); } if (count != CORD_ITER_CNT + 2) ABORT("Position based iteration failed"); @@ -122,7 +122,7 @@ static void test_cord_x2(CORD x) count = 0; if (CORD_iter5(x, CORD_ITER_CNT - 1, test_fn, CORD_NO_FN, - (void *)(GC_word)13) == 0) { + (void *)(GC_uintptr_t)13) == 0) { ABORT("CORD_iter5 failed"); } if (count != CORD_ITER_CNT + 2) ABORT("CORD_iter5 failed"); diff --git a/dbg_mlc.c b/dbg_mlc.c index 33ef717bd..528b77cd9 100644 --- a/dbg_mlc.c +++ b/dbg_mlc.c @@ -38,15 +38,16 @@ ptr_t body = (ptr_t)((oh *)base + 1); word sz = GC_size(base); - if (HBLKPTR(base) != HBLKPTR((ptr_t)body) + if (HBLKPTR(base) != HBLKPTR(body) || sz < DEBUG_BYTES + EXTRA_BYTES) { return 0; } - if (((oh *)base) -> oh_sf != (START_FLAG ^ (word)body) - && ((word *)base)[BYTES_TO_WORDS(sz)-1] != (END_FLAG ^ (word)body)) { + if (((oh *)base) -> oh_sf != (START_FLAG ^ (GC_uintptr_t)body) + && ((GC_uintptr_t *)base)[BYTES_TO_WORDS(sz) - 1] + != (END_FLAG ^ (GC_uintptr_t)body)) { return 0; } - if (((oh *)base)->oh_sz == sz) { + if (((oh *)base) -> oh_sz == (GC_uintptr_t)sz) { /* Object may have had debug info, but has been deallocated. */ return -1; } @@ -95,8 +96,7 @@ size_t *offset_p) { oh * ohdr = (oh *)GC_base(dest); - ptr_t bp; - ptr_t bp_base; + ptr_t bp, bp_base; # ifdef LINT2 /* Explicitly instruct the code analysis tool that */ @@ -162,11 +162,8 @@ ABORT("GC_generate_random_heap_address: size inconsistency"); size = GC_heap_sects[i].hs_bytes; - if (heap_offset < size) { - break; - } else { - heap_offset -= size; - } + if (heap_offset < size) break; + heap_offset -= size; } return GC_heap_sects[i].hs_start + heap_offset; } @@ -176,6 +173,7 @@ { ptr_t result; ptr_t base; + do { result = (ptr_t)GC_generate_random_heap_address(); base = (ptr_t)GC_base(result); @@ -198,35 +196,34 @@ source = GC_get_back_ptr_info(current, &base, &offset); if (GC_UNREFERENCED == source) { GC_err_printf("Reference could not be found\n"); - goto out; + break; } if (GC_NO_SPACE == source) { GC_err_printf("No debug info in object: Can't find reference\n"); - goto out; + break; } GC_err_printf("Reachable via %d levels of pointers from ", i); - switch(source) { - case GC_REFD_FROM_ROOT: - GC_err_printf("root at %p\n\n", base); - goto out; - case GC_REFD_FROM_REG: - GC_err_printf("root in register\n\n"); - goto out; - case GC_FINALIZER_REFD: - GC_err_printf("list of finalizable objects\n\n"); - goto out; - case GC_REFD_FROM_HEAP: - GC_err_printf("offset %ld in object:\n", (long)offset); - /* Take GC_base(base) to get real base, i.e. header. */ - GC_print_heap_obj((ptr_t)GC_base(base)); - break; - default: - GC_err_printf("INTERNAL ERROR: UNEXPECTED SOURCE!!!!\n"); - goto out; + switch (source) { + case GC_REFD_FROM_ROOT: + GC_err_printf("root at %p\n\n", base); + return; + case GC_REFD_FROM_REG: + GC_err_printf("root in register\n\n"); + return; + case GC_FINALIZER_REFD: + GC_err_printf("list of finalizable objects\n\n"); + return; + case GC_REFD_FROM_HEAP: + GC_err_printf("offset %ld in object:\n", (long)offset); + /* Take GC_base(base) to get real base, i.e. header. */ + GC_print_heap_obj((ptr_t)GC_base(base)); + break; + default: + GC_err_printf("INTERNAL ERROR: UNEXPECTED SOURCE!!!!\n"); + return; } current = base; } - out:; } GC_API void GC_CALL GC_generate_random_backtrace(void) @@ -250,13 +247,13 @@ #endif /* KEEP_BACK_PTRS */ -# define CROSSES_HBLK(p, sz) \ +#define CROSSES_HBLK(p, sz) \ ((ADDR((p) + sizeof(oh) + (sz) - 1) ^ ADDR(p)) >= HBLKSIZE) GC_INNER void *GC_store_debug_info_inner(void *base, word sz, const char *string, int linenum) { - word *result = (word *)((oh *)base + 1); + GC_uintptr_t *result = (GC_uintptr_t *)((oh *)base + 1); GC_ASSERT(I_HOLD_LOCK()); GC_ASSERT(GC_size(base) >= sizeof(oh) + sz); @@ -272,10 +269,11 @@ GC_INNER void *GC_store_debug_info_inner(void *base, word sz, # ifdef SHORT_DBG_HDRS UNUSED_ARG(sz); # else - ((oh *)base) -> oh_sz = sz; - ((oh *)base) -> oh_sf = START_FLAG ^ (word)result; - ((word *)base)[BYTES_TO_WORDS(GC_size(base))-1] = - result[SIMPLE_ROUNDED_UP_WORDS(sz)] = END_FLAG ^ (word)result; + ((oh *)base) -> oh_sz = (GC_uintptr_t)sz; + ((oh *)base) -> oh_sf = START_FLAG ^ (GC_uintptr_t)result; + ((GC_uintptr_t *)base)[BYTES_TO_WORDS(GC_size(base)) - 1] + = result[SIMPLE_ROUNDED_UP_WORDS(sz)] + = END_FLAG ^ (GC_uintptr_t)result; # endif return result; } @@ -308,19 +306,22 @@ static void *store_debug_info(void *base, size_t lb, STATIC ptr_t GC_check_annotated_obj(oh *ohdr) { ptr_t body = (ptr_t)(ohdr + 1); - word gc_sz = GC_size((ptr_t)ohdr); - if (ohdr -> oh_sz + DEBUG_BYTES > gc_sz) { + word gc_sz = GC_size(ohdr); + + if (ohdr -> oh_sz + DEBUG_BYTES > (GC_uintptr_t)gc_sz) { return (ptr_t)(&(ohdr -> oh_sz)); } - if (ohdr -> oh_sf != (START_FLAG ^ (word)body)) { + if (ohdr -> oh_sf != (START_FLAG ^ (GC_uintptr_t)body)) { return (ptr_t)(&(ohdr -> oh_sf)); } - if (((word *)ohdr)[BYTES_TO_WORDS(gc_sz)-1] != (END_FLAG ^ (word)body)) { - return (ptr_t)(&((word *)ohdr)[BYTES_TO_WORDS(gc_sz)-1]); + if (((GC_uintptr_t *)ohdr)[BYTES_TO_WORDS(gc_sz) - 1] + != (END_FLAG ^ (GC_uintptr_t)body)) { + return (ptr_t)(&((GC_uintptr_t *)ohdr)[BYTES_TO_WORDS(gc_sz) - 1]); } - if (((word *)body)[SIMPLE_ROUNDED_UP_WORDS(ohdr -> oh_sz)] - != (END_FLAG ^ (word)body)) { - return (ptr_t)(&((word *)body)[SIMPLE_ROUNDED_UP_WORDS(ohdr->oh_sz)]); + if (((GC_uintptr_t *)body)[SIMPLE_ROUNDED_UP_WORDS((size_t)(ohdr -> oh_sz))] + != (END_FLAG ^ (GC_uintptr_t)body)) { + return (ptr_t)(&((GC_uintptr_t *)body)[SIMPLE_ROUNDED_UP_WORDS( + (size_t)(ohdr -> oh_sz))]); } return NULL; } @@ -335,7 +336,7 @@ GC_API void GC_CALL GC_register_describe_type_fn(int k, GC_describe_type_fns[k] = fn; } -#define GET_OH_LINENUM(ohdr) ((int)(ohdr)->oh_int) +#define GET_OH_LINENUM(ohdr) ((int)((ohdr) -> oh_int)) #ifndef SHORT_DBG_HDRS # define IF_NOT_SHORTDBG_HDRS(x) x @@ -375,21 +376,21 @@ STATIC void GC_print_obj(ptr_t base) kind_str = buffer; } else { switch (k) { - case PTRFREE: + case PTRFREE: kind_str = "PTRFREE"; break; - case NORMAL: + case NORMAL: kind_str = "NORMAL"; break; - case UNCOLLECTABLE: + case UNCOLLECTABLE: kind_str = "UNCOLLECTABLE"; break; -# ifdef GC_ATOMIC_UNCOLLECTABLE +# ifdef GC_ATOMIC_UNCOLLECTABLE case AUNCOLLECTABLE: kind_str = "ATOMIC_UNCOLLECTABLE"; break; -# endif - default: +# endif + default: kind_str = NULL; /* The alternative is to use snprintf(buffer) but it is */ /* not quite portable (see vsnprintf in misc.c). */ @@ -399,14 +400,14 @@ STATIC void GC_print_obj(ptr_t base) if (NULL != kind_str) { GC_err_printf("%p (%s:%d," IF_NOT_SHORTDBG_HDRS(" sz= %lu,") " %s)\n", (void *)((ptr_t)ohdr + sizeof(oh)), - ohdr->oh_string, GET_OH_LINENUM(ohdr) /*, */ + ohdr -> oh_string, GET_OH_LINENUM(ohdr) /*, */ COMMA_IFNOT_SHORTDBG_HDRS((unsigned long)ohdr->oh_sz), kind_str); } else { GC_err_printf("%p (%s:%d," IF_NOT_SHORTDBG_HDRS(" sz= %lu,") " kind= %d, descr= 0x%lx)\n", (void *)((ptr_t)ohdr + sizeof(oh)), - ohdr->oh_string, GET_OH_LINENUM(ohdr) /*, */ + ohdr -> oh_string, GET_OH_LINENUM(ohdr) /*, */ COMMA_IFNOT_SHORTDBG_HDRS((unsigned long)ohdr->oh_sz), k, (unsigned long)(hhdr -> hb_descr)); } @@ -425,10 +426,9 @@ STATIC void GC_debug_print_heap_obj_proc(ptr_t base) #ifndef SHORT_DBG_HDRS /* Use GC_err_printf and friends to print a description of the object */ - /* whose client-visible address is p, and which was smashed at */ - /* clobbered_addr. */ - STATIC void GC_print_smashed_obj(const char *msg, void *p, - ptr_t clobbered_addr) + /* whose client-visible address is p, and which was smashed at memory */ + /* location pointed by clobbered. */ + STATIC void GC_print_smashed_obj(const char *msg, void *p, ptr_t clobbered) { oh * ohdr = (oh *)GC_base(p); @@ -436,15 +436,15 @@ STATIC void GC_debug_print_heap_obj_proc(ptr_t base) # ifdef LINT2 if (!ohdr) ABORT("Invalid GC_print_smashed_obj argument"); # endif - if (ADDR_GE((ptr_t)(&(ohdr -> oh_sz)), clobbered_addr) - || NULL == ohdr -> oh_string) { + if (ADDR_GE((ptr_t)(&(ohdr -> oh_sz)), clobbered) + || NULL == ohdr -> oh_string) { GC_err_printf( "%s %p in or near object at %p(, appr. sz= %lu)\n", - msg, (void *)clobbered_addr, p, - (unsigned long)(GC_size((ptr_t)ohdr) - DEBUG_BYTES)); + msg, (void *)clobbered, p, + (unsigned long)(GC_size(ohdr) - DEBUG_BYTES)); } else { GC_err_printf("%s %p in or near object at %p (%s:%d, sz= %lu)\n", - msg, (void *)clobbered_addr, p, + msg, (void *)clobbered, p, ADDR(ohdr -> oh_string) < HBLKSIZE ? "(smashed string)" : ohdr -> oh_string[0] == '\0' ? "EMPTY(smashed?)" : ohdr -> oh_string, @@ -709,14 +709,6 @@ GC_API GC_ATTR_MALLOC void * GC_CALL GC_debug_malloc_uncollectable(size_t lb, } #endif /* GC_ATOMIC_UNCOLLECTABLE */ -#ifndef GC_FREED_MEM_MARKER -# if CPP_WORDSZ == 32 -# define GC_FREED_MEM_MARKER 0xdeadbeef -# else -# define GC_FREED_MEM_MARKER GC_WORD_C(0xEFBEADDEdeadbeef) -# endif -#endif - #ifdef LINT2 # include "private/gc_alloc_ptrs.h" #endif @@ -753,9 +745,9 @@ GC_API void GC_CALL GC_debug_free(void * p) ptr_t clobbered = GC_check_annotated_obj((oh *)base); word sz = GC_size(base); - if (clobbered != 0) { + if (clobbered != NULL) { GC_SET_HAVE_ERRORS(); /* no "release" barrier is needed */ - if (((oh *)base) -> oh_sz == sz) { + if (((oh *)base) -> oh_sz == (GC_uintptr_t)sz) { GC_print_smashed_obj( "GC_debug_free: found previously deallocated (?) object at", p, clobbered); @@ -766,7 +758,7 @@ GC_API void GC_CALL GC_debug_free(void * p) } } /* Invalidate size (mark the object as deallocated) */ - ((oh *)base) -> oh_sz = sz; + ((oh *)base) -> oh_sz = (GC_uintptr_t)sz; # endif /* !SHORT_DBG_HDRS */ } if (GC_find_leak @@ -789,8 +781,8 @@ GC_API void GC_CALL GC_debug_free(void * p) word obj_sz = BYTES_TO_WORDS(sz - sizeof(oh)); for (i = 0; i < obj_sz; ++i) - ((word *)p)[i] = GC_FREED_MEM_MARKER; - GC_ASSERT((word *)p + i == (word *)(base + sz)); + ((GC_uintptr_t *)p)[i] = GC_FREED_MEM_MARKER; + GC_ASSERT((GC_uintptr_t *)p + i == (GC_uintptr_t *)(base + sz)); /* Update the counter even though the real deallocation */ /* is deferred. */ LOCK(); @@ -817,7 +809,7 @@ GC_API void GC_CALL GC_debug_free(void * p) # endif # ifndef SHORT_DBG_HDRS /* Invalidate size */ - ((oh *)base) -> oh_sz = GC_size(base); + ((oh *)base) -> oh_sz = (GC_uintptr_t)GC_size(base); # endif GC_free_inner(base); } @@ -838,7 +830,7 @@ GC_API void * GC_CALL GC_debug_realloc(void * p, size_t lb, GC_EXTRA_PARAMS) } # ifdef GC_ADD_CALLER - if (s == NULL) { + if (NULL == s) { GC_caller_func_offset(ra, &s, &i); } # endif @@ -859,7 +851,7 @@ GC_API void * GC_CALL GC_debug_realloc(void * p, size_t lb, GC_EXTRA_PARAMS) # ifdef SHORT_DBG_HDRS old_sz = GC_size(base) - sizeof(oh); # else - old_sz = ((oh *)base) -> oh_sz; + old_sz = (size_t)(((oh *)base) -> oh_sz); # endif if (old_sz > 0) BCOPY(p, result, old_sz < lb ? old_sz : lb); @@ -872,48 +864,48 @@ GC_API GC_ATTR_MALLOC void * GC_CALL GC_debug_generic_or_special_malloc(size_t lb, int k, GC_EXTRA_PARAMS) { switch (k) { - case PTRFREE: - return GC_debug_malloc_atomic(lb, OPT_RA s, i); - case NORMAL: - return GC_debug_malloc(lb, OPT_RA s, i); - case UNCOLLECTABLE: - return GC_debug_malloc_uncollectable(lb, OPT_RA s, i); -# ifdef GC_ATOMIC_UNCOLLECTABLE + case PTRFREE: + return GC_debug_malloc_atomic(lb, OPT_RA s, i); + case NORMAL: + return GC_debug_malloc(lb, OPT_RA s, i); + case UNCOLLECTABLE: + return GC_debug_malloc_uncollectable(lb, OPT_RA s, i); +# ifdef GC_ATOMIC_UNCOLLECTABLE case AUNCOLLECTABLE: return GC_debug_malloc_atomic_uncollectable(lb, OPT_RA s, i); -# endif - default: - return GC_debug_generic_malloc(lb, k, OPT_RA s, i); +# endif + default: + return GC_debug_generic_malloc(lb, k, OPT_RA s, i); } } #ifndef SHORT_DBG_HDRS -/* List of smashed (clobbered) locations. We defer printing these, */ -/* since we cannot always print them nicely with the allocator lock */ -/* held. We put them here instead of in GC_arrays, since it may be */ -/* useful to be able to look at them with the debugger. */ -#ifndef MAX_SMASHED -# define MAX_SMASHED 20 -#endif -STATIC ptr_t GC_smashed[MAX_SMASHED] = {0}; -STATIC unsigned GC_n_smashed = 0; + /* List of smashed (clobbered) locations. We defer printing these, */ + /* since we cannot always print them nicely with the allocator lock */ + /* held. We put them here instead of in GC_arrays, since it may be */ + /* useful to be able to look at them with the debugger. */ +# ifndef MAX_SMASHED +# define MAX_SMASHED 20 +# endif + STATIC ptr_t GC_smashed[MAX_SMASHED] = {0}; + STATIC unsigned GC_n_smashed = 0; -STATIC void GC_add_smashed(ptr_t smashed) -{ + STATIC void GC_add_smashed(ptr_t smashed) + { GC_ASSERT(I_HOLD_LOCK()); GC_ASSERT(GC_is_marked(GC_base(smashed))); /* FIXME: Prevent adding an object while printing smashed list. */ GC_smashed[GC_n_smashed] = smashed; if (GC_n_smashed < MAX_SMASHED - 1) ++GC_n_smashed; - /* In case of overflow, we keep the first MAX_SMASHED-1 */ - /* entries plus the last one. */ + /* In case of overflow, we keep the first MAX_SMASHED-1 */ + /* entries plus the last one. */ GC_SET_HAVE_ERRORS(); -} + } -/* Print all objects on the list. Clear the list. */ -STATIC void GC_print_all_smashed_proc(void) -{ + /* Print all objects on the list. Clear the list. */ + STATIC void GC_print_all_smashed_proc(void) + { unsigned i; GC_ASSERT(I_DONT_HOLD_LOCK()); @@ -930,12 +922,12 @@ STATIC void GC_print_all_smashed_proc(void) GC_smashed[i] = 0; } GC_n_smashed = 0; -} + } -/* Check all marked objects in the given block for validity */ -/* Avoid GC_apply_to_each_object for performance reasons. */ -STATIC void GC_CALLBACK GC_check_heap_block(struct hblk *hbp, GC_word dummy) -{ + /* Check all marked objects in the given block for validity */ + /* Avoid GC_apply_to_each_object for performance reasons. */ + STATIC void GC_CALLBACK GC_check_heap_block(struct hblk *hbp, GC_word dummy) + { const hdr *hhdr = HDR(hbp); ptr_t p = hbp -> hb_body; ptr_t plim; @@ -953,55 +945,55 @@ STATIC void GC_CALLBACK GC_check_heap_block(struct hblk *hbp, GC_word dummy) if (clobbered != NULL) GC_add_smashed(clobbered); } } -} + } -/* This assumes that all accessible objects are marked. */ -/* Normally called by collector. */ -STATIC void GC_check_heap_proc(void) -{ - GC_ASSERT(I_HOLD_LOCK()); - GC_STATIC_ASSERT((sizeof(oh) & (GC_GRANULE_BYTES-1)) == 0); - /* FIXME: Should we check for twice that alignment? */ - GC_apply_to_all_blocks(GC_check_heap_block, 0); -} + /* This assumes that all accessible objects are marked. */ + /* Normally called by collector. */ + STATIC void GC_check_heap_proc(void) + { + GC_ASSERT(I_HOLD_LOCK()); + GC_STATIC_ASSERT((sizeof(oh) & (GC_GRANULE_BYTES-1)) == 0); + /* FIXME: Should we check for twice that alignment? */ + GC_apply_to_all_blocks(GC_check_heap_block, 0); + } -GC_INNER GC_bool GC_check_leaked(ptr_t base) -{ - word i; - word obj_sz; - word *p; + GC_INNER GC_bool GC_check_leaked(ptr_t base) + { + word i; + word obj_sz; + word *p; - if ( -# if defined(KEEP_BACK_PTRS) || defined(MAKE_BACK_GRAPH) - (*(word *)base & 1) != 0 && -# endif - GC_has_other_debug_info(base) >= 0) - return TRUE; /* object has leaked */ - - /* Validate freed object's content. */ - p = (word *)(base + sizeof(oh)); - obj_sz = BYTES_TO_WORDS(HDR(base) -> hb_sz - sizeof(oh)); - for (i = 0; i < obj_sz; ++i) - if (p[i] != GC_FREED_MEM_MARKER) { + if ( +# if defined(KEEP_BACK_PTRS) || defined(MAKE_BACK_GRAPH) + (*(GC_uintptr_t *)base & 1) != 0 && +# endif + GC_has_other_debug_info(base) >= 0) + return TRUE; /* object has leaked */ + + /* Validate freed object's content. */ + p = (word *)(base + sizeof(oh)); + obj_sz = BYTES_TO_WORDS(HDR(base) -> hb_sz - sizeof(oh)); + for (i = 0; i < obj_sz; ++i) + if (p[i] != GC_FREED_MEM_MARKER) { GC_set_mark_bit(base); /* do not reclaim it in this cycle */ GC_add_smashed((ptr_t)(&p[i])); /* alter-after-free detected */ break; /* don't report any other smashed locations in the object */ - } + } - return FALSE; /* GC_debug_free() has been called */ -} + return FALSE; /* GC_debug_free() has been called */ + } #endif /* !SHORT_DBG_HDRS */ #ifndef GC_NO_FINALIZATION -struct closure { + struct closure { GC_finalization_proc cl_fn; void * cl_data; -}; + }; -STATIC void * GC_make_closure(GC_finalization_proc fn, void * data) -{ + STATIC void * GC_make_closure(GC_finalization_proc fn, void *data) + { struct closure * result = # ifdef DBG_HDRS_ALL (struct closure *)GC_debug_malloc(sizeof(struct closure), GC_EXTRAS); @@ -1013,24 +1005,25 @@ STATIC void * GC_make_closure(GC_finalization_proc fn, void * data) result -> cl_data = data; } return result; -} + } + + /* An auxiliary function to make finalization work correctly with */ + /* displaced pointers introduced by the debugging allocators. */ + STATIC void GC_CALLBACK GC_debug_invoke_finalizer(void *obj, void *data) + { + struct closure *cl = (struct closure *)data; -/* An auxiliary fns to make finalization work correctly with displaced */ -/* pointers introduced by the debugging allocators. */ -STATIC void GC_CALLBACK GC_debug_invoke_finalizer(void * obj, void * data) -{ - struct closure * cl = (struct closure *) data; cl -> cl_fn((ptr_t)obj + sizeof(oh), cl -> cl_data); -} + } -/* Special finalizer_proc value to detect GC_register_finalizer() failure. */ -#define OFN_UNSET ((GC_finalization_proc)~(GC_funcptr_uint)0) + /* Special finalizer_proc value to detect GC_register_finalizer failure. */ +# define OFN_UNSET ((GC_finalization_proc)~(GC_funcptr_uint)0) -/* Set ofn and ocd to reflect the values we got back. */ -static void store_old(void *obj, GC_finalization_proc my_old_fn, - struct closure *my_old_cd, GC_finalization_proc *ofn, - void **ocd) -{ + /* Set ofn and ocd to reflect the values we got back. */ + static void store_old(void *obj, GC_finalization_proc my_old_fn, + struct closure *my_old_cd, GC_finalization_proc *ofn, + void **ocd) + { if (my_old_fn != 0) { if (my_old_fn == OFN_UNSET) { /* GC_register_finalizer() failed; (*ofn) and (*ocd) are unchanged. */ @@ -1046,121 +1039,118 @@ static void store_old(void *obj, GC_finalization_proc my_old_fn, } } else { if (ofn) *ofn = 0; - if (ocd) *ocd = 0; + if (ocd) *ocd = NULL; } -} + } -GC_API void GC_CALL GC_debug_register_finalizer(void *obj, + GC_API void GC_CALL GC_debug_register_finalizer(void *obj, GC_finalization_proc fn, void *cd, GC_finalization_proc *ofn, void **ocd) -{ + { GC_finalization_proc my_old_fn = OFN_UNSET; void * my_old_cd = NULL; /* to avoid "might be uninitialized" warning */ ptr_t base = (ptr_t)GC_base(obj); if (NULL == base) { - /* We won't collect it, hence finalizer wouldn't be run. */ - if (ocd) *ocd = 0; - if (ofn) *ofn = 0; - return; + /* We will not collect it, hence finalizer wouldn't be run. */ + if (ocd) *ocd = NULL; + if (ofn) *ofn = 0; + return; } if ((ptr_t)obj - base != sizeof(oh)) { - GC_err_printf("GC_debug_register_finalizer called with" - " non-base-pointer %p\n", obj); + GC_err_printf("GC_debug_register_finalizer called with" + " non-base-pointer %p\n", obj); } if (0 == fn) { - GC_register_finalizer(base, 0, 0, &my_old_fn, &my_old_cd); + GC_register_finalizer(base, 0, NULL, &my_old_fn, &my_old_cd); } else { cd = GC_make_closure(fn, cd); if (NULL == cd) return; /* out of memory; *ofn and *ocd are unchanged */ - GC_register_finalizer(base, GC_debug_invoke_finalizer, - cd, &my_old_fn, &my_old_cd); + GC_register_finalizer(base, GC_debug_invoke_finalizer, cd, + &my_old_fn, &my_old_cd); } store_old(obj, my_old_fn, (struct closure *)my_old_cd, ofn, ocd); -} + } -GC_API void GC_CALL GC_debug_register_finalizer_no_order(void *obj, + GC_API void GC_CALL GC_debug_register_finalizer_no_order(void *obj, GC_finalization_proc fn, void *cd, GC_finalization_proc *ofn, void **ocd) -{ + { GC_finalization_proc my_old_fn = OFN_UNSET; void * my_old_cd = NULL; ptr_t base = (ptr_t)GC_base(obj); if (NULL == base) { - /* We won't collect it, hence finalizer wouldn't be run. */ - if (ocd) *ocd = 0; - if (ofn) *ofn = 0; - return; + if (ocd) *ocd = NULL; + if (ofn) *ofn = 0; + return; } if ((ptr_t)obj - base != sizeof(oh)) { - GC_err_printf("GC_debug_register_finalizer_no_order called with" - " non-base-pointer %p\n", obj); + GC_err_printf("GC_debug_register_finalizer_no_order called with" + " non-base-pointer %p\n", obj); } if (0 == fn) { - GC_register_finalizer_no_order(base, 0, 0, &my_old_fn, &my_old_cd); + GC_register_finalizer_no_order(base, 0, NULL, &my_old_fn, &my_old_cd); } else { cd = GC_make_closure(fn, cd); if (NULL == cd) return; /* out of memory */ - GC_register_finalizer_no_order(base, GC_debug_invoke_finalizer, - cd, &my_old_fn, &my_old_cd); + GC_register_finalizer_no_order(base, GC_debug_invoke_finalizer, cd, + &my_old_fn, &my_old_cd); } store_old(obj, my_old_fn, (struct closure *)my_old_cd, ofn, ocd); -} + } -GC_API void GC_CALL GC_debug_register_finalizer_unreachable(void *obj, + GC_API void GC_CALL GC_debug_register_finalizer_unreachable(void *obj, GC_finalization_proc fn, void *cd, GC_finalization_proc *ofn, void **ocd) -{ + { GC_finalization_proc my_old_fn = OFN_UNSET; void * my_old_cd = NULL; ptr_t base = (ptr_t)GC_base(obj); if (NULL == base) { - /* We won't collect it, hence finalizer wouldn't be run. */ - if (ocd) *ocd = 0; - if (ofn) *ofn = 0; - return; + if (ocd) *ocd = NULL; + if (ofn) *ofn = 0; + return; } if ((ptr_t)obj - base != sizeof(oh)) { - GC_err_printf("GC_debug_register_finalizer_unreachable called with" - " non-base-pointer %p\n", obj); + GC_err_printf("GC_debug_register_finalizer_unreachable called with" + " non-base-pointer %p\n", obj); } if (0 == fn) { - GC_register_finalizer_unreachable(base, 0, 0, &my_old_fn, &my_old_cd); + GC_register_finalizer_unreachable(base, 0, NULL, &my_old_fn, &my_old_cd); } else { cd = GC_make_closure(fn, cd); if (NULL == cd) return; /* out of memory */ - GC_register_finalizer_unreachable(base, GC_debug_invoke_finalizer, - cd, &my_old_fn, &my_old_cd); + GC_register_finalizer_unreachable(base, GC_debug_invoke_finalizer, cd, + &my_old_fn, &my_old_cd); } store_old(obj, my_old_fn, (struct closure *)my_old_cd, ofn, ocd); -} + } -GC_API void GC_CALL GC_debug_register_finalizer_ignore_self(void *obj, + GC_API void GC_CALL GC_debug_register_finalizer_ignore_self(void *obj, GC_finalization_proc fn, void *cd, GC_finalization_proc *ofn, void **ocd) -{ + { GC_finalization_proc my_old_fn = OFN_UNSET; void * my_old_cd = NULL; ptr_t base = (ptr_t)GC_base(obj); if (NULL == base) { - /* We won't collect it, hence finalizer wouldn't be run. */ - if (ocd) *ocd = 0; - if (ofn) *ofn = 0; - return; + if (ocd) *ocd = NULL; + if (ofn) *ofn = 0; + return; } if ((ptr_t)obj - base != sizeof(oh)) { - GC_err_printf("GC_debug_register_finalizer_ignore_self called with" - " non-base-pointer %p\n", obj); + GC_err_printf("GC_debug_register_finalizer_ignore_self called with" + " non-base-pointer %p\n", obj); } if (0 == fn) { - GC_register_finalizer_ignore_self(base, 0, 0, &my_old_fn, &my_old_cd); + GC_register_finalizer_ignore_self(base, 0, NULL, &my_old_fn, &my_old_cd); } else { cd = GC_make_closure(fn, cd); if (NULL == cd) return; /* out of memory */ - GC_register_finalizer_ignore_self(base, GC_debug_invoke_finalizer, - cd, &my_old_fn, &my_old_cd); + GC_register_finalizer_ignore_self(base, GC_debug_invoke_finalizer, cd, + &my_old_fn, &my_old_cd); } store_old(obj, my_old_fn, (struct closure *)my_old_cd, ofn, ocd); -} + } # ifndef GC_TOGGLE_REFS_NOT_NEEDED GC_API int GC_CALL GC_debug_toggleref_add(void *obj, int is_strong_ref) diff --git a/gc.man b/gc.man index 86065b52c..802dfbc05 100644 --- a/gc.man +++ b/gc.man @@ -1,4 +1,4 @@ -.TH BDWGC 3 "23 Aug 2023" +.TH BDWGC 3 "10 Jun 2024" .SH NAME GC_malloc, GC_malloc_atomic, GC_free, GC_realloc, GC_enable_incremental, GC_register_finalizer, GC_malloc_ignore_off_page, @@ -21,7 +21,7 @@ void * GC_malloc_ignore_off_page(size_t size); .br void * GC_malloc_atomic_ignore_off_page(size_t size); .br -void GC_set_warn_proc(void (*proc)(char *, GC_word)); +void GC_set_warn_proc(void (*proc)(char *, GC_uintptr_t)); .br .sp cc ... -lgc diff --git a/gcj_mlc.c b/gcj_mlc.c index e6c7b1973..de2a1c79f 100644 --- a/gcj_mlc.c +++ b/gcj_mlc.c @@ -11,7 +11,6 @@ * Permission to modify the code and to distribute modified code is granted, * provided the above notices are retained, and a notice that the code was * modified is included with the above copyright notice. - * */ #include "private/gc_pmark.h" /* includes gc_priv.h */ @@ -46,24 +45,24 @@ int GC_gcj_debug_kind = 0; STATIC struct GC_ms_entry *GC_CALLBACK GC_gcj_fake_mark_proc(word *addr, struct GC_ms_entry *mark_stack_top, - struct GC_ms_entry * mark_stack_limit, word env) + struct GC_ms_entry *mark_stack_limit, word env) { UNUSED_ARG(addr); UNUSED_ARG(mark_stack_limit); UNUSED_ARG(env); -# if defined(FUNCPTR_IS_WORD) && defined(CPPCHECK) +# if defined(FUNCPTR_IS_DATAPTR) && defined(CPPCHECK) GC_noop1((word)&GC_init_gcj_malloc); # endif ABORT_RET("No client gcj mark proc is specified"); return mark_stack_top; } -#ifdef FUNCPTR_IS_WORD +#ifdef FUNCPTR_IS_DATAPTR GC_API void GC_CALL GC_init_gcj_malloc(int mp_index, void *mp) { GC_init_gcj_malloc_mp((unsigned)mp_index, (GC_mark_proc)(word)mp); } -#endif /* FUNCPTR_IS_WORD */ +#endif /* FUNCPTR_IS_DATAPTR */ GC_API void GC_CALL GC_init_gcj_malloc_mp(unsigned mp_index, GC_mark_proc mp) { diff --git a/include/gc/gc.h b/include/gc/gc.h index 0b5601c7b..1743fba91 100644 --- a/include/gc/gc.h +++ b/include/gc/gc.h @@ -58,6 +58,13 @@ typedef GC_SIGNEDWORD GC_signed_word; #undef GC_SIGNEDWORD #undef GC_UNSIGNEDWORD +#if !defined(_UINTPTR_T) && !defined(_UINTPTR_T_DEFINED) \ + && !defined(UINTPTR_MAX) + typedef GC_word GC_uintptr_t; +#else + typedef uintptr_t GC_uintptr_t; +#endif + /* Is first pointer has a smaller address than the second one? The */ /* arguments should be of the same pointer type, e.g. of char* type. */ /* Ancient compilers might treat a pointer as a signed value, thus we */ @@ -1355,7 +1362,7 @@ GC_API int GC_CALL GC_general_register_disappearing_link(void ** /* link */, /* with) are ignored. This was added after a long */ /* email discussion with John Ellis. */ /* link must be non-NULL (and be properly aligned). */ - /* obj must be a pointer to the first word of an object */ + /* obj must be a pointer to the beginning of an object */ /* allocated by GC_malloc or friends. A link */ /* disappears when it is unregistered manually, or when */ /* (*link) is cleared, or when the object containing */ @@ -1532,14 +1539,13 @@ GC_API void GC_CALL GC_noop1_ptr(volatile void *); /* data race. In GC v7.1 and before, the setter returned the old */ /* warn_proc value. */ typedef void (GC_CALLBACK * GC_warn_proc)(char * /* msg */, - GC_word /* arg */); + GC_uintptr_t /* arg */); GC_API void GC_CALL GC_set_warn_proc(GC_warn_proc /* p */) GC_ATTR_NONNULL(1); -/* GC_get_warn_proc returns the current warn_proc. */ GC_API GC_warn_proc GC_CALL GC_get_warn_proc(void); /* GC_ignore_warn_proc may be used as an argument for GC_set_warn_proc */ /* to suppress all warnings (unless statistics printing is turned on). */ -GC_API void GC_CALLBACK GC_ignore_warn_proc(char *, GC_word); +GC_API void GC_CALLBACK GC_ignore_warn_proc(char *, GC_uintptr_t); /* Change file descriptor of GC log. Unavailable on some targets. */ GC_API void GC_CALL GC_set_log_fd(int); @@ -1576,7 +1582,7 @@ GC_API void GC_CALL GC_abort_on_oom(void); /* a race with the collector (e.g., one thread might fetch hidden link */ /* value, while another thread might collect the relevant object and */ /* reuse the free space for another object). */ -typedef GC_word GC_hidden_pointer; +typedef GC_uintptr_t GC_hidden_pointer; #define GC_HIDE_POINTER(p) (~(GC_hidden_pointer)(p)) #define GC_REVEAL_POINTER(p) ((void *)GC_HIDE_POINTER(p)) @@ -1931,11 +1937,11 @@ GC_API void GC_CALL GC_dump_finalization(void); /* Note that GC_PTR_ADD evaluates the first argument more than once. */ #if defined(GC_DEBUG) && (defined(__GNUC__) || defined(__clang__)) # define GC_PTR_ADD3(x, n, type_of_result) \ - ((type_of_result)GC_same_obj((x)+(n), (x))) + ((type_of_result)GC_same_obj((x) + (n), (x))) # define GC_PRE_INCR3(x, n, type_of_result) \ - ((type_of_result)GC_pre_incr((void **)(&(x)), (n)*sizeof(*x))) + ((type_of_result)GC_pre_incr((void **)&(x), (n) * sizeof(*(x)))) # define GC_POST_INCR3(x, n, type_of_result) \ - ((type_of_result)GC_post_incr((void **)(&(x)), (n)*sizeof(*x))) + ((type_of_result)GC_post_incr((void **)&(x), (n) * sizeof(*(x)))) # define GC_PTR_ADD(x, n) GC_PTR_ADD3(x, n, __typeof__(x)) # define GC_PRE_INCR(x, n) GC_PRE_INCR3(x, n, __typeof__(x)) # define GC_POST_INCR(x) GC_POST_INCR3(x, 1, __typeof__(x)) @@ -1944,7 +1950,7 @@ GC_API void GC_CALL GC_dump_finalization(void); /* We can't do this right without typeof, which ANSI decided was not */ /* sufficiently useful. Without it we resort to the non-debug version. */ /* TODO: This should eventually support C++0x decltype. */ -# define GC_PTR_ADD(x, n) ((x)+(n)) +# define GC_PTR_ADD(x, n) ((x) + (n)) # define GC_PRE_INCR(x, n) ((x) += (n)) # define GC_POST_INCR(x) ((x)++) # define GC_POST_DECR(x) ((x)--) @@ -1979,12 +1985,12 @@ GC_API void GC_CALL GC_debug_ptr_store_and_dirty(void * /* p */, # endif #endif -/* This returns a list of objects, linked through their first word. */ -/* Its use can greatly reduce lock contention problems, since the */ -/* allocator lock can be acquired and released many fewer times. */ -/* Note that there is no "atomic" version of this function, as */ -/* otherwise the links would not be seen by the collector. */ -/* If the argument is zero, then it is treated as one. */ +/* This returns a list of objects with the link pointer located at the */ +/* beginning of each object. The use of such list can greatly reduce */ +/* lock contention problems, since the allocator lock can be acquired */ +/* and released many fewer times. Note that there is no "atomic" */ +/* version of this function, as otherwise the links would not be seen */ +/* by the collector. If the argument is zero, then it is treated as 1. */ GC_API GC_ATTR_MALLOC void * GC_CALL GC_malloc_many(size_t /* lb */); #define GC_NEXT(p) (*(void * *)(p)) /* Retrieve the next element */ /* in the returned list. */ @@ -2056,13 +2062,6 @@ GC_API void GC_CALL GC_register_has_static_roots_callback( # endif # endif -# if !defined(_UINTPTR_T) && !defined(_UINTPTR_T_DEFINED) \ - && !defined(UINTPTR_MAX) - typedef GC_word GC_uintptr_t; -# else - typedef uintptr_t GC_uintptr_t; -# endif - # ifdef _WIN64 # define GC_WIN32_SIZE_T GC_uintptr_t # elif defined(GC_WINDOWS_H_INCLUDED) diff --git a/include/private/dbg_mlc.h b/include/private/dbg_mlc.h index de069af00..939e2001c 100644 --- a/include/private/dbg_mlc.h +++ b/include/private/dbg_mlc.h @@ -32,12 +32,20 @@ EXTERN_C_BEGIN +#ifndef GC_FREED_MEM_MARKER +# if CPP_WORDSZ == 32 +# define GC_FREED_MEM_MARKER (GC_uintptr_t)0xdeadbeef +# else +# define GC_FREED_MEM_MARKER (GC_uintptr_t)GC_WORD_C(0xEFBEADDEdeadbeef) +# endif +#endif /* !GC_FREED_MEM_MARKER */ + #if CPP_WORDSZ == 32 -# define START_FLAG (word)0xfedcedcb -# define END_FLAG (word)0xbcdecdef +# define START_FLAG (GC_uintptr_t)0xfedcedcb +# define END_FLAG (GC_uintptr_t)0xbcdecdef #else -# define START_FLAG GC_WORD_C(0xFEDCEDCBfedcedcb) -# define END_FLAG GC_WORD_C(0xBCDECDEFbcdecdef) +# define START_FLAG (GC_uintptr_t)GC_WORD_C(0xFEDCEDCBfedcedcb) +# define END_FLAG (GC_uintptr_t)GC_WORD_C(0xBCDECDEFbcdecdef) #endif /* Stored both one past the end of user object, and one before */ /* the end of the object as seen by the allocator. */ @@ -46,15 +54,15 @@ EXTERN_C_BEGIN /* Pointer "source"s that aren't real locations. */ /* Used in oh_back_ptr fields and as "source" */ /* argument to some marking functions. */ -# define MARKED_FOR_FINALIZATION ((ptr_t)(word)2) +# define MARKED_FOR_FINALIZATION ((ptr_t)(GC_uintptr_t)2) /* Object was marked because it is finalizable. */ -# define MARKED_FROM_REGISTER ((ptr_t)(word)4) +# define MARKED_FROM_REGISTER ((ptr_t)(GC_uintptr_t)4) /* Object was marked from a register. Hence the */ /* source of the reference doesn't have an address. */ -# define NOT_MARKED ((ptr_t)(word)8) +# define NOT_MARKED ((ptr_t)(GC_uintptr_t)8) #endif /* KEEP_BACK_PTRS || PRINT_BLACK_LIST */ -/* Object header */ +/* Object debug header. */ typedef struct { # if defined(KEEP_BACK_PTRS) || defined(MAKE_BACK_GRAPH) /* We potentially keep two different kinds of back */ @@ -78,20 +86,15 @@ typedef struct { /* never to overwrite such a value. */ # if ALIGNMENT == 1 /* Fudge back pointer to be even. */ -# define HIDE_BACK_PTR(p) GC_HIDE_POINTER(~(word)1 & (word)(p)) +# define HIDE_BACK_PTR(p) \ + GC_HIDE_POINTER((ptr_t)(~(GC_uintptr_t)1 & (GC_uintptr_t)(p))) # else # define HIDE_BACK_PTR(p) GC_HIDE_POINTER(p) # endif -# ifdef KEEP_BACK_PTRS - GC_hidden_pointer oh_back_ptr; -# endif -# ifdef MAKE_BACK_GRAPH - GC_hidden_pointer oh_bg_ptr; -# endif -# if defined(KEEP_BACK_PTRS) != defined(MAKE_BACK_GRAPH) - /* Keep double-pointer-sized alignment. */ - word oh_dummy; -# endif + GC_hidden_pointer oh_back_ptr; + GC_hidden_pointer oh_bg_ptr; + /* Always define either none or both of the */ + /* fields to ensure double-pointer alignment. */ # endif const char * oh_string; /* object descriptor string (file name) */ signed_word oh_int; /* object descriptor integer (line number) */ @@ -99,12 +102,12 @@ typedef struct { struct callinfo oh_ci[NFRAMES]; # endif # ifndef SHORT_DBG_HDRS - word oh_sz; /* Original malloc arg. */ - word oh_sf; /* start flag */ -# endif /* SHORT_DBG_HDRS */ + GC_uintptr_t oh_sz; /* Original malloc argument. */ + GC_uintptr_t oh_sf; /* Start flag. */ +# endif } oh; /* The size of the above structure is assumed not to de-align things, */ -/* and to be a multiple of the word length. */ +/* and to be a multiple of a double-pointer length. */ #ifdef SHORT_DBG_HDRS # define DEBUG_BYTES sizeof(oh) @@ -176,7 +179,8 @@ typedef struct { /* warning. */ # else # define GC_HAS_DEBUG_INFO(base) \ - ((*(word *)(base) & 1) && GC_has_other_debug_info(base) > 0) + ((*(GC_uintptr_t *)(base) & 1) != 0 \ + && GC_has_other_debug_info(base) > 0) # endif #else # define GC_HAS_DEBUG_INFO(base) (GC_has_other_debug_info(base) > 0) diff --git a/include/private/gc_priv.h b/include/private/gc_priv.h index d2b6a47b3..f182789dd 100644 --- a/include/private/gc_priv.h +++ b/include/private/gc_priv.h @@ -184,8 +184,8 @@ typedef int GC_bool; # define GC_ATTR_WORD_ALIGNED /* empty */ #endif - typedef GC_word GC_funcptr_uint; -# define FUNCPTR_IS_WORD + typedef GC_uintptr_t GC_funcptr_uint; +# define FUNCPTR_IS_DATAPTR typedef unsigned int unsigned32; @@ -290,6 +290,27 @@ typedef struct hblkhdr hdr; #include "gc_locks.h" +#ifdef GC_ASSERTIONS +# define GC_ASSERT(expr) \ + do { \ + if (EXPECT(!(expr), FALSE)) { \ + GC_err_printf("Assertion failure: %s:%d\n", __FILE__, __LINE__); \ + ABORT("assertion failure"); \ + } \ + } while (0) +#else +# define GC_ASSERT(expr) +#endif + +#include "gc/gc_inline.h" + +/*********************************/ +/* */ +/* Definitions for conservative */ +/* collector. */ +/* */ +/*********************************/ + #define GC_WORD_MAX (~(word)0) /* Convert given pointer to its address. Result is of word type. */ @@ -322,27 +343,6 @@ typedef struct hblkhdr hdr; # define GC_FAR #endif -#ifdef GC_ASSERTIONS -# define GC_ASSERT(expr) \ - do { \ - if (EXPECT(!(expr), FALSE)) { \ - GC_err_printf("Assertion failure: %s:%d\n", __FILE__, __LINE__); \ - ABORT("assertion failure"); \ - } \ - } while (0) -#else -# define GC_ASSERT(expr) -#endif - -#include "gc/gc_inline.h" - -/*********************************/ -/* */ -/* Definitions for conservative */ -/* collector */ -/* */ -/*********************************/ - /*********************************/ /* */ /* Easily changeable parameters */ @@ -747,7 +747,7 @@ EXTERN_C_BEGIN #define WARN(msg, arg) \ (*GC_current_warn_proc)((/* no const */ char *) \ (word)("GC Warning: " msg), \ - (word)(arg)) + (GC_uintptr_t)(arg)) GC_EXTERN GC_warn_proc GC_current_warn_proc; /* Print format type macro for decimal signed_word value passed WARN(). */ @@ -755,8 +755,8 @@ GC_EXTERN GC_warn_proc GC_current_warn_proc; /* not be done as the WARN format string is, possibly, processed on the */ /* client side, so non-standard print type modifiers (like MS "I64d") */ /* should be avoided here if possible. */ +/* TODO: Assuming sizeof(void*) == sizeof(long) or a little-endian machine. */ #ifndef WARN_PRIdPTR - /* Assume sizeof(void *) == sizeof(long) or a little-endian machine. */ # define WARN_PRIdPTR "ld" # define WARN_PRIuPTR "lu" #endif @@ -1640,7 +1640,7 @@ struct _GC_arrays { /* the allocator lock held. */ # ifndef MARK_BIT_PER_OBJ # define GC_obj_map GC_arrays._obj_map - unsigned short * _obj_map[MAXOBJGRANULES + 1]; + unsigned short * _obj_map[MAXOBJGRANULES+1]; /* If not NULL, then a pointer to a map of valid */ /* object addresses. GC_obj_map[lg][i] is */ /* i % lg. This is now used purely to replace */ @@ -1938,7 +1938,7 @@ struct GC_traced_stack_sect_s { /* offset and size (in bytes). */ # define MARK_BIT_OFFSET(sz) 1 /* Spacing between useful mark bits. */ -# define FINAL_MARK_BIT(sz) ((sz) > MAXOBJBYTES? 1 : HBLK_OBJS(sz)) +# define FINAL_MARK_BIT(sz) ((sz) > MAXOBJBYTES ? 1 : HBLK_OBJS(sz)) /* Position of final, always set, mark bit. */ #else # define MARK_BIT_NO(offset, sz) BYTES_TO_GRANULES((word)(offset)) @@ -1989,7 +1989,7 @@ GC_INNER GC_bool GC_collection_in_progress(void); /* Push contents of the symbol residing in the static roots area */ /* excluded from scanning by the the collector for a reason. */ /* Note: it should be used only for symbols of relatively small size */ -/* (one or several words). */ +/* (containing one or several pointers). */ #define GC_PUSH_ALL_SYM(sym) GC_push_all_eager(&(sym), &(sym) + 1) GC_INNER void GC_push_all_stack(ptr_t b, ptr_t t); @@ -2161,7 +2161,7 @@ GC_INNER void GC_with_callee_saves_pushed(GC_with_callee_saves_func fn, #if defined(AMIGA) || defined(MACOS) || defined(GC_DARWIN_THREADS) void GC_push_one(word p); /* If p points to an object, mark it */ - /* and push contents on the mark stack */ + /* and push contents on the mark stack. */ /* Pointer recognition test always */ /* accepts interior pointers, i.e. this */ /* is appropriate for pointers found on */ diff --git a/mallocx.c b/mallocx.c index 0481d93af..2c2a16e0d 100644 --- a/mallocx.c +++ b/mallocx.c @@ -78,11 +78,13 @@ GC_API void * GC_CALL GC_realloc(void * p, size_t lb) hdr * hhdr; void * result; # if defined(_FORTIFY_SOURCE) && defined(__GNUC__) && !defined(__clang__) - volatile /* Use cleared_p instead of p as a workaround to avoid */ - /* passing alloc_size(lb) attribute associated with p */ - /* to memset (including memset call inside GC_free). */ + /* Use cleared_p instead of p as a workaround to avoid */ + /* passing alloc_size(lb) attribute associated with p to */ + /* memset (including a memset call inside GC_free). */ + volatile GC_uintptr_t cleared_p = (GC_uintptr_t)p; +# else +# define cleared_p p # endif - word cleared_p = (word)p; size_t sz; /* Current size in bytes */ size_t orig_sz; /* Original sz in bytes */ int obj_kind; @@ -173,6 +175,7 @@ GC_API void * GC_CALL GC_realloc(void * p, size_t lb) # endif } return result; +# undef cleared_p } # if defined(REDIRECT_MALLOC) && !defined(REDIRECT_REALLOC) diff --git a/misc.c b/misc.c index 7a7ab9d9c..fe82ae8c3 100644 --- a/misc.c +++ b/misc.c @@ -1330,11 +1330,12 @@ GC_API void GC_CALL GC_init(void) } # endif # if !defined(CPPCHECK) - GC_STATIC_ASSERT(sizeof(ptr_t) == sizeof(word)); + GC_STATIC_ASSERT(sizeof(ptrdiff_t) == sizeof(word)); GC_STATIC_ASSERT(sizeof(signed_word) == sizeof(word)); + GC_STATIC_ASSERT(sizeof(ptr_t) == sizeof(GC_uintptr_t)); GC_STATIC_ASSERT(sizeof(GC_oom_func) == sizeof(GC_funcptr_uint)); -# ifdef FUNCPTR_IS_WORD - GC_STATIC_ASSERT(sizeof(word) == sizeof(GC_funcptr_uint)); +# ifdef FUNCPTR_IS_DATAPTR + GC_STATIC_ASSERT(sizeof(ptr_t) == sizeof(GC_funcptr_uint)); # endif # if !defined(_AUX_SOURCE) || defined(__GNUC__) GC_STATIC_ASSERT((word)(-1) > (word)0); @@ -1996,7 +1997,7 @@ void GC_err_puts(const char *s) (void)WRITE(GC_stderr, s, strlen(s)); /* ignore errors */ } -STATIC void GC_CALLBACK GC_default_warn_proc(char *msg, GC_word arg) +STATIC void GC_CALLBACK GC_default_warn_proc(char *msg, GC_uintptr_t arg) { /* TODO: Add assertion on arg comply with msg (format). */ # if defined(CPPCHECK) @@ -2010,7 +2011,7 @@ STATIC void GC_CALLBACK GC_default_warn_proc(char *msg, GC_word arg) GC_INNER GC_warn_proc GC_current_warn_proc = GC_default_warn_proc; /* This is recommended for production code (release). */ -GC_API void GC_CALLBACK GC_ignore_warn_proc(char *msg, GC_word arg) +GC_API void GC_CALLBACK GC_ignore_warn_proc(char *msg, GC_uintptr_t arg) { if (GC_print_stats) { /* Don't ignore warnings if stats printing is on. */ diff --git a/pthread_support.c b/pthread_support.c index 5be420707..4975e3452 100644 --- a/pthread_support.c +++ b/pthread_support.c @@ -1558,7 +1558,7 @@ GC_INNER_WIN32THREAD void GC_record_stack_base(GC_stack_context_t crtn, if ((crtn -> stack_end = (ptr_t)(sb -> mem_base)) == NULL) ABORT("Bad stack base in GC_register_my_thread"); # ifdef E2K - crtn -> ps_ofs = (size_t)ADDR(sb -> reg_base); + crtn -> ps_ofs = (size_t)(GC_uintptr_t)(sb -> reg_base); # elif defined(IA64) crtn -> backing_store_end = (ptr_t)(sb -> reg_base); # elif defined(I386) && defined(GC_WIN32_THREADS) @@ -1993,7 +1993,7 @@ GC_API void GC_CALL GC_set_stackbottom(void *gc_thread_handle, crtn -> stack_end = (ptr_t)(sb -> mem_base); # ifdef E2K - crtn -> ps_ofs = (size_t)ADDR(sb -> reg_base); + crtn -> ps_ofs = (size_t)(GC_uintptr_t)(sb -> reg_base); # elif defined(IA64) crtn -> backing_store_end = (ptr_t)(sb -> reg_base); # endif @@ -2014,7 +2014,8 @@ GC_API void * GC_CALL GC_get_my_stackbottom(struct GC_stack_base *sb) crtn = me -> crtn; sb -> mem_base = crtn -> stack_end; # ifdef E2K - sb -> reg_base = (void *)(word)(crtn -> ps_ofs); + /* Store the offset in the procedure stack, not address. */ + sb -> reg_base = (void *)(GC_uintptr_t)(crtn -> ps_ofs); # elif defined(IA64) sb -> reg_base = crtn -> backing_store_end; # endif @@ -2478,7 +2479,7 @@ GC_API int GC_CALL GC_register_my_thread(const struct GC_stack_base *sb) *pstart = psi -> start_routine; *pstart_arg = psi -> arg; -# if defined(DEBUG_THREADS) && defined(FUNCPTR_IS_WORD) +# if defined(DEBUG_THREADS) && defined(FUNCPTR_IS_DATAPTR) GC_log_printf("start_routine= %p\n", (void *)(word)(*pstart)); # endif sem_post(&(psi -> registered)); /* Last action on *psi; */ diff --git a/tests/cpp.cc b/tests/cpp.cc index 15fa9d32e..2e8a1839d 100644 --- a/tests/cpp.cc +++ b/tests/cpp.cc @@ -240,12 +240,12 @@ int F::nFreedF = 0; int F::nAllocatedF = 0; -GC_word Disguise( void* p ) { +GC_uintptr_t Disguise(void *p) { return GC_HIDE_NZ_POINTER(p); } -void* Undisguise( GC_word i ) { - return GC_REVEAL_NZ_POINTER(i); +void* Undisguise(GC_uintptr_t v) { + return GC_REVEAL_NZ_POINTER(v); } #define GC_CHECKED_DELETE(p) \ @@ -352,8 +352,8 @@ void* Undisguise( GC_word i ) { /* Allocate some uncollectible As and disguise their pointers. Later we'll check to see if the objects are still there. We're checking to make sure these objects really are uncollectible. */ - GC_word as[ 1000 ]; - GC_word bs[ 1000 ]; + GC_uintptr_t as[1000]; + GC_uintptr_t bs[1000]; for (i = 0; i < 1000; i++) { as[ i ] = Disguise( new (GC_NS_QUALIFY(NoGC)) A(i) ); bs[ i ] = Disguise( new (GC_NS_QUALIFY(NoGC)) B(i) ); } diff --git a/tests/gctest.c b/tests/gctest.c index 515d0493a..90d5dd788 100644 --- a/tests/gctest.c +++ b/tests/gctest.c @@ -311,8 +311,8 @@ struct SEXPR { typedef struct SEXPR * sexpr; -# define INT_TO_SEXPR(x) ((sexpr)(GC_word)(x)) -# define SEXPR_TO_INT(x) ((int)(GC_word)(x)) +# define INT_TO_SEXPR(v) ((sexpr)(GC_uintptr_t)(unsigned)(v)) +# define SEXPR_TO_INT(p) ((int)(GC_word)(p)) # undef nil # define nil (INT_TO_SEXPR(0)) @@ -464,7 +464,7 @@ static sexpr reverse1(sexpr x, sexpr y) static sexpr reverse(sexpr x) { # ifdef TEST_WITH_SYSTEM_MALLOC - GC_noop1(GC_HIDE_NZ_POINTER(checkOOM(malloc(100000)))); + GC_noop1((GC_word)GC_HIDE_NZ_POINTER(checkOOM(malloc(100000)))); # endif return reverse1(x, nil); } @@ -853,7 +853,8 @@ static void *GC_CALLBACK reverse_test_inner(void *data) if (data == 0) { /* This stack frame is not guaranteed to be scanned. */ - return GC_call_with_gc_active(reverse_test_inner, (void*)(GC_word)1); + return GC_call_with_gc_active(reverse_test_inner, + (void *)(GC_uintptr_t)1); } # if defined(CPPCHECK) @@ -1018,7 +1019,7 @@ int dropped_something = 0; tn *t = (tn *)obj; FINALIZER_LOCK(); - if ((int)(GC_word)client_data != t -> level) { + if ((int)(GC_uintptr_t)client_data != t -> level) { GC_printf("Wrong finalization data - collector is broken\n"); FAIL; } @@ -1101,7 +1102,7 @@ static tn * mktree(int n) # ifndef GC_NO_FINALIZATION if (!GC_get_find_leak()) { - GC_REGISTER_FINALIZER(result, finalizer, (void *)(GC_word)n, + GC_REGISTER_FINALIZER(result, finalizer, (void *)(GC_uintptr_t)n, (GC_finalization_proc *)0, (void **)0); if (my_index >= MAX_FINALIZED) { GC_printf("live_indicators overflowed\n"); @@ -2222,12 +2223,12 @@ void SetMinimumStack(long minSize) #define cMinStackSpace (512L * 1024L) #endif -static void GC_CALLBACK warn_proc(char *msg, GC_word p) +static void GC_CALLBACK warn_proc(char *msg, GC_uintptr_t arg) { # if defined(CPPCHECK) GC_noop1_ptr(msg); # endif - GC_printf(msg, (unsigned long)p); + GC_printf(msg, arg); /*FAIL;*/ } diff --git a/thread_local_alloc.c b/thread_local_alloc.c index 25b5d8be3..d5f20947b 100644 --- a/thread_local_alloc.c +++ b/thread_local_alloc.c @@ -65,7 +65,7 @@ static void return_freelists(void **fl, void **gfl) } /* Clear fl[i], since the thread structure may hang around. */ /* Do it in a way that is likely to trap if we access it. */ - fl[i] = (ptr_t)HBLKSIZE; + fl[i] = (ptr_t)(GC_uintptr_t)HBLKSIZE; } /* The 0 granule freelist really contains 1 granule objects. */ if (ADDR(fl[0]) >= HBLKSIZE @@ -112,10 +112,10 @@ GC_INNER void GC_init_thread_local(GC_tlfs p) } for (j = 0; j < GC_TINY_FREELISTS; ++j) { for (k = 0; k < THREAD_FREELISTS_KINDS; ++k) { - p -> _freelists[k][j] = (void *)(word)1; + p -> _freelists[k][j] = (void *)(GC_uintptr_t)1; } # ifdef GC_GCJ_SUPPORT - p -> gcj_freelists[j] = (void *)(word)1; + p -> gcj_freelists[j] = (void *)(GC_uintptr_t)1; # endif } /* The size 0 free lists are handled like the regular free lists, */