X-Git-Url: http://repo.macrolet.net/gitweb/?a=blobdiff_plain;f=src%2Fruntime%2Fgc-common.c;h=96de1729b7fed83ad965c6c1d2b441ab7fbf970d;hb=ab5427d31da2bd95805cccc8e47b8f43d3dd606d;hp=a9f69b6dbc1a23217a21a5707399533546a6eb0c;hpb=58513220fcf87e161a5e0d3fbadd76c45f27d584;p=sbcl.git diff --git a/src/runtime/gc-common.c b/src/runtime/gc-common.c index a9f69b6..96de172 100644 --- a/src/runtime/gc-common.c +++ b/src/runtime/gc-common.c @@ -1885,7 +1885,7 @@ scav_lose(lispobj *where, lispobj object) { lose("no scavenge function for object 0x%08x (widetag 0x%x)\n", (unsigned long)object, - widetag_of(object)); + widetag_of(*where)); return 0; /* bogus return value to satisfy static type checking */ } @@ -1904,7 +1904,7 @@ size_lose(lispobj *where) { lose("no size function for object at 0x%08x (widetag 0x%x)\n", (unsigned long)where, - widetag_of(LOW_WORD(where))); + widetag_of(*where)); return 1; /* bogus return value to satisfy static type checking */ } @@ -1916,7 +1916,7 @@ size_lose(lispobj *where) void gc_init_tables(void) { - unsigned long i; + unsigned long i, j; /* Set default value in all slots of scavenge table. FIXME * replace this gnarly sizeof with something based on @@ -1931,11 +1931,14 @@ gc_init_tables(void) */ for (i = 0; i < (1<<(N_WIDETAG_BITS-N_LOWTAG_BITS)); i++) { - scavtab[EVEN_FIXNUM_LOWTAG|(i<= 0) { \ + ACCESS_INTERIOR_POINTER_##name = \ + (*os_context_register_addr(context, \ + name##_register_pair) \ + & ~LOWTAG_MASK) \ + + name##_offset; \ + } \ + } while (0) + + +static void +pair_interior_pointer(os_context_t *context, unsigned long pointer, + unsigned long *saved_offset, int *register_pair) +{ + int i; + + /* + * I (RLT) think this is trying to find the boxed register that is + * closest to the LIP address, without going past it. Usually, it's + * reg_CODE or reg_LRA. But sometimes, nothing can be found. + */ + /* 0x7FFFFFFF on 32-bit platforms; + 0x7FFFFFFFFFFFFFFF on 64-bit platforms */ + *saved_offset = (((unsigned long)1) << (N_WORD_BITS - 1)) - 1; + *register_pair = -1; + for (i = 0; i < (sizeof(boxed_registers) / sizeof(int)); i++) { + unsigned long reg; + long offset; + int index; + + index = boxed_registers[i]; + reg = *os_context_register_addr(context, index); + + /* An interior pointer is never relative to a non-pointer + * register (an oversight in the original implementation). + * The simplest argument for why this is true is to consider + * the fixnum that happens by coincide to be the word-index in + * memory of the header for some object plus two. This is + * happenstance would cause the register containing the fixnum + * to be selected as the register_pair if the interior pointer + * is to anywhere after the first two words of the object. + * The fixnum won't be changed during GC, but the object might + * move, thus destroying the interior pointer. --AB, + * 2010-Jul-14 */ + + if (is_lisp_pointer(reg) && + ((reg & ~LOWTAG_MASK) <= pointer)) { + offset = pointer - (reg & ~LOWTAG_MASK); + if (offset < *saved_offset) { + *saved_offset = offset; + *register_pair = index; + } + } + } +} + +static void +scavenge_interrupt_context(os_context_t * context) +{ + int i; + + /* FIXME: The various #ifdef noise here is precisely that: noise. + * Is it possible to fold it into the macrology so that we have + * one set of #ifdefs and then INTERIOR_POINTER_VARS /et alia/ + * compile out for the registers that don't exist on a given + * platform? */ + + INTERIOR_POINTER_VARS(pc); +#ifdef reg_LIP + INTERIOR_POINTER_VARS(lip); +#endif +#ifdef ARCH_HAS_LINK_REGISTER + INTERIOR_POINTER_VARS(lr); +#endif +#ifdef ARCH_HAS_NPC_REGISTER + INTERIOR_POINTER_VARS(npc); +#endif +#ifdef LISP_FEATURE_PPC + INTERIOR_POINTER_VARS(ctr); +#endif + + PAIR_INTERIOR_POINTER(pc); +#ifdef reg_LIP + PAIR_INTERIOR_POINTER(lip); +#endif +#ifdef ARCH_HAS_LINK_REGISTER + PAIR_INTERIOR_POINTER(lr); +#endif +#ifdef ARCH_HAS_NPC_REGISTER + PAIR_INTERIOR_POINTER(npc); +#endif +#ifdef LISP_FEATURE_PPC + PAIR_INTERIOR_POINTER(ctr); +#endif + + /* Scavenge all boxed registers in the context. */ + for (i = 0; i < (sizeof(boxed_registers) / sizeof(int)); i++) { + int index; + lispobj foo; + + index = boxed_registers[i]; + foo = *os_context_register_addr(context, index); + scavenge(&foo, 1); + *os_context_register_addr(context, index) = foo; + + /* this is unlikely to work as intended on bigendian + * 64 bit platforms */ + + scavenge((lispobj *) os_context_register_addr(context, index), 1); + } + + /* Now that the scavenging is done, repair the various interior + * pointers. */ + FIXUP_INTERIOR_POINTER(pc); +#ifdef reg_LIP + FIXUP_INTERIOR_POINTER(lip); +#endif +#ifdef ARCH_HAS_LINK_REGISTER + FIXUP_INTERIOR_POINTER(lr); +#endif +#ifdef ARCH_HAS_NPC_REGISTER + FIXUP_INTERIOR_POINTER(npc); +#endif +#ifdef LISP_FEATURE_PPC + FIXUP_INTERIOR_POINTER(ctr); +#endif +} + +void +scavenge_interrupt_contexts(struct thread *th) +{ + int i, index; + os_context_t *context; + + index = fixnum_value(SymbolValue(FREE_INTERRUPT_CONTEXT_INDEX,th)); + +#if defined(DEBUG_PRINT_CONTEXT_INDEX) + printf("Number of active contexts: %d\n", index); +#endif + + for (i = 0; i < index; i++) { + context = th->interrupt_contexts[i]; + scavenge_interrupt_context(context); + } +} +#endif /* x86oid targets */