X-Git-Url: http://repo.macrolet.net/gitweb/?a=blobdiff_plain;f=src%2Fruntime%2Fgc-common.c;h=81ffae4bd8de7777d23dead0c48ffb679eec72ad;hb=f7faed97898dd0e94a18b0d1fca03aaa0fe24ab0;hp=a3eb313233f68b22cab2e67a5814ab099be16d05;hpb=a369686d65039bc87497039ac4db6c4c7c44f443;p=sbcl.git diff --git a/src/runtime/gc-common.c b/src/runtime/gc-common.c index a3eb313..81ffae4 100644 --- a/src/runtime/gc-common.c +++ b/src/runtime/gc-common.c @@ -52,8 +52,8 @@ #endif #endif -size_t dynamic_space_size = DEFAULT_DYNAMIC_SPACE_SIZE; -size_t thread_control_stack_size = DEFAULT_CONTROL_STACK_SIZE; +os_vm_size_t dynamic_space_size = DEFAULT_DYNAMIC_SPACE_SIZE; +os_vm_size_t thread_control_stack_size = DEFAULT_CONTROL_STACK_SIZE; inline static boolean forwarding_pointer_p(lispobj *pointer) { @@ -90,8 +90,7 @@ lispobj (*transother[256])(lispobj object); long (*sizetab[256])(lispobj *where); struct weak_pointer *weak_pointers; -unsigned long bytes_consed_between_gcs = 12*1024*1024; - +os_vm_size_t bytes_consed_between_gcs = 12*1024*1024; /* * copying objects @@ -2409,6 +2408,231 @@ gc_search_space(lispobj *start, size_t words, lispobj *pointer) return (NULL); } +/* Helper for valid_lisp_pointer_p (below) and + * possibly_valid_dynamic_space_pointer (gencgc). + * + * pointer is the pointer to validate, and start_addr is the address + * of the enclosing object. + */ +int +looks_like_valid_lisp_pointer_p(lispobj pointer, lispobj *start_addr) +{ + if (!is_lisp_pointer(pointer)) { + return 0; + } + + /* Check that the object pointed to is consistent with the pointer + * low tag. */ + switch (lowtag_of(pointer)) { + case FUN_POINTER_LOWTAG: + /* Start_addr should be the enclosing code object, or a closure + * header. */ + switch (widetag_of(*start_addr)) { + case CODE_HEADER_WIDETAG: + /* Make sure we actually point to a function in the code object, + * as opposed to a random point there. */ + if (SIMPLE_FUN_HEADER_WIDETAG==widetag_of(native_pointer(pointer)[0])) + return 1; + else + return 0; + case CLOSURE_HEADER_WIDETAG: + case FUNCALLABLE_INSTANCE_HEADER_WIDETAG: + if (pointer != make_lispobj(start_addr, FUN_POINTER_LOWTAG)) { + return 0; + } + break; + default: + return 0; + } + break; + case LIST_POINTER_LOWTAG: + if (pointer != make_lispobj(start_addr, LIST_POINTER_LOWTAG)) { + return 0; + } + /* Is it plausible cons? */ + if ((is_lisp_pointer(start_addr[0]) || + is_lisp_immediate(start_addr[0])) && + (is_lisp_pointer(start_addr[1]) || + is_lisp_immediate(start_addr[1]))) + break; + else { + return 0; + } + case INSTANCE_POINTER_LOWTAG: + if (pointer != make_lispobj(start_addr, INSTANCE_POINTER_LOWTAG)) { + return 0; + } + if (widetag_of(start_addr[0]) != INSTANCE_HEADER_WIDETAG) { + return 0; + } + break; + case OTHER_POINTER_LOWTAG: + +#if !defined(LISP_FEATURE_X86) && !defined(LISP_FEATURE_X86_64) + /* The all-architecture test below is good as far as it goes, + * but an LRA object is similar to a FUN-POINTER: It is + * embedded within a CODE-OBJECT pointed to by start_addr, and + * cannot be found by simply walking the heap, therefore we + * need to check for it. -- AB, 2010-Jun-04 */ + if ((widetag_of(start_addr[0]) == CODE_HEADER_WIDETAG)) { + lispobj *potential_lra = native_pointer(pointer); + if ((widetag_of(potential_lra[0]) == RETURN_PC_HEADER_WIDETAG) && + ((potential_lra - HeaderValue(potential_lra[0])) == start_addr)) { + return 1; /* It's as good as we can verify. */ + } + } +#endif + + if (pointer != make_lispobj(start_addr, OTHER_POINTER_LOWTAG)) { + return 0; + } + /* Is it plausible? Not a cons. XXX should check the headers. */ + if (is_lisp_pointer(start_addr[0]) || ((start_addr[0] & 3) == 0)) { + return 0; + } + switch (widetag_of(start_addr[0])) { + case UNBOUND_MARKER_WIDETAG: + case NO_TLS_VALUE_MARKER_WIDETAG: + case CHARACTER_WIDETAG: +#if N_WORD_BITS == 64 + case SINGLE_FLOAT_WIDETAG: +#endif + return 0; + + /* only pointed to by function pointers? */ + case CLOSURE_HEADER_WIDETAG: + case FUNCALLABLE_INSTANCE_HEADER_WIDETAG: + return 0; + + case INSTANCE_HEADER_WIDETAG: + return 0; + + /* the valid other immediate pointer objects */ + case SIMPLE_VECTOR_WIDETAG: + case RATIO_WIDETAG: + case COMPLEX_WIDETAG: +#ifdef COMPLEX_SINGLE_FLOAT_WIDETAG + case COMPLEX_SINGLE_FLOAT_WIDETAG: +#endif +#ifdef COMPLEX_DOUBLE_FLOAT_WIDETAG + case COMPLEX_DOUBLE_FLOAT_WIDETAG: +#endif +#ifdef COMPLEX_LONG_FLOAT_WIDETAG + case COMPLEX_LONG_FLOAT_WIDETAG: +#endif + case SIMPLE_ARRAY_WIDETAG: + case COMPLEX_BASE_STRING_WIDETAG: +#ifdef COMPLEX_CHARACTER_STRING_WIDETAG + case COMPLEX_CHARACTER_STRING_WIDETAG: +#endif + case COMPLEX_VECTOR_NIL_WIDETAG: + case COMPLEX_BIT_VECTOR_WIDETAG: + case COMPLEX_VECTOR_WIDETAG: + case COMPLEX_ARRAY_WIDETAG: + case VALUE_CELL_HEADER_WIDETAG: + case SYMBOL_HEADER_WIDETAG: + case FDEFN_WIDETAG: + case CODE_HEADER_WIDETAG: + case BIGNUM_WIDETAG: +#if N_WORD_BITS != 64 + case SINGLE_FLOAT_WIDETAG: +#endif + case DOUBLE_FLOAT_WIDETAG: +#ifdef LONG_FLOAT_WIDETAG + case LONG_FLOAT_WIDETAG: +#endif + case SIMPLE_BASE_STRING_WIDETAG: +#ifdef SIMPLE_CHARACTER_STRING_WIDETAG + case SIMPLE_CHARACTER_STRING_WIDETAG: +#endif + case SIMPLE_BIT_VECTOR_WIDETAG: + case SIMPLE_ARRAY_NIL_WIDETAG: + case SIMPLE_ARRAY_UNSIGNED_BYTE_2_WIDETAG: + case SIMPLE_ARRAY_UNSIGNED_BYTE_4_WIDETAG: + case SIMPLE_ARRAY_UNSIGNED_BYTE_7_WIDETAG: + case SIMPLE_ARRAY_UNSIGNED_BYTE_8_WIDETAG: + case SIMPLE_ARRAY_UNSIGNED_BYTE_15_WIDETAG: + case SIMPLE_ARRAY_UNSIGNED_BYTE_16_WIDETAG: + + case SIMPLE_ARRAY_UNSIGNED_FIXNUM_WIDETAG: + + case SIMPLE_ARRAY_UNSIGNED_BYTE_31_WIDETAG: + case SIMPLE_ARRAY_UNSIGNED_BYTE_32_WIDETAG: +#ifdef SIMPLE_ARRAY_UNSIGNED_BYTE_63_WIDETAG + case SIMPLE_ARRAY_UNSIGNED_BYTE_63_WIDETAG: +#endif +#ifdef SIMPLE_ARRAY_UNSIGNED_BYTE_64_WIDETAG + case SIMPLE_ARRAY_UNSIGNED_BYTE_64_WIDETAG: +#endif +#ifdef SIMPLE_ARRAY_SIGNED_BYTE_8_WIDETAG + case SIMPLE_ARRAY_SIGNED_BYTE_8_WIDETAG: +#endif +#ifdef SIMPLE_ARRAY_SIGNED_BYTE_16_WIDETAG + case SIMPLE_ARRAY_SIGNED_BYTE_16_WIDETAG: +#endif + + case SIMPLE_ARRAY_FIXNUM_WIDETAG: + +#ifdef SIMPLE_ARRAY_SIGNED_BYTE_32_WIDETAG + case SIMPLE_ARRAY_SIGNED_BYTE_32_WIDETAG: +#endif +#ifdef SIMPLE_ARRAY_SIGNED_BYTE_64_WIDETAG + case SIMPLE_ARRAY_SIGNED_BYTE_64_WIDETAG: +#endif + case SIMPLE_ARRAY_SINGLE_FLOAT_WIDETAG: + case SIMPLE_ARRAY_DOUBLE_FLOAT_WIDETAG: +#ifdef SIMPLE_ARRAY_LONG_FLOAT_WIDETAG + case SIMPLE_ARRAY_LONG_FLOAT_WIDETAG: +#endif +#ifdef SIMPLE_ARRAY_COMPLEX_SINGLE_FLOAT_WIDETAG + case SIMPLE_ARRAY_COMPLEX_SINGLE_FLOAT_WIDETAG: +#endif +#ifdef SIMPLE_ARRAY_COMPLEX_DOUBLE_FLOAT_WIDETAG + case SIMPLE_ARRAY_COMPLEX_DOUBLE_FLOAT_WIDETAG: +#endif +#ifdef SIMPLE_ARRAY_COMPLEX_LONG_FLOAT_WIDETAG + case SIMPLE_ARRAY_COMPLEX_LONG_FLOAT_WIDETAG: +#endif + case SAP_WIDETAG: + case WEAK_POINTER_WIDETAG: + break; + + default: + return 0; + } + break; + default: + return 0; + } + + /* looks good */ + return 1; +} + +/* Used by the debugger to validate possibly bogus pointers before + * calling MAKE-LISP-OBJ on them. + * + * FIXME: We would like to make this perfect, because if the debugger + * constructs a reference to a bugs lisp object, and it ends up in a + * location scavenged by the GC all hell breaks loose. + * + * Whereas possibly_valid_dynamic_space_pointer has to be conservative + * and return true for all valid pointers, this could actually be eager + * and lie about a few pointers without bad results... but that should + * be reflected in the name. + */ +int +valid_lisp_pointer_p(lispobj *pointer) +{ + lispobj *start; + if (((start=search_dynamic_space(pointer))!=NULL) || + ((start=search_static_space(pointer))!=NULL) || + ((start=search_read_only_space(pointer))!=NULL)) + return looks_like_valid_lisp_pointer_p((lispobj)pointer, start); + else + return 0; +} + boolean maybe_gc(os_context_t *context) { @@ -2516,12 +2740,13 @@ scrub_control_stack(void) struct thread *th = arch_os_get_current_thread(); os_vm_address_t guard_page_address = CONTROL_STACK_GUARD_PAGE(th); os_vm_address_t hard_guard_page_address = CONTROL_STACK_HARD_GUARD_PAGE(th); - lispobj *sp; #ifdef LISP_FEATURE_C_STACK_IS_CONTROL_STACK - sp = (lispobj *)&sp - 1; + /* On these targets scrubbing from C is a bad idea, so we punt to + * a routine in $ARCH-assem.S. */ + extern void arch_scrub_control_stack(struct thread *, os_vm_address_t, os_vm_address_t); + arch_scrub_control_stack(th, guard_page_address, hard_guard_page_address); #else - sp = access_control_stack_pointer(th); -#endif + lispobj *sp = access_control_stack_pointer(th); scrub: if ((((os_vm_address_t)sp < (hard_guard_page_address + os_vm_page_size)) && ((os_vm_address_t)sp >= hard_guard_page_address)) || @@ -2550,6 +2775,7 @@ scrub_control_stack(void) goto scrub; } while (((unsigned long)++sp) & (BYTES_ZERO_BEFORE_END - 1)); #endif +#endif /* LISP_FEATURE_C_STACK_IS_CONTROL_STACK */ } #if !defined(LISP_FEATURE_X86) && !defined(LISP_FEATURE_X86_64)