/[cmucl]/src/lisp/gencgc.c
ViewVC logotype

Diff of /src/lisp/gencgc.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.107.2.2 by rtoy, Sun Jul 18 20:29:21 2010 UTC revision 1.107.2.3 by rtoy, Mon Jul 19 17:54:42 2010 UTC
# Line 2583  scavenge(void *start_obj, long nwords) Line 2583  scavenge(void *start_obj, long nwords)
2583    
2584  static int boxed_registers[] = BOXED_REGISTERS;  static int boxed_registers[] = BOXED_REGISTERS;
2585    
2586    /* The GC has a notion of an "interior pointer" register, an unboxed
2587     * register that typically contains a pointer to inside an object
2588     * referenced by another pointer.  The most obvious of these is the
2589     * program counter, although many compiler backends define a "Lisp
2590     * Interior Pointer" register known as reg_LIP, and various CPU
2591     * architectures have other registers that also partake of the
2592     * interior-pointer nature.  As the code for pairing an interior
2593     * pointer value up with its "base" register, and fixing it up after
2594     * scavenging is complete is horribly repetitive, a few macros paper
2595     * over the monotony.  --AB, 2010-Jul-14 */
2596    
2597    #define INTERIOR_POINTER_VARS(name) \
2598        unsigned long name;             \
2599        unsigned long name##_offset;    \
2600        int name##_register_pair
2601    
2602    #define PAIR_INTERIOR_POINTER(name, accessor)           \
2603        name = accessor;                                    \
2604        pair_interior_pointer(context, name,                \
2605                              &name##_offset,               \
2606                              &name##_register_pair)
2607    
2608    /*
2609     * Do we need to check if the register we're fixing up is in the
2610     * from-space?
2611     */
2612    #define FIXUP_INTERIOR_POINTER(name, accessor)                          \
2613        do {                                                                \
2614            if (name##_register_pair >= 0) {                                \
2615                accessor =                                                  \
2616                    SC_REG(context, name##_register_pair)                   \
2617                    + name##_offset;                                        \
2618            }                                                               \
2619        } while (0)
2620    
2621    
2622    static void
2623    pair_interior_pointer(os_context_t *context, unsigned long pointer,
2624                          unsigned long *saved_offset, int *register_pair)
2625    {
2626        int i;
2627    
2628        /*
2629         * I (RLT) think this is trying to find the boxed register that is
2630         * closest to the LIP address, without going past it.  Usually, it's
2631         * reg_CODE or reg_LRA.  But sometimes, nothing can be found.
2632         */
2633        *saved_offset = 0x7FFFFFFF;
2634        *register_pair = -1;
2635        for (i = 0; i < (sizeof(boxed_registers) / sizeof(int)); i++) {
2636            unsigned long reg;
2637            long offset;
2638            int index;
2639    
2640            index = boxed_registers[i];
2641            reg = SC_REG(context, index);
2642    
2643            /* An interior pointer is never relative to a non-pointer
2644             * register (an oversight in the original implementation).
2645             * The simplest argument for why this is true is to consider
2646             * the fixnum that happens by coincide to be the word-index in
2647             * memory of the header for some object plus two.  This is
2648             * happenstance would cause the register containing the fixnum
2649             * to be selected as the register_pair if the interior pointer
2650             * is to anywhere after the first two words of the object.
2651             * The fixnum won't be changed during GC, but the object might
2652             * move, thus destroying the interior pointer.  --AB,
2653             * 2010-Jul-14 */
2654    
2655            if (Pointerp(reg) && (PTR(reg) <= pointer)) {
2656                offset = pointer - reg;
2657                if (offset < *saved_offset) {
2658                    *saved_offset = offset;
2659                    *register_pair = index;
2660                }
2661            }
2662        }
2663    }
2664    
2665    
2666  static void  static void
2667  scavenge_interrupt_context(os_context_t * context)  scavenge_interrupt_context(os_context_t * context)
2668  {  {
2669      int i;      int i;
     unsigned long pc_code_offset;  
2670    
2671        INTERIOR_POINTER_VARS(pc);
2672  #ifdef reg_LIP  #ifdef reg_LIP
2673      unsigned long lip;      INTERIOR_POINTER_VARS(lip);
     unsigned long lip_offset;  
     int lip_register_pair;  
2674  #endif  #endif
2675  #ifdef reg_LR  #ifdef reg_LR
2676      unsigned long lr_code_offset;      INTERIOR_POINTER_VARS(lr);
2677  #endif  #endif
2678  #ifdef reg_CTR  #ifdef reg_CTR
2679      unsigned long ctr_code_offset;      INTERIOR_POINTER_VARS(ctr);
2680  #endif  #endif
2681  #ifdef SC_NPC  #ifdef SC_NPC
2682      unsigned long npc_code_offset;      INTERIOR_POINTER_VARS(npc);
2683  #endif  #endif
2684    
2685  #ifdef reg_LIP  #ifdef reg_LIP
2686      /* Find the LIP's register pair and calculate it's offset */      PAIR_INTERIOR_POINTER(lip, SC_REG(context, reg_LIP));
     /* before we scavenge the context. */  
   
     /*  
      * 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.  
      */  
     lip = SC_REG(context, reg_LIP);  
     lip_offset = 0x7FFFFFFF;  
     lip_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 = SC_REG(context, index);  
         if (Pointerp(reg) && PTR(reg) <= lip) {  
             offset = lip - reg;  
             if (offset < lip_offset) {  
                 lip_offset = offset;  
                 lip_register_pair = index;  
             }  
         }  
     }  
2687  #endif /* reg_LIP */  #endif /* reg_LIP */
2688    
2689      /*      PAIR_INTERIOR_POINTER(pc, SC_PC(context));
2690       * Compute the PC's offset from the start of the CODE  
      * register.  
      */  
     pc_code_offset = SC_PC(context) - SC_REG(context, reg_CODE);  
2691  #ifdef SC_NPC  #ifdef SC_NPC
2692      npc_code_offset = SC_NPC(context) - SC_REG(context, reg_CODE);      PAIR_INTERIOR_POINTER(npc, SC_NPC(context));
2693  #endif /* SC_NPC */  #endif
2694    
2695  #ifdef reg_LR  #ifdef reg_LR
2696      lr_code_offset = SC_REG(context, reg_LR) - SC_REG(context, reg_CODE);      PAIR_INTERIOR_POINTER(pc, SC_REG(context, reg_LR));
2697  #endif  #endif
2698    
2699  #ifdef reg_CTR  #ifdef reg_CTR
2700      ctr_code_offset = SC_REG(context, reg_CTR) - SC_REG(context, reg_CODE);      PAIR_INTERIOR_POINTER(pc, SC_REG(context, reg_CTR));
2701  #endif  #endif
2702    
2703      /* Scanvenge all boxed registers in the context. */      /* Scanvenge all boxed registers in the context. */
2704      for (i = 0; i < (sizeof(boxed_registers) / sizeof(int)); i++) {      for (i = 0; i < (sizeof(boxed_registers) / sizeof(int)); i++) {
2705          int index;          int index;
# Line 2662  scavenge_interrupt_context(os_context_t Line 2713  scavenge_interrupt_context(os_context_t
2713          scavenge(&(SC_REG(context, index)), 1);          scavenge(&(SC_REG(context, index)), 1);
2714      }      }
2715    
 #ifdef reg_LIP  
     /* Fix the LIP */  
   
2716      /*      /*
2717       * But what happens if lip_register_pair is -1?  SC_REG on Solaris       * Now that the scavenging is done, repair the various interior
2718       * (see solaris_register_address in solaris-os.c) will return       * pointers.
      * &context->uc_mcontext.gregs[2].  But gregs[2] is REG_nPC.  Is  
      * that what we really want?  My guess is that that is not what we  
      * want, so if lip_register_pair is -1, we don't touch reg_LIP at  
      * all.  But maybe it doesn't really matter if LIP is trashed?  
2719       */       */
2720      if (lip_register_pair >= 0) {  #ifdef reg_LIP
2721          SC_REG(context, reg_LIP) =      FIXUP_INTERIOR_POINTER(lip, SC_REG(context, reg_LIP));
2722              SC_REG(context, lip_register_pair) + lip_offset;  #endif
2723      }  
2724  #endif /* reg_LIP */      FIXUP_INTERIOR_POINTER(pc, SC_PC(context));
2725    
     /* Fix the PC if it was in from space */  
     if (from_space_p(SC_PC(context))) {  
         SC_PC(context) = SC_REG(context, reg_CODE) + pc_code_offset;  
     }  
2726  #ifdef SC_NPC  #ifdef SC_NPC
2727      if (from_space_p(SC_NPC(context))) {      FIXUP_INTERIOR_POINTER(npc, SC_NPC(context));
2728          SC_NPC(context) = SC_REG(context, reg_CODE) + npc_code_offset;  #endif
     }  
 #endif /* SC_NPC */  
2729    
2730  #ifdef reg_LR  #ifdef reg_LR
2731      if (from_space_p(SC_REG(context, reg_LR))) {      FIXUP_INTERIOR_POINTER(lr, SC_REG(context, reg_LR));
2732          SC_REG(context, reg_LR) = SC_REG(context, reg_CODE) + lr_code_offset;  #endif
2733      }  
 #endif  
2734  #ifdef reg_CTR  #ifdef reg_CTR
2735      if (from_space_p(SC_REG(context, reg_CTR))) {      FIXUP_INTERIOR_POINTER(ctr, SC_REG(context, reg_CTR));
2736        SC_REG(context, reg_CTR) = SC_REG(context, reg_CODE) + ctr_code_offset;  #endif
     }  
 #endif  
2737  }  }
2738    
2739  void  void

Legend:
Removed from v.1.107.2.2  
changed lines
  Added in v.1.107.2.3

  ViewVC Help
Powered by ViewVC 1.1.5