X-Git-Url: http://repo.macrolet.net/gitweb/?a=blobdiff_plain;f=src%2Fruntime%2Fgc-common.c;h=96ac8df05e719371dc08bd214cc1a4c4ec5e3a91;hb=eac461c1f1ca91cfe282c779291d582ed6b336cb;hp=6db65fc592bb6db9857955f813c63fe320fdb496;hpb=3cd198ea8fb1635057038934730624e68b5da012;p=sbcl.git diff --git a/src/runtime/gc-common.c b/src/runtime/gc-common.c index 6db65fc..96ac8df 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) { @@ -95,27 +95,8 @@ os_vm_size_t bytes_consed_between_gcs = 12*1024*1024; /* * copying objects */ -static -lispobj -gc_general_copy_object(lispobj object, long nwords, int page_type_flag) -{ - int tag; - lispobj *new; - - gc_assert(is_lisp_pointer(object)); - gc_assert(from_space_p(object)); - gc_assert((nwords & 0x01) == 0); - /* Get tag of object. */ - tag = lowtag_of(object); - - /* Allocate space. */ - new = gc_general_alloc(nwords*N_WORD_BYTES, page_type_flag, ALLOC_QUICK); - - /* Copy the object. */ - memcpy(new,native_pointer(object),nwords*N_WORD_BYTES); - return make_lispobj(new,tag); -} +/* gc_general_copy_object is inline from gc-internal.h */ /* to copy a boxed object */ lispobj @@ -2415,30 +2396,29 @@ gc_search_space(lispobj *start, size_t words, lispobj *pointer) * of the enclosing object. */ int -looks_like_valid_lisp_pointer_p(lispobj *pointer, lispobj *start_addr) +looks_like_valid_lisp_pointer_p(lispobj pointer, lispobj *start_addr) { - if (!is_lisp_pointer((lispobj)pointer)) { + if (!is_lisp_pointer(pointer)) { return 0; } /* Check that the object pointed to is consistent with the pointer * low tag. */ - switch (lowtag_of((lispobj)pointer)) { + 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(*((lispobj *)(((unsigned long)pointer)-FUN_POINTER_LOWTAG)))) - return 1; - else - return 0; + /* 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 ((unsigned long)pointer != - ((unsigned long)start_addr+FUN_POINTER_LOWTAG)) { + if (pointer != make_lispobj(start_addr, FUN_POINTER_LOWTAG)) { return 0; } break; @@ -2447,8 +2427,7 @@ looks_like_valid_lisp_pointer_p(lispobj *pointer, lispobj *start_addr) } break; case LIST_POINTER_LOWTAG: - if ((unsigned long)pointer != - ((unsigned long)start_addr+LIST_POINTER_LOWTAG)) { + if (pointer != make_lispobj(start_addr, LIST_POINTER_LOWTAG)) { return 0; } /* Is it plausible cons? */ @@ -2461,8 +2440,7 @@ looks_like_valid_lisp_pointer_p(lispobj *pointer, lispobj *start_addr) return 0; } case INSTANCE_POINTER_LOWTAG: - if ((unsigned long)pointer != - ((unsigned long)start_addr+INSTANCE_POINTER_LOWTAG)) { + if (pointer != make_lispobj(start_addr, INSTANCE_POINTER_LOWTAG)) { return 0; } if (widetag_of(start_addr[0]) != INSTANCE_HEADER_WIDETAG) { @@ -2478,8 +2456,7 @@ looks_like_valid_lisp_pointer_p(lispobj *pointer, lispobj *start_addr) * 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 = - (lispobj *)(((unsigned long)pointer) - OTHER_POINTER_LOWTAG); + 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. */ @@ -2487,8 +2464,7 @@ looks_like_valid_lisp_pointer_p(lispobj *pointer, lispobj *start_addr) } #endif - if ((unsigned long)pointer != - ((unsigned long)start_addr+OTHER_POINTER_LOWTAG)) { + if (pointer != make_lispobj(start_addr, OTHER_POINTER_LOWTAG)) { return 0; } /* Is it plausible? Not a cons. XXX should check the headers. */ @@ -2633,7 +2609,7 @@ valid_lisp_pointer_p(lispobj *pointer) 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(pointer, start); + return looks_like_valid_lisp_pointer_p((lispobj)pointer, start); else return 0; } @@ -2667,7 +2643,7 @@ maybe_gc(os_context_t *context) * A kludgy alternative is to propagate the sigmask change to the * outer context. */ -#ifndef LISP_FEATURE_WIN32 +#if !(defined(LISP_FEATURE_WIN32) || defined(LISP_FEATURE_SB_SAFEPOINT)) check_gc_signals_unblocked_or_lose(os_context_sigmask_addr(context)); unblock_gc_signals(0, 0); #endif @@ -2692,8 +2668,10 @@ maybe_gc(os_context_t *context) sigset_t *context_sigmask = os_context_sigmask_addr(context); if (!deferrables_blocked_p(context_sigmask)) { thread_sigmask(SIG_SETMASK, context_sigmask, 0); +#ifndef LISP_FEATURE_SB_SAFEPOINT check_gc_signals_unblocked_or_lose(0); #endif +#endif FSHOW((stderr, "/maybe_gc: calling POST_GC\n")); funcall0(StaticSymbolFunction(POST_GC)); #ifndef LISP_FEATURE_WIN32 @@ -2745,12 +2723,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)) || @@ -2779,10 +2758,57 @@ 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) +void +scavenge_control_stack(struct thread *th) +{ + lispobj *object_ptr; + + /* In order to properly support dynamic-extent allocation of + * non-CONS objects, the control stack requires special handling. + * Rather than calling scavenge() directly, grovel over it fixing + * broken hearts, scavenging pointers to oldspace, and pitching a + * fit when encountering unboxed data. This prevents stray object + * headers from causing the scavenger to blow past the end of the + * stack (an error case checked in scavenge()). We don't worry + * about treating unboxed words as boxed or vice versa, because + * the compiler isn't allowed to store unboxed objects on the + * control stack. -- AB, 2011-Dec-02 */ + + for (object_ptr = th->control_stack_start; + object_ptr < access_control_stack_pointer(th); + object_ptr++) { + + lispobj object = *object_ptr; +#ifdef LISP_FEATURE_GENCGC + if (forwarding_pointer_p(object_ptr)) + lose("unexpected forwarding pointer in scavenge_control_stack: %p, start=%p, end=%p\n", + object_ptr, th->control_stack_start, access_control_stack_pointer(th)); +#endif + if (is_lisp_pointer(object) && from_space_p(object)) { + /* It currently points to old space. Check for a + * forwarding pointer. */ + lispobj *ptr = native_pointer(object); + if (forwarding_pointer_p(ptr)) { + /* Yes, there's a forwarding pointer. */ + *object_ptr = LOW_WORD(forwarding_pointer_value(ptr)); + } else { + /* Scavenge that pointer. */ + long n_words_scavenged = + (scavtab[widetag_of(object)])(object_ptr, object); + gc_assert(n_words_scavenged == 1); + } + } else if (scavtab[widetag_of(object)] == scav_lose) { + lose("unboxed object in scavenge_control_stack: %p->%x, start=%p, end=%p\n", + object_ptr, object, th->control_stack_start, access_control_stack_pointer(th)); + } + } +} + /* Scavenging Interrupt Contexts */ static int boxed_registers[] = BOXED_REGISTERS;