--- jikesrvm-2.3.4-org/./rvm/src/tools/bootImageRunner/GenerateInterfaceDeclarations.java	2004-11-15 00:59:19.000000000 -0500
+++ jikesrvm-2.3.4-bi/./rvm/src/tools/bootImageRunner/GenerateInterfaceDeclarations.java	2007-02-16 15:02:32.666703416 -0500
@@ -80,7 +80,7 @@
       }
     }
 
-    VM.initForTool();
+    VM.initForTool(); 
 
     emitStuff();
     if (out.checkError()) {
@@ -204,17 +204,37 @@
     // Header Space for objects
     int startOffset = VM_ObjectModel.objectStartOffset(cls);
     int current = startOffset;
-    for(int i = 0; current < fields[0].f.getOffset(); i++) {
-      pln("  uint32_t    headerPadding" + i + ";\n");
-      current += 4; 
-    }
-    
+	
+	
+    /*** bi-directional start ***/	
+    boolean RSPartFlag = true;   // firstly set the flag for Reference sections to true 	
+    /*** bi-directional end ***/
+	
+	
+        
     for (int i = 0; i<fields.length; i++) {
       VM_Field field = fields[i].f;
       VM_TypeReference t = field.getType();
       int offset = field.getOffset();
       String name = field.getName().toString();
       // Align by blowing 4 bytes if needed
+	  
+	 /*** bi-directional start ***/	  	  
+	 /***--bi:  check for reference section's end  */
+
+	  if ( ( RSPartFlag ) && (offset > startOffset) )
+	  {
+		  RSPartFlag = false;		  
+		  for(int j = 0; current < offset; j++) {
+			  pln("  uint32_t    headerPadding" + j + ";\n");	  
+			  current += 4;   
+	  	  }
+		    
+	  }
+	 /*** bi-directional start ***/	
+	  
+	  
+	  
       if (needsAlign && current + 4 == offset) {
           pln("  uint32_t    padding" + i + ";");
           current += 4;
@@ -349,76 +369,76 @@
 
     // values in VM_Constants, from VM_Configuration
     //
-    //-#if RVM_FOR_POWERPC
-    if (VM.BuildForPowerPC) {
-      p("static const int VM_Constants_JTOC_POINTER               = "
-          + VM_Constants.JTOC_POINTER + ";\n");
-      p("static const int VM_Constants_FRAME_POINTER              = "
-          + VM_Constants.FRAME_POINTER + ";\n");
-      p("static const int VM_Constants_PROCESSOR_REGISTER         = "
-          + VM_Constants.PROCESSOR_REGISTER + ";\n");
-      p("static const int VM_Constants_FIRST_VOLATILE_GPR         = "
-          + VM_Constants.FIRST_VOLATILE_GPR + ";\n");
-      p("static const int VM_Constants_DIVIDE_BY_ZERO_MASK        = "
-          + VM_Constants.DIVIDE_BY_ZERO_MASK + ";\n");
-      p("static const int VM_Constants_DIVIDE_BY_ZERO_TRAP        = "
-          + VM_Constants.DIVIDE_BY_ZERO_TRAP + ";\n");
-      p("static const int VM_Constants_MUST_IMPLEMENT_MASK        = "
-          + VM_Constants.MUST_IMPLEMENT_MASK + ";\n");
-      p("static const int VM_Constants_MUST_IMPLEMENT_TRAP        = "
-          + VM_Constants.MUST_IMPLEMENT_TRAP + ";\n");
-      p("static const int VM_Constants_STORE_CHECK_MASK           = "
-          + VM_Constants.STORE_CHECK_MASK + ";\n");
-      p("static const int VM_Constants_STORE_CHECK_TRAP           = "
-          + VM_Constants.STORE_CHECK_TRAP + ";\n");
-      p("static const int VM_Constants_ARRAY_INDEX_MASK           = "
-          + VM_Constants.ARRAY_INDEX_MASK + ";\n");
-      p("static const int VM_Constants_ARRAY_INDEX_TRAP           = "
-          + VM_Constants.ARRAY_INDEX_TRAP + ";\n");
-      p("static const int VM_Constants_ARRAY_INDEX_REG_MASK       = "
-          + VM_Constants.ARRAY_INDEX_REG_MASK + ";\n");
-      p("static const int VM_Constants_ARRAY_INDEX_REG_SHIFT      = "
-          + VM_Constants.ARRAY_INDEX_REG_SHIFT + ";\n");
-      p("static const int VM_Constants_CONSTANT_ARRAY_INDEX_MASK  = "
-          + VM_Constants.CONSTANT_ARRAY_INDEX_MASK + ";\n");
-      p("static const int VM_Constants_CONSTANT_ARRAY_INDEX_TRAP  = "
-          + VM_Constants.CONSTANT_ARRAY_INDEX_TRAP + ";\n");
-      p("static const int VM_Constants_CONSTANT_ARRAY_INDEX_INFO  = "
-          + VM_Constants.CONSTANT_ARRAY_INDEX_INFO + ";\n");
-      p("static const int VM_Constants_WRITE_BUFFER_OVERFLOW_MASK = "
-          + VM_Constants.WRITE_BUFFER_OVERFLOW_MASK + ";\n");
-      p("static const int VM_Constants_WRITE_BUFFER_OVERFLOW_TRAP = "
-          + VM_Constants.WRITE_BUFFER_OVERFLOW_TRAP + ";\n");
-      p("static const int VM_Constants_STACK_OVERFLOW_MASK        = "
-          + VM_Constants.STACK_OVERFLOW_MASK + ";\n");
-      p("static const int VM_Constants_STACK_OVERFLOW_HAVE_FRAME_TRAP = "
-          + VM_Constants.STACK_OVERFLOW_HAVE_FRAME_TRAP + ";\n");
-      p("static const int VM_Constants_STACK_OVERFLOW_TRAP        = "
-          + VM_Constants.STACK_OVERFLOW_TRAP + ";\n");
-      p("static const int VM_Constants_CHECKCAST_MASK             = "
-          + VM_Constants.CHECKCAST_MASK + ";\n");
-      p("static const int VM_Constants_CHECKCAST_TRAP             = "
-          + VM_Constants.CHECKCAST_TRAP + ";\n");
-      p("static const int VM_Constants_REGENERATE_MASK            = "
-          + VM_Constants.REGENERATE_MASK + ";\n");
-      p("static const int VM_Constants_REGENERATE_TRAP            = "
-          + VM_Constants.REGENERATE_TRAP + ";\n");
-      p("static const int VM_Constants_NULLCHECK_MASK             = "
-          + VM_Constants.NULLCHECK_MASK + ";\n");
-      p("static const int VM_Constants_NULLCHECK_TRAP             = "
-          + VM_Constants.NULLCHECK_TRAP + ";\n");
-      p("static const int VM_Constants_JNI_STACK_TRAP_MASK             = "
-          + VM_Constants.JNI_STACK_TRAP_MASK + ";\n");
-      p("static const int VM_Constants_JNI_STACK_TRAP             = "
-          + VM_Constants.JNI_STACK_TRAP + ";\n");
-      p("static const int VM_Constants_STACKFRAME_NEXT_INSTRUCTION_OFFSET = "
-          + VM_Constants.STACKFRAME_NEXT_INSTRUCTION_OFFSET + ";\n");
-          p("static const int VM_Constants_STACKFRAME_ALIGNMENT = "
-                  + VM_Constants.STACKFRAME_ALIGNMENT + " ;\n");
-    }
-    //-#endif
 
-    //-#if RVM_FOR_IA32
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
     if (VM.BuildForIA32) {
       p("static const int VM_Constants_EAX                    = "
           + VM_Constants.EAX + ";\n");
@@ -443,23 +463,23 @@
       p("static const int VM_Constants_RVM_TRAP_BASE  = "
           + VM_Constants.RVM_TRAP_BASE   + ";\n");    
     }
-    //-#endif
+
 
     p("static const int VM_Constants_STACK_SIZE_GUARD          = "
         + VM_Constants.STACK_SIZE_GUARD + ";\n");
 
-    //-#if RVM_WITH_FLEXIBLE_STACK_SIZES
-    p("static const int VM_Constants_STACK_SIZE_MIN      = "
-        + VM_Constants.STACK_SIZE_MIN + ";\n");
-    p("static const int VM_Constants_STACK_SIZE_NORMAL_DEFAULT  = "
-        + VM_Constants.STACK_SIZE_NORMAL_DEFAULT + ";\n");
-    p("static const int VM_Constants_STACK_SIZE_GROW_MIN       = "
-        + VM_Constants.STACK_SIZE_GROW_MIN + ";\n");
-    p("static const int VM_Constants_STACK_SIZE_GROW_DEFAULT   = "
-        + VM_Constants.STACK_SIZE_GROW_DEFAULT + ";\n");
-    p("static const int VM_Constants_STACK_SIZE_MAX_DEFAULT    = "
-        + VM_Constants.STACK_SIZE_MAX_DEFAULT + ";\n");
-    //-#endif // RVM_WITH_FLEXIBLE_STACK_SIZES
+
+
+
+
+
+
+
+
+
+
+
+
 
     p("static const int VM_Constants_INVISIBLE_METHOD_ID       = "
         + VM_Constants.INVISIBLE_METHOD_ID + ";\n");
@@ -610,7 +630,7 @@
     offset = VM_Entrypoints.threadIdField.getOffset();
     p("static const int VM_Processor_threadId_offset = "
                      + offset + ";\n");
-    //-#if RVM_FOR_IA32
+
     offset = VM_Entrypoints.framePointerField.getOffset();
     p("static const int VM_Processor_framePointer_offset = "
                      + offset + ";\n");
@@ -620,7 +640,7 @@
     offset = VM_Entrypoints.arrayIndexTrapParamField.getOffset();
     p("static const int VM_Processor_arrayIndexTrapParam_offset = "
                      + offset + ";\n");
-    //-#endif
+
 
     // fields in VM_Thread
     //
@@ -643,14 +663,14 @@
     p("static const int VM_Registers_fprs_offset = " + offset + ";\n");
     offset = VM_Entrypoints.registersIPField.getOffset();
     p("static const int VM_Registers_ip_offset = " + offset + ";\n");
-    //-#if RVM_FOR_IA32
+
     offset = VM_Entrypoints.registersFPField.getOffset();
     p("static const int VM_Registers_fp_offset = " + offset + ";\n");
-    //-#endif
-    //-#if RVM_FOR_POWERPC
-    offset = VM_Entrypoints.registersLRField.getOffset();
-    p("static const int VM_Registers_lr_offset = " + offset + ";\n");
-    //-#endif
+
+
+
+
+
 
     offset = VM_Entrypoints.registersInUseField.getOffset();
     p("static const int VM_Registers_inuse_offset = " + 
@@ -711,40 +731,40 @@
   //
   static void emitAssemblerDeclarations () {
 
-    //-#if RVM_FOR_POWERPC
-    //-#if RVM_FOR_OSX
-    if (VM.BuildForPowerPC) {
-      pln("#define FP r"   + VM_BaselineConstants.FP);
-      pln("#define JTOC r" + VM_BaselineConstants.JTOC);
-      pln("#define PROCESSOR_REGISTER r"    + VM_BaselineConstants.PROCESSOR_REGISTER);
-      pln("#define S0 r"   + VM_BaselineConstants.S0);
-      pln("#define T0 r"   + VM_BaselineConstants.T0);
-      pln("#define T1 r"   + VM_BaselineConstants.T1);
-      pln("#define T2 r"   + VM_BaselineConstants.T2);
-      pln("#define T3 r"   + VM_BaselineConstants.T3);
-      pln("#define STACKFRAME_NEXT_INSTRUCTION_OFFSET " + VM_Constants.STACKFRAME_NEXT_INSTRUCTION_OFFSET);
-    }
-    //-#else
-    if (VM.BuildForPowerPC) {
-      pln(".set FP,"   + VM_BaselineConstants.FP);
-      pln(".set JTOC," + VM_BaselineConstants.JTOC);
-      pln(".set PROCESSOR_REGISTER,"    
-          + VM_BaselineConstants.PROCESSOR_REGISTER);
-      pln(".set S0,"   + VM_BaselineConstants.S0);
-      pln(".set T0,"   + VM_BaselineConstants.T0);
-      pln(".set T1,"   + VM_BaselineConstants.T1);
-      pln(".set T2,"   + VM_BaselineConstants.T2);
-      pln(".set T3,"   + VM_BaselineConstants.T3);
-      pln(".set STACKFRAME_NEXT_INSTRUCTION_OFFSET," 
-          + VM_Constants.STACKFRAME_NEXT_INSTRUCTION_OFFSET);
 
-      if (!VM.BuildForAix) 
-        pln(".set T4,"   + (VM_BaselineConstants.T3 + 1));
-    }
-    //-#endif
-    //-#endif
 
-    //-#if RVM_FOR_IA32
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
     if (VM.BuildForIA32) {
       p("#define JTOC %" 
         + VM_RegisterConstants.GPR_NAMES[VM_BaselineConstants.JTOC]
@@ -753,7 +773,7 @@
         + VM_RegisterConstants.GPR_NAMES[VM_BaselineConstants.ESI]
           + ";\n");
     }
-    //-#endif
+
 
   }
 }
--- jikesrvm-2.3.4-org/./rvm/src/tools/bootImageWriter/BootImage.java	2004-10-06 07:23:41.000000000 -0400
+++ jikesrvm-2.3.4-bi/./rvm/src/tools/bootImageWriter/BootImage.java	2005-11-14 17:01:28.000000000 -0500
@@ -193,6 +193,9 @@
    * @param value value to write
    */
   public void setFullWord(int offset, int value) {
+	  
+	    
+	  
     if (littleEndian) {
       bootImage[offset++] = (byte) (value);
       bootImage[offset++] = (byte) (value >>  8);
--- jikesrvm-2.3.4-org/./rvm/src/tools/bootImageWriter/BootImageWriter.java	2004-11-15 13:31:56.000000000 -0500
+++ jikesrvm-2.3.4-bi/./rvm/src/tools/bootImageWriter/BootImageWriter.java	2007-02-16 15:05:51.642454504 -0500
@@ -1457,7 +1457,7 @@
         // allocate space in image
         //
         VM_Class rvmScalarType = rvmType.asClass();
-        int scalarImageOffset = (overwriteOffset == -1) ? bootImage.allocateScalar(rvmScalarType) : overwriteOffset;
+        int scalarImageOffset = (overwriteOffset == -1) ? bootImage.allocateScalar(rvmScalarType) : overwriteOffset;		
         mapEntry.imageOffset = scalarImageOffset;
 
         if (verbose >= 2) {
@@ -1546,7 +1546,7 @@
             } else {
               fail("unexpected primitive field type: " + rvmFieldType);
             }
-          } else {
+          } else {			  
             // field is reference type
             Object value = jdkFieldAcc.get(jdkObject);
             if (!allocOnly && value != null) {
@@ -1560,6 +1560,7 @@
                 if (verbose >= 2) traceContext.traceObjectNotInBootImage();
                 bootImage.setNullAddressWord(rvmFieldOffset);
               } else
+				  
                 bootImage.setAddressWord(rvmFieldOffset,
                                          bootImageAddress.add(imageOffset).toWord());
               if (verbose >= 2) traceContext.pop();
--- jikesrvm-2.3.4-org/./rvm/src/vm/HPM/HPM_counters.java	2004-12-18 20:15:25.000000000 -0500
+++ jikesrvm-2.3.4-bi/./rvm/src/vm/HPM/HPM_counters.java	2007-02-16 15:07:10.854412456 -0500
@@ -54,22 +54,20 @@
    * Dump out counter values.
    * @return        return true if at least one counter not zero.
    */
-  public boolean dump() throws UninterruptiblePragma 
+  
+   public boolean dump() throws UninterruptiblePragma 
   {
     boolean notZero = false;
     for (int i=0; i<HPM_info.getNumberOfValues(); i++) {
       if (counters[i] > 0) {
-	notZero = true;
-        //	System.out.println(i+": "+HPM_info.short_name(i)+":"+format_long(counters[i]));
-	VM.sysWrite  (i,": ");
-        VM.sysWrite  (HPM_info.short_name(i));
-        VM.sysWrite  (":");
-        VM.sysWrite  (format_long(counters[i]),MAX_LONG_FORMAT_LENGTH);
-        VM.sysWriteln();
+	notZero = true;    
+	VM.sysWrite  (format_long(counters[i]),MAX_LONG_FORMAT_LENGTH);        
       }
     }
+    VM.sysWriteln();    
     return notZero;
   }
+  
   /*
    * Reset counters to zero
    */
@@ -118,10 +116,10 @@
     long l_value = value;
     int l_index = MAX_LONG_LENGTH-1;
     while (l_value > 0) {
-      int remainder = (int)(l_value - ((int)(l_value/10))*10);
+      int remainder = (int)(l_value - ((l_value/10))*10);
       l_buffer[l_index] = (char)((int)'0' + remainder);
 
-      l_value = (int)(l_value/10);
+      l_value = (l_value/10);
       l_index--;
     }
 
--- jikesrvm-2.3.4-org/./rvm/src/vm/HPM/VM_HardwarePerformanceMonitors.java	2004-11-10 23:21:54.000000000 -0500
+++ jikesrvm-2.3.4-bi/./rvm/src/vm/HPM/VM_HardwarePerformanceMonitors.java	2005-06-23 17:26:22.000000000 -0400
@@ -36,7 +36,8 @@
  *
  * @author Peter F. Sweeney
  * @author Dave Grove
- * @modified Matthias Hauswirth  August 2003
+ * @ modified Matthias Hauswirth  August 2003
+ * @modified Dayong Gu  May 2005
  */
 public class VM_HardwarePerformanceMonitors 
 {
@@ -1053,6 +1054,8 @@
     if (VM.BuildForHPM && enabled) {
       //-#if RVM_WITH_HPM
       if (verbose<0) return;
+      
+      int tGC=-1;
 
       //      HPM_counters sum = new HPM_counters();
       VM.sysWriteln("\nDump HPM counter values for virtual processors");
@@ -1077,26 +1080,46 @@
       aos.reset();
       int n_aosThreads = 0;
       int n_nonZeroThreads = 0; 
+      
+      //***--bi change the output format only 
       for (int i = 1, n = VM_Scheduler.hpm_threads.length; i < n; i++) {
-	VM_Thread t = VM_Scheduler.hpm_threads[i];
-	if (t != null) {
+      VM_Thread t = VM_Scheduler.hpm_threads[i];
+      if (t != null) {
           int global_index = t.getGlobalIndex();
 	  String thread_name = VM_HardwarePerformanceMonitors.getThreadName(global_index); // t.getClass().getName();
 	  // dump HPM counter values
           //	  synchronized (System.out) {
+	  if (thread_name.compareTo("class com.ibm.JikesRVM.memoryManagers.mmInterface.VM_CollectorThread") == 0 ) tGC=global_index;
+	  
 	    VM.sysWrite(" ThreadIndex: ");VM.sysWrite(global_index);VM.sysWrite(" (");
             VM.sysWrite(t.getIndex());VM.sysWrite(") ");VM.sysWrite(thread_name);VM.sysWrite(" ");
-            VM.sysWriteln();
+            VM.sysWriteln();	    
+	    } else {
+	      if(verbose>=2)
+		VM.sysWriteln(" hpm_counters == null!***");
+	    }
+      }
+      
+      for (int i = 1, n = VM_Scheduler.hpm_threads.length; i < n; i++) {
+	VM_Thread t = VM_Scheduler.hpm_threads[i];
+	if (t != null) {          
 	    if (t.hpm_counters != null) {
+	    int global_index = t.getGlobalIndex();
+	    
+	    if (global_index == tGC) 
+	    {
+	    	VM.sysWrite("T_GC");
+	    }
+	    else
+	    {
+	    	VM.sysWrite("T_");
+	    	VM.sysWrite(global_index);
+	    }
+	    
+	    
+	    
 	      if (t.hpm_counters.dump()) n_nonZeroThreads++;
-	      t.hpm_counters.accumulate(sum, HPM_info.getNumberOfValues());
-              /*
-	      if (thread_name.startsWith("VM_ControllerThread") ||
-                  thread_name.startsWith("VM_MethodSampleOrganizer")) {
-		t.hpm_counters.accumulate(aos, HPM_info.getNumberOfValues());
-		n_aosThreads++;
-	      }
-              */
+	      t.hpm_counters.accumulate(sum, HPM_info.getNumberOfValues());        
 	      t.hpm_counters.reset();
 	    } else {
 	      if(verbose>=2)
@@ -1105,17 +1128,11 @@
             //	  }
 	}
       }
-      /*
-      if (n_aosThreads > 1) {
-        //	synchronized (System.out) {
-	  VM.sysWriteln("\nDump aggregate HPM counter values for AOS threads");
-	  aos.dump();
-          //	}
-      }
-      */
+    
       if (n_nonZeroThreads > 1) {
         //	synchronized (System.out) {
-	  VM.sysWriteln("\nDump aggregate HPM counter values for threads");
+	  //VM.sysWriteln("\nDump aggregate HPM counter values for threads");
+	  VM.sysWrite("\nAllTs");
 	  sum.dump();
           //	}
       }
--- jikesrvm-2.3.4-org/./rvm/src/vm/classLoader/VM_Class.java	2004-12-18 19:33:51.000000000 -0500
+++ jikesrvm-2.3.4-bi/./rvm/src/vm/classLoader/VM_Class.java	2007-02-16 15:14:37.954442920 -0500
@@ -72,10 +72,24 @@
    * total size of per-instance data, in bytes
    */
   private int          instanceSize;  
+  
+  
+  /***--bi  Add for bidirectional, store the number of references  */
+  /**
+   * total number of references in this object
+   */
+  private int          referenceNum; 
+  
+  /***--bi  Add for bidirectional, store the length of the reference section  */
+  /**
+   * total length of the refererence section, ie, referenceNum << LOG_BYTES_IN_ADDRESS 
+   */
+  private int          referenceSectionLen; 
+  
   /**
    * offsets of reference-containing instance fields
    */
-  private int[]        referenceOffsets;       
+  //  private int[]        referenceOffsets;         // In bi, can be deleted 
   /**
    * offset of hole due to alignment, zero if none
    */
@@ -113,7 +127,10 @@
    */
   private Object[] typeInformationBlock;   
 
-
+  
+  
+  
+  
   /**
    * Name - something like "java.lang.String".
    */ 
@@ -260,6 +277,27 @@
     }
     return null;
   }
+  
+  
+  /*** bi-directional start ***/
+  /**
+   * Get the total number of references number 
+   * @return referenceNum
+   */
+  public final int getReferenceNumInternal() throws UninterruptiblePragma {    
+    return referenceNum;
+  }
+  
+  /**
+  * Get the length the  references section 
+  * @return  referenceSectionLen
+  */
+  public final int getReferenceSectionSize() throws UninterruptiblePragma {    
+   return referenceSectionLen;
+  }
+  
+  /*** bi-directional end ***/
+  
 
   /** 
    * Find description of a method of this class.
@@ -510,7 +548,8 @@
   public final int getInstanceSizeInternal() throws UninterruptiblePragma {
     return instanceSize;
   }
-
+  
+  
   /**
    * Add a field to the object; only meant to be called from VM_ObjectModel et al.
    * must be called when lock on class object is already held (ie from resolve).
@@ -518,16 +557,46 @@
   public final void increaseInstanceSize(int numBytes) throws UninterruptiblePragma {
     instanceSize += numBytes;
   }
+  
+   /*** bi-directional start ***/  
+  
+  /**
+   * Increase the number of reference.
+   * 
+   */
+  public final void increaseReferenceNum(int num) throws UninterruptiblePragma {
+    referenceNum += num;
+  }
+  
+  /**
+   * Set the number of reference.
+   * 
+   */
+  public final void setReferenceNum(int num) throws UninterruptiblePragma {
+    referenceNum = num;
+  }
+
+  /**
+   * Set the length of reference section.
+   * 
+   */
+  
+  public final void setReferenceSectionLength(int num) throws UninterruptiblePragma {
+    referenceSectionLen = num;
+  }
 
+  /*** bi-directional end ***/
+  
   /**
    * Offsets of reference-containing instance fields of this class type.
    * Offsets are with respect to object pointer -- see VM_Field.getOffset().
    */
+  /***--bi  remove getReferenceOffsets(). We don't need it any more  
   public final int[] getReferenceOffsets() throws UninterruptiblePragma {
     if (VM.VerifyAssertions) VM._assert(isResolved());
     return referenceOffsets;
   }
-
+ */
   /**
    * Offset of hole, due to alignment; 
    * returns zero if none.
@@ -981,6 +1050,9 @@
       if (VM.VerifyAssertions) VM._assert(superClass == null);
       instanceSize = VM_ObjectModel.computeScalarHeaderSize(this);
       alignment = BYTES_IN_ADDRESS;
+      /***--bi, set the referenceNum to zero */
+      referenceNum = 0;
+      
     } else {
       if (VM.VerifyAssertions) VM._assert(superClass != null);
       depth = superClass.depth + 1;
@@ -988,6 +1060,9 @@
       instanceSize = superClass.instanceSize;
       emptySlot = superClass.emptySlot;
       alignment= superClass.alignment;
+      
+      /***--bi, set the referenceNum as that of the super class  */
+      referenceNum = superClass.referenceNum;
     }
 
     if (isSynchronizedObject() || this == VM_Type.JavaLangClassType)
@@ -1152,8 +1227,11 @@
     //
     VM_ObjectModel.layoutInstanceFields(this);
 
+
+/*** --bi can delete this part from the original version ----*/
+
     // count reference fields
-    int referenceFieldCount = 0;
+    /*int referenceFieldCount = 0;
     for (int i = 0, n = instanceFields.length; i < n; ++i) {
       VM_Field field     = instanceFields[i];
       if (field.getType().isReferenceType())
@@ -1162,12 +1240,14 @@
 
     // record offsets of those instance fields that contain references
     //
-    referenceOffsets = new int[referenceFieldCount];
+    /*referenceOffsets = new int[referenceFieldCount];
     for (int i = 0, j = 0, n = instanceFields.length; i < n; ++i) {
       VM_Field field = instanceFields[i];
       if (field.getType().isReferenceType())
         referenceOffsets[j++] = field.offset;
-    }
+    }*/ 
+
+/*** end of --bi can delete this part ----*/
 
     // Allocate space for <init> method pointers
     //
--- jikesrvm-2.3.4-org/./rvm/src/vm/memoryManagers/JMTk/vmInterface/Constants.java	2004-10-06 07:24:43.000000000 -0400
+++ jikesrvm-2.3.4-bi/./rvm/src/vm/memoryManagers/JMTk/vmInterface/Constants.java	2007-02-16 15:25:17.245255944 -0500
@@ -11,6 +11,9 @@
 import org.vmmagic.unboxed.*;
 import com.ibm.JikesRVM.VM_JavaHeader;
 
+/***-- bi */
+//import com.ibm.JikesRVM.VM_JavaHeaderConstants;
+
 /**
  * JMTk follows the pattern set by Jikes RVM for defining sizes of
  * primitive types thus:
@@ -28,8 +31,8 @@
  *
  * @author Perry Cheng
  */
-public interface Constants extends VM_SizeConstants {
-
+public interface Constants extends VM_SizeConstants { 
+//public interface Constants extends VM_JavaHeaderConstants { // retore to the org, bi need this line 
   /* Read and write barrier flavors */
   static final int PUTFIELD_WRITE_BARRIER = 0;
   static final int GETFIELD_READ_BARRIER = 0;
@@ -52,6 +55,8 @@
 
   /* Assume an address refers to a byte */
   static final int LOG_BYTES_IN_ADDRESS_SPACE = BITS_IN_ADDRESS;
+   
+  
 
   /**
    * This value specifies the <i>minimum</i> allocation alignment
--- jikesrvm-2.3.4-org/./rvm/src/vm/memoryManagers/JMTk/vmInterface/MM_Interface.java	2004-12-18 16:27:26.000000000 -0500
+++ jikesrvm-2.3.4-bi/./rvm/src/vm/memoryManagers/JMTk/vmInterface/MM_Interface.java	2007-02-16 15:34:26.826706864 -0500
@@ -602,7 +602,7 @@
    * @param allocator Specify which allocation scheme/area JMTk should
    * allocate the memory from.
    * @param align the alignment requested; must be a power of 2.
-   * @param offset the offset at which the alignment is desired.
+   * @param offset the offset at which the alignment is desired. (in bi-directional, this is the object pointer offset)
    * @return the initialized Object
    */
   public static Object allocateScalar(int size, Object [] tib, int allocator,
@@ -610,8 +610,13 @@
     throws UninterruptiblePragma, InlinePragma {
     Plan plan = Plan.getInstance();
     allocator = Plan.checkAllocator(size, align, allocator);
-    Address region = allocateSpace(plan, size, align, offset, allocator);
-    Object result = VM_ObjectModel.initializeScalar(region, tib, size);
+
+    /***--bi   */
+    Address region = allocateSpace(plan, size, align, 0, allocator);     
+
+    /***--bi */	
+    Object result = VM_ObjectModel.initializeScalar(region, tib, offset);
+    
     plan.postAlloc(ObjectReference.fromObject(result), 
                    ObjectReference.fromObject(tib), size, allocator);
     return result;
@@ -759,7 +764,9 @@
     Object [] tib = type.getTypeInformationBlock();
     int headerSize = VM_ObjectModel.computeArrayHeaderSize(type);
     int align = VM_ObjectModel.getAlignment(type);
+    
     int offset = VM_ObjectModel.getOffsetForAlignment(type);
+	
     return allocateArray(length, type.getLogElementSize(), headerSize,
                          tib, allocator, align, offset);
   }
@@ -819,7 +826,10 @@
     VM_Array objectArrayType = VM_Type.JavaLangObjectArrayType;
     Object [] objectArrayTib = objectArrayType.getTypeInformationBlock();
     int align = VM_ObjectModel.getAlignment(objectArrayType);
-    int offset = VM_ObjectModel.getOffsetForAlignment(objectArrayType);
+	
+    /***--bi */
+    int offset = VM_ObjectModel.getOffsetForAlignment(objectArrayType);	
+	
     Object result = allocateArray(n, objectArrayType.getLogElementSize(),
                                   VM_ObjectModel.computeArrayHeaderSize(objectArrayType),
                                   objectArrayTib, Plan.ALLOC_IMMORTAL, align, offset);
@@ -984,7 +994,7 @@
    *
    * @param vmType The newly resolved type
    */
-  public static void notifyClassResolved(VM_Type vmType) 
+ /* public static void notifyClassResolved(VM_Type vmType) 
     throws InterruptiblePragma {
     MMType type;
     if (vmType.isArrayType()) {
@@ -1001,6 +1011,29 @@
                         vmType.asClass().getReferenceOffsets());
     }
     vmType.setMMType(type);
+  }*/
+  
+  /***--bi 
+   * In bi-directional layout, we  rewrite the whole method. 
+   *  We use both reference num and offset 
+   */
+  public static void notifyClassResolved(VM_Type vmType) 
+    throws InterruptiblePragma {
+    MMType type;
+    if (vmType.isArrayType()) {
+      type = new MMType(false,
+                        vmType.asArray().getElementType().isReferenceType(),
+                        vmType.isAcyclicReference(),
+                        pickAllocatorForType(vmType),                        
+                        0);
+    } else {
+      type = new MMType(false,
+                        false,
+                        vmType.isAcyclicReference(),
+                        pickAllocatorForType(vmType),			
+                        vmType.asClass().getReferenceNumInternal());
+    }
+    vmType.setMMType(type);
   }
 
   /**
--- jikesrvm-2.3.4-org/./rvm/src/vm/memoryManagers/JMTk/vmInterface/ObjectModel.java	2004-12-14 22:10:25.000000000 -0500
+++ jikesrvm-2.3.4-bi/./rvm/src/vm/memoryManagers/JMTk/vmInterface/ObjectModel.java	2007-02-16 15:36:02.243201352 -0500
@@ -219,7 +219,7 @@
    * @param object the address of the object
    * @return the value of the bits
    */
-  public static Word prepareAvailableBits(ObjectReference object) {
+  public static Word prepareAvailableBits(ObjectReference object) {    
     return VM_ObjectModel.prepareAvailableBits(object.toObject());
   }
 
--- jikesrvm-2.3.4-org/./rvm/src/vm/memoryManagers/JMTk/vmInterface/Plan.java	2004-12-17 05:07:17.000000000 -0500
+++ jikesrvm-2.3.4-bi/./rvm/src/vm/memoryManagers/JMTk/vmInterface/Plan.java	2005-04-19 15:55:46.000000000 -0400
@@ -22,6 +22,8 @@
  */
 //-#if RVM_WITH_SEMI_SPACE
 public class Plan extends SemiSpace implements Uninterruptible {
+//-#elif RVM_WITH_RS_SL
+public class Plan extends RS_sl implements Uninterruptible {
 //-#elif RVM_WITH_MARK_SWEEP
 public class Plan extends MarkSweep implements Uninterruptible {
 //-#elif RVM_WITH_REF_COUNT
--- jikesrvm-2.3.4-org/./rvm/src/vm/objectModel/default/VM_JavaHeader.java	2004-12-18 20:15:26.000000000 -0500
+++ jikesrvm-2.3.4-bi/./rvm/src/vm/objectModel/default/VM_JavaHeader.java	2007-02-16 15:59:07.494611128 -0500
@@ -97,16 +97,46 @@
    * What is the offset of the first word after the class?
    * For use by VM_ObjectModel.layoutInstanceFields
    */
+  
+  
+  /*** bi-directional start ***/
   public static int objectEndOffset(VM_Class klass) {
-    return klass.getInstanceSizeInternal() - OBJECT_REF_OFFSET;
+	  return klass.getInstanceSizeInternal() - OBJECT_REF_OFFSET- (klass.getReferenceNumInternal() << LOG_BYTES_IN_ADDRESS);
+	  
+  }
+  /*** bi-directional end ***/
+  
+  /**
+   * What is the start offset of the class, which is the distance from the 
+   * beginning to the object pointer, we also use this as the alignment offset
+   * The real alignment is only Four bytes different (The ARRAY_LENGTH_BYTES)  
+   */
+   
+    public static int getStartOffset(VM_Class klass) {    
+    /***--bi */
+	  return (klass.getReferenceSectionSize() ) + OBJECT_REF_OFFSET;	    
   }
 
+
   /**
    * What is the offset of the first word of the class?
    */
-  public static int objectStartOffset(VM_Class klass) {
-    return - OBJECT_REF_OFFSET;
-  }
+   /***--bi,  remove this method   */
+/*  public static int objectStartOffset(VM_Class klass) {
+    //return - OBJECT_REF_OFFSET;
+  } 
+*/  
+
+  /*** bi-directional start ***/	
+  /**
+   * What is the offset of the header 
+   */
+  public static int objectHeaderOffset(VM_Class klass) {
+    return - OBJECT_REF_OFFSET;  
+	    
+  }  
+  /*** bi-directional end ***/
+  
 
   /**
    * What is the last word of the header from an out-to-in perspective?
@@ -219,6 +249,171 @@
     }
     return VM_Memory.alignUp(size, BYTES_IN_INT);
   }
+  
+   
+   /*** bi-directional start ***/    
+   public static Object moveObject(Address toAddress, Object fromObj, 
+                                  int numBytes, boolean noGCHeader,
+				  VM_Class type)
+    throws InlinePragma  
+    {
+    
+    /***--bi  in bi-directional, we can not copy them in the same way, 
+     *	here is the code  for mv a scalar object only */
+     
+     // Default values
+    int copyBytes = numBytes;
+    int objRefOffset = OBJECT_REF_OFFSET;
+    Word statusWord = Word.zero(); 
+    Word hashState = HASH_STATE_UNHASHED;   
+    
+    int refSecSz = type.getReferenceSectionSize();     
+    
+    if (ADDRESS_BASED_HASHING) {
+      // Read the hash state (used below)
+      statusWord = VM_Magic.getWordAtOffset(fromObj, STATUS_OFFSET);
+      hashState = statusWord.and(HASH_STATE_MASK);
+      if (hashState.EQ(HASH_STATE_HASHED)) {
+        // We do not copy the hashcode, but we do allocate it
+        copyBytes -= HASHCODE_BYTES;
+
+        if (!DYNAMIC_HASH_OFFSET) {
+          // The hashcode is the first word, so we copy to object one word higher
+          toAddress = toAddress.add(HASHCODE_BYTES);
+        }
+      } else if (!DYNAMIC_HASH_OFFSET && hashState.EQ(HASH_STATE_HASHED_AND_MOVED)) {
+        // Simple operation (no hash state change), but one word larger header
+        objRefOffset += HASHCODE_BYTES;
+      }
+    }
+
+    // Low memory word of source object 
+    Address fromAddress = VM_Magic.objectAsAddress(fromObj).sub(objRefOffset+refSecSz);
+   
+    // Was the GC header stolen at allocation time? ok for arrays and scalars.
+    if (noGCHeader) {
+      if (VM.VerifyAssertions) {
+        // No object can be hashed and moved unless using dynamic hash offset
+        VM._assert(hashState.NE(HASH_STATE_HASHED_AND_MOVED) || DYNAMIC_HASH_OFFSET);
+      }
+ 
+      // We copy less but start higher in memory.
+      copyBytes -= GC_HEADER_BYTES;
+      objRefOffset -= GC_HEADER_BYTES;
+      toAddress = toAddress.add(GC_HEADER_BYTES);
+    }
+
+    // Do the copy
+    VM_Memory.aligned32Copy(toAddress, fromAddress, copyBytes); 
+    Object toObj = VM_Magic.addressAsObject(toAddress.add(objRefOffset+refSecSz)); //***--bi this toObj is the object pointer  
+                                                                          
+    									   
+
+    // Do we need to copy the hash code?
+    if (hashState.EQ(HASH_STATE_HASHED)) {
+      int hashCode = VM_Magic.objectAsAddress(fromObj).toWord().rshl(LOG_BYTES_IN_ADDRESS).toInt();  
+      
+           
+      
+      if (DYNAMIC_HASH_OFFSET) {
+      
+        VM_Magic.setIntAtOffset(toObj, numBytes - objRefOffset -refSecSz- HASHCODE_BYTES, hashCode); //***--bi
+      } else {
+      
+        VM_Magic.setIntAtOffset(toObj, HASHCODE_OFFSET, hashCode);
+      } 
+      VM_Magic.setWordAtOffset(toObj, STATUS_OFFSET, statusWord.or(HASH_STATE_HASHED_AND_MOVED));
+      if (VM_ObjectModel.HASH_STATS) VM_ObjectModel.hashTransition2++;
+    }
+
+    return toObj;   
+     
+ }
+
+ 
+    public static Object moveObject(Address toAddress, Object fromObj, 
+                                  int numBytes, boolean noGCHeader,
+				  VM_Array type)
+    throws InlinePragma  
+    {
+
+    // We copy arrays and scalars the same way
+    //return moveObject(toAddress, fromObj, numBytes, noGCHeader);
+    
+    /***--bi  in bi-directional, we can not copy them in the same way, 
+     *	here is the code  for mv a scalar object only */
+     
+     // Default values
+    int copyBytes = numBytes;
+    int objRefOffset = OBJECT_REF_OFFSET;
+    Word statusWord = Word.zero(); 
+    Word hashState = HASH_STATE_UNHASHED;   
+    
+    
+    if (ADDRESS_BASED_HASHING) {
+      // Read the hash state (used below)
+      statusWord = VM_Magic.getWordAtOffset(fromObj, STATUS_OFFSET);
+      hashState = statusWord.and(HASH_STATE_MASK);
+      if (hashState.EQ(HASH_STATE_HASHED)) {
+        // We do not copy the hashcode, but we do allocate it
+        copyBytes -= HASHCODE_BYTES;
+
+        if (!DYNAMIC_HASH_OFFSET) {
+          // The hashcode is the first word, so we copy to object one word higher
+          toAddress = toAddress.add(HASHCODE_BYTES);
+        }
+      } else if (!DYNAMIC_HASH_OFFSET && hashState.EQ(HASH_STATE_HASHED_AND_MOVED)) {
+        // Simple operation (no hash state change), but one word larger header
+        objRefOffset += HASHCODE_BYTES;
+      }
+    }
+
+    // Low memory word of source object 
+    Address fromAddress = VM_Magic.objectAsAddress(fromObj).sub(objRefOffset);
+   
+    // Was the GC header stolen at allocation time? ok for arrays and scalars.
+    if (noGCHeader) {
+      if (VM.VerifyAssertions) {
+        // No object can be hashed and moved unless using dynamic hash offset
+        VM._assert(hashState.NE(HASH_STATE_HASHED_AND_MOVED) || DYNAMIC_HASH_OFFSET);
+      }
+ 
+      // We copy less but start higher in memory.
+      copyBytes -= GC_HEADER_BYTES;
+      objRefOffset -= GC_HEADER_BYTES;
+      toAddress = toAddress.add(GC_HEADER_BYTES);
+    }
+
+    // Do the copy
+    VM_Memory.aligned32Copy(toAddress, fromAddress, copyBytes); 
+    Object toObj = VM_Magic.addressAsObject(toAddress.add(objRefOffset)); //***--bi this toObj is the object pointer  
+                                                                          
+    									   
+
+    // Do we need to copy the hash code?
+    if (hashState.EQ(HASH_STATE_HASHED)) {
+      int hashCode = VM_Magic.objectAsAddress(fromObj).toWord().rshl(LOG_BYTES_IN_ADDRESS).toInt();  
+      
+           
+      
+      if (DYNAMIC_HASH_OFFSET) {
+      
+        VM_Magic.setIntAtOffset(toObj, numBytes - objRefOffset - HASHCODE_BYTES, hashCode); //***--bi
+      } else {
+      
+        VM_Magic.setIntAtOffset(toObj, HASHCODE_OFFSET, hashCode);
+      } 
+      VM_Magic.setWordAtOffset(toObj, STATUS_OFFSET, statusWord.or(HASH_STATE_HASHED_AND_MOVED));
+      if (VM_ObjectModel.HASH_STATS) VM_ObjectModel.hashTransition2++;
+    }
+
+    return toObj;   
+     
+ }
+
+ /*** bi-directional end ***/
+ 
+  
 
   /**
    * Map from the object ref to the lowest address of the storage
@@ -226,15 +421,20 @@
    */
   public static Address objectStartRef(ObjectReference obj)
     throws InlinePragma {
-    if (MM_Interface.MOVES_OBJECTS) {
-      if (ADDRESS_BASED_HASHING && !DYNAMIC_HASH_OFFSET) {
-        Word hashState = obj.toAddress().loadWord(Offset.fromInt(STATUS_OFFSET)).and(HASH_STATE_MASK);
-        if (hashState.EQ(HASH_STATE_HASHED_AND_MOVED)) {
-          return obj.toAddress().sub(OBJECT_REF_OFFSET + HASHCODE_BYTES);
-        }
-      }
-    }
-    return obj.toAddress().sub(OBJECT_REF_OFFSET);
+    	
+    	
+    /***--bi , We need to firstly get the reference section (rs) size */
+    int rs_length =0;
+    Object[] tib = VM_ObjectModel.getTIB(obj);
+    VM_Type type = VM_Magic.objectAsType(tib[VM_TIBLayoutConstants.TIB_TYPE_INDEX]);
+    
+    if (type.isClassType()) {
+      VM_Class klass = type.asClass();
+      rs_length = klass.getReferenceSectionSize();
+      
+    } 
+ 
+    return obj.toAddress().sub(OBJECT_REF_OFFSET + rs_length);
   }
 
   /**
@@ -244,6 +444,8 @@
    * hashing. However, the GC algorithm could safely do this in the
    * nursery so we can't assert DYNAMIC_HASH_OFFSET.
    */
+  
+  
   public static ObjectReference getObjectFromStartAddress(Address start) {
     if (VM.VerifyAssertions) VM._assert(OTHER_HEADER_BYTES == 0);
 
@@ -307,6 +509,9 @@
    
     return next.toObjectReference();
   }
+  
+  
+  
  
   /**
    * Get the next scalar in the heap under contiguous
@@ -325,97 +530,7 @@
 					      VM_Array type, int numElements) {
     return getNextObject(obj, bytesUsed(obj, type, numElements));
   }
-
-  /**
-   * Copy a scalar to the given raw storage address
-   */
-  public static Object moveObject(Address toAddress, Object fromObj, 
-                                  int numBytes, boolean noGCHeader,
-				  VM_Class type)
-    throws InlinePragma {
-
-    // We copy arrays and scalars the same way
-    return moveObject(toAddress, fromObj, numBytes, noGCHeader);
- }
-
-  /**
-   * Copy an array to the given raw storage address
-   */
-  public static Object moveObject(Address toAddress, Object fromObj,
-                                  int numBytes, boolean noGCHeader, 
-				  VM_Array type)
-    throws InlinePragma {
-
-    // We copy arrays and scalars the same way
-    return moveObject(toAddress, fromObj, numBytes, noGCHeader);
-  }
-
-  /**
-   * Copy an object to the given raw storage address
-   */
-  public static Object moveObject(Address toAddress, Object fromObj, 
-                                  int numBytes, boolean noGCHeader)
-    throws InlinePragma {
-
-    // Default values
-    int copyBytes = numBytes;
-    int objRefOffset = OBJECT_REF_OFFSET;
-    Word statusWord = Word.zero(); 
-    Word hashState = HASH_STATE_UNHASHED;
-    
-    if (ADDRESS_BASED_HASHING) {
-      // Read the hash state (used below)
-      statusWord = VM_Magic.getWordAtOffset(fromObj, STATUS_OFFSET);
-      hashState = statusWord.and(HASH_STATE_MASK);
-      if (hashState.EQ(HASH_STATE_HASHED)) {
-        // We do not copy the hashcode, but we do allocate it
-        copyBytes -= HASHCODE_BYTES;
-
-        if (!DYNAMIC_HASH_OFFSET) {
-          // The hashcode is the first word, so we copy to object one word higher
-          toAddress = toAddress.add(HASHCODE_BYTES);
-        }
-      } else if (!DYNAMIC_HASH_OFFSET && hashState.EQ(HASH_STATE_HASHED_AND_MOVED)) {
-        // Simple operation (no hash state change), but one word larger header
-        objRefOffset += HASHCODE_BYTES;
-      }
-    }
-
-    // Low memory word of source object 
-    Address fromAddress = VM_Magic.objectAsAddress(fromObj).sub(objRefOffset);
-   
-    // Was the GC header stolen at allocation time? ok for arrays and scalars.
-    if (noGCHeader) {
-      if (VM.VerifyAssertions) {
-        // No object can be hashed and moved unless using dynamic hash offset
-        VM._assert(hashState.NE(HASH_STATE_HASHED_AND_MOVED) || DYNAMIC_HASH_OFFSET);
-      }
- 
-      // We copy less but start higher in memory.
-      copyBytes -= GC_HEADER_BYTES;
-      objRefOffset -= GC_HEADER_BYTES;
-      toAddress = toAddress.add(GC_HEADER_BYTES);
-    }
-
-    // Do the copy
-    VM_Memory.aligned32Copy(toAddress, fromAddress, copyBytes); 
-    Object toObj = VM_Magic.addressAsObject(toAddress.add(objRefOffset));
-
-    // Do we need to copy the hash code?
-    if (hashState.EQ(HASH_STATE_HASHED)) {
-      int hashCode = VM_Magic.objectAsAddress(fromObj).toWord().rshl(LOG_BYTES_IN_ADDRESS).toInt();  
-      if (DYNAMIC_HASH_OFFSET) {
-        VM_Magic.setIntAtOffset(toObj, numBytes - objRefOffset - HASHCODE_BYTES, hashCode);
-      } else {
-        VM_Magic.setIntAtOffset(toObj, HASHCODE_OFFSET, hashCode);
-      } 
-      VM_Magic.setWordAtOffset(toObj, STATUS_OFFSET, statusWord.or(HASH_STATE_HASHED_AND_MOVED));
-      if (VM_ObjectModel.HASH_STATS) VM_ObjectModel.hashTransition2++;
-    }
-
-    return toObj;
-  }
-  
+     
 
   /**
    * Get the hash code of an object.
@@ -474,7 +589,10 @@
 	return hashCode.rshl(HASH_CODE_SHIFT).toInt();  // we installed the hash code
     }
   }
-
+  
+  
+  
+ 
   /**
    * Get the offset of the thin lock word in this object
    */
@@ -595,6 +713,7 @@
    * A prepare on the word containing the available bits
    */
   public static Word prepareAvailableBits(Object o) {
+  
     return VM_Magic.prepareWord(o, STATUS_OFFSET);
   }
   
@@ -681,8 +800,9 @@
    */
   public static int getOffsetForAlignment(VM_Class t) {
     /* Align the first field - note that this is one word off from
-       the reference. */ 
-    return SCALAR_HEADER_SIZE; 
+       the reference. */   
+          return SCALAR_HEADER_SIZE; 
+	  
   }
 
   /**
@@ -691,14 +811,10 @@
    * @param t VM_Class instance being copied
    * @param obj the object being copied
    */
+   //***--bi : in bi-directional, there is no so called hashcode move bytes 
   public static int getOffsetForAlignment(VM_Class t, ObjectReference obj) {
-    if (ADDRESS_BASED_HASHING && !DYNAMIC_HASH_OFFSET) {
-      Word hashState = obj.toAddress().loadWord(Offset.fromInt(STATUS_OFFSET)).and(HASH_STATE_MASK);
-      if (hashState.NE(HASH_STATE_UNHASHED)) {
-        return SCALAR_HEADER_SIZE + HASHCODE_BYTES;
-      }
-    } 
-    return SCALAR_HEADER_SIZE; 
+    
+	return 0;  // For bi, just align to the real begining of the object 	
   }
 
   /**
@@ -709,7 +825,9 @@
   public static int getOffsetForAlignment(VM_Array t) {
     /* although array_header_size == object_ref_offset we say this
        because the whole point is to align the object ref */
-    return OBJECT_REF_OFFSET;
+	  
+    return OBJECT_REF_OFFSET; 
+	
   }
 
   /**
@@ -719,14 +837,8 @@
    * @param obj the object being copied
    */
   public static int getOffsetForAlignment(VM_Array t, ObjectReference obj) {
-    /* although array_header_size == object_ref_offset we say this
-       because the whole point is to align the object ref */
-    if (ADDRESS_BASED_HASHING && !DYNAMIC_HASH_OFFSET) {
-      Word hashState = obj.toAddress().loadWord(Offset.fromInt(STATUS_OFFSET)).and(HASH_STATE_MASK);
-      if (hashState.NE(HASH_STATE_UNHASHED)) {
-        return OBJECT_REF_OFFSET + HASHCODE_BYTES;
-      }
-    }
+       
+       /***---bi  in bi, there is no need to change for the possible hashcode */ 
     return OBJECT_REF_OFFSET;
   }
 
@@ -738,8 +850,10 @@
    */
   public static Object initializeScalarHeader(Address ptr, Object[] tib, 
 					      int size) {
-    // (TIB set by VM_ObjectModel)
-    Object ref = VM_Magic.addressAsObject(ptr.add(OBJECT_REF_OFFSET));
+    
+    //***--bi
+    //Object ref = VM_Magic.addressAsObject(ptr.add(OBJECT_REF_OFFSET  + (getRefNumfromTIB(tib) << LOG_BYTES_IN_ADDRESS) ));
+    Object ref = VM_Magic.addressAsObject(ptr.add(size));
     return ref;
   }
 
@@ -748,14 +862,38 @@
    * @param bootImage The bootimage being written
    * @param ptr  The object ref to the storage to be initialized
    * @param tib  The TIB of the instance being created
-   * @param size The number of bytes allocated by the GC system for this object.
+   * @param size The number of bytes allocated by the GC system for this object. (bi, the start offset to the object pointer)
    */
   public static int initializeScalarHeader(BootImageInterface bootImage,
                                            int ptr, Object[] tib, int size)
     throws InterruptiblePragma {
-    int ref = ptr + OBJECT_REF_OFFSET;
-    return ref;
+    
+	  //***--bi 
+	  int ref = ptr + size;
+    	  return ref;
   }
+  
+  /*** bi-directional start ***/
+  /*  add a new method, to get the reference number from TIB */
+  /**
+   * Perform a transformation from tib to its reference number 
+   * @param tib The TIB of the instance call this
+   */
+   public static int getRefNumfromTIB(Object[] tib)
+   {
+   	
+	 VM_Type type = (VM_Type)(tib[VM_TIBLayoutConstants.TIB_TYPE_INDEX]);
+	 
+	 if ( type.isClassType() )   	
+	 {
+	    return type.asClass().getReferenceNumInternal();
+	 }
+	
+	 // This is an array
+	 return 0;  	 
+   }
+   
+   /*** bi-directional end ***/
 
   /**
    * Perform any required initialization of the JAVA portion of the header.
@@ -845,5 +983,7 @@
     VM.sysWriteln("VM_AllocatorHeader.REQUESTED_BITS  = ", VM_AllocatorHeader.REQUESTED_BITS);
   }
   */
+  
+  
 
 }
--- jikesrvm-2.3.4-org/./rvm/src/vm/objectModel/default/VM_JavaHeaderConstants.java	2004-11-17 23:56:39.000000000 -0500
+++ jikesrvm-2.3.4-bi/./rvm/src/vm/objectModel/default/VM_JavaHeaderConstants.java	2007-02-16 16:05:39.330043088 -0500
@@ -40,6 +40,11 @@
   static final int MISC_HEADER_OFFSET  = JAVA_HEADER_OFFSET  - MISC_HEADER_BYTES;
   static final int GC_HEADER_OFFSET    = MISC_HEADER_OFFSET  - GC_HEADER_BYTES;
   
+  /***--bi  Add for bi-directional, define an offset of the first reference */
+  static final int REFERENCE_SECTION_OFFSET =  GC_HEADER_OFFSET; 
+  
+  
+  
 
   /**
    * This object model supports two schemes for hashcodes:
@@ -69,7 +74,9 @@
    * after the data (at a dynamic offset)
    */
   static final boolean DYNAMIC_HASH_OFFSET 
-    = ADDRESS_BASED_HASHING && VM_AllocatorHeader.NEEDS_LINEAR_SCAN;
+
+       //***--bi, For bi, we set it to ture directly 
+	=  true;
                                            
   /**
    * Can we perform a linear scan?
@@ -90,6 +97,6 @@
   static final Word HASH_STATE_MASK             = HASH_STATE_UNHASHED.or(HASH_STATE_HASHED).or(HASH_STATE_HASHED_AND_MOVED);
   
   static final int HASHCODE_BYTES              = BYTES_IN_INT;
-  static final int HASHCODE_OFFSET = GC_HEADER_OFFSET - HASHCODE_BYTES; 
+  static final int HASHCODE_OFFSET = GC_HEADER_OFFSET - HASHCODE_BYTES;
   
 }
--- jikesrvm-2.3.4-org/./rvm/src/vm/objectModel/VM_ObjectModel.java	2004-10-18 07:13:44.000000000 -0400
+++ jikesrvm-2.3.4-bi/./rvm/src/vm/objectModel/VM_ObjectModel.java	2007-02-16 16:13:51.789177920 -0500
@@ -124,52 +124,66 @@
   /** count transitions from HASHED to HASHED_AND_MOVED */
   public static int hashTransition2 = 0; 
 
+
+  
   /**
-   * Layout the instance fields declared in this class.
-   * TODO: If we allocate a 4-byte and then an 8-byte field on a 32 bit architecture
-   *       we can possibly waste 4 bytes.  
+   * Copy a scalar object to the given raw storage address
    */
-  public static void layoutInstanceFields(VM_Class klass) throws InterruptiblePragma {
-    int fieldOffset = VM_JavaHeader.objectEndOffset(klass);
-    int doubleAlign = Math.abs(VM_JavaHeader.objectStartOffset(klass) % BYTES_IN_DOUBLE);
-    VM_Field fields[] = klass.getDeclaredFields();
-    for (int i = 0, n = fields.length; i < n; ++i) {
-      VM_Field field = fields[i];
-      if (!field.isStatic()) {
-        int fieldSize = field.getType().getSize();
-        if (fieldSize == BYTES_IN_INT) {
-          int emptySlot = klass.getEmptySlot();
-          if (emptySlot != 0) {
-            field.setOffset(emptySlot);
-            klass.setEmptySlot(0);
-          } else {
-            field.setOffset(fieldOffset);
-            fieldOffset += BYTES_IN_INT;
-            klass.increaseInstanceSize(BYTES_IN_INT);
-          }
-        } else {
-          if (VM.VerifyAssertions) {
-            VM._assert(fieldSize == BYTES_IN_DOUBLE); // (or ADDRESS in 64 bit mode)
-          }
-          klass.setAlignment(BYTES_IN_DOUBLE);
-          if (Math.abs(fieldOffset % BYTES_IN_DOUBLE) == doubleAlign) {
-            field.setOffset(fieldOffset);
-            fieldOffset += BYTES_IN_DOUBLE;
-            klass.increaseInstanceSize(BYTES_IN_DOUBLE);
-          } else {
-            if (VM.VerifyAssertions) VM._assert(klass.getEmptySlot() == 0);
-            klass.setEmptySlot(fieldOffset);
-            fieldOffset += BYTES_IN_INT;
-            field.setOffset(fieldOffset);
-            fieldOffset += BYTES_IN_DOUBLE;
-            klass.increaseInstanceSize(BYTES_IN_INT+BYTES_IN_DOUBLE);
-          }
-        }
-      }
+  public static Object moveObject(Address toAddress, Object fromObj,
+                                  int numBytes, boolean noGCHeader, VM_Class type) {
+    return VM_JavaHeader.moveObject(toAddress, fromObj, numBytes, noGCHeader, type);
+  }
+
+  /**
+   * Copy an array object to the given raw storage address
+   */
+  public static Object moveObject(Address toAddress, Object fromObj,
+                                  int numBytes, boolean noGCHeader, VM_Array type) {
+    return VM_JavaHeader.moveObject(toAddress, fromObj, numBytes, noGCHeader, type);
+  }
+
+  
+  /**
+   * Compute the header size of an instance of the given type.
+   */
+  public static int computeHeaderSize(VM_Type type) throws InlinePragma {
+    if (type.isArrayType()) {
+      return computeArrayHeaderSize(type.asArray());
+    } else {
+      return computeScalarHeaderSize(type.asClass());
     }
   }
 
   /**
+   * Compute the header size of an object 
+   */
+  public static int computeHeaderSize(Object ref) throws InterruptiblePragma {
+    return computeHeaderSize(getObjectType(ref));
+  }
+
+  /**
+   * Compute the header size of an instance of the given type.
+   */
+  public static int computeScalarHeaderSize(VM_Class type) throws InlinePragma {
+    return VM_JavaHeader.computeScalarHeaderSize(type);
+  }
+
+  /**
+   * Compute the header size of an instance of the given type.
+   */
+  public static int computeArrayHeaderSize(VM_Array type) {
+    return VM_JavaHeader.computeArrayHeaderSize(type);
+  }
+
+  /**
+   * Given a TIB, compute the header size of an instance of the TIB's class
+   */
+  public static int computeHeaderSize(Object[] tib) {
+    return computeHeaderSize(VM_Magic.objectAsType(tib[0]));
+  }
+
+  
+  /**
    * Given a reference, return an address which is guaranteed to be inside
    * the memory region allocated to the object.
    */
@@ -345,22 +359,7 @@
     return VM_JavaHeader.objectStartRef(obj);
   }
 
-  /**
-   * Copy a scalar object to the given raw storage address
-   */
-  public static Object moveObject(Address toAddress, Object fromObj,
-                                  int numBytes, boolean noGCHeader, VM_Class type) {
-    return VM_JavaHeader.moveObject(toAddress, fromObj, numBytes, noGCHeader, type);
-  }
-
-  /**
-   * Copy an array object to the given raw storage address
-   */
-  public static Object moveObject(Address toAddress, Object fromObj,
-                                  int numBytes, boolean noGCHeader, VM_Array type) {
-    return VM_JavaHeader.moveObject(toAddress, fromObj, numBytes, noGCHeader, type);
-  }
-
+  
   /**
    * Get the type of an object.  
    */
@@ -374,6 +373,16 @@
   public static int getArrayLength(Object o) {
     return VM_Magic.getIntAtOffset(o, getArrayLengthOffset());
   }
+  
+  
+  /*** bi-directional start ***/
+  /**
+   * Get the length of an array from the objectReference  
+   */
+   public static int getArrayLength(ObjectReference obj) {
+    return VM_Magic.getIntAtOffset(obj.toObject(), getArrayLengthOffset());
+  }
+  /*** bi-directional end ***/
 
   /**
    * Set the length of an array
@@ -493,6 +502,7 @@
    * A prepare on the word containing the available bits
    */
   public static Word prepareAvailableBits(Object o) {
+  
     return VM_JavaHeader.prepareAvailableBits(o);
   }
   
@@ -520,45 +530,7 @@
     return VM_JavaHeader.maximumObjectRef(regionHighAddr);
   }
 
-  /**
-   * Compute the header size of an instance of the given type.
-   */
-  public static int computeHeaderSize(VM_Type type) throws InlinePragma {
-    if (type.isArrayType()) {
-      return computeArrayHeaderSize(type.asArray());
-    } else {
-      return computeScalarHeaderSize(type.asClass());
-    }
-  }
-
-  /**
-   * Compute the header size of an object 
-   */
-  public static int computeHeaderSize(Object ref) throws InterruptiblePragma {
-    return computeHeaderSize(getObjectType(ref));
-  }
-
-  /**
-   * Compute the header size of an instance of the given type.
-   */
-  public static int computeScalarHeaderSize(VM_Class type) throws InlinePragma {
-    return VM_JavaHeader.computeScalarHeaderSize(type);
-  }
-
-  /**
-   * Compute the header size of an instance of the given type.
-   */
-  public static int computeArrayHeaderSize(VM_Array type) {
-    return VM_JavaHeader.computeArrayHeaderSize(type);
-  }
-
-  /**
-   * Given a TIB, compute the header size of an instance of the TIB's class
-   */
-  public static int computeHeaderSize(Object[] tib) {
-    return computeHeaderSize(VM_Magic.objectAsType(tib[0]));
-  }
-
+  
   /**
    * For a reference to an object, what is the offset in bytes to the 
    * last word of the header from an out-to-in perspective for the object?
@@ -572,8 +544,10 @@
    * word of the object?
    */
   public static int objectStartOffset(VM_Class t) {
-    return VM_JavaHeader.objectStartOffset(t);
+    //***-- bi, use the getStartOffset to replace objectStartOffset 
+    return (-VM_JavaHeader.getStartOffset(t));  
   }
+  
 
   /**
    * Return the desired aligment of the alignment point in the object returned
@@ -591,7 +565,9 @@
    * @param obj the object being copied
    */
   public static int getAlignment(VM_Class t, Object obj) {
+    
     return VM_JavaHeader.getAlignment(t, obj);
+    
   }
 
   /**
@@ -619,7 +595,9 @@
    * @param t VM_Class instance being created
    */
   public static int getOffsetForAlignment(VM_Class t) {
-    return VM_JavaHeader.getOffsetForAlignment(t);
+    // return VM_JavaHeader.getOffsetForAlignment(t);
+    //***--bi , change it into start Offset directly  
+    return VM_JavaHeader.getStartOffset(t);
   }
 
   /**
@@ -629,7 +607,7 @@
    * @param obj the object being copied
    */
   public static int getOffsetForAlignment(VM_Class t, ObjectReference obj) {
-    return VM_JavaHeader.getOffsetForAlignment(t, obj);
+      return VM_JavaHeader.getOffsetForAlignment(t, obj);
   }
 
   /**
@@ -661,6 +639,8 @@
    */
   public static Object initializeScalar(Address ptr, Object[] tib, int size)
     throws InlinePragma {
+	  
+	  //***--bi
     Object ref = VM_JavaHeader.initializeScalarHeader(ptr, tib, size);
     VM_MiscHeader.initializeHeader(ref, tib, size, true);
     setTIB(ref, tib);
@@ -680,11 +660,19 @@
     Object[] tib = klass.getTypeInformationBlock();
     int size = klass.getInstanceSize();
     int align = getAlignment(klass);
-    int offset = getOffsetForAlignment(klass);
-    int ptr = bootImage.allocateStorage(size, align, offset);
-    int ref = VM_JavaHeader.initializeScalarHeader(bootImage, ptr, tib, size);
-    VM_AllocatorHeader.initializeHeader(bootImage, ref, tib, size, true);
-    VM_MiscHeader.initializeHeader(bootImage, ref, tib, size, true);
+	
+	/***--bi , we still use the name  getOffsetForAlignment, but actually for 
+	scalars, just call the getStartOffset */
+	 
+    int offset = getOffsetForAlignment(klass);    
+	
+    int ptr = bootImage.allocateStorage(size, align, 0); 
+    
+    int ref = VM_JavaHeader.initializeScalarHeader(bootImage, ptr, tib, offset);	
+    VM_AllocatorHeader.initializeHeader(bootImage, ref, tib, offset, true);
+    VM_MiscHeader.initializeHeader(bootImage, ref, tib, offset, true);
+	
+    
     return ref;
   }
 
@@ -723,7 +711,10 @@
     Object[] tib = array.getTypeInformationBlock();
     int size = array.getInstanceSize(numElements);
     int align = getAlignment(array);
+	
+    //***--bi
     int offset = getOffsetForAlignment(array);
+	
     int ptr = bootImage.allocateStorage(size, align, offset);
     int ref = VM_JavaHeader.initializeArrayHeader(bootImage, ptr, tib, size);
     bootImage.setFullWord(ref + getArrayLengthOffset(), numElements);
@@ -780,6 +771,82 @@
                                          ) throws InterruptiblePragma {
     VM_JavaHeader.baselineEmitLoadTIB(asm, dest, object);
   }
+  
+  
+    /**
+   * Layout the instance fields declared in this class.
+   * TODO: If we allocate a 4-byte and then an 8-byte field on a 32 bit architecture
+   *       we can possibly waste 4 bytes.  
+   */
+  public static void layoutInstanceFields(VM_Class klass) throws InterruptiblePragma {
+    int fieldOffset = VM_JavaHeader.objectEndOffset(klass);
+    
+    /***-- bi */
+    int referenceNumber = klass.getReferenceNumInternal();
+    int referenceOffset = -(referenceNumber << LOG_BYTES_IN_ADDRESS)+REFERENCE_SECTION_OFFSET-BYTES_IN_ADDRESS;
+    /***-- bi end*/
+
+    int doubleAlign = Math.abs( (-VM_JavaHeader.getStartOffset(klass)) % BYTES_IN_DOUBLE);
+    
+    VM_Field fields[] = klass.getDeclaredFields();
+    for (int i = 0, n = fields.length; i < n; ++i) {
+      VM_Field field = fields[i];
+      if (!field.isStatic()) {
+      	VM_TypeReference type_var = field.getType();
+      	int fieldSize = type_var.getSize();
+        
+        /***--bi: check whether it is reference type   */
+        if (type_var.isReferenceType()) {
+        	/* For reference, this is no need to keep an emptySlot, use a reference offset */       	        	
+		field.setOffset(referenceOffset);
+        	referenceNumber++;
+		referenceOffset-=BYTES_IN_ADDRESS;
+        	klass.increaseInstanceSize(BYTES_IN_ADDRESS);        	
+        }
+       /*** end of --bi: check whether it is reference type  */ 
+        else {
+               	
+        
+        if (fieldSize == BYTES_IN_INT) {
+          int emptySlot = klass.getEmptySlot();
+          if (emptySlot != 0) {
+            field.setOffset(emptySlot);
+            klass.setEmptySlot(0);
+          } else {
+            field.setOffset(fieldOffset);
+            fieldOffset += BYTES_IN_INT;
+            klass.increaseInstanceSize(BYTES_IN_INT);
+          }
+        	} else {
+          if (VM.VerifyAssertions) {
+            VM._assert(fieldSize == BYTES_IN_DOUBLE); // (or ADDRESS in 64 bit mode)
+          }
+          klass.setAlignment(BYTES_IN_DOUBLE);
+          if (Math.abs(fieldOffset % BYTES_IN_DOUBLE) == doubleAlign) {
+            field.setOffset(fieldOffset);
+            fieldOffset += BYTES_IN_DOUBLE;
+            klass.increaseInstanceSize(BYTES_IN_DOUBLE);
+          } else {
+            if (VM.VerifyAssertions) VM._assert(klass.getEmptySlot() == 0);
+            klass.setEmptySlot(fieldOffset);
+            fieldOffset += BYTES_IN_INT;
+            field.setOffset(fieldOffset);
+            fieldOffset += BYTES_IN_DOUBLE;
+            klass.increaseInstanceSize(BYTES_IN_INT+BYTES_IN_DOUBLE);
+          }
+        	}
+      	}
+      }
+    }
+    
+     /***--bi: set the reference number in this class  */
+     klass.setReferenceNum(referenceNumber);
+     klass.setReferenceSectionLength(referenceNumber << LOG_BYTES_IN_ADDRESS);
+     
+     /*** end of --bi: set the reference number in this class   */
+  }
+
+  
 
   //-#if RVM_WITH_OPT_COMPILER
   /**
--- jikesrvm-2.3.4-org/./rvm/src/vm/runtime/VM_Runtime.java	2004-12-18 20:15:27.000000000 -0500
+++ jikesrvm-2.3.4-bi/./rvm/src/vm/runtime/VM_Runtime.java	2007-02-16 16:15:38.001031264 -0500
@@ -280,7 +280,10 @@
 
     int allocator = MM_Interface.pickAllocator(cls);
     int align = VM_ObjectModel.getAlignment(cls);
+    
+    /***--bi ,change it to return the start offset */
     int offset = VM_ObjectModel.getOffsetForAlignment(cls);
+    
     return resolvedNewScalar(cls.getInstanceSize(), 
                              cls.getTypeInformationBlock(), 
                              cls.hasFinalizer(),
@@ -300,7 +303,10 @@
     
     int allocator = MM_Interface.pickAllocator(cls);
     int align = VM_ObjectModel.getAlignment(cls);
+	
+	/***--bi ,change it to start offset */
     int offset = VM_ObjectModel.getOffsetForAlignment(cls);
+    
     return resolvedNewScalar(cls.getInstanceSize(), 
                              cls.getTypeInformationBlock(), 
                              cls.hasFinalizer(),
@@ -380,6 +386,7 @@
   public static Object resolvedNewArray(int numElements, VM_Array array) 
     throws OutOfMemoryError, NegativeArraySizeException { 
 
+	  
     return resolvedNewArray(numElements, 
                             array.getLogElementSize(),
                             VM_ObjectModel.computeArrayHeaderSize(array),
--- jikesrvm-2.3.4-org/./rvm/src/vm/vmmagic/unboxed/Word.java	2004-09-09 02:40:51.000000000 -0400
+++ jikesrvm-2.3.4-bi/./rvm/src/vm/vmmagic/unboxed/Word.java	2007-02-16 16:16:49.605145784 -0500
@@ -225,7 +225,7 @@
   public Word rsha (int amt) throws UninterruptibleNoWarnPragma {
     if (VM.VerifyAssertions && VM.runningVM) VM._assert(VM.NOT_REACHED);
     return new Word(value >> amt);
-  }
+  } 
 
 }
 
--- jikesrvm-2.3.4-org/./rvm/src/vm/VM.java	2004-12-18 20:15:24.000000000 -0500
+++ jikesrvm-2.3.4-bi/./rvm/src/vm/VM.java	2007-02-16 16:17:57.780781512 -0500
@@ -312,11 +312,6 @@
     if (verboseBoot >= 1) VM.sysWriteln("Initializing JNI for boot thread");
     VM_Thread.getCurrentThread().initializeJNIEnv();
 
-    //-#if RVM_WITH_HPM
-    runClassInitializer("com.ibm.JikesRVM.Java2HPM");
-    VM_HardwarePerformanceMonitors.setUpHPMinfo();
-    //-#endif
-
     // Run class intializers that require JNI
     if (verboseBoot >= 1) VM.sysWriteln("Running late class initializers");
     runClassInitializer("gnu.java.nio.channels.FileChannelImpl");
@@ -324,6 +319,11 @@
     runClassInitializer("java.lang.Double");
     runClassInitializer("java.util.PropertyPermission");
     runClassInitializer("com.ibm.JikesRVM.VM_Process");
+    
+    //-#if RVM_WITH_HPM
+    runClassInitializer("com.ibm.JikesRVM.Java2HPM");
+    VM_HardwarePerformanceMonitors.setUpHPMinfo();
+    //-#endif
 
     // Initialize java.lang.System.out, java.lang.System.err, java.lang.System.in
     VM_FileSystem.initializeStandardStreams();
--- jikesrvm-2.3.4-org/./rvm/src/vm/VM_SizeConstants.java	2004-08-29 01:18:41.000000000 -0400
+++ jikesrvm-2.3.4-bi/./rvm/src/vm/VM_SizeConstants.java	2007-02-16 16:19:43.340733960 -0500
@@ -63,4 +63,9 @@
   static final int BYTES_IN_WORD = 1<<LOG_BYTES_IN_WORD;
   static final int LOG_BITS_IN_WORD = LOG_BITS_IN_BYTE + LOG_BYTES_IN_WORD;
   static final int BITS_IN_WORD = 1<<LOG_BITS_IN_WORD;
+  
+  /***--bi  Add for bidirectional */
+  static final int REF_SECTION_OFFSET =  -3*BYTES_IN_ADDRESS; 
+  
+  
 }
--- jikesrvm-2.3.4-org/./MMTk/src/org/mmtk/plan/CopyMS.java	2004-12-16 01:12:58.000000000 -0500
+++ jikesrvm-2.3.4-bi/./MMTk/src/org/mmtk/plan/CopyMS.java	2007-02-16 16:20:45.908222256 -0500
@@ -78,7 +78,7 @@
    *
    * Instance variables
    */
-
+  
   // allocators
   private CopyLocal nursery;
   private MarkSweepLocal ms;
--- jikesrvm-2.3.4-org/./MMTk/src/org/mmtk/plan/Generational.java	2004-12-16 01:12:58.000000000 -0500
+++ jikesrvm-2.3.4-bi/./MMTk/src/org/mmtk/plan/Generational.java	2007-02-16 16:21:55.675616000 -0500
@@ -552,9 +552,11 @@
    *
    * @param object The object to be scanned.
    */
+   
+   /***--bi useless in bi-directional layout 
   protected final void scanForwardedObject(ObjectReference object) {
     Scan.scanObject(object);
-  }
+  }*/
 
   /**
    * If the object in question has been forwarded, return its
--- jikesrvm-2.3.4-org/./MMTk/src/org/mmtk/plan/SemiSpaceBase.java	2004-12-17 05:25:04.000000000 -0500
+++ jikesrvm-2.3.4-bi/./MMTk/src/org/mmtk/plan/SemiSpaceBase.java	2007-02-16 16:23:29.901291520 -0500
@@ -58,6 +58,9 @@
   public static final boolean MOVES_OBJECTS = true;
   public static final int GC_HEADER_BITS_REQUIRED = CopySpace.LOCAL_GC_BITS_REQUIRED;
   public static final int GC_HEADER_BYTES_REQUIRED = CopySpace.GC_HEADER_BYTES_REQUIRED;
+  
+  //***--bi
+  public static final boolean NEEDS_LINEAR_SCAN = true;
 
   // GC state
   protected static boolean hi = false; // True if allocing to "higher" semispace
@@ -321,7 +324,8 @@
    * @return The possibly moved reference.
    */
   public static ObjectReference traceObject(ObjectReference object) 
-    throws InlinePragma {
+    throws InlinePragma {   
+        
     if (object.isNull())
       return object;
     else if (Space.isInSpace(SS0, object))
@@ -329,7 +333,7 @@
     else if (Space.isInSpace(SS1, object))
       return hi ? object: copySpace1.forwardAndScanObject(object);
     else
-      return Space.getSpaceForObject(object).traceObject(object);
+     return Space.getSpaceForObject(object).traceObject(object);
   }
 
   /**
@@ -372,6 +376,8 @@
   public static void forwardObjectLocation(Address location) 
     throws InlinePragma {
     ObjectReference object = location.loadObjectReference();
+    
+    
     if (!object.isNull()) {
       if ((hi && Space.isInSpace(SS0, object)) || 
  	  (!hi && Space.isInSpace(SS1, object)))
--- jikesrvm-2.3.4-org/./MMTk/src/org/mmtk/plan/StopTheWorldGC.java	2004-12-16 01:12:58.000000000 -0500
+++ jikesrvm-2.3.4-bi/./MMTk/src/org/mmtk/plan/StopTheWorldGC.java	2007-02-16 16:25:09.982076928 -0500
@@ -76,6 +76,10 @@
 
   // GC stress test
   private static long lastStressCumulativeCommittedPages = 0;  
+  
+  
+  //***--bi, add here to make it a as a public variable
+  public static final boolean NEEDS_LINEAR_SCAN = true;
 
   /****************************************************************************
    *
@@ -189,6 +193,7 @@
     Collection.rendezvous(4901);
 
     if (timekeeper) scanTime.start();
+    
     processAllWork(); 
     if (timekeeper) scanTime.stop();
 
--- jikesrvm-2.3.4-org/./MMTk/src/org/mmtk/policy/Space.java	2004-10-18 07:13:46.000000000 -0400
+++ jikesrvm-2.3.4-bi/./MMTk/src/org/mmtk/policy/Space.java	2007-02-16 16:27:09.899846656 -0500
@@ -402,7 +402,7 @@
    * @return The space containing the object
    */
   public static Space getSpaceForObject(ObjectReference object) 
-    throws InlinePragma {
+    throws InlinePragma {       
     return Map.getSpaceForObject(object);
   }
 
--- jikesrvm-2.3.4-org/./MMTk/src/org/mmtk/utility/scan/MMType.java	2004-12-06 00:25:22.000000000 -0500
+++ jikesrvm-2.3.4-bi/./MMTk/src/org/mmtk/utility/scan/MMType.java	2007-02-16 16:47:22.610486616 -0500
@@ -25,9 +25,18 @@
   private boolean isDelegated;
   private boolean isAcyclic;
   private Offset arrayOffset;
-  private int [] offsets;
+  /***-- bi: no use in bi-directional layout */
+  // private int [] offsets;
+
+
   private int allocator;
   
+  /***--bi add private data fields for reference number */
+  private int refNum = 0;  
+  private int rsOffset = 0;	// beginning of the reference section offset, it is negative for normal objects 
+  
+  
+  
   // per-type statistics
   private int allocCount;
   private int allocBytes;
@@ -56,14 +65,19 @@
    * @param offsets An array of integer offsets for the fields of this
    * type (if any).
    */
+  
+  
+  /***--bi the constructor for bi mode, here we only need the reference number */
+  
   public MMType(boolean isDelegated, boolean isReferenceArray, 
-                boolean isAcyclic, int allocator, int [] offsets)
+                boolean isAcyclic, int allocator, int refNum)
     throws InterruptiblePragma {
     this.isDelegated = isDelegated;
     this.isReferenceArray = isReferenceArray;
     this.isAcyclic = isAcyclic;
-    this.allocator = allocator;
-    this.offsets = offsets;
+    this.allocator = allocator;    
+    this.refNum = refNum;
+    this.rsOffset = - (refNum << LOG_BYTES_IN_ADDRESS);    
   }
 
   /****************************************************************************
@@ -80,12 +94,17 @@
    * into an array
    * @return The address of the relevant slot within the object
    */
+   
+ /***--bi modified it for bi-directinal layout **/  
   Address getSlot(ObjectReference object, int reference) throws InlinePragma {
-    Address addr = object.toAddress();
-    if (isReferenceArray)
+    Address addr = object.toAddress();    
+        
+    if (isReferenceArray)      
       return addr.add(arrayOffset).add(reference << LOG_BYTES_IN_ADDRESS);
     else
-      return addr.add(offsets[reference]);
+    { 
+      return addr.add(- ((reference+1) << LOG_BYTES_IN_ADDRESS)+REF_SECTION_OFFSET);
+    }
   }
 
   /**
@@ -95,12 +114,45 @@
    *
    * @param object The object in question
    * @return The number of references in the object
+   * bi: Actually the org version returns the length of array where save the
+   * the references's offset 
    */
   int getReferences(ObjectReference object) throws InlinePragma {
     if (isReferenceArray)
       return ObjectModel.getArrayLength(object);
-    else
-      return offsets.length;
+    else      
+      /***--bi, in getReference, return the value refNum */
+      return refNum;      
+  }
+  
+  //***--bi add a public version to get the reference number 
+  public int getRefNum(ObjectReference object) throws InlinePragma {
+    if (isReferenceArray)
+     {   
+      return ObjectModel.getArrayLength(object);
+      }
+    else      
+      return refNum;       
+  }
+  
+    /***--bi return the distance of the reference section, 
+     * positive for arrays and negative for normal object  */
+  public int getRefSectionSizeDiff(ObjectReference object) throws InlinePragma {
+    if (isReferenceArray)
+     {   
+      return ObjectModel.getArrayLength(object) << LOG_BYTES_IN_ADDRESS;
+      }
+    else      
+      return rsOffset;       
+  }
+
+  
+  //***--bi  return the Address of the beginning point of the reference section */
+  
+  public Address getRefSectionBeginAddress(ObjectReference object)throws InlinePragma {
+      if (isReferenceArray) return object.toAddress();      
+      // For normal objects, record the end of the reference sections, first sub and than scan  
+      return object.toAddress().add(REF_SECTION_OFFSET);
   }
 
   /****************************************************************************
--- jikesrvm-2.3.4-org/./MMTk/src/org/mmtk/utility/scan/Scan.java	2004-10-18 07:13:47.000000000 -0400
+++ jikesrvm-2.3.4-bi/./MMTk/src/org/mmtk/utility/scan/Scan.java	2007-02-16 16:49:52.980626880 -0500
@@ -6,6 +6,7 @@
 
 package org.mmtk.utility.scan;
 
+import org.mmtk.vm.Constants;
 import org.mmtk.vm.Assert;
 import org.mmtk.vm.ObjectModel;
 import org.mmtk.vm.Plan;
@@ -14,6 +15,11 @@
 import org.vmmagic.unboxed.*;
 import org.vmmagic.pragma.*;
 
+
+
+
+
+
 /**
  * Class that supports scanning of objects (scalar and array)
  *
@@ -23,7 +29,7 @@
  * @version $Revision: 1.7 $
  * @date $Date: 2004/10/18 11:13:47 $
  */  
-public final class Scan implements Uninterruptible {
+public final class Scan implements Constants, Uninterruptible {
   /**
    * Scan a object, processing each pointer field encountered. 
    *
@@ -32,7 +38,7 @@
   public static void scanObject(ObjectReference object) throws InlinePragma {
     MMType type = ObjectModel.getObjectType(object);
     if (!type.isDelegated()) {
-      int references = type.getReferences(object);
+      int references = type.getReferences(object);             
       for (int i = 0; i < references; i++) {
         Address slot = type.getSlot(object, i);
         Plan.traceObjectLocation(slot);
@@ -42,6 +48,37 @@
   }
 
   /**
+   *  ***--bi: We scan an address directly
+   *
+   * @param address The beginning of the reference section
+   * @param refNum  The number of reference 
+   */
+    
+    // This version read two addresses directly   
+    public static void scanReferenceSection(Address address, Address addressEnd) throws InlinePragma {             
+      // Make the scan order the same as traditional layout, array the same, object go downward 
+            
+      if ( address.LT(addressEnd) )  // a reference array 
+      {
+      
+         while ( address.LT(addressEnd) )
+         {
+      
+         	if ( !address.isZero())  Plan.traceObjectLocation(address); 
+         	address=address.add( BYTES_IN_ADDRESS);  	 		       
+         }
+	return;      
+      }  
+      
+        while (address.GT(addressEnd)) 
+	{
+	address=address.sub( BYTES_IN_ADDRESS);
+   	if ( !address.isZero()) Plan.traceObjectLocation(address);           
+	}
+  }
+
+  
+  /**
    * Enumerate the pointers in an object, calling back to a given plan
    * for each pointer encountered. <i>NOTE</i> that only the "real"
    * pointer fields are enumerated, not the TIB.
@@ -54,11 +91,32 @@
     throws InlinePragma {
     MMType type = ObjectModel.getObjectType(object);
     if (!type.isDelegated()) {
-      int references = type.getReferences(object);
-      for (int i = 0; i < references; i++) {
-        Address slot = type.getSlot(object, i);
-        enum.enumeratePointerLocation(slot);
-      }
+      int references = type.getReferences(object);          
+     
+
+      /***--bi  , in bi, we can do it in a simple way*/
+     // for (int i = 0; i < references; i++) {
+     //   Address slot = type.getSlot(object, i);		        
+     //   enum.enumeratePointerLocation(slot);
+     // }
+     //Address slot = type.getSlot(object, 0);
+     Address slot = type.getRefSectionBeginAddress(object);
+     if (type.isReferenceArray())
+     {
+     		for (int i = 0; i < references; i++) {
+	        enum.enumeratePointerLocation(slot);
+	        slot = slot.add( BYTES_IN_ADDRESS); 
+         }
+     }
+     else
+     {
+     		for (int i = 0; i < references; i++) {
+	        slot = slot.sub(BYTES_IN_ADDRESS); 
+		enum.enumeratePointerLocation(slot);
+	        
+         }
+     }
+     
     } else
       Scanning.enumeratePointers(object, enum);
   }
--- jikesrvm-2.3.4-org/./MMTk/src/org/mmtk/vm/ObjectModel.java	2004-12-14 22:10:25.000000000 -0500
+++ jikesrvm-2.3.4-bi/./MMTk/src/org/mmtk/vm/ObjectModel.java	2007-02-16 16:51:03.237946144 -0500
@@ -145,10 +145,11 @@
    * @param object the address of the object
    * @return the value of the bits
    */
-  public static Word prepareAvailableBits(ObjectReference object) {
+  public static Word prepareAvailableBits(ObjectReference object) { 
      return null;
  }
 
+
   /**
    * Sets the bits available for memory manager use in an object.
    *
