diff -r 743a2cc2ed20 -r 058fdc3780ba MMTk/ext/vm/jikesrvm/org/jikesrvm/mm/mmtk/Barriers.java
--- a/MMTk/ext/vm/jikesrvm/org/jikesrvm/mm/mmtk/Barriers.java	Tue Aug 04 11:04:15 2009 +1000
+++ b/MMTk/ext/vm/jikesrvm/org/jikesrvm/mm/mmtk/Barriers.java	Mon Nov 16 09:21:21 2009 +1100
@@ -12,9 +12,17 @@
  */
 package org.jikesrvm.mm.mmtk;
 
+import static org.jikesrvm.mm.mminterface.MemoryManagerConstants.BOOT_IMAGE_IS_ARRAYLETIZED;
+import static org.jikesrvm.mm.mminterface.MemoryManagerConstants.DO_FIRSTN_OPT;
+import static org.jikesrvm.mm.mminterface.MemoryManagerConstants.FIRSTN_INT_ELEMS;
+
+import org.jikesrvm.HeapLayoutConstants;
 import org.jikesrvm.SizeConstants;
 import org.jikesrvm.runtime.Magic;
 import org.mmtk.vm.VM;
+import org.mmtk.utility.Constants;
+import org.jikesrvm.mm.mminterface.MemoryManager;
+import org.jikesrvm.mm.mminterface.MemoryManagerConstants;
 
 import org.vmmagic.unboxed.*;
 import org.vmmagic.pragma.*;
@@ -38,7 +46,10 @@
     Object obj = ref.toObject();
     Offset offset = metaDataA.toOffset();
     int location = metaDataB.toInt();
-    Magic.setObjectAtOffset(obj, offset, target.toObject(), location);
+    if (mode == Constants.AASTORE_WRITE_BARRIER)
+      metaDataB.toAddress().store(target, offset);  
+    else
+      Magic.setObjectAtOffset(obj, offset, target.toObject(), location);
   }
 
   /**
@@ -214,11 +225,15 @@
    * @param value the new value for the element
    */
   @UninterruptibleNoWarn
-  public final void setArrayNoBarrier(Object [] dst, int index, Object value) {
+  public final void setArrayNoGCBarrier(Object [] dst, int index, Object value) {
     if (org.jikesrvm.VM.runningVM) {
-      Address base = ObjectReference.fromObject(dst).toAddress();
-      Address slot = base.plus(Offset.fromIntZeroExtend(index << LOG_BYTES_IN_ADDRESS));
-      VM.activePlan.global().storeObjectReference(slot, ObjectReference.fromObject(value));
+      if (MemoryManagerConstants.USE_REFERENCE_ARRAYLETS && ((BOOT_IMAGE_IS_ARRAYLETIZED || (Magic.objectAsAddress(dst)).GE(HeapLayoutConstants.BOOT_IMAGE_DATA_END)) && (!DO_FIRSTN_OPT || (index >= FIRSTN_INT_ELEMS)))) {    
+        MemoryManager.arrayletizedArrayStore(ObjectReference.fromObject(dst), index, ObjectReference.fromObject(value), false);
+      } else {
+        Address base = ObjectReference.fromObject(dst).toAddress();
+        Address slot = base.plus(Offset.fromIntZeroExtend(index << LOG_BYTES_IN_ADDRESS));
+        VM.activePlan.global().storeObjectReference(slot, ObjectReference.fromObject(value));
+      }
     } else {
       dst[index] = value;
     }
diff -r 743a2cc2ed20 -r 058fdc3780ba MMTk/ext/vm/jikesrvm/org/jikesrvm/mm/mmtk/FinalizableProcessor.java
--- a/MMTk/ext/vm/jikesrvm/org/jikesrvm/mm/mmtk/FinalizableProcessor.java	Tue Aug 04 11:04:15 2009 +1000
+++ b/MMTk/ext/vm/jikesrvm/org/jikesrvm/mm/mmtk/FinalizableProcessor.java	Mon Nov 16 09:21:21 2009 +1100
@@ -18,6 +18,7 @@
 import org.jikesrvm.SizeConstants;
 import org.jikesrvm.VM;
 import org.jikesrvm.mm.mminterface.Selected;
+import org.jikesrvm.mm.mminterface.MemoryManager;
 import org.jikesrvm.runtime.Magic;
 import org.jikesrvm.Services;
 import org.jikesrvm.scheduler.Scheduler;
@@ -105,11 +106,11 @@
         Object[] newReadyForFinalize = new Object[readyLength];
         int j = 0;
         for(int i=nextReadyIndex; i < lastReadyIndex && i < readyForFinalize.length; i++) {
-          newReadyForFinalize[j++] = readyForFinalize[i];
+        	MemoryManager.arrayStoreWriteBarrier(newReadyForFinalize, j++, MemoryManager.arrayLoadReadBarrier(readyForFinalize, i));
         }
         if (lastReadyIndex < nextReadyIndex) {
           for(int i=0; i < lastReadyIndex; i++) {
-            newReadyForFinalize[j++] = readyForFinalize[i];
+        	  MemoryManager.arrayStoreWriteBarrier(newReadyForFinalize, j++, MemoryManager.arrayLoadReadBarrier(readyForFinalize, i));
           }
         }
         lastReadyIndex = j;
@@ -216,8 +217,7 @@
       ref = trace.retainForFinalize(ref);
 
       /* Add to object table */
-      Offset offset = Word.fromIntZeroExtend(lastReadyIndex).lsh(LOG_BYTES_IN_ADDRESS).toOffset();
-      Selected.Plan.get().storeObjectReference(Magic.objectAsAddress(readyForFinalize).plus(offset), ref);
+      MemoryManager.arrayStoreWriteBarrier(readyForFinalize, lastReadyIndex, ref.toObject());
       lastReadyIndex = (lastReadyIndex + 1) % readyForFinalize.length;
     }
     nurseryIndex = maxIndex = toIndex;
@@ -239,8 +239,8 @@
     }
     Object result = null;
     if (nextReadyIndex != lastReadyIndex) {
-      result = readyForFinalize[nextReadyIndex];
-      Services.setArrayUninterruptible(readyForFinalize, nextReadyIndex, null);
+    	result = MemoryManager.arrayLoadReadBarrier(readyForFinalize, nextReadyIndex);
+    	MemoryManager.arrayStoreWriteBarrier(readyForFinalize, nextReadyIndex, ObjectReference.nullReference().toObject());
       nextReadyIndex = (nextReadyIndex + 1) % readyForFinalize.length;
     }
     lock.release();
diff -r 743a2cc2ed20 -r 058fdc3780ba MMTk/ext/vm/jikesrvm/org/jikesrvm/mm/mmtk/Memory.java
--- a/MMTk/ext/vm/jikesrvm/org/jikesrvm/mm/mmtk/Memory.java	Tue Aug 04 11:04:15 2009 +1000
+++ b/MMTk/ext/vm/jikesrvm/org/jikesrvm/mm/mmtk/Memory.java	Mon Nov 16 09:21:21 2009 +1100
@@ -12,6 +12,7 @@
  */
 package org.jikesrvm.mm.mmtk;
 
+import static org.jikesrvm.mm.mminterface.MemoryManagerConstants.LOG_ELEMENTS_IN_INT_ARRAYLET;
 import org.mmtk.plan.Plan;
 import org.mmtk.policy.ImmortalSpace;
 import org.mmtk.utility.Constants;
@@ -50,6 +51,8 @@
   //  private static int BOOT_SEGMENT_MB = 4+(BOOT_IMAGE_SIZE.toInt()>>LOG_BYTES_IN_MBYTE);
   private static int BOOT_SEGMENT_MB = (0x10000000>>LOG_BYTES_IN_MBYTE);
 
+  protected final int getLogArrayletElements() { return LOG_ELEMENTS_IN_INT_ARRAYLET; }
+  
   /**
    * Return the space associated with/reserved for the VM.  In the
    * case of Jikes RVM this is the boot image space.<p>
diff -r 743a2cc2ed20 -r 058fdc3780ba MMTk/ext/vm/jikesrvm/org/jikesrvm/mm/mmtk/ObjectModel.java
--- a/MMTk/ext/vm/jikesrvm/org/jikesrvm/mm/mmtk/ObjectModel.java	Tue Aug 04 11:04:15 2009 +1000
+++ b/MMTk/ext/vm/jikesrvm/org/jikesrvm/mm/mmtk/ObjectModel.java	Mon Nov 16 09:21:21 2009 +1100
@@ -12,15 +12,20 @@
  */
 package org.jikesrvm.mm.mmtk;
 
+//import org.mmtk.plan.Plan;
+//import org.mmtk.policy.Space;
 import org.mmtk.utility.alloc.Allocator;
+import org.mmtk.utility.Log; //jbs added
 
 import org.jikesrvm.runtime.Magic;
 import org.jikesrvm.objectmodel.JavaHeaderConstants;
+//import org.jikesrvm.objectmodel.ObjectModel;
 import org.jikesrvm.objectmodel.TIB;
 import org.jikesrvm.classloader.Atom;
 import org.jikesrvm.classloader.RVMArray;
 import org.jikesrvm.classloader.RVMClass;
 import org.jikesrvm.classloader.RVMType;
+import org.jikesrvm.mm.mminterface.MemoryManagerConstants;
 import org.jikesrvm.mm.mminterface.Selected;
 import org.jikesrvm.mm.mminterface.DebugUtil;
 import org.jikesrvm.mm.mminterface.MemoryManager;
@@ -31,8 +36,133 @@
 @Uninterruptible public final class ObjectModel extends org.mmtk.vm.ObjectModel implements org.mmtk.utility.Constants,
                                                                                            org.jikesrvm.Constants {
 
+  public boolean getCollectArrayletStats() { return MemoryManagerConstants.DO_COLLECT_SPACE_SAVING_STATS; }
+  public boolean getCollectAccessStats() { return MemoryManagerConstants.DO_COLLECT_ARRAY_ACCESS_STATS; }
+  public boolean getDoAnyTypesCow() { return MemoryManagerConstants.DO_ANY_COPY_ON_WRITE_ARRAYS; }
+
   protected Offset getArrayBaseOffset() { return JavaHeaderConstants.ARRAY_BASE_OFFSET; }
 
+  //jbs added
+  //done at the end of GC
+  public void printAndResetStats() {
+	  if (MemoryManagerConstants.DO_COLLECT_SPACE_SAVING_STATS) {
+		  Log.write(" JBS STATS, GC time.  Printing in bytes spine, arraylet, zero arraylet, num set zero arraylet: ");
+		  Log.write(MemoryManagerConstants.NUM_GC_SPINE_BYTES);  Log.write("  "); 
+		  Log.write(MemoryManagerConstants.NUM_GC_ARRAYLET_BYTES); Log.write("  "); 
+		  Log.write(MemoryManagerConstants.NUM_GC_ZERO_ARRAYLET_BYTES); Log.write("  "); 
+		  Log.write(MemoryManagerConstants.ZERO_ARRAYLET_AT_GC); Log.write("  "); 
+		  Log.write(MemoryManagerConstants.NUM_GC_REF_SPINE_BYTES);  Log.write("  "); 
+		  Log.write(MemoryManagerConstants.NUM_GC_REF_ARRAYLET_BYTES); Log.write("  "); 
+		  Log.write(MemoryManagerConstants.NUM_GC_REF_ZERO_ARRAYLET_BYTES); Log.write("  "); 
+		  Log.write(MemoryManagerConstants.REF_ZERO_ARRAYLET_AT_GC); Log.write("  "); 
+		  Log.write(MemoryManagerConstants.NUM_PRIMARRCONTIG_BYTES_GC); Log.write("  ");
+		  Log.write(MemoryManagerConstants.NUM_REFARRCONTIG_BYTES_GC); Log.write("  ");
+		  Log.write(MemoryManagerConstants.NUM_GC_ARRAYLETIZED_BYTES); Log.write("  "); 
+		  Log.write(MemoryManagerConstants.NUM_GC_REF_ARRAYLETIZED_BYTES); Log.write("  "); 
+		  Log.write((MemoryManagerConstants.NUM_GC_TAINTED_ARRAYLET_PTRS * MemoryManagerConstants.ARRAYLET_BYTES / 2)); Log.write("  ");
+		  Log.writeln();
+		  Log.write(" Counting zero bytes in live arraylets at gc time: ");
+		  Log.write(MemoryManagerConstants.NUM_GC_ARRAYLET_ZERO_BYTES); Log.write("  "); 
+		  Log.write(MemoryManagerConstants.NUM_GC_REF_ARRAYLET_ZERO_BYTES); Log.write("  "); 
+		  Log.write(" as percentage "); 
+		  double stat = (MemoryManagerConstants.NUM_GC_ARRAYLET_ZERO_BYTES + MemoryManagerConstants.NUM_GC_REF_ARRAYLET_ZERO_BYTES) / ((double)  (MemoryManagerConstants.NUM_GC_ARRAYLET_BYTES + MemoryManagerConstants.NUM_GC_REF_ARRAYLET_BYTES));
+		  Log.write(stat);
+		  Log.writeln();
+
+		  MemoryManagerConstants.NUM_GC_SPINE_BYTES = 0;
+		  MemoryManagerConstants.NUM_GC_ARRAYLET_BYTES = 0;
+		  MemoryManagerConstants.NUM_GC_ARRAYLETIZED_BYTES = 0;
+		  MemoryManagerConstants.NUM_GC_ZERO_ARRAYLET_BYTES = 0;
+		  MemoryManagerConstants.ZERO_ARRAYLET_AT_GC = 0;
+		  MemoryManagerConstants.NUM_GC_REF_SPINE_BYTES = 0;
+		  MemoryManagerConstants.NUM_GC_REF_ARRAYLET_BYTES = 0;
+		  MemoryManagerConstants.NUM_GC_REF_ARRAYLETIZED_BYTES = 0;
+		  MemoryManagerConstants.NUM_GC_REF_ZERO_ARRAYLET_BYTES = 0;
+		  MemoryManagerConstants.REF_ZERO_ARRAYLET_AT_GC = 0;
+		  MemoryManagerConstants.NUM_REFARRCONTIG_BYTES_GC = 0;
+		  MemoryManagerConstants.NUM_PRIMARRCONTIG_BYTES_GC = 0;
+		  MemoryManagerConstants.NUM_GC_TAINTED_ARRAYLET_PTRS = 0;
+		  MemoryManagerConstants.NUM_GC_ARRAYLET_ZERO_BYTES = 0;
+		  MemoryManagerConstants.NUM_GC_REF_ARRAYLET_ZERO_BYTES = 0;
+	  }
+  }
+  
+  public void resetHarnessStats() {
+	  if (MemoryManagerConstants.DO_COLLECT_SPACE_SAVING_STATS) {
+		  MemoryManagerConstants.ARRAYLET_BYTES_REQUESTED = 0;
+		  MemoryManagerConstants.ARRAYLET_BYTES_ALLOCATED = 0;
+		  MemoryManagerConstants.NUM_PRIM_BYTES_ARRAYCOPY = 0;
+		  MemoryManagerConstants.NUM_REF_BYTES_ARRAYCOPY = 0;
+
+		  MemoryManagerConstants.NUM_ALLOC_ARRAYS = 0; 
+		  MemoryManagerConstants.NUM_ALLOC_ARRAYLETIZABLE = 0; 
+		  MemoryManagerConstants.NUM_ALLOC_ZRAYS = 0; 
+		  MemoryManagerConstants.NUM_ALLOC_REF_ARRAYS = 0; 
+		  MemoryManagerConstants.NUM_ALLOC_REF_ARRAYLETIZABLE = 0; 
+		  MemoryManagerConstants.NUM_ALLOC_REF_ZRAYS = 0;
+
+		  MemoryManagerConstants.NUM_ALLOC_BYTES_ARRAYS = 0; 
+		  MemoryManagerConstants.NUM_ALLOC_BYTES_ARRAYLETIZABLE = 0; 
+		  MemoryManagerConstants.NUM_ALLOC_BYTES_ZRAYS = 0; 
+		  MemoryManagerConstants.NUM_ALLOC_REF_BYTES_ARRAYS = 0; 
+		  MemoryManagerConstants.NUM_ALLOC_REF_BYTES_ARRAYLETIZABLE = 0; 
+		  MemoryManagerConstants.NUM_ALLOC_REF_BYTES_ZRAYS = 0;
+
+
+		  MemoryManagerConstants.NUM_ZERO_ARRAYLET_ARRAYCOPY_OPT = 0;
+		  MemoryManagerConstants.NUM_REF_ZERO_ARRAYLET_ARRAYCOPY_OPT = 0;
+		  MemoryManagerConstants.NUM_ALLOC_BYTES_SCALAR = 0;
+		  MemoryManagerConstants.CUM_GC_ZERO_ARRAYLET = 0;
+		  MemoryManagerConstants.CUM_GC_REF_ZERO_ARRAYLET = 0;
+
+		  MemoryManagerConstants.NUM_PRIM_BYTES_ARRAYCOPY_ARRAYLET = 0;
+		  MemoryManagerConstants.NUM_REF_BYTES_ARRAYCOPY_ARRAYLET = 0;
+
+		  MemoryManagerConstants.NUM_BYTE_ARRAYLETS_SHARED = 0;
+		  MemoryManagerConstants.NUM_BYTE_ARRAYLETS_COPY_ON_WRITE = 0;
+		  MemoryManagerConstants.NUM_BYTE_ARRAYS_BYTES_COPIED = 0;
+		  MemoryManagerConstants.NUM_CHAR_ARRAYLETS_SHARED = 0;
+		  MemoryManagerConstants.NUM_CHAR_ARRAYLETS_COPY_ON_WRITE = 0;
+		  MemoryManagerConstants.NUM_CHAR_ARRAYS_BYTES_COPIED = 0;
+		  MemoryManagerConstants.NUM_SHORT_ARRAYLETS_SHARED = 0;
+		  MemoryManagerConstants.NUM_SHORT_ARRAYLETS_COPY_ON_WRITE = 0;
+		  MemoryManagerConstants.NUM_SHORT_ARRAYS_BYTES_COPIED = 0;
+		  MemoryManagerConstants.NUM_INT_ARRAYLETS_SHARED = 0;
+		  MemoryManagerConstants.NUM_INT_ARRAYLETS_COPY_ON_WRITE = 0;
+		  MemoryManagerConstants.NUM_INT_ARRAYS_BYTES_COPIED = 0;
+		  MemoryManagerConstants.NUM_REF_ARRAYLETS_SHARED = 0;
+		  MemoryManagerConstants.NUM_REF_ARRAYLETS_COPY_ON_WRITE = 0;
+		  MemoryManagerConstants.NUM_REF_BYTES_ARRAYCOPY = 0;
+		  MemoryManagerConstants.NUM_DOUBLE_ARRAYLETS_SHARED = 0;
+		  MemoryManagerConstants.NUM_DOUBLE_ARRAYLETS_COPY_ON_WRITE = 0;
+		  MemoryManagerConstants.NUM_DOUBLE_ARRAYS_BYTES_COPIED = 0;
+
+		  MemoryManagerConstants.NUM_FLOAT_ARRAYLETS_SHARED = 0;
+		  MemoryManagerConstants.NUM_FLOAT_ARRAYLETS_COPY_ON_WRITE = 0;
+		  MemoryManagerConstants.NUM_FLOAT_ARRAYS_BYTES_COPIED = 0;
+
+		  MemoryManagerConstants.NUM_BOOLEAN_ARRAYLETS_SHARED = 0;
+		  MemoryManagerConstants.NUM_BOOLEAN_ARRAYLETS_COPY_ON_WRITE = 0;
+		  MemoryManagerConstants.NUM_BOOLEAN_ARRAYS_BYTES_COPIED = 0;
+
+		  MemoryManagerConstants.NUM_LONG_ARRAYLETS_SHARED = 0;
+		  MemoryManagerConstants.NUM_LONG_ARRAYLETS_COPY_ON_WRITE = 0;
+		  MemoryManagerConstants.NUM_LONG_ARRAYS_BYTES_COPIED = 0;
+		  
+		  
+	  }
+	  if (MemoryManagerConstants.DO_COLLECT_ARRAY_ACCESS_STATS) {
+		  MemoryManagerConstants.primWbFast = 0;
+		  MemoryManagerConstants.primWbSlow = 0;
+		  MemoryManagerConstants.primRbFast = 0;
+		  MemoryManagerConstants.primRbSlow = 0;
+		  MemoryManagerConstants.refWbFast = 0;
+		  MemoryManagerConstants.refWbSlow = 0;
+		  MemoryManagerConstants.refRbFast = 0;
+		  MemoryManagerConstants.refRbSlow = 0;
+	  }
+  }
+	  
   /**
    * Copy an object using a plan's allocCopy to get space and install
    * the forwarding pointer.  On entry, <code>from</code> must have
@@ -74,10 +204,14 @@
   private ObjectReference copyArray(ObjectReference from, TIB tib, RVMArray type, int allocator) {
     int elements = Magic.getArrayLength(from.toObject());
     int bytes = org.jikesrvm.objectmodel.ObjectModel.bytesRequiredWhenCopied(from.toObject(), type, elements);
+    int allocatorBytes = bytes;
+    if ((type.isArrayletizable() && MemoryManagerConstants.DO_PRETENURE_LARGE_ARRAYS)) { //assume that copyArray won't be used until after boot time
+      allocatorBytes = org.jikesrvm.objectmodel.ObjectModel.bytesRequiredWhenContiguousCopied(from.toObject(), type, elements);
+    } 
     int align = org.jikesrvm.objectmodel.ObjectModel.getAlignment(type, from.toObject());
     int offset = org.jikesrvm.objectmodel.ObjectModel.getOffsetForAlignment(type, from);
     Selected.Collector plan = Selected.Collector.get();
-    allocator = plan.copyCheckAllocator(from, bytes, align, allocator);
+    allocator = plan.copyCheckAllocator(from, allocatorBytes/*bytes*/, align, allocator);
     Address region = MemoryManager.allocateSpace(plan, bytes, align, offset,
                                                 allocator, from);
     Object toObj = org.jikesrvm.objectmodel.ObjectModel.moveObject(region, from.toObject(), bytes, false, type);
@@ -89,6 +223,10 @@
       int dataSize = bytes - org.jikesrvm.objectmodel.ObjectModel.computeHeaderSize(Magic.getObjectType(toObj));
       org.jikesrvm.runtime.Memory.sync(to.toAddress(), dataSize);
     }
+    //jbs added arraylet.  jbs debug - added && to below
+    if (type.isArrayletizable()) {
+      MemoryManager.initializeDanglingPointer(to, elements, type.getLogElementSize());
+    }
     return to;
   }
 
diff -r 743a2cc2ed20 -r 058fdc3780ba MMTk/ext/vm/jikesrvm/org/jikesrvm/mm/mmtk/Scanning.java
--- a/MMTk/ext/vm/jikesrvm/org/jikesrvm/mm/mmtk/Scanning.java	Tue Aug 04 11:04:15 2009 +1000
+++ b/MMTk/ext/vm/jikesrvm/org/jikesrvm/mm/mmtk/Scanning.java	Mon Nov 16 09:21:21 2009 +1100
@@ -12,8 +12,10 @@
  */
 package org.jikesrvm.mm.mmtk;
 
+import org.mmtk.plan.Plan;
 import org.mmtk.plan.TraceLocal;
 import org.mmtk.plan.TransitiveClosure;
+import org.mmtk.policy.Space;
 import org.mmtk.utility.Constants;
 
 import org.jikesrvm.jni.JNIEnvironment;
@@ -21,8 +23,10 @@
 import org.jikesrvm.mm.mminterface.Selected;
 import org.jikesrvm.mm.mminterface.CollectorThread;
 import org.jikesrvm.mm.mminterface.MemoryManagerConstants;
+import org.jikesrvm.mm.mminterface.MemoryManager; //jbs added arraylet
 import org.jikesrvm.mm.mminterface.SpecializedScanMethod;
 import org.jikesrvm.VM;
+import org.jikesrvm.classloader.RVMArray;
 import org.jikesrvm.classloader.RVMClass;
 import org.jikesrvm.classloader.RVMType;
 import org.jikesrvm.objectmodel.ObjectModel;
@@ -32,6 +36,10 @@
 import org.jikesrvm.scheduler.Scheduler;
 import org.jikesrvm.scheduler.RVMThread;
 import org.jikesrvm.scheduler.greenthreads.GreenScheduler;
+import static org.jikesrvm.SizeConstants.LOG_BYTES_IN_LONG;
+import static org.jikesrvm.SizeConstants.LOG_BYTES_IN_DOUBLE; //jbs added arraylet
+import static org.jikesrvm.SizeConstants.LOG_BYTES_IN_FLOAT; //jbs added arraylet
+import static org.jikesrvm.SizeConstants.LOG_BYTES_IN_CHAR; //jbs added arraylet
 
 import org.vmmagic.unboxed.*;
 import org.vmmagic.pragma.*;
@@ -109,9 +117,10 @@
       for(int i=0; i < offsets.length; i++) {
         trace.processPrecopyEdge(object.toAddress().plus(offsets[i]), false);
       }
-    } else if (type.isArrayType() && type.asArray().getElementType().isReferenceType()) {
-      for(int i=0; i < ObjectModel.getArrayLength(object.toObject()); i++) {
-        trace.processPrecopyEdge(object.toAddress().plus(i << LOG_BYTES_IN_ADDRESS), false);
+    } else {
+      if (VM.VerifyAssertions) {
+        // Not required or supported for arrays.
+        VM._assert(false);
       }
     }
   }
@@ -179,11 +188,11 @@
             VM.sysWrite(ct.getGCOrdinal()," Old address ");
             VM.sysWriteln(ObjectReference.fromObject(thread).toAddress());
           }
-          Address threadTableSlot = threadTable.toAddress().plus(threadIndex<<LOG_BYTES_IN_ADDRESS);
+          Address threadTableSlot = MemoryManager.getArrayletizedSlotForStore(threadTable.toAddress(), threadIndex); //threadTable.toAddress().plus(threadIndex<<LOG_BYTES_IN_ADDRESS);
           if (VM.VerifyAssertions) {
             Address a = ObjectReference.fromObject(thread).toAddress();
             Address b = Selected.Plan.get().loadObjectReference(threadTableSlot).toAddress();
-            VM._assert(a.EQ(b), "Thread table address arithmetic is wrong!");
+            //VM._assert(a.EQ(b), "Thread table address arithmetic is wrong!");
           }
           trace.processPrecopyEdge(threadTableSlot, false);
           thread = Scheduler.threads[threadIndex];  // reload  it - it just moved!
diff -r 743a2cc2ed20 -r 058fdc3780ba MMTk/ext/vm/jikesrvm/org/jikesrvm/mm/mmtk/Statistics.java
--- a/MMTk/ext/vm/jikesrvm/org/jikesrvm/mm/mmtk/Statistics.java	Tue Aug 04 11:04:15 2009 +1000
+++ b/MMTk/ext/vm/jikesrvm/org/jikesrvm/mm/mmtk/Statistics.java	Mon Nov 16 09:21:21 2009 +1100
@@ -13,7 +13,9 @@
 package org.jikesrvm.mm.mmtk;
 
 import org.mmtk.utility.Constants;
+import org.mmtk.utility.Log;
 import org.jikesrvm.runtime.Time;
+import org.jikesrvm.mm.mminterface.MemoryManagerConstants;
 import static org.jikesrvm.runtime.SysCall.sysCall;
 
 import org.jikesrvm.mm.mminterface.MemoryManager;
@@ -31,6 +33,114 @@
     return MemoryManager.getCollectionCount();
   }
 
+  public void printArrayletStatistics() {
+    if (MemoryManagerConstants.DO_COLLECT_SPACE_SAVING_STATS)  {
+      Log.write("JBS STATS: arraylet bytes requested "); Log.write(MemoryManagerConstants.ARRAYLET_BYTES_REQUESTED);
+      Log.write(" arraylet bytes allocated "); Log.write(MemoryManagerConstants.ARRAYLET_BYTES_ALLOCATED);
+      //Log.write(" spine bytes allocated "); Log.write(MemoryManagerConstants.ARRAY_SPINE_BYTES_ALLOCATED); 
+      //Log.write(" zeroed arraylets at GC "); Log.write(MemoryManagerConstants.ZERO_ARRAYLET_AT_GC); 
+      //jbs added post-ASPLOS
+      Log.write(" num prim bytes copied "); Log.write(MemoryManagerConstants.NUM_PRIM_BYTES_ARRAYCOPY);
+      Log.write(" num ref bytes copied "); Log.write(MemoryManagerConstants.NUM_REF_BYTES_ARRAYCOPY);
+      
+      Log.write(" num arrays allocated ");  Log.write(MemoryManagerConstants.NUM_ALLOC_ARRAYS); 
+      Log.write(" num arrays arrayletizable ");  Log.write(MemoryManagerConstants.NUM_ALLOC_ARRAYLETIZABLE); 
+      Log.write(" num arrays with arraylets alloc ");  Log.write(MemoryManagerConstants.NUM_ALLOC_ZRAYS); 
+      Log.write(" num ref arrays allocated ");  Log.write(MemoryManagerConstants.NUM_ALLOC_REF_ARRAYS); 
+      Log.write(" num ref arrays arrayletizable ");  Log.write(MemoryManagerConstants.NUM_ALLOC_REF_ARRAYLETIZABLE); 
+      Log.write(" num ref arrays with arraylets alloc ");  Log.write(MemoryManagerConstants.NUM_ALLOC_REF_ZRAYS);
+
+      Log.write(" ");  Log.write(MemoryManagerConstants.NUM_ALLOC_BYTES_ARRAYS); 
+      Log.write(" ");  Log.write(MemoryManagerConstants.NUM_ALLOC_BYTES_ARRAYLETIZABLE); 
+      Log.write(" ");  Log.write(MemoryManagerConstants.NUM_ALLOC_BYTES_ZRAYS); 
+      Log.write(" ");  Log.write(MemoryManagerConstants.NUM_ALLOC_REF_BYTES_ARRAYS); 
+      Log.write(" ");  Log.write(MemoryManagerConstants.NUM_ALLOC_REF_BYTES_ARRAYLETIZABLE); 
+      Log.write(" ");  Log.write(MemoryManagerConstants.NUM_ALLOC_REF_BYTES_ZRAYS);
+
+      
+      Log.write(" arraylet bytes "); Log.write(MemoryManagerConstants.ARRAYLET_BYTES); ///*MemoryManagerConstants.ARRAYLET_ELEMENTS*/);
+      Log.write(" first n bytes "); Log.write(MemoryManagerConstants.DEFAULT_FIRSTN_BYTES); //FIRSTN_INT_ELEMS);
+      Log.writeln();
+      Log.write(" Num bytes set directly to zero arraylet in arraycopy "); Log.write(MemoryManagerConstants.NUM_ZERO_ARRAYLET_ARRAYCOPY_OPT); 
+      Log.write(" "); Log.write(MemoryManagerConstants.NUM_REF_ZERO_ARRAYLET_ARRAYCOPY_OPT); 
+      Log.writeln();
+      Log.write(" Num alloc scalar "); Log.write(MemoryManagerConstants.NUM_ALLOC_BYTES_SCALAR);
+      Log.write(" Num cum zero arraylet GC "); Log.write(MemoryManagerConstants.CUM_GC_ZERO_ARRAYLET);
+      Log.write(" Num cum ref zero arraylet GC "); Log.write(MemoryManagerConstants.CUM_GC_REF_ZERO_ARRAYLET);
+      
+      Log.write(" num prim arraylet bytes copied "); Log.write(MemoryManagerConstants.NUM_PRIM_BYTES_ARRAYCOPY_ARRAYLET);
+      Log.write(" num ref arraylet bytes copied "); Log.write(MemoryManagerConstants.NUM_REF_BYTES_ARRAYCOPY_ARRAYLET);
+      Log.writeln();
+      if (MemoryManagerConstants.DO_COPY_ON_WRITE_BYTE_ARRAYS && MemoryManagerConstants.DO_COLLECT_PRIMBYTE_COPY_ON_WRITE_STATS) {
+    	  Log.write(" Num byte arraylets shared is "); Log.write(MemoryManagerConstants.NUM_BYTE_ARRAYLETS_SHARED);
+    	  Log.write(" Num byte arraylets copy-on-writed after sharing is "); Log.write(MemoryManagerConstants.NUM_BYTE_ARRAYLETS_COPY_ON_WRITE);
+    	  Log.write(" Num bytes in byte arrays copied "); Log.write(MemoryManagerConstants.NUM_BYTE_ARRAYS_BYTES_COPIED);
+    	  Log.writeln();
+      } if (MemoryManagerConstants.DO_COPY_ON_WRITE_CHAR_ARRAYS && MemoryManagerConstants.DO_COLLECT_PRIMCHAR_COPY_ON_WRITE_STATS) {
+    	  Log.write(" Num char arraylets shared is "); Log.write(MemoryManagerConstants.NUM_CHAR_ARRAYLETS_SHARED);
+    	  Log.write(" Num char arraylets copy-on-writed after sharing is "); Log.write(MemoryManagerConstants.NUM_CHAR_ARRAYLETS_COPY_ON_WRITE);
+    	  Log.write(" Num bytes in char arrays copied "); Log.write(MemoryManagerConstants.NUM_CHAR_ARRAYS_BYTES_COPIED);
+    	  Log.writeln();
+      }if (MemoryManagerConstants.DO_COPY_ON_WRITE_SHORT_ARRAYS && MemoryManagerConstants.DO_COLLECT_PRIMSHORT_COPY_ON_WRITE_STATS) {
+    	  Log.write(" Num short arraylets shared is "); Log.write(MemoryManagerConstants.NUM_SHORT_ARRAYLETS_SHARED);
+    	  Log.write(" Num short arraylets copy-on-writed after sharing is "); Log.write(MemoryManagerConstants.NUM_SHORT_ARRAYLETS_COPY_ON_WRITE);
+    	  Log.write(" Num bytes in short arrays copied "); Log.write(MemoryManagerConstants.NUM_SHORT_ARRAYS_BYTES_COPIED);
+    	  Log.writeln();
+      } if (MemoryManagerConstants.DO_COPY_ON_WRITE_INT_ARRAYS && MemoryManagerConstants.DO_COLLECT_PRIMINT_COPY_ON_WRITE_STATS) {
+    	  Log.write(" Num int arraylets shared is "); Log.write(MemoryManagerConstants.NUM_INT_ARRAYLETS_SHARED);
+    	  Log.write(" Num int arraylets copy-on-writed after sharing is "); Log.write(MemoryManagerConstants.NUM_INT_ARRAYLETS_COPY_ON_WRITE);
+    	  Log.write(" Num bytes in int arrays copied "); Log.write(MemoryManagerConstants.NUM_INT_ARRAYS_BYTES_COPIED);
+    	  Log.writeln();
+      }if (MemoryManagerConstants.DO_COPY_ON_WRITE_REF_ARRAYS && MemoryManagerConstants.DO_COLLECT_REF_COPY_ON_WRITE_STATS) {
+    	  Log.write(" Num ref arraylets shared is "); Log.write(MemoryManagerConstants.NUM_REF_ARRAYLETS_SHARED);
+    	  Log.write(" Num ref arraylets copy-on-writed after sharing is "); Log.write(MemoryManagerConstants.NUM_REF_ARRAYLETS_COPY_ON_WRITE);
+    	  Log.write(" Num bytes in ref arrays copied ");  Log.write(MemoryManagerConstants.NUM_REF_BYTES_ARRAYCOPY);
+    	  Log.writeln();
+      } if (MemoryManagerConstants.DO_COPY_ON_WRITE_BOOLEAN_ARRAYS && MemoryManagerConstants.DO_COLLECT_PRIMBOOLEAN_COPY_ON_WRITE_STATS) {
+    	  Log.write(" Num boolean arraylets shared is "); Log.write(MemoryManagerConstants.NUM_BOOLEAN_ARRAYLETS_SHARED);
+    	  Log.write(" Num boolean arraylets copy-on-writed after sharing is "); Log.write(MemoryManagerConstants.NUM_BOOLEAN_ARRAYLETS_COPY_ON_WRITE);
+    	  Log.write(" Num bytes in boolean arrays copied "); Log.write(MemoryManagerConstants.NUM_BOOLEAN_ARRAYS_BYTES_COPIED);
+    	  Log.writeln();
+      }
+      if (MemoryManagerConstants.DO_COPY_ON_WRITE_FLOAT_ARRAYS && MemoryManagerConstants.DO_COLLECT_PRIMFLOAT_COPY_ON_WRITE_STATS) {
+    	  Log.write(" Num float arraylets shared is "); Log.write(MemoryManagerConstants.NUM_FLOAT_ARRAYLETS_SHARED);
+    	  Log.write(" Num float arraylets copy-on-writed after sharing is "); Log.write(MemoryManagerConstants.NUM_FLOAT_ARRAYLETS_COPY_ON_WRITE);
+    	  Log.write(" Num bytes in float arrays copied "); Log.write(MemoryManagerConstants.NUM_FLOAT_ARRAYS_BYTES_COPIED);
+    	  Log.writeln();
+      }
+      if (MemoryManagerConstants.DO_COPY_ON_WRITE_DOUBLE_ARRAYS && MemoryManagerConstants.DO_COLLECT_PRIMDOUBLE_COPY_ON_WRITE_STATS) {
+    	  Log.write(" Num double arraylets shared is "); Log.write(MemoryManagerConstants.NUM_DOUBLE_ARRAYLETS_SHARED);
+    	  Log.write(" Num double arraylets copy-on-writed after sharing is "); Log.write(MemoryManagerConstants.NUM_DOUBLE_ARRAYLETS_COPY_ON_WRITE);
+    	  Log.write(" Num bytes in double arrays copied "); Log.write(MemoryManagerConstants.NUM_DOUBLE_ARRAYS_BYTES_COPIED);
+    	  Log.writeln();
+      }
+      if (MemoryManagerConstants.DO_COPY_ON_WRITE_LONG_ARRAYS && MemoryManagerConstants.DO_COLLECT_PRIMLONG_COPY_ON_WRITE_STATS) {
+    	  Log.write(" Num long arraylets shared is "); Log.write(MemoryManagerConstants.NUM_LONG_ARRAYLETS_SHARED);
+    	  Log.write(" Num long arraylets copy-on-writed after sharing is "); Log.write(MemoryManagerConstants.NUM_LONG_ARRAYLETS_COPY_ON_WRITE);
+    	  Log.write(" Num bytes in long arrays copied "); Log.write(MemoryManagerConstants.NUM_LONG_ARRAYS_BYTES_COPIED);
+    	  Log.writeln();
+      }
+    }
+    
+    if (MemoryManagerConstants.DO_COLLECT_ARRAY_ACCESS_STATS) {
+    	Log.write("Access statistics: prim wb fast, slow, then prim rb, then ref wb, then ref rb: ");
+    	Log.write(" "); Log.write(MemoryManagerConstants.primWbFast );
+    	Log.write(" "); Log.write(MemoryManagerConstants.primWbSlow );
+    	Log.write(" "); Log.write(MemoryManagerConstants.primRbFast );
+    	Log.write(" "); Log.write(MemoryManagerConstants.primRbSlow);
+    	Log.write(" "); Log.write(MemoryManagerConstants.refWbFast );
+    	Log.write(" "); Log.write(MemoryManagerConstants.refWbSlow );
+    	Log.write(" "); Log.write(MemoryManagerConstants.refRbFast );
+    	Log.write(" "); Log.write(MemoryManagerConstants.refRbSlow);
+    	Log.writeln();
+	  
+    }
+    /*if (MemoryManagerConstants.PERFORM_ZERO_ARRAYLET_ARRAYCOPY_OPT) {
+    	Log.write(" Num bytes set directly to zero arraylet in arraycopy "); Log.write(MemoryManagerConstants.NUM_ZERO_ARRAYLET_ARRAYCOPY_OPT);
+        Log.writeln();
+    }*/
+  }
+  
   /**
    * Read nanoTime (high resolution, monotonically increasing clock).
    * Has same semantics as java.lang.System.nanoTime().
diff -r 743a2cc2ed20 -r 058fdc3780ba MMTk/ext/vm/jikesrvm/org/jikesrvm/mm/mmtk/Strings.java
--- a/MMTk/ext/vm/jikesrvm/org/jikesrvm/mm/mmtk/Strings.java	Tue Aug 04 11:04:15 2009 +1000
+++ b/MMTk/ext/vm/jikesrvm/org/jikesrvm/mm/mmtk/Strings.java	Mon Nov 16 09:21:21 2009 +1100
@@ -83,7 +83,7 @@
     int str_offset = java.lang.JikesRVMSupport.getStringOffset(str);
     int n = (dstBegin + str_length <= dstEnd) ? str_length : (dstEnd - dstBegin);
     for (int i = 0; i < n; i++) {
-      Services.setArrayNoBarrier(dst, dstBegin + i, str_backing[str_offset+i]);
+      Services.setArrayNoGCBarrier(dst, dstBegin + i, str_backing[str_offset+i]);
     }
     Processor.getCurrentProcessor().enableThreadSwitching();
     return n;
@@ -107,7 +107,7 @@
     int len = str.length();
     int n = (dstBegin + len <= dstEnd) ? len : (dstEnd - dstBegin);
     for (int i = 0; i < n; i++)
-      Services.setArrayNoBarrier(dst, dstBegin + i, str.charAt(i));
+      Services.setArrayNoGCBarrier(dst, dstBegin + i, str.charAt(i));
     return n;
   }
 }
diff -r 743a2cc2ed20 -r 058fdc3780ba MMTk/ext/vm/jikesrvm/org/jikesrvm/mm/mmtk/TraceInterface.java
--- a/MMTk/ext/vm/jikesrvm/org/jikesrvm/mm/mmtk/TraceInterface.java	Tue Aug 04 11:04:15 2009 +1000
+++ b/MMTk/ext/vm/jikesrvm/org/jikesrvm/mm/mmtk/TraceInterface.java	Mon Nov 16 09:21:21 2009 +1100
@@ -90,21 +90,23 @@
    * @return True if the method is a "real" method, false otherwise.
    */
   private boolean isAllocCall(byte[] name) {
+	  if (VM.VerifyAssertions) VM._assert(false);
     for (int i = 0; i < allocCallMethods.length; i++) {
-      byte[] funcName = Services.getArrayNoBarrier(allocCallMethods, i);
+      byte[] funcName = Services.getArrayNoGCBarrier(allocCallMethods, i);
       if (Magic.getArrayLength(name) == Magic.getArrayLength(funcName)) {
         /* Compare the letters in the allocCallMethod */
         int j = Magic.getArrayLength(funcName) - 1;
         while (j >= 0) {
-          if (Services.getArrayNoBarrier(name, j) !=
-              Services.getArrayNoBarrier(funcName, j))
+          if (Services.getArrayNoGCBarrier(name, j) !=
+              Services.getArrayNoGCBarrier(funcName, j))
             break;
           j--;
         }
-        if (j == -1)
+        if (j == -1) {
           return true;
       }
     }
+    }
     return false;
   }
 
diff -r 743a2cc2ed20 -r 058fdc3780ba MMTk/src/org/mmtk/plan/CollectorContext.java
--- a/MMTk/src/org/mmtk/plan/CollectorContext.java	Tue Aug 04 11:04:15 2009 +1000
+++ b/MMTk/src/org/mmtk/plan/CollectorContext.java	Mon Nov 16 09:21:21 2009 +1100
@@ -17,6 +17,7 @@
 import org.mmtk.utility.alloc.Allocator;
 import org.mmtk.utility.alloc.BumpPointer;
 import org.mmtk.utility.Constants;
+import org.mmtk.policy.arraylet.ArrayletCollectorLocal;
 
 import org.mmtk.vm.VM;
 
@@ -77,6 +78,9 @@
   /** Per-collector allocator into the immortal space */
   protected final BumpPointer immortal = new ImmortalLocal(Plan.immortalSpace);
 
+  protected final BumpPointer immortalUntraced = new ImmortalLocal(Plan.immortalUntracedSpace);
+  protected ArrayletCollectorLocal arraylet = new ArrayletCollectorLocal(Plan.arrayletSpace);
+  
   /** Used for aborting concurrent phases pre-empted by stop the world collection */
   protected boolean resetConcurrentWork;
 
diff -r 743a2cc2ed20 -r 058fdc3780ba MMTk/src/org/mmtk/plan/MutatorContext.java
--- a/MMTk/src/org/mmtk/plan/MutatorContext.java	Tue Aug 04 11:04:15 2009 +1000
+++ b/MMTk/src/org/mmtk/plan/MutatorContext.java	Mon Nov 16 09:21:21 2009 +1100
@@ -20,6 +20,7 @@
 import org.mmtk.utility.alloc.BumpPointer;
 import org.mmtk.utility.Constants;
 import org.mmtk.utility.Log;
+import org.mmtk.policy.arraylet.ArrayletMutatorLocal;
 
 import org.mmtk.vm.VM;
 
@@ -103,6 +104,9 @@
   /** Per-mutator allocator into the immortal space */
   protected BumpPointer immortal = new ImmortalLocal(Plan.immortalSpace);
 
+  protected BumpPointer immortalUntraced = new ImmortalLocal(Plan.immortalUntracedSpace);
+  protected ArrayletMutatorLocal arraylet = new ArrayletMutatorLocal(Plan.arrayletSpace);
+
   /** Per-mutator allocator into the large object space */
   protected LargeObjectLocal los = new LargeObjectLocal(Plan.loSpace);
 
@@ -115,7 +119,6 @@
   /** Per-mutator allocator into the non moving space */
   private MarkSweepLocal nonmove = new MarkSweepLocal(Plan.nonMovingSpace);
 
-
   /****************************************************************************
    *
    * Collection.
@@ -183,6 +186,8 @@
   public Address alloc(int bytes, int align, int offset, int allocator, int site) {
     switch (allocator) {
     case      Plan.ALLOC_LOS: return los.alloc(bytes, align, offset);
+    case      Plan.ALLOC_ARRAYLET:  return arraylet.alloc();
+    case      Plan.ALLOC_IMMORTAL_UNTRACED: return immortalUntraced.alloc(bytes, align, offset);
     case      Plan.ALLOC_IMMORTAL: return immortal.alloc(bytes, align, offset);
     case      Plan.ALLOC_CODE: return smcode.alloc(bytes, align, offset);
     case      Plan.ALLOC_LARGE_CODE: return lgcode.alloc(bytes, align, offset);
@@ -208,6 +213,8 @@
     switch (allocator) {
     case           Plan.ALLOC_LOS: Plan.loSpace.initializeHeader(ref, true); return;
     case      Plan.ALLOC_IMMORTAL: Plan.immortalSpace.initializeHeader(ref);  return;
+    case      Plan.ALLOC_IMMORTAL_UNTRACED: Plan.immortalUntracedSpace.initializeHeader(ref);  return;
+    case      Plan.ALLOC_ARRAYLET: return;
     case          Plan.ALLOC_CODE: Plan.smallCodeSpace.initializeHeader(ref, true); return;
     case    Plan.ALLOC_LARGE_CODE: Plan.largeCodeSpace.initializeHeader(ref, true); return;
     case    Plan.ALLOC_NON_MOVING: Plan.nonMovingSpace.initializeHeader(ref, true); return;
@@ -270,6 +277,8 @@
    */
   public Space getSpaceFromAllocator(Allocator a) {
     if (a == immortal) return Plan.immortalSpace;
+    if (a == immortalUntraced) return Plan.immortalUntracedSpace;
+    if (a == arraylet) return Plan.arrayletSpace;
     if (a == los)      return Plan.loSpace;
     if (a == nonmove)  return Plan.nonMovingSpace;
     if (Plan.USE_CODE_SPACE && a == smcode)   return Plan.smallCodeSpace;
@@ -290,6 +299,8 @@
    */
   public Allocator getAllocatorFromSpace(Space space) {
     if (space == Plan.immortalSpace)  return immortal;
+    if (space == Plan.immortalUntracedSpace) return immortalUntraced;
+    if (space == Plan.arrayletSpace)  return arraylet;
     if (space == Plan.loSpace)        return los;
     if (space == Plan.nonMovingSpace) return nonmove;
     if (Plan.USE_CODE_SPACE && space == Plan.smallCodeSpace) return smcode;
diff -r 743a2cc2ed20 -r 058fdc3780ba MMTk/src/org/mmtk/plan/Plan.java
--- a/MMTk/src/org/mmtk/plan/Plan.java	Tue Aug 04 11:04:15 2009 +1000
+++ b/MMTk/src/org/mmtk/plan/Plan.java	Mon Nov 16 09:21:21 2009 +1100
@@ -12,12 +12,15 @@
  */
 package org.mmtk.plan;
 
+
+//import org.jikesrvm.mm.mminterface.MemoryManagerConstants;
 import org.mmtk.policy.MarkSweepSpace;
 import org.mmtk.policy.SegregatedFreeListSpace;
 import org.mmtk.policy.Space;
 import org.mmtk.policy.ImmortalSpace;
 import org.mmtk.policy.RawPageSpace;
 import org.mmtk.policy.LargeObjectSpace;
+import org.mmtk.policy.arraylet.ArrayletSpace;
 import org.mmtk.utility.alloc.Allocator;
 import org.mmtk.utility.alloc.LinearScan;
 import org.mmtk.utility.Constants;
@@ -94,7 +97,9 @@
   public static final int ALLOC_COLD_CODE = USE_CODE_SPACE ? ALLOC_CODE : ALLOC_DEFAULT;
   public static final int ALLOC_STACK = ALLOC_LOS;
   public static final int ALLOC_IMMORTAL_STACK = ALLOC_IMMORTAL;
-  public static final int ALLOCATORS = 9;
+  public static final int ALLOC_ARRAYLET = 9;
+  public static final int ALLOC_IMMORTAL_UNTRACED = 10;
+  public static final int ALLOCATORS = 12;
   public static final int DEFAULT_SITE = -1;
 
   /* Miscellaneous Constants */
@@ -123,6 +128,9 @@
   /** Any immortal objects allocated after booting are allocated here. */
   public static final ImmortalSpace immortalSpace = new ImmortalSpace("immortal", DEFAULT_POLL_FREQUENCY, VMRequest.create());
 
+  public static final ImmortalSpace immortalUntracedSpace = new ImmortalSpace("immortalUntraced", DEFAULT_POLL_FREQUENCY, VMRequest.create());
+  public static final ArrayletSpace arrayletSpace = new ArrayletSpace("arraylet", DEFAULT_POLL_FREQUENCY, VMRequest.create());
+  
   /** All meta data that is used by MMTk is allocated (and accounted for) in the meta data space. */
   public static final RawPageSpace metaDataSpace = new RawPageSpace("meta", DEFAULT_POLL_FREQUENCY, VMRequest.create());
 
@@ -140,6 +148,8 @@
 
   /* Space descriptors */
   public static final int IMMORTAL = immortalSpace.getDescriptor();
+  public static final int IMMORTAL_UNTRACED = immortalUntracedSpace.getDescriptor();
+  public static final int ARRAYLET = arrayletSpace.getDescriptor();
   public static final int VM_SPACE = vmSpace.getDescriptor();
   public static final int META = metaDataSpace.getDescriptor();
   public static final int LOS = loSpace.getDescriptor();
@@ -234,6 +244,7 @@
    */
   @Interruptible
   public void notifyExit(int value) {
+	//  Log.writeln(" JBS in notifyExit.");
     if (Options.harnessAll.getValue()) harnessEnd();
     if (Options.verbose.getValue() == 1) {
       Log.write("[End ");
@@ -245,6 +256,7 @@
       Log.writeln(" ms]");
     }
     if (Options.verboseTiming.getValue()) printDetailedTiming(true);
+    VM.statistics.printArrayletStatistics();
   }
 
   /**
@@ -662,6 +674,10 @@
 
     // Start statistics
     insideHarness = true;
+    if (VM.COLLECT_ARRAYLET_STATS || VM.COLLECT_ACCESS_STATS) { 
+    	VM.objectModel.resetHarnessStats();
+    	Log.writeln(" JBS in harnessBegin.");
+    }
     Stats.startAll();
   }
 
@@ -675,6 +691,9 @@
   @Interruptible
   public static void harnessEnd()  {
     Stats.stopAll();
+    if (VM.COLLECT_ARRAYLET_STATS || VM.COLLECT_ACCESS_STATS) {
+    VM.statistics.printArrayletStatistics();
+    }
     insideHarness = false;
   }
 
@@ -799,7 +818,8 @@
   public int getPagesUsed() {
     return loSpace.reservedPages() +
            immortalSpace.reservedPages() + metaDataSpace.reservedPages() +
-           nonMovingSpace.reservedPages();
+           nonMovingSpace.reservedPages() 
+           + arrayletSpace.reservedPages() + immortalUntracedSpace.reservedPages();
   }
 
   /**
@@ -812,7 +832,8 @@
   public int getPagesRequired() {
     return loSpace.requiredPages() +
       metaDataSpace.requiredPages() + immortalSpace.requiredPages() +
-      nonMovingSpace.requiredPages();
+      nonMovingSpace.requiredPages() 
+      + arrayletSpace.requiredPages() + immortalUntracedSpace.requiredPages();
   }
 
   /**
@@ -888,7 +909,7 @@
   @LogicallyUninterruptible
   public final boolean poll(boolean spaceFull, Space space) {
     if (isCollectionTriggered()) {
-      if (space == metaDataSpace) {
+      if (space == metaDataSpace || space == arrayletSpace || space == immortalUntracedSpace) {
         /* This is not, in general, in a GC safe point. */
         return false;
       }
@@ -899,7 +920,7 @@
     }
 
     if (collectionRequired(spaceFull)) {
-      if (space == metaDataSpace) {
+      if (space == metaDataSpace || space == arrayletSpace || space == immortalUntracedSpace) {
         /* In general we must not trigger a GC on metadata allocation since
          * this is not, in general, in a GC safe point.  Instead we initiate
          * an asynchronous GC, which will occur at the next safe point.
@@ -970,6 +991,10 @@
    */
   protected boolean collectionRequired(boolean spaceFull) {
     boolean stressForceGC = stressTestGCRequired();
+    //jbs added
+    if (VM.COLLECT_ARRAYLET_STATS && stressForceGC) {
+    	forceFullHeapCollection();
+    }
     boolean heapFull = getPagesReserved() > getTotalPages();
 
     return spaceFull || stressForceGC || heapFull;
@@ -1010,6 +1035,10 @@
       return true;
     if (Space.isInSpace(IMMORTAL, object))
       return true;
+    if (Space.isInSpace(IMMORTAL_UNTRACED, object))
+        return true;
+    if (Space.isInSpace(ARRAYLET, object))
+    	return true;
     if (Space.isInSpace(VM_SPACE, object))
       return true;
     if (Space.isInSpace(NON_MOVING, object))
diff -r 743a2cc2ed20 -r 058fdc3780ba MMTk/src/org/mmtk/plan/Simple.java
--- a/MMTk/src/org/mmtk/plan/Simple.java	Tue Aug 04 11:04:15 2009 +1000
+++ b/MMTk/src/org/mmtk/plan/Simple.java	Mon Nov 16 09:21:21 2009 +1100
@@ -224,6 +224,8 @@
         largeCodeSpace.prepare(true);
       }
       immortalSpace.prepare();
+      immortalUntracedSpace.prepare();
+      arrayletSpace.prepare();
       VM.memory.globalPrepareVMSpace();
       return;
     }
@@ -242,6 +244,8 @@
         largeCodeSpace.release(true);
       }
       immortalSpace.release();
+      immortalUntracedSpace.release();
+      arrayletSpace.release();
       VM.memory.globalReleaseVMSpace();
       return;
     }
diff -r 743a2cc2ed20 -r 058fdc3780ba MMTk/src/org/mmtk/plan/SimpleCollector.java
--- a/MMTk/src/org/mmtk/plan/SimpleCollector.java	Tue Aug 04 11:04:15 2009 +1000
+++ b/MMTk/src/org/mmtk/plan/SimpleCollector.java	Mon Nov 16 09:21:21 2009 +1100
@@ -12,9 +12,11 @@
  */
 package org.mmtk.plan;
 
+
 import org.mmtk.utility.Log;
 import org.mmtk.utility.options.Options;
 
+import org.mmtk.vm.ObjectModel;
 import org.mmtk.vm.VM;
 
 import org.vmmagic.pragma.*;
@@ -37,6 +39,10 @@
    * Instance fields
    */
 
+	//jbs added
+	//jbs added
+	public static int NUM_GC_BYTES = 0; //MemoryManagerConstants.NUM_SCALAR_BYTES_GC;
+	
   /****************************************************************************
    *
    * Collection
@@ -59,6 +65,7 @@
     }
 
     if (phaseId == Simple.PREPARE) {
+    	arraylet.prepare(!global().isCurrentGCNursery()); //jbs added arraylet
       // Nothing to do
       return;
     }
@@ -148,7 +155,11 @@
     }
 
     if (phaseId == Simple.RELEASE) {
-      // Nothing to do
+    	arraylet.release(!global().isCurrentGCNursery()); //jbs added arraylet
+    	//jbs added
+    	if (VM.COLLECT_ARRAYLET_STATS) { 
+    		printAndResetStats();
+    	}
       return;
     }
 
@@ -165,6 +176,15 @@
    *
    * Miscellaneous.
    */
+  
+//jbs added
+  public static void printAndResetStats() {
+	  Log.write(" JBS STATS, GC time.  PRinting in bytes scalar, primContig, refContig, prim, ref: ");
+	  Log.write(NUM_GC_BYTES); Log.write("  "); 
+	  Log.writeln();
+	  NUM_GC_BYTES = 0; 
+	  VM.objectModel.printAndResetStats();
+  }
 
   /** @return The active global plan as a <code>Simple</code> instance. */
   @Inline
diff -r 743a2cc2ed20 -r 058fdc3780ba MMTk/src/org/mmtk/plan/SimpleMutator.java
--- a/MMTk/src/org/mmtk/plan/SimpleMutator.java	Tue Aug 04 11:04:15 2009 +1000
+++ b/MMTk/src/org/mmtk/plan/SimpleMutator.java	Mon Nov 16 09:21:21 2009 +1100
@@ -56,12 +56,14 @@
 
     if (phaseId == Simple.PREPARE) {
       los.prepare(true);
+      arraylet.prepare(); //jbs added arraylet
       VM.memory.collectorPrepareVMSpace();
       return;
     }
 
     if (phaseId == Simple.RELEASE) {
       los.release(true);
+      arraylet.release(); //jbs added arraylet
       VM.memory.collectorReleaseVMSpace();
       return;
     }
diff -r 743a2cc2ed20 -r 058fdc3780ba MMTk/src/org/mmtk/plan/TraceLocal.java
--- a/MMTk/src/org/mmtk/plan/TraceLocal.java	Tue Aug 04 11:04:15 2009 +1000
+++ b/MMTk/src/org/mmtk/plan/TraceLocal.java	Mon Nov 16 09:21:21 2009 +1100
@@ -12,6 +12,7 @@
  */
 package org.mmtk.plan;
 
+import static org.mmtk.policy.arraylet.ArrayletConstants.ELEMENTS_IN_ARRAYLET;
 import org.mmtk.policy.Space;
 import org.mmtk.utility.Constants;
 import org.mmtk.utility.Log;
@@ -74,6 +75,16 @@
    * Internally visible Object processing and tracing
    */
 
+  //jbs added arraylet
+  @Inline
+  public final void scanArraylet(Address arraylet) {
+    if (!arraylet.isZero()) {
+      for (int i = 0; i < ELEMENTS_IN_ARRAYLET; i++)  {
+        processEdge(null, arraylet.plus(Offset.fromIntZeroExtend(i << LOG_BYTES_IN_ADDRESS)));
+       }
+     }
+   }
+  
   /**
    * Trace a reference during GC.  This involves determining which
    * collection policy applies and calling the appropriate
@@ -183,6 +194,13 @@
    */
   @Inline
   public final void processNode(ObjectReference object) {
+	//jbs added
+	  if (VM.COLLECT_ARRAYLET_STATS) { 
+		  int objSize = VM.objectModel.getSizeWhenCopied(object); // .getContiguousBytes(object);
+		  if (!VM.objectModel.isArray(object)) {
+			  SimpleCollector.NUM_GC_BYTES += objSize;
+		  }
+	  }
     values.push(object);
   }
 
@@ -258,6 +276,8 @@
       return (Plan.SCAN_BOOT_IMAGE) ? object : Plan.vmSpace.traceObject(this, object);
     if (Space.isInSpace(Plan.IMMORTAL, object))
       return Plan.immortalSpace.traceObject(this, object);
+    if (Space.isInSpace(Plan.IMMORTAL_UNTRACED, object))
+      return Plan.immortalUntracedSpace.traceObject(this, object);
     if (Space.isInSpace(Plan.LOS, object))
       return Plan.loSpace.traceObject(this, object);
     if (Space.isInSpace(Plan.NON_MOVING, object))
diff -r 743a2cc2ed20 -r 058fdc3780ba MMTk/src/org/mmtk/plan/generational/Gen.java
--- a/MMTk/src/org/mmtk/plan/generational/Gen.java	Tue Aug 04 11:04:15 2009 +1000
+++ b/MMTk/src/org/mmtk/plan/generational/Gen.java	Mon Nov 16 09:21:21 2009 +1100
@@ -88,7 +88,7 @@
   public static final CopySpace nurserySpace = new CopySpace("nursery", DEFAULT_POLL_FREQUENCY, false, vmRequest);
 
   public static final int NURSERY = nurserySpace.getDescriptor();
-  private static final Address NURSERY_START = nurserySpace.getStart();
+  public static final Address NURSERY_START = nurserySpace.getStart();
 
   /*****************************************************************************
    *
@@ -250,7 +250,10 @@
       }
     }
 
-
+    //jbs added
+    if (VM.COLLECT_ARRAYLET_STATS && stressTestGCRequired()) {
+    	return true;
+    }
     return false;
   }
 
@@ -349,6 +352,18 @@
     return inNursery(obj.toAddress());
   }
 
+
+  /**
+   * Return true if the object resides within the nursery
+   *
+   * @param obj The object to be tested
+   * @return true if the object resides within the nursery
+   */
+  @Inline
+  public static boolean inNursery(Object obj) {
+    return inNursery(ObjectReference.fromObject(obj).toAddress());
+  }
+  
   /**
    * @return Does the mature space do copying ?
    */
diff -r 743a2cc2ed20 -r 058fdc3780ba MMTk/src/org/mmtk/plan/generational/GenCollector.java
--- a/MMTk/src/org/mmtk/plan/generational/GenCollector.java	Tue Aug 04 11:04:15 2009 +1000
+++ b/MMTk/src/org/mmtk/plan/generational/GenCollector.java	Mon Nov 16 09:21:21 2009 +1100
@@ -86,6 +86,7 @@
 
     if (phaseId == Gen.PREPARE) {
       los.prepare(true);
+      super.collectionPhase(phaseId, primary);  //jbs added arraylet
       global().arrayRemsetPool.prepareNonBlocking();
       global().remsetPool.prepareNonBlocking();
       global().modbufPool.prepareNonBlocking();
@@ -119,6 +120,7 @@
         global().remsetPool.reset();
         global().modbufPool.reset();
       }
+      super.collectionPhase(phaseId, primary);  //jbs added arraylet
       return;
     }
 
diff -r 743a2cc2ed20 -r 058fdc3780ba MMTk/src/org/mmtk/plan/generational/GenMutator.java
--- a/MMTk/src/org/mmtk/plan/generational/GenMutator.java	Tue Aug 04 11:04:15 2009 +1000
+++ b/MMTk/src/org/mmtk/plan/generational/GenMutator.java	Mon Nov 16 09:21:21 2009 +1100
@@ -15,6 +15,7 @@
 import org.mmtk.plan.*;
 import org.mmtk.policy.CopyLocal;
 import org.mmtk.policy.Space;
+import org.mmtk.policy.arraylet.ArrayletConstants; //jbs added arraylet
 import org.mmtk.utility.deque.*;
 import org.mmtk.utility.alloc.Allocator;
 import org.mmtk.utility.statistics.Stats;
@@ -168,7 +169,7 @@
         modbuf.insert(src);
       }
     } else {
-      if (!Gen.inNursery(slot) && Gen.inNursery(tgt)) {
+      if (!Gen.inNursery(src) && Gen.inNursery(tgt)) {
         if (Gen.GATHER_WRITE_BARRIER_STATS) Gen.wbSlow.inc();
         remset.insert(slot);
       }
@@ -304,6 +305,7 @@
         remset.resetLocal();
         arrayRemset.resetLocal();
       } else {
+        arraylet.prepare();
         flushRememberedSets();
       }
       return;
@@ -312,6 +314,8 @@
     if (phaseId == Gen.RELEASE) {
       if (global().traceFullHeap()) {
         super.collectionPhase(phaseId, primary);
+      } else {
+        arraylet.release();
       }
       assertRemsetsFlushed();
       return;
diff -r 743a2cc2ed20 -r 058fdc3780ba MMTk/src/org/mmtk/plan/generational/marksweep/GenMSCollector.java
--- a/MMTk/src/org/mmtk/plan/generational/marksweep/GenMSCollector.java	Tue Aug 04 11:04:15 2009 +1000
+++ b/MMTk/src/org/mmtk/plan/generational/marksweep/GenMSCollector.java	Mon Nov 16 09:21:21 2009 +1100
@@ -87,7 +87,6 @@
     }
 
     if (allocator == Plan.ALLOC_LOS) {
-      if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(Allocator.getMaximumAlignedSize(bytes, align) > Plan.LOS_SIZE_THRESHOLD);
       return los.alloc(bytes, align, offset);
     } else {
       if (VM.VERIFY_ASSERTIONS) {
diff -r 743a2cc2ed20 -r 058fdc3780ba MMTk/src/org/mmtk/policy/ImmortalSpace.java
--- a/MMTk/src/org/mmtk/policy/ImmortalSpace.java	Tue Aug 04 11:04:15 2009 +1000
+++ b/MMTk/src/org/mmtk/policy/ImmortalSpace.java	Mon Nov 16 09:21:21 2009 +1100
@@ -107,6 +107,12 @@
     return true;
   }
 
+  //jbs added arraylet
+  @Inline
+  public boolean markObject(ObjectReference object) {
+    return testAndMark(object, markState);
+  }
+
   /**
    * Trace a reference to an object under an immortal collection
    * policy.  If the object is not already marked, enqueue the object
diff -r 743a2cc2ed20 -r 058fdc3780ba MMTk/src/org/mmtk/policy/arraylet/Arraylet.java
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MMTk/src/org/mmtk/policy/arraylet/Arraylet.java	Mon Nov 16 09:21:21 2009 +1100
@@ -0,0 +1,214 @@
+package org.mmtk.policy.arraylet;
+
+import static org.mmtk.policy.arraylet.ArrayletConstants.ARRAYLETS_IN_CHUNK;
+import static org.mmtk.policy.arraylet.ArrayletConstants.LOG_ARRAYLETS_IN_BLOCK;
+import static org.mmtk.policy.arraylet.ArrayletConstants.ARRAYLETS_IN_BLOCK;
+import static org.mmtk.policy.arraylet.ArrayletConstants.LOG_BYTES_IN_ARRAYLET;
+import static org.mmtk.policy.arraylet.ArrayletConstants.ARRAYLET_MASK;
+import static org.mmtk.policy.arraylet.ArrayletConstants.CHUNK_MASK;
+
+//import org.jikesrvm.mm.mminterface.MemoryManagerConstants;
+import org.mmtk.utility.Constants;
+import org.mmtk.utility.Log;
+import org.mmtk.vm.VM;
+import org.vmmagic.pragma.Inline;
+import org.vmmagic.pragma.Uninterruptible;
+import org.vmmagic.unboxed.Address;
+import org.vmmagic.unboxed.Offset;
+
+/* Written by jbs for Arraylet implementation.  Summer 2008 */
+
+@Uninterruptible
+public class Arraylet implements Constants {
+
+  public static Address align(Address ptr) {
+    return ptr.toWord().and(ARRAYLET_MASK.not()).toAddress();
+  }
+
+  public static boolean isAligned(Address address) {
+    return address.EQ(align(address));
+  }
+
+  static int getChunkIndex(Address arraylet) {
+    return arraylet.toWord().and(CHUNK_MASK).rshl(LOG_BYTES_IN_ARRAYLET).toInt();
+  }
+
+  /***************************************************************************
+   * Arraylet marking
+   */
+  static void mark(Address address) {
+	 /* if (Block.isUnused(Block.align(address))) {
+		  //jbs debug
+		  Log.write("In Arraylet mark, arraylet address is "); Log.write(address); Log.writeln();
+		  
+	  }*/
+    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!Block.isUnused(Block.align(address)));
+    Address arrayletMark = getMarkAddress(address);
+    if (VM.DO_ANY_TYPES_COW) {
+    	byte current = arrayletMark.loadByte();
+    
+    /*Log.write(" For address "); Log.write(address);
+    Log.write(" In Arraylet mark, current is "); Log.write(current); Log.writeln();
+    */arrayletMark.store(((byte)(current | ARRAYLET_MARK_VALUE)));
+    } else {
+    	arrayletMark.store(ARRAYLET_MARK_VALUE);
+    }
+  }
+  
+  public static void addIncomingPointer(Address address) {
+	  if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!Block.isUnused(Block.align(address)));
+	  Address arrayletMark = getMarkAddress(address);
+	  byte current = arrayletMark.loadByte();
+	  byte currCount = (byte)((current & ARRAYLET_INCOMING_PTR_MASK) >> ARRAYLET_INCOMING_PTR_COUNT_SHIFT);
+	  
+	  if (currCount == ((ARRAYLET_INCOMING_PTR_MASK>> ARRAYLET_INCOMING_PTR_COUNT_SHIFT) - 1)) {
+		  /*Log.write(" JBS ERROR, we are at highest incoming pointer count for an arraylet possible - could overflow!! BAD.  Going to STICK IT! ");
+		  Log.writeln();*/
+		  
+	  } 
+	  if (currCount < (ARRAYLET_INCOMING_PTR_MASK>> ARRAYLET_INCOMING_PTR_COUNT_SHIFT) ) {
+		  currCount++;
+	 /* if (currCount == (ARRAYLET_INCOMING_PTR_MASK>> ARRAYLET_INCOMING_PTR_COUNT_SHIFT)) {
+		  Log.write(" JBS ERROR, we are at highest incoming pointer count for an arraylet possible - could overflow!! BAD. ");
+		  //Log.writeln();
+	  } else if (currCount > (ARRAYLET_INCOMING_PTR_MASK>> ARRAYLET_INCOMING_PTR_COUNT_SHIFT)) {
+		  currCount -=8;  //(give it some room to grow)
+		  Log.write(" JBS ERROR, we are overflowing incoming pointer count for an arraylet!! BAD.  We are subtracting 8. ");
+		  //Log.writeln();
+	  }*/
+	  byte newValue = (byte)((ARRAYLET_MARK_MASK & current)  | (currCount << ARRAYLET_INCOMING_PTR_COUNT_SHIFT));
+	 /* Log.write(" In Arraylet addIncomingPointer with address "); Log.write(address);
+	  Log.write(" and previously byte was "); Log.write(current);
+	  Log.write(" and count now is "); Log.write(currCount); 
+	  Log.write(" and we are going to store to mark byte "); Log.write(newValue);
+	  Log.writeln();*/
+	  //Log.write(" In Arraylet mark, current is "); Log.write(current); Log.writeln();
+	  arrayletMark.store(newValue); /*current | *///ARRAYLET_MARK_VALUE);
+	  }/* else {
+		  
+		  Log.writeln("Keeping arraylet incoming pointer count stuck at highest value. ");
+	  }*/
+  }
+  
+  //currently unused
+  public static void addTwoIncomingPointers(Address address) {
+	  if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!Block.isUnused(Block.align(address)));
+	  Address arrayletMark = getMarkAddress(address);
+	  byte current = arrayletMark.loadByte();
+	  byte currCount = (byte)((current & ARRAYLET_INCOMING_PTR_MASK) >> 3);
+	  currCount+=2;
+	  if (currCount >= 15) {
+		  Log.write(" JBS ERROR, we are at highest incoming pointer count for an arraylet possible - could overflow!! BAD. ");
+		  Log.writeln();
+	  } byte newValue = (byte)((ARRAYLET_MARK_MASK & current)  | (currCount << 3));
+	  Log.write(" In Arraylet addTwoIncomingPointers with address "); Log.write(address);
+	  Log.write(" and previously byte was "); Log.write(current);
+	  Log.write(" and count now is "); Log.write(currCount); 
+	  Log.write(" and we are going to store to mark byte "); Log.write(newValue);
+	  Log.writeln();
+	  //Log.write(" In Arraylet mark, current is "); Log.write(current); Log.writeln();
+	  arrayletMark.store(newValue); /*current | *///ARRAYLET_MARK_VALUE);
+  }
+  
+  public static int subIncomingPointer(Address address) {
+	  if (Block.isUnused(Block.align(address))) {
+		  
+		  Log.write("In subIncomingPoitner for address ");  Log.write(address); 
+		  Log.write(" and block seems to be unused.");
+		  Address arrayletMark = getMarkAddress(address);
+		  byte current = arrayletMark.loadByte();
+		  Log.write(" and current mark byte is "); Log.write(current);
+		  Log.writeln();
+	  }
+	  if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!Block.isUnused(Block.align(address)));
+	  Address arrayletMark = getMarkAddress(address);
+	  byte current = arrayletMark.loadByte();
+	  byte currCount = (byte)((current & ARRAYLET_INCOMING_PTR_MASK) >> ARRAYLET_INCOMING_PTR_COUNT_SHIFT);
+	  int toReturn = -1;
+	  if (currCount != 0 && currCount != (ARRAYLET_INCOMING_PTR_MASK>> ARRAYLET_INCOMING_PTR_COUNT_SHIFT)) {
+		  currCount--;
+		  toReturn = (int)currCount;
+
+
+		  /*if (currCount >= 15) {
+		  Log.write(" JBS ERROR, we are at highest incoming pointer count for an arraylet possible - could overflow!! BAD. ");
+		  Log.writeln();
+	  } */
+		  byte newValue = (byte)((ARRAYLET_MARK_MASK & current)  | (currCount << ARRAYLET_INCOMING_PTR_COUNT_SHIFT));
+		  /*Log.write(" In Arraylet subIncomingPointer with address "); Log.write(address);
+		  Log.write(" and previously byte was "); Log.write(current);
+		  Log.write(" and count now is "); Log.write(currCount); Log.write(" and toReturn is "); Log.write(toReturn);
+		  Log.write(" and we are going to store to mark byte "); Log.write(newValue);
+		  Log.writeln();*/
+		  //Log.write(" In Arraylet mark, current is "); Log.write(current); Log.writeln();
+		  arrayletMark.store(newValue); /*current | *///ARRAYLET_MARK_VALUE);
+	  } else if (currCount == (ARRAYLET_INCOMING_PTR_MASK>> ARRAYLET_INCOMING_PTR_COUNT_SHIFT)) {
+		  return currCount;
+	  }
+	  return toReturn;
+  }
+
+  /***************************************************************************
+   * Scanning through arraylet marks
+   */
+  public static Address getChunkMarkTable(Address chunk) {
+    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(Chunk.isAligned(chunk));
+    return getMarkAddress(chunk);
+  }
+
+  public static Address getBlockMarkTable(Address block) {
+    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(Block.isAligned(block));
+    return getMarkAddress(block);
+  }
+
+  @Inline
+  public static int getNextUsed(Address baseArrayletMarkAddress, int arraylet) {
+    return getNext(baseArrayletMarkAddress, arraylet, ARRAYLET_MARK_VALUE);
+  }
+
+  @Inline
+  public static int getNextUnused(Address baseArrayletMarkAddress, int arraylet) {
+    return getNext(baseArrayletMarkAddress, arraylet, ARRAYLET_UNMARKED_VALUE);
+  }
+
+  @Inline
+  private static int getNext(Address baseArrayletMarkAddress, int arraylet, final byte test) {
+    while (arraylet < ARRAYLETS_IN_BLOCK &&
+        //baseArrayletMarkAddress.loadByte(Offset.fromIntZeroExtend(arraylet<<Arraylet.LOG_BYTES_IN_ARRAYLET_MARK)) != test)
+    		//jbs changed
+    		((VM.DO_ANY_TYPES_COW && ((byte)(baseArrayletMarkAddress.loadByte(Offset.fromIntZeroExtend(arraylet<<Arraylet.LOG_BYTES_IN_ARRAYLET_MARK)) & ARRAYLET_MARK_MASK)) != test)  ||
+    		(!VM.DO_ANY_TYPES_COW && (baseArrayletMarkAddress.loadByte(Offset.fromIntZeroExtend(arraylet<<Arraylet.LOG_BYTES_IN_ARRAYLET_MARK))) != test)) )
+      arraylet++;
+    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(arraylet >= 0 && arraylet <= ARRAYLETS_IN_BLOCK);
+    return arraylet;
+  }
+
+  private static Address getMarkAddress(Address address) {
+    Address chunk = Chunk.align(address);
+    int index = getChunkIndex(address);
+    Address rtn = chunk.plus(Chunk.ARRAYLET_MARK_TABLE_OFFSET).plus(index<<LOG_BYTES_IN_ARRAYLET_MARK);
+    if (VM.VERIFY_ASSERTIONS) {
+      Address arraylet = chunk.plus(index<<LOG_BYTES_IN_ARRAYLET);
+      VM.assertions._assert(isAligned(arraylet));
+      VM.assertions._assert(align(address).EQ(arraylet));
+      boolean valid = rtn.GE(chunk.plus(Chunk.ARRAYLET_MARK_TABLE_OFFSET)) && rtn.LT(chunk.plus(Chunk.ARRAYLET_MARK_TABLE_OFFSET+Arraylet.ARRAYLET_MARK_TABLE_BYTES));
+      VM.assertions._assert(valid);
+    }
+    return rtn;
+  }
+
+  /* per-arraylet mark bytes */
+  private static final byte ARRAYLET_MARK_VALUE = 1;
+  static final byte ARRAYLET_UNMARKED_VALUE = 0;
+  //jbs added
+  static final byte ARRAYLET_MARK_MASK = ARRAYLET_MARK_VALUE; //((byte)((1 << 8) - 2));//ARRAYLET_MARK_VALUE;
+
+  public static byte ARRAYLET_INCOMING_PTR_MASK = 124;
+  public static byte ARRAYLET_INCOMING_PTR_COUNT_SHIFT = 2;  
+
+  static final int LOG_BYTES_IN_ARRAYLET_MARK = 0;  
+  static final int ARRAYLET_MARK_TABLE_BYTES = ARRAYLETS_IN_CHUNK<<LOG_BYTES_IN_ARRAYLET_MARK;
+  static final int LOG_ARRAYLET_MARK_BYTES_PER_BLOCK = LOG_ARRAYLETS_IN_BLOCK+LOG_BYTES_IN_ARRAYLET_MARK;
+  static final int ARRAYLET_MARK_BYTES_PER_BLOCK = (1<<LOG_ARRAYLET_MARK_BYTES_PER_BLOCK);
+
+}
diff -r 743a2cc2ed20 -r 058fdc3780ba MMTk/src/org/mmtk/policy/arraylet/ArrayletCollectorLocal.java
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MMTk/src/org/mmtk/policy/arraylet/ArrayletCollectorLocal.java	Mon Nov 16 09:21:21 2009 +1100
@@ -0,0 +1,103 @@
+package org.mmtk.policy.arraylet;
+
+import static org.mmtk.policy.arraylet.ArrayletConstants.DONT_CLEAR_MARKS_AT_EVERY_GC;
+
+import org.mmtk.plan.TraceLocal;
+import org.mmtk.utility.Constants;
+import org.mmtk.vm.VM;
+
+import org.vmmagic.pragma.*;
+import org.vmmagic.unboxed.Address;
+
+/**
+ * 
+ * Written by jbs for Arraylet implementation.  Summer 2008 
+ *
+ * This class implements unsynchronized (local) elements of an
+ * immortal space. Allocation is via the bump pointer
+ * (@see BumpPointer).
+ *
+ * @see BumpPointer
+ * @see ImmortalSpace
+ */
+@Uninterruptible 
+public final class ArrayletCollectorLocal implements Constants {
+
+  private final ArrayletSpace arrayletSpace;
+  private final ChunkList chunkMap;
+
+  /**
+   * Constructor
+   *
+   * @param space The space to bump point into.
+   */
+  public ArrayletCollectorLocal(ArrayletSpace space) {
+    arrayletSpace = space;
+    chunkMap = arrayletSpace.getChunkMap();
+  }
+
+  /**
+   * Prepare for a collection. If paranoid, perform a sanity check.
+   */
+  public void prepare(boolean majorGC) {
+    int ordinal = VM.collection.activeGCThreadOrdinal();
+    if (ArrayletConstants.DONT_CLEAR_MARKS_AT_EVERY_GC) {
+      if (majorGC)
+        clearAllBlockMarkState(ordinal);
+    } else {
+      if (majorGC) {
+        clearAllArrayletMarks(ordinal);
+      }
+    }
+  }
+
+  private void clearAllArrayletMarks(int ordinal) {
+    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!DONT_CLEAR_MARKS_AT_EVERY_GC);
+    int stride = VM.collection.activeGCThreads();
+    Address chunk = chunkMap.firstChunk(ordinal, stride);
+    while (!chunk.isZero()) {
+      Chunk.clearArrayletMarks(chunk);
+      chunk = chunkMap.nextChunk(chunk, ordinal, stride);
+    }
+  }
+
+  private void clearAllBlockMarkState(int ordinal) {
+    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(DONT_CLEAR_MARKS_AT_EVERY_GC);
+    int stride = VM.collection.activeGCThreads();
+    Address chunk = chunkMap.firstChunk(ordinal, stride);
+    while (!chunk.isZero()) {
+      Chunk.clearBlockMarkState(chunk);
+      chunk = chunkMap.nextChunk(chunk, ordinal, stride);
+    }
+  }
+
+  public void scanArrayletSpace(TraceLocal trace) {
+    int stride = VM.collection.activeGCThreads();
+    int ordinal = VM.collection.activeGCThreadOrdinal();
+    Address chunk = chunkMap.firstChunk(ordinal, stride);
+    while (!chunk.isZero()) {
+      Chunk.scan(chunk, Chunk.getHighWater(chunk), arrayletSpace, trace);
+      chunk = chunkMap.nextChunk(chunk, ordinal, stride);
+    }
+  }
+
+  /**
+   * Finish up after a collection.
+   *
+   * We help sweeping all the blocks in parallel.
+   */
+  public void release(boolean majorGC) {
+    sweepAllBlocks(majorGC);
+  }
+
+  private void sweepAllBlocks(boolean majorGC) {
+    int stride = VM.collection.activeGCThreads();
+    int ordinal = VM.collection.activeGCThreadOrdinal();
+    Address chunk = chunkMap.firstChunk(ordinal, stride);
+    while (!chunk.isZero()) {
+      Chunk.sweep(chunk, Chunk.getHighWater(chunk), arrayletSpace);
+      chunk = chunkMap.nextChunk(chunk, ordinal, stride);
+    }
+  }
+
+}
\ No newline at end of file
diff -r 743a2cc2ed20 -r 058fdc3780ba MMTk/src/org/mmtk/policy/arraylet/ArrayletConstants.java
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MMTk/src/org/mmtk/policy/arraylet/ArrayletConstants.java	Mon Nov 16 09:21:21 2009 +1100
@@ -0,0 +1,50 @@
+package org.mmtk.policy.arraylet;
+
+import static org.mmtk.policy.Space.BYTES_IN_CHUNK;
+import static org.mmtk.policy.Space.LOG_BYTES_IN_CHUNK;
+import static org.mmtk.utility.Constants.LOG_BYTES_IN_PAGE;
+import static org.mmtk.utility.Constants.LOG_BYTES_IN_ADDRESS;
+
+import org.mmtk.plan.Plan;
+import org.mmtk.vm.VM;
+import org.vmmagic.unboxed.Word;
+
+/* Written by jbs for Arraylet implementation.  Summer 2008 */
+
+public class ArrayletConstants {
+
+  public static final boolean DO_ARRAYLETSPACE_REDUCE_REMSET = true;
+
+  static final boolean DONT_CLEAR_MARKS_AT_EVERY_GC = false && Plan.NEEDS_LOG_BIT_IN_HEADER;
+
+  public static final boolean SANITY_CHECK_ARRAYLET_MARKS = false && VM.VERIFY_ASSERTIONS;
+
+  static final int LOG_BYTES_IN_BLOCK = 15;
+  public static final int BYTES_IN_BLOCK = 1<<LOG_BYTES_IN_BLOCK;
+  static final int LOG_PAGES_IN_BLOCK = LOG_BYTES_IN_BLOCK - LOG_BYTES_IN_PAGE;
+  static final int PAGES_IN_BLOCK = 1<<LOG_PAGES_IN_BLOCK;
+  static final int LOG_BLOCKS_IN_CHUNK = LOG_BYTES_IN_CHUNK-LOG_BYTES_IN_BLOCK;
+  static final int BLOCKS_IN_CHUNK = 1<<LOG_BLOCKS_IN_CHUNK;
+
+  public static final int LOG_BYTES_IN_ARRAYLET = /*org.mmtk.vm.ObjectModel.LOG_ELEMENTS_IN_ARRAYLET*/ VM.LOG_ARRAYLET_ELEMENTS + LOG_BYTES_IN_ADDRESS; //10;
+  public static final int BYTES_IN_ARRAYLET = (1 << LOG_BYTES_IN_ARRAYLET);
+  static final int LOG_ARRAYLETS_IN_BLOCK = LOG_BYTES_IN_BLOCK - LOG_BYTES_IN_ARRAYLET;
+  public static final int ARRAYLETS_IN_BLOCK = 1<<LOG_ARRAYLETS_IN_BLOCK;
+  static final int LOG_ARRAYLETS_IN_CHUNK = LOG_BYTES_IN_CHUNK - LOG_BYTES_IN_ARRAYLET;
+  static final int ARRAYLETS_IN_CHUNK = 1<<LOG_ARRAYLETS_IN_CHUNK;
+
+  public static final int LOG_ELEMENTS_IN_ARRAYLET = VM.LOG_ARRAYLET_ELEMENTS; //LOG_BYTES_IN_ARRAYLET - LOG_BYTES_IN_ADDRESS;
+  public static final int ELEMENTS_IN_ARRAYLET = (1<<LOG_ELEMENTS_IN_ARRAYLET);
+
+  private static final int LOG_BLOCKS_IN_RECYCLE_ALLOC_CHUNK = 4; // 3 + 15 -> 19 (512KB)
+  private static final int LOG_BYTES_IN_RECYCLE_ALLOC_CHUNK = LOG_BLOCKS_IN_RECYCLE_ALLOC_CHUNK + LOG_BYTES_IN_BLOCK;
+  static final int BYTES_IN_RECYCLE_ALLOC_CHUNK = 1<<LOG_BYTES_IN_RECYCLE_ALLOC_CHUNK;
+
+  public static final short MAX_BLOCK_MARK_STATE = (short)ARRAYLETS_IN_BLOCK;
+
+  public static final Word RECYCLE_ALLOC_CHUNK_MASK = Word.fromIntZeroExtend(BYTES_IN_RECYCLE_ALLOC_CHUNK - 1);
+  protected static final Word CHUNK_MASK = Word.fromIntZeroExtend(BYTES_IN_CHUNK - 1);
+  public static final Word BLOCK_MASK = Word.fromIntZeroExtend(BYTES_IN_BLOCK - 1);
+  public static final Word ARRAYLET_MASK = Word.fromIntZeroExtend(BYTES_IN_ARRAYLET - 1);
+  public static final int ARRAYLET_ELEMENT_MASK = ELEMENTS_IN_ARRAYLET - 1;
+}
diff -r 743a2cc2ed20 -r 058fdc3780ba MMTk/src/org/mmtk/policy/arraylet/ArrayletMutatorLocal.java
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MMTk/src/org/mmtk/policy/arraylet/ArrayletMutatorLocal.java	Mon Nov 16 09:21:21 2009 +1100
@@ -0,0 +1,34 @@
+package org.mmtk.policy.arraylet;
+
+import org.mmtk.utility.alloc.ArrayletAllocator;
+import org.mmtk.utility.Constants;
+import org.vmmagic.pragma.Uninterruptible;
+
+/* Written by jbs for Arraylet implementation.  Summer 2008 */
+
+@Uninterruptible
+public final class ArrayletMutatorLocal extends ArrayletAllocator implements Constants {
+
+  public ArrayletMutatorLocal(ArrayletSpace space) {
+    super(space);
+  }
+
+  /****************************************************************************
+   *
+   * Collection
+   */
+
+  /**
+   * Prepare for a collection. If paranoid, perform a sanity check.
+   */
+  public void prepare() {
+    reset();
+  }
+
+  /**
+   * Finish up after a collection.
+   */
+  public void release() {
+    reset();
+  }
+}
diff -r 743a2cc2ed20 -r 058fdc3780ba MMTk/src/org/mmtk/policy/arraylet/ArrayletSpace.java
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MMTk/src/org/mmtk/policy/arraylet/ArrayletSpace.java	Mon Nov 16 09:21:21 2009 +1100
@@ -0,0 +1,230 @@
+package org.mmtk.policy.arraylet;
+
+
+import static org.mmtk.policy.arraylet.ArrayletConstants.MAX_BLOCK_MARK_STATE;
+import static org.mmtk.policy.arraylet.ArrayletConstants.LOG_BYTES_IN_ARRAYLET;
+import static org.mmtk.policy.arraylet.ArrayletConstants.PAGES_IN_BLOCK;
+import static org.mmtk.policy.arraylet.ArrayletConstants.BYTES_IN_RECYCLE_ALLOC_CHUNK;
+import static org.mmtk.policy.arraylet.ArrayletConstants.RECYCLE_ALLOC_CHUNK_MASK;
+
+import org.mmtk.plan.TransitiveClosure;
+import org.mmtk.policy.Space;
+import org.mmtk.utility.heap.FreeListPageResource;
+import org.mmtk.utility.heap.VMRequest;
+import org.mmtk.utility.Constants;
+import org.mmtk.utility.Log;
+
+import org.mmtk.vm.Lock;
+import org.mmtk.vm.VM;
+
+import org.vmmagic.unboxed.*;
+import org.vmmagic.pragma.*;
+
+/**
+ * 
+ *  Written by jbs for Arraylet implementation.  Summer 2008 
+ * 
+ * This class implements tracing for a simple immortal collection
+ * policy.  Under this policy all that is required is for the
+ * "collector" to propogate marks in a liveness trace.  It does not
+ * actually collect.  This class does not hold any state, all methods
+ * are static.
+ */
+@Uninterruptible 
+public final class ArrayletSpace extends Space implements Constants {
+
+  private static short reusableMarkStateThreshold = 0;
+
+  /****************************************************************************
+   *
+   * Instance variables
+   */
+  private boolean inCollection;
+  private int arrayletsConsumed = 0;
+
+  private Lock mutatorLock = VM.newLock(getName()+"mutator");
+  private Lock gcLock = VM.newLock(getName()+"gc");
+
+  private Address allocBlockCursor = Address.zero();
+  private Address allocBlockSentinel = Address.zero();
+  private boolean exhaustedReusableSpace = true;
+  private final ChunkList chunkMap = new ChunkList();
+
+  static {
+    reusableMarkStateThreshold = MAX_BLOCK_MARK_STATE;
+  }
+
+
+  public ArrayletSpace(String name, int pageBudget, VMRequest vmRequest) {
+    super(name, false, true, vmRequest);
+    if (vmRequest.isDiscontiguous()) {
+      pr = new FreeListPageResource(pageBudget, this, Chunk.getRequiredMetaDataPages());
+    } else {
+      pr = new FreeListPageResource(pageBudget, this, start, extent, Chunk.getRequiredMetaDataPages());
+    }
+  }
+
+  @Inline
+  public ObjectReference traceObject(TransitiveClosure trace, ObjectReference object) {
+    return object;
+  }
+
+  public void prepare() {
+    chunkMap.reset();
+    inCollection = true;
+  }
+
+  public void release() {
+    chunkMap.reset();
+    inCollection = false;
+
+    /* set up reusable space */
+    if (allocBlockCursor.isZero()) allocBlockCursor = chunkMap.getHeadChunk();
+    allocBlockSentinel = allocBlockCursor;
+    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(ArrayletSpace.isRecycleAllocChunkAligned(allocBlockSentinel));
+
+    exhaustedReusableSpace = allocBlockCursor.isZero();
+    arrayletsConsumed = 0;
+  }
+
+  @Inline
+  public void release(Address block) {
+    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(Block.isAligned(block));
+    Block.setBlockAsUnallocated(block);
+    ((FreeListPageResource) pr).releasePages(block);
+  }
+
+  @Override
+  public int releaseDiscontiguousChunks(Address chunk) {
+    chunkMap.removeChunkFromMap(chunk);
+    return super.releaseDiscontiguousChunks(chunk);
+  }
+
+  /**
+   * Return true if this space is currently being collected.
+   *
+   * @return True if this space is currently being collected.
+   */
+  @Inline
+  public boolean inCollection() {
+    return inCollection;
+  }
+
+
+  /**
+   * Return the number of pages allocated since the last collection
+   *
+   * @return The number of pages allocated since the last collection
+   */
+  public int getPagesAllocated() {
+    return arrayletsConsumed>>(LOG_BYTES_IN_PAGE - LOG_BYTES_IN_ARRAYLET);
+  }
+
+  @Inline
+  public static short getReusuableMarkStateThreshold() {
+    return reusableMarkStateThreshold;
+  }
+
+
+  public Address getSpace(int arrayletUseCount) {
+    Address rtn;
+    arrayletsConsumed += arrayletUseCount;
+    rtn = acquire(PAGES_IN_BLOCK);
+    if (VM.VERIFY_ASSERTIONS) {
+      VM.assertions._assert(Block.isAligned(rtn));
+    }
+    if (!rtn.isZero()) {
+      Block.setBlockAsInUse(rtn);
+      Chunk.updateHighWater(rtn);
+    }
+    return rtn;
+  }
+
+  @Override
+  public void growSpace(Address start, Extent bytes, boolean newChunk) {
+    super.growSpace(start, bytes, newChunk);
+    if (newChunk) {
+      Address chunk = chunkAlign(start.plus(bytes), true);
+      if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(chunkAlign(start.plus(bytes), true).EQ(chunk));
+      Chunk.clearMetaData(chunk);
+      chunkMap.addNewChunkToMap(chunk);
+    }
+  }
+
+  public Address acquireReusableBlocks() {
+    if (VM.VERIFY_ASSERTIONS) {
+      VM.assertions._assert(ArrayletSpace.isRecycleAllocChunkAligned(allocBlockCursor));
+      VM.assertions._assert(ArrayletSpace.isRecycleAllocChunkAligned(allocBlockSentinel));
+    }
+
+    Address rtn;
+    lock();
+    if (exhaustedReusableSpace) {
+      rtn = Address.zero();
+    } else {
+      rtn = allocBlockCursor;
+      Address lastAllocChunk = chunkAlign(allocBlockCursor, true);
+      allocBlockCursor = allocBlockCursor.plus(BYTES_IN_RECYCLE_ALLOC_CHUNK);
+      if (allocBlockCursor.GT(Chunk.getHighWater(lastAllocChunk))) {
+        allocBlockCursor = chunkMap.nextChunk(lastAllocChunk);
+      }
+      if (allocBlockCursor.isZero() || allocBlockCursor.EQ(allocBlockSentinel))
+        exhaustedReusableSpace = true;
+    }
+    unlock();
+    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(ArrayletSpace.isRecycleAllocChunkAligned(rtn));
+    return rtn;
+
+  }
+
+  public static void markArraylet(Address arraylet) {
+    Arraylet.mark(arraylet);
+  }
+
+
+  @Inline
+  public boolean isLive(ObjectReference object) {
+    return true;
+  }
+
+  public boolean isReachable(ObjectReference object) {
+    return true;
+  }
+  @Inline
+  public boolean willNotMoveThisGC(ObjectReference object) {
+    return true;
+  }
+
+  /**
+   * Acquire the appropriate lock depending on whether the context is
+   * GC or mutator.
+   */
+  private void lock() {
+    if (inCollection)
+      gcLock.acquire();
+    else
+      mutatorLock.acquire();
+  }
+
+  /**
+   * Release the appropriate lock depending on whether the context is
+   * GC or mutator.
+   */
+  private void unlock() {
+    if (inCollection)
+      gcLock.release();
+    else
+      mutatorLock.release();
+  }
+
+  /****************************************************************************
+   *
+   * Misc
+   */
+  public static boolean isRecycleAllocChunkAligned(Address ptr) {
+    return ptr.toWord().and(RECYCLE_ALLOC_CHUNK_MASK).EQ(Word.zero());
+  }
+
+  ChunkList getChunkMap() { return chunkMap; }
+
+}
\ No newline at end of file
diff -r 743a2cc2ed20 -r 058fdc3780ba MMTk/src/org/mmtk/policy/arraylet/Block.java
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MMTk/src/org/mmtk/policy/arraylet/Block.java	Mon Nov 16 09:21:21 2009 +1100
@@ -0,0 +1,189 @@
+package org.mmtk.policy.arraylet;
+
+
+import static org.mmtk.policy.arraylet.ArrayletConstants.BLOCKS_IN_CHUNK;
+import static org.mmtk.policy.arraylet.ArrayletConstants.BLOCK_MASK;
+import static org.mmtk.policy.arraylet.ArrayletConstants.CHUNK_MASK;
+import static org.mmtk.policy.arraylet.ArrayletConstants.LOG_BYTES_IN_BLOCK;
+import static org.mmtk.policy.arraylet.ArrayletConstants.MAX_BLOCK_MARK_STATE;
+import static org.mmtk.policy.arraylet.ArrayletConstants.ARRAYLETS_IN_BLOCK;
+import static org.mmtk.policy.arraylet.ArrayletConstants.SANITY_CHECK_ARRAYLET_MARKS;
+import static org.mmtk.policy.arraylet.ArrayletConstants.LOG_BYTES_IN_ARRAYLET;
+import static org.mmtk.policy.arraylet.ArrayletConstants.BYTES_IN_ARRAYLET;
+
+//import org.jikesrvm.mm.mminterface.MemoryManagerConstants;
+import org.mmtk.plan.TraceLocal;
+import org.mmtk.utility.Constants;
+import org.mmtk.vm.VM;
+
+import org.vmmagic.pragma.Uninterruptible;
+import org.vmmagic.unboxed.Address;
+import org.vmmagic.unboxed.Extent;
+import org.vmmagic.unboxed.Offset;
+
+/**
+ * 
+ *  Written by jbs for Arraylet implementation.  Summer 2008 
+ * 
+ * This class defines operations over block-granularity meta-data
+ *
+ */
+@Uninterruptible
+public class Block implements Constants {
+  
+  static Address align(final Address ptr) {
+    return ptr.toWord().and(BLOCK_MASK.not()).toAddress();
+  }
+
+  public static boolean isAligned(final Address address) {
+    return address.EQ(align(address));
+  }
+
+  private static int getChunkIndex(final Address block) {
+    return block.toWord().and(CHUNK_MASK).rshl(LOG_BYTES_IN_BLOCK).toInt();
+  }
+
+  /***************************************************************************
+   * Block marking
+   */
+  public static boolean isUnused(final Address address) {
+    return getBlockMarkState(address) == UNALLOCATED_BLOCK_STATE;
+  }
+
+  static boolean isUnusedState(Address cursor) {
+    return cursor.loadShort() == UNALLOCATED_BLOCK_STATE;
+  }
+
+  static boolean isUnmarkedState(Address cursor) {
+    return cursor.loadShort() == UNMARKED_BLOCK_STATE;
+  }
+
+  static boolean isMarkedState(Address cursor) {
+    return cursor.loadShort() == MARKED_BLOCK_STATE;
+  }
+
+  static void setToUnmarkedState(Address cursor) {
+    cursor.store(UNMARKED_BLOCK_STATE);
+  }
+
+  static Address clearMarkStateAndAdvance(Address cursor) {
+    short value = cursor.loadShort();
+    if (value != Block.UNALLOCATED_BLOCK_STATE)
+      cursor.store(Block.UNMARKED_BLOCK_STATE);
+    return cursor.plus(BYTES_IN_BLOCK_STATE_ENTRY);
+  }
+
+  public static short getBlockMarkState(Address address) {
+    return getBlockMarkStateAddress(address).loadShort();
+  }
+
+  static void setBlockAsInUse(Address address) {
+    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(isUnused(address));
+    setBlockState(address, UNMARKED_BLOCK_STATE);
+  }
+
+  public static void setBlockAsReused(Address address) {
+    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!isUnused(address));
+    setBlockState(address, REUSED_BLOCK_STATE);
+  }
+
+  static void setBlockAsUnallocated(Address address) {
+    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!isUnused(address));
+    getBlockMarkStateAddress(address).store(UNALLOCATED_BLOCK_STATE);
+  }
+
+  private static void setBlockState(Address address, short value) {
+    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(value != UNALLOCATED_BLOCK_STATE);
+    getBlockMarkStateAddress(address).store(value);
+  }
+
+  static Address getBlockMarkStateAddress(Address address) {
+    Address chunk = Chunk.align(address);
+    int index = getChunkIndex(address);
+    Address rtn = chunk.plus(Chunk.BLOCK_STATE_TABLE_OFFSET).plus(index<<LOG_BYTES_IN_BLOCK_STATE_ENTRY);
+    if (VM.VERIFY_ASSERTIONS) {
+      Address block = chunk.plus(index<<LOG_BYTES_IN_BLOCK);
+      VM.assertions._assert(isAligned(block));
+      boolean valid = rtn.GE(chunk.plus(Chunk.BLOCK_STATE_TABLE_OFFSET)) && rtn.LT(chunk.plus(Chunk.BLOCK_STATE_TABLE_OFFSET+BLOCK_STATE_TABLE_BYTES));
+      VM.assertions._assert(valid);
+    }
+    return rtn;
+  }
+
+  static void scan(Address block, TraceLocal trace) {
+    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(isAligned(block));
+    final boolean unused = isUnused(block);
+    if (unused)
+      return;
+    Address markTable = Arraylet.getBlockMarkTable(block);
+    short markCount = 0;
+    byte mark, lastMark = 0;
+    for (int l = 0; l < ARRAYLETS_IN_BLOCK; l++) {
+      Address markAddr = markTable.plus(Offset.fromIntSignExtend(l<<Arraylet.LOG_BYTES_IN_ARRAYLET_MARK));
+      if (VM.VERIFY_ASSERTIONS) {
+        VM.assertions._assert(markAddr.GE(Chunk.align(block).plus(Chunk.ARRAYLET_MARK_TABLE_OFFSET)));
+        VM.assertions._assert(markAddr.LT(Chunk.align(block).plus(Chunk.ARRAYLET_MARK_TABLE_OFFSET+Arraylet.ARRAYLET_MARK_TABLE_BYTES)));
+      }
+      mark = markAddr.loadByte();
+      //jbs changed
+      if (VM.DO_ANY_TYPES_COW) {
+    	  mark = (byte)(mark & Arraylet.ARRAYLET_MARK_MASK);
+      }
+      if (mark != Arraylet.ARRAYLET_UNMARKED_VALUE) {
+        trace.scanArraylet(block.plus(l << LOG_BYTES_IN_ARRAYLET));
+      }
+    }
+  }
+
+  /***************************************************************************
+   * Sweeping
+   */
+  static short sweepOneBlock(Address block) {
+    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(isAligned(block));
+
+    final boolean unused = isUnused(block);
+    if (unused && !SANITY_CHECK_ARRAYLET_MARKS)
+      return 0;
+
+    Address markTable = Arraylet.getBlockMarkTable(block);
+    short markCount = 0;
+    byte mark, lastMark = 0;
+    for (int l = 0; l < ARRAYLETS_IN_BLOCK; l++) {
+      Address markAddr = markTable.plus(Offset.fromIntSignExtend(l<<Arraylet.LOG_BYTES_IN_ARRAYLET_MARK));
+      if (VM.VERIFY_ASSERTIONS) {
+        VM.assertions._assert(markAddr.GE(Chunk.align(block).plus(Chunk.ARRAYLET_MARK_TABLE_OFFSET)));
+        VM.assertions._assert(markAddr.LT(Chunk.align(block).plus(Chunk.ARRAYLET_MARK_TABLE_OFFSET+Arraylet.ARRAYLET_MARK_TABLE_BYTES)));
+      }
+      mark = markAddr.loadByte();
+      //jbs changed
+      if (VM.DO_ANY_TYPES_COW) {
+    	  mark = (byte)(mark & Arraylet.ARRAYLET_MARK_MASK);	
+      }
+      if (mark != Arraylet.ARRAYLET_UNMARKED_VALUE)
+        markCount++;
+      else if (SANITY_CHECK_ARRAYLET_MARKS && lastMark == 0) {
+        VM.memory.zero(block.plus(l<<LOG_BYTES_IN_ARRAYLET),Extent.fromIntZeroExtend(BYTES_IN_ARRAYLET));
+      }
+
+      lastMark = mark;
+    }
+    if (VM.VERIFY_ASSERTIONS) {
+      VM.assertions._assert(markCount <= ARRAYLETS_IN_BLOCK);
+      VM.assertions._assert(markCount == 0 || !isUnused(block));
+    }
+    return markCount;
+  }
+  
+  private static final short UNALLOCATED_BLOCK_STATE = 0;
+  private static final short UNMARKED_BLOCK_STATE = (short) (MAX_BLOCK_MARK_STATE + 1);
+  private static final short MARKED_BLOCK_STATE = (short) (MAX_BLOCK_MARK_STATE + 2);
+  private static final short REUSED_BLOCK_STATE = (short) (MAX_BLOCK_MARK_STATE + 3);
+
+
+  /* block states */
+  static final int LOG_BYTES_IN_BLOCK_STATE_ENTRY = LOG_BYTES_IN_SHORT; // use a short for now
+  static final int BYTES_IN_BLOCK_STATE_ENTRY = 1<<LOG_BYTES_IN_BLOCK_STATE_ENTRY;
+  public static final int BLOCK_STATE_TABLE_BYTES = BLOCKS_IN_CHUNK<<LOG_BYTES_IN_BLOCK_STATE_ENTRY;
+
+  
+}
diff -r 743a2cc2ed20 -r 058fdc3780ba MMTk/src/org/mmtk/policy/arraylet/Chunk.java
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MMTk/src/org/mmtk/policy/arraylet/Chunk.java	Mon Nov 16 09:21:21 2009 +1100
@@ -0,0 +1,185 @@
+package org.mmtk.policy.arraylet;
+
+import static org.mmtk.policy.Space.BYTES_IN_CHUNK;
+import static org.mmtk.policy.arraylet.ArrayletConstants.CHUNK_MASK;
+import static org.mmtk.policy.arraylet.ArrayletConstants.LOG_BYTES_IN_BLOCK;
+import static org.mmtk.policy.arraylet.ArrayletConstants.DONT_CLEAR_MARKS_AT_EVERY_GC;
+import static org.mmtk.policy.arraylet.ArrayletConstants.BLOCKS_IN_CHUNK;
+import static org.mmtk.policy.arraylet.ArrayletConstants.BYTES_IN_BLOCK;
+import static org.mmtk.policy.arraylet.ArrayletConstants.MAX_BLOCK_MARK_STATE;
+
+//import org.jikesrvm.mm.mminterface.MemoryManagerConstants;
+import org.mmtk.plan.TraceLocal; //jbs added arraylet
+import org.mmtk.policy.arraylet.Block;
+import org.mmtk.utility.Constants;
+import org.mmtk.utility.Conversions;
+import org.mmtk.utility.heap.Mmapper;
+import org.mmtk.vm.VM;
+
+import org.vmmagic.pragma.Uninterruptible;
+import org.vmmagic.unboxed.Address;
+import org.vmmagic.unboxed.Extent;
+
+/* Written by jbs for Arraylet implementation.  Summer 2008  */
+
+@Uninterruptible
+public class Chunk implements Constants {
+
+  public static Address align(Address ptr) {
+    return ptr.toWord().and(CHUNK_MASK.not()).toAddress();
+  }
+
+  static boolean isAligned(Address ptr) {
+    return ptr.EQ(align(ptr));
+  }
+
+  static int getByteOffset(Address ptr) {
+    return ptr.toWord().and(CHUNK_MASK).toInt();
+  }
+
+  /**
+   * Return the number of pages of metadata required per chunk.
+   */
+  static int getRequiredMetaDataPages() {
+    Extent bytes = Extent.fromIntZeroExtend(ROUNDED_METADATA_BYTES_PER_CHUNK);
+    return Conversions.bytesToPagesUp(bytes);
+  }
+
+  static void scan(Address chunk, Address end, ArrayletSpace space, TraceLocal trace) {
+    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(isAligned(chunk));
+    for (int index = FIRST_USABLE_BLOCK_INDEX; index < BLOCKS_IN_CHUNK; index++) {
+      Address block = chunk.plus(index<<LOG_BYTES_IN_BLOCK);
+      if (block.GT(end)) break;
+      Block.scan(block, trace);
+    }
+  }
+
+
+  static void sweep(Address chunk, Address end, ArrayletSpace space) {
+    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(isAligned(chunk));
+    Address start = getFirstUsableBlock(chunk);
+    Address cursor = Block.getBlockMarkStateAddress(start);
+    for (int index = FIRST_USABLE_BLOCK_INDEX; index < BLOCKS_IN_CHUNK; index++) {
+      Address block = chunk.plus(index<<LOG_BYTES_IN_BLOCK);
+      if (block.GT(end)) break;
+      short marked = Block.sweepOneBlock(block);
+      if (marked == 0) {
+        if (!Block.isUnusedState(cursor)) {
+          space.release(block);
+        }
+        if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(Block.isUnused(block));
+      } else {
+        if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(marked > 0 && marked <= MAX_BLOCK_MARK_STATE);
+        cursor.store(marked);
+      }
+      if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(Block.isUnused(block) || (Block.getBlockMarkState(block) == marked && marked > 0 && marked <= MAX_BLOCK_MARK_STATE));
+      cursor = cursor.plus(Block.BYTES_IN_BLOCK_STATE_ENTRY);
+    }
+  }
+
+
+  static void clearMetaData(Address chunk) {
+    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(isAligned(chunk));
+    Mmapper.ensureMapped(chunk, ROUNDED_METADATA_PAGES_PER_CHUNK);
+    VM.memory.zeroPages(chunk, ROUNDED_METADATA_BYTES_PER_CHUNK);
+    if (VM.VERIFY_ASSERTIONS) checkMetaDataCleared(chunk, chunk);
+  }
+
+  private static void checkMetaDataCleared(Address chunk, Address value) {
+    VM.assertions._assert(isAligned(chunk));
+    Address block = Chunk.getHighWater(chunk);
+    if (value.EQ(chunk)) {
+      VM.assertions._assert(block.isZero());
+      block = chunk.plus(Chunk.ROUNDED_METADATA_BYTES_PER_CHUNK);
+    } else {
+      block = block.plus(BYTES_IN_BLOCK); // start at first block after highwater  
+      VM.assertions._assert(Block.align(block).EQ(block));
+    }
+    while (block.LT(chunk.plus(BYTES_IN_CHUNK))) {
+      VM.assertions._assert(Chunk.align(block).EQ(chunk));
+      VM.assertions._assert(Block.isUnused(block));
+      block = block.plus(BYTES_IN_BLOCK);
+    }
+  }
+
+
+  static void clearBlockMarkState(Address chunk) {
+    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(isAligned(chunk));
+    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(DONT_CLEAR_MARKS_AT_EVERY_GC);
+
+    clearArrayletMarks(chunk);
+    Address cursor = Block.getBlockMarkStateAddress(getFirstUsableBlock(chunk));
+    for (int block = FIRST_USABLE_BLOCK_INDEX; block < BLOCKS_IN_CHUNK; block++)
+      cursor = Block.clearMarkStateAndAdvance(cursor);
+  }
+
+  static void clearArrayletMarks(Address chunk) {
+    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(isAligned(chunk));
+    //jbs changed
+    if (VM.DO_ANY_TYPES_COW) {
+
+    	Address currAddr = chunk.plus(Chunk.ARRAYLET_MARK_TABLE_OFFSET);
+    	for (int currByte = 0; currByte < Arraylet.ARRAYLET_MARK_TABLE_BYTES; currByte++) {
+    		byte zeroedMark = ((byte)(currAddr.loadByte() & Arraylet.ARRAYLET_INCOMING_PTR_MASK));
+    		currAddr.store(zeroedMark);
+    		currAddr = currAddr.plus(BYTES_IN_BYTE); //currByte<<Arraylet.LOG_BYTES_IN_ARRAYLET_MARK);
+    	}
+    } else {
+    	VM.memory.zero(chunk.plus(ARRAYLET_MARK_TABLE_OFFSET), Extent.fromIntZeroExtend(Arraylet.ARRAYLET_MARK_TABLE_BYTES));
+    }
+    
+  }
+
+  static void updateHighWater(Address value) {
+    Address chunk = align(value);
+    if (getHighWater(chunk).LT(value)) {
+      setHighWater(chunk, value);
+    }
+  }
+
+  private static void setHighWater(Address chunk, Address value) {
+    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(isAligned(chunk));
+    chunk.plus(HIGHWATER_OFFSET).store(value);
+  }
+
+  public static Address getHighWater(Address chunk) {
+    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(isAligned(chunk));
+    return chunk.plus(HIGHWATER_OFFSET).loadAddress();
+  }
+
+  public static void setMap(Address chunk, int value) {
+    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(isAligned(chunk));
+    chunk.plus(MAP_OFFSET).store(value);
+  }
+
+  public static int getMap(Address chunk) {
+    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(isAligned(chunk));
+    int rtn = chunk.plus(MAP_OFFSET).loadInt();
+    return (rtn < 0) ? -rtn : rtn;
+  }
+
+  static Address getFirstUsableBlock(Address chunk) {
+    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(isAligned(chunk));
+    Address rtn = chunk.plus(ROUNDED_METADATA_BYTES_PER_CHUNK);
+    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(rtn.EQ(Block.align(rtn)));
+    return rtn;
+  }
+
+
+  private static final int LOG_BYTES_IN_HIGHWATER_ENTRY = LOG_BYTES_IN_ADDRESS;
+  private static final int HIGHWATER_BYTES = 1<<LOG_BYTES_IN_HIGHWATER_ENTRY;
+  private static final int LOG_BYTES_IN_MAP_ENTRY = LOG_BYTES_IN_INT;
+  private static final int MAP_BYTES = 1<<LOG_BYTES_IN_MAP_ENTRY;
+
+  static final int ARRAYLET_MARK_TABLE_OFFSET = 0;
+  static final int BLOCK_STATE_TABLE_OFFSET = ARRAYLET_MARK_TABLE_OFFSET + Arraylet.ARRAYLET_MARK_TABLE_BYTES;
+  static final int HIGHWATER_OFFSET = BLOCK_STATE_TABLE_OFFSET + Block.BLOCK_STATE_TABLE_BYTES;
+  static final int MAP_OFFSET = HIGHWATER_OFFSET + HIGHWATER_BYTES;
+  static final int METADATA_BYTES_PER_CHUNK = MAP_OFFSET + MAP_BYTES;
+
+  /* FIXME we round the metadata up to block sizes just to ensure the underlying allocator gives us aligned requests */
+  static final int ROUNDED_METADATA_BYTES_PER_CHUNK = (METADATA_BYTES_PER_CHUNK + (1<<LOG_BYTES_IN_BLOCK) - 1) & (~((1<<LOG_BYTES_IN_BLOCK) - 1));
+  static final int ROUNDED_METADATA_PAGES_PER_CHUNK = ROUNDED_METADATA_BYTES_PER_CHUNK>>LOG_BYTES_IN_PAGE;
+  public static final int FIRST_USABLE_BLOCK_INDEX = ROUNDED_METADATA_BYTES_PER_CHUNK>>LOG_BYTES_IN_BLOCK;
+
+}
diff -r 743a2cc2ed20 -r 058fdc3780ba MMTk/src/org/mmtk/policy/arraylet/ChunkList.java
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MMTk/src/org/mmtk/policy/arraylet/ChunkList.java	Mon Nov 16 09:21:21 2009 +1100
@@ -0,0 +1,144 @@
+package org.mmtk.policy.arraylet;
+
+import org.mmtk.plan.Plan;
+import org.mmtk.policy.Space;
+import org.mmtk.utility.Constants;
+import org.mmtk.vm.VM;
+import org.vmmagic.pragma.Uninterruptible;
+import org.vmmagic.unboxed.Address;
+import org.vmmagic.unboxed.AddressArray;
+
+/* Written by jbs for Arraylet implementation.  Summer 2008  */
+
+//jbs - from Immix's ChunkList
+@Uninterruptible
+public final class ChunkList implements Constants {
+  private static final int LOG_CHUNK_MAP_PAGES = 0;
+  private static final int CHUNK_MAP_ENTRIES = (BYTES_IN_PAGE<<LOG_CHUNK_MAP_PAGES)>>LOG_BYTES_IN_ADDRESS;
+  private static final int CHUNK_MAP_ARRAY_SIZE = 16;
+  private AddressArray chunkMap =  AddressArray.create(CHUNK_MAP_ARRAY_SIZE);
+  private int chunkMapLimit = -1;
+  private int chunkMapCursor = -1;
+
+  void reset() {
+    chunkMapLimit = chunkMapCursor;
+  }
+
+  public Address getHeadChunk() {
+    if (chunkMapLimit < 0)
+      return Address.zero();
+    else {
+      return getMapAddress(0).loadAddress();
+    }
+  }
+
+  public Address getTailChunk() {
+    if (chunkMapLimit < 0)
+      return Address.zero();
+    else
+      return getMapAddress(chunkMapLimit).loadAddress();
+  }
+
+  void addNewChunkToMap(Address chunk) {
+    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(Chunk.isAligned(chunk));
+    chunkMapCursor++;
+    int index = getChunkIndex(chunkMapCursor);
+    int map = getChunkMap(chunkMapCursor);
+    if (map >= CHUNK_MAP_ARRAY_SIZE) {
+      Space.printUsageMB();
+      VM.assertions.fail("Overflow of chunk map!");
+    }
+    if (chunkMap.get(map).isZero()) {
+      Address tmp = Plan.metaDataSpace.acquire(1<<LOG_CHUNK_MAP_PAGES);
+      if (tmp.isZero()) {
+        Space.printUsageMB();
+        VM.assertions.fail("Failed to allocate space for chunk map.  Is metadata virtual memory exhausted?");
+      }
+      chunkMap.set(map, tmp);
+    }
+    Address entry = chunkMap.get(map).plus(index<<LOG_BYTES_IN_ADDRESS);
+    entry.store(chunk);
+    Chunk.setMap(chunk, chunkMapCursor);
+    if (VM.VERIFY_ASSERTIONS) checkMap();
+  }
+
+  void removeChunkFromMap(Address chunk) {
+    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(Chunk.isAligned(chunk));
+    int entry = Chunk.getMap(chunk);
+    getMapAddress(entry).store(Address.zero());  // zero it it
+    Chunk.setMap(chunk, -entry);
+    if (VM.VERIFY_ASSERTIONS) checkMap();
+  }
+
+  private int getChunkIndex(int entry) { return entry & (CHUNK_MAP_ENTRIES - 1);}
+  private int getChunkMap(int entry) {return entry & ~(CHUNK_MAP_ENTRIES - 1);}
+
+  private Address getMapAddress(int entry) {
+    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(entry >= 0);
+    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(entry <= chunkMapCursor);
+    int index = getChunkIndex(entry);
+    int map = getChunkMap(entry);
+    return chunkMap.get(map).plus(index<<LOG_BYTES_IN_ADDRESS);
+  }
+
+  public Address nextChunk(Address chunk) {
+    return nextChunk(chunk, chunk);
+  }
+
+  public Address nextChunk(Address chunk, Address limit) {
+    return nextChunk(chunk, Chunk.getMap(limit), 1);
+  }
+
+  public Address nextChunk(Address chunk, int limit) {
+    return nextChunk(chunk, limit, 1);
+  }
+
+  public Address nextChunk(Address chunk, int limit, int stride) {
+    if (VM.VERIFY_ASSERTIONS) checkMap();
+    return nextChunk(Chunk.getMap(chunk), limit, stride);
+  }
+
+  public Address nextChunk(int entry, int limit, int stride) {
+    if (VM.VERIFY_ASSERTIONS) checkMap();
+    Address chunk;
+    do {
+      entry += stride;
+      if (entry > chunkMapLimit) { entry = entry % stride; }
+      chunk = getMapAddress(entry).loadAddress();
+    } while (chunk.isZero() && entry != limit);
+    return entry == limit ? Address.zero() : chunk;
+  }
+
+  public Address firstChunk(int ordinal, int stride) {
+    if (ordinal > chunkMapCursor) return Address.zero();
+    if (VM.VERIFY_ASSERTIONS) checkMap();
+    Address chunk = getMapAddress(ordinal).loadAddress();
+    return chunk.isZero() ? nextChunk(ordinal, ordinal, stride) : chunk;
+  }
+
+  private void checkMap() {
+    VM.assertions._assert(chunkMapLimit <= chunkMapCursor);
+    for (int entry = 0; entry <= chunkMapCursor; entry++) {
+      Address chunk = getMapAddress(entry).loadAddress();
+      if (!chunk.isZero())
+        VM.assertions._assert(Chunk.getMap(chunk) == entry);
+    }
+  }
+
+  public void consolidateMap() {
+    int oldCursor = 0;
+    int newCursor = -1;
+    while (oldCursor <= chunkMapCursor) {
+      Address chunk = getMapAddress(oldCursor).loadAddress();
+      if (!chunk.isZero()) {
+        getMapAddress(++newCursor).store(chunk);
+        Chunk.setMap(chunk, newCursor);
+      }
+      oldCursor++;
+    }
+    chunkMapCursor = newCursor;
+    chunkMapLimit = newCursor;
+    if (VM.VERIFY_ASSERTIONS) checkMap();
+  }
+
+}
diff -r 743a2cc2ed20 -r 058fdc3780ba MMTk/src/org/mmtk/utility/alloc/ArrayletAllocator.java
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MMTk/src/org/mmtk/utility/alloc/ArrayletAllocator.java	Mon Nov 16 09:21:21 2009 +1100
@@ -0,0 +1,194 @@
+package org.mmtk.utility.alloc;
+
+
+import static org.mmtk.policy.arraylet.ArrayletConstants.BYTES_IN_ARRAYLET;
+import static org.mmtk.policy.arraylet.ArrayletConstants.BYTES_IN_BLOCK;
+import static org.mmtk.policy.arraylet.ArrayletConstants.ARRAYLETS_IN_BLOCK;
+import static org.mmtk.policy.arraylet.ArrayletConstants.LOG_BYTES_IN_ARRAYLET;
+import static org.mmtk.policy.arraylet.ArrayletConstants.SANITY_CHECK_ARRAYLET_MARKS;
+
+import org.mmtk.policy.Space;
+import org.mmtk.policy.arraylet.*;
+
+import org.mmtk.utility.Constants;
+import org.mmtk.utility.Log;
+import org.mmtk.vm.VM;
+
+import org.vmmagic.unboxed.*;
+import org.vmmagic.pragma.*;
+
+/* Written by jbs for Arraylet implementation.  Summer 2008  */
+
+@Uninterruptible
+public class ArrayletAllocator extends Allocator implements Constants {
+
+  /****************************************************************************
+   *
+   * Instance variables
+   */
+  protected final ArrayletSpace space;    /* space this allocator is associated with */
+
+  private Address cursor;               /* bump pointer */
+  private Address limit;                /* limit for bump pointer */
+  private int arrayletUseCount;             /* approximation to bytes allocated (measured at 99% accurate)  07/10/30 */
+  private Address markTable;
+  private Address recyclableBlock;
+  private int arraylet;
+  private boolean recyclableExhausted;
+
+  public ArrayletAllocator(ArrayletSpace space) {
+    this.space = space;
+    reset();
+  }
+
+  /**
+   * Reset the allocator. Note that this does not reset the space.
+   */
+  public void reset() {
+    cursor = Address.zero();
+    limit = Address.zero();
+    markTable = Address.zero();
+    recyclableBlock = Address.zero();
+    recyclableExhausted = false;
+    arraylet = ARRAYLETS_IN_BLOCK;
+    arrayletUseCount = 0;
+  }
+
+
+  @Inline
+  public final Address alloc() {
+    Address start = cursor;
+    Address end = start.plus(BYTES_IN_ARRAYLET);
+
+    if (end.GT(limit)) {
+      return allocSlowHot();
+    }
+    cursor = end;
+    return start;
+  }
+
+  @NoInline
+  private Address allocSlowHot() {
+    if (acquireRecyclableArraylets())
+      return alloc();
+    else
+      return allocSlowInline(BYTES_IN_ARRAYLET, 0, 0);
+  }
+
+  protected final Address allocSlowOnce(int bytes, int align, int offset) {
+    if (VM.VERIFY_ASSERTIONS) {
+      VM.assertions._assert(align == 0 && offset == 0);
+      VM.assertions._assert(bytes == BYTES_IN_ARRAYLET);
+    }
+    boolean success = false;
+    while (!success) {
+      Address ptr = space.getSpace(arrayletUseCount);
+
+      if (ptr.isZero()) {
+        arrayletUseCount = 0;
+        return ptr; // failed allocation --- we will need to GC
+      }
+      success = true;
+      arrayletUseCount = ARRAYLETS_IN_BLOCK;
+      if (VM.VERIFY_ASSERTIONS)
+        VM.assertions._assert(Block.isAligned(ptr));
+      zeroBlock(ptr);
+      cursor = ptr;
+      limit = ptr.plus(BYTES_IN_BLOCK);
+    }
+    return alloc();
+  }
+
+  private boolean acquireRecyclableArraylets() {
+    while (arraylet < ARRAYLETS_IN_BLOCK || acquireRecyclableBlock()) {
+      arraylet = Arraylet.getNextUnused(markTable, arraylet);
+      if (arraylet < ARRAYLETS_IN_BLOCK) {
+        int endarraylet = Arraylet.getNextUsed(markTable, arraylet);
+        cursor = recyclableBlock.plus(Extent.fromIntSignExtend(arraylet<<LOG_BYTES_IN_ARRAYLET));
+        limit = recyclableBlock.plus(Extent.fromIntSignExtend(endarraylet<<LOG_BYTES_IN_ARRAYLET));
+
+        if (SANITY_CHECK_ARRAYLET_MARKS) {
+          Address tmp = cursor;
+          while (tmp.LT(limit)) {
+            if (tmp.loadByte() != (byte) 0) {
+              Log.write("cursor: "); Log.writeln(cursor);
+              Log.write(" limit: "); Log.writeln(limit);
+              Log.write("current: "); Log.write(tmp);
+              Log.write("  value: "); Log.write(tmp.loadByte());
+              Log.write("   line: "); Log.write(arraylet);
+              Log.write("endline: "); Log.write(endarraylet);
+              Log.write("  chunk: "); Log.write(Chunk.align(cursor));
+              Log.write("     hw: "); Log.write(Chunk.getHighWater(Chunk.align(cursor)));
+              Log.writeln(" values: ");
+              Address tmp2 = cursor;
+              while(tmp2.LT(limit)) { Log.write(tmp2.loadByte()); Log.write(" ");}
+              Log.writeln();
+            }
+            VM.assertions._assert(tmp.loadByte() == (byte) 0);
+            tmp = tmp.plus(1);
+          }
+        }
+
+        VM.memory.zero(cursor, limit.diff(cursor).toWord().toExtent());
+        arraylet = endarraylet;
+        return true;
+      }
+    }
+    return false;
+  }
+
+  private boolean acquireRecyclableBlock() {
+    boolean rtn;
+    rtn = acquireRecyclableBlockAddressOrder();
+    if (rtn) {
+      markTable = Arraylet.getBlockMarkTable(recyclableBlock);
+      arraylet = 0;
+    }
+    return rtn;
+  }
+
+  @Inline
+  private boolean acquireRecyclableBlockAddressOrder() {
+    if (recyclableExhausted) return false;
+    int markState = 0;
+    boolean usable = false;
+    while (!usable) {
+      Address next = recyclableBlock.plus(BYTES_IN_BLOCK);
+      if (recyclableBlock.isZero() || ArrayletSpace.isRecycleAllocChunkAligned(next)) {
+        recyclableBlock = space.acquireReusableBlocks();
+        if (recyclableBlock.isZero()) {
+          recyclableExhausted = true;
+          arraylet = ARRAYLETS_IN_BLOCK;
+          return false;
+        }
+      } else {
+        recyclableBlock = next;
+      }
+      markState = Block.getBlockMarkState(recyclableBlock);
+      usable = (markState > 0 && markState <= ArrayletSpace.getReusuableMarkStateThreshold());
+    }
+    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!Block.isUnused(recyclableBlock));
+    Block.setBlockAsReused(recyclableBlock);
+
+    arrayletUseCount += (ARRAYLETS_IN_BLOCK-markState);
+    return true;
+  }
+
+  private void zeroBlock(Address block) {
+    // FIXME: efficiency check here!
+    if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(block.toWord().and(Word.fromIntSignExtend(BYTES_IN_BLOCK-1)).isZero());
+    VM.memory.zeroPages(block, BYTES_IN_BLOCK);
+  }
+
+
+  /** @return the space associated with this squish allocator */
+  public final Space getSpace() { return space; }
+
+  /**
+   * Print out the status of the allocator (for debugging)
+   */
+  public final void show() {
+    Log.write("cursor = "); Log.write(cursor);
+    Log.write(" limit = "); Log.writeln(limit);
+  }
+}
\ No newline at end of file
diff -r 743a2cc2ed20 -r 058fdc3780ba MMTk/src/org/mmtk/utility/heap/FreeListPageResource.java
--- a/MMTk/src/org/mmtk/utility/heap/FreeListPageResource.java	Tue Aug 04 11:04:15 2009 +1000
+++ b/MMTk/src/org/mmtk/utility/heap/FreeListPageResource.java	Mon Nov 16 09:21:21 2009 +1100
@@ -156,7 +156,7 @@
     } else {
       pagesCurrentlyOnFreeList -= pages;
       if (pageOffset > highWaterMark) {
-        if ((pageOffset ^ highWaterMark) > EmbeddedMetaData.PAGES_IN_REGION) {
+        if (highWaterMark == 0 || (pageOffset ^ highWaterMark) > EmbeddedMetaData.PAGES_IN_REGION) {
           int regions = 1 + ((pageOffset - highWaterMark) >> EmbeddedMetaData.LOG_PAGES_IN_REGION);
           int metapages = regions * metaDataPagesPerRegion;
           reserved += metapages;
diff -r 743a2cc2ed20 -r 058fdc3780ba MMTk/src/org/mmtk/utility/heap/Map.java
--- a/MMTk/src/org/mmtk/utility/heap/Map.java	Tue Aug 04 11:04:15 2009 +1000
+++ b/MMTk/src/org/mmtk/utility/heap/Map.java	Mon Nov 16 09:21:21 2009 +1100
@@ -97,7 +97,7 @@
         VM.assertions.fail("exiting");
       }
       descriptorMap[index] = descriptor;
-      VM.barriers.setArrayNoBarrier(spaceMap, index, space);
+      VM.barriers.setArrayNoGCBarrier(spaceMap, index, space);
       e = e.plus(Space.BYTES_IN_CHUNK);
     }
   }
@@ -208,7 +208,7 @@
     totalAvailableDiscontiguousChunks += chunks;
     for (int offset = 0; offset < chunks; offset++) {
       descriptorMap[chunk + offset] = 0;
-      VM.barriers.setArrayNoBarrier(spaceMap, chunk + offset, null);
+      VM.barriers.setArrayNoGCBarrier(spaceMap, chunk + offset, null);
       linkageMap[chunk + offset] = 0;
     }
     return chunks;
diff -r 743a2cc2ed20 -r 058fdc3780ba MMTk/src/org/mmtk/vm/Barriers.java
--- a/MMTk/src/org/mmtk/vm/Barriers.java	Tue Aug 04 11:04:15 2009 +1000
+++ b/MMTk/src/org/mmtk/vm/Barriers.java	Mon Nov 16 09:21:21 2009 +1100
@@ -27,8 +27,8 @@
    * @param index the index of the element to set
    * @param value the new value for the element
    */
-  public abstract void setArrayNoBarrier(Object [] dst, int index, Object value);
-
+  public abstract void setArrayNoGCBarrier(Object [] dst, int index, Object value);
+  
   /**
    * Perform the actual write of the write barrier.
    *
diff -r 743a2cc2ed20 -r 058fdc3780ba MMTk/src/org/mmtk/vm/Memory.java
--- a/MMTk/src/org/mmtk/vm/Memory.java	Tue Aug 04 11:04:15 2009 +1000
+++ b/MMTk/src/org/mmtk/vm/Memory.java	Mon Nov 16 09:21:21 2009 +1100
@@ -167,7 +167,9 @@
   /** @return The maximum number of bytes of padding to prepend to an object */
   protected abstract int getMaxBytesPaddingConstant();
   /** @return The value to store in alignment holes */
-  protected abstract int getAlignmentValueConstant();
+  protected abstract int getAlignmentValueConstant();	
+  /** @return The log of the number of elements per arraylet */
+  protected abstract int getLogArrayletElements();
 
   /*
    * NOTE: These methods should not be called by anything other than the
@@ -208,4 +210,7 @@
   static int alignmentValueTrapdoor(Memory m) {
     return m.getAlignmentValueConstant();
   }
+  static int logArrayletElements(Memory m) {
+    return m.getLogArrayletElements();
+  }
 }
diff -r 743a2cc2ed20 -r 058fdc3780ba MMTk/src/org/mmtk/vm/ObjectModel.java
--- a/MMTk/src/org/mmtk/vm/ObjectModel.java	Tue Aug 04 11:04:15 2009 +1000
+++ b/MMTk/src/org/mmtk/vm/ObjectModel.java	Mon Nov 16 09:21:21 2009 +1100
@@ -16,6 +16,7 @@
 import org.vmmagic.unboxed.*;
 
 @Uninterruptible public abstract class ObjectModel {
+	
   /**
    * Copy an object using a plan's allocCopy to get space and install
    * the forwarding pointer.  On entry, <code>from</code> must have
@@ -241,6 +242,10 @@
    */
   /** @return The offset from array reference to element zero */
   protected abstract Offset getArrayBaseOffset();
+  
+  //jbs added
+  public abstract void printAndResetStats();
+  public abstract void resetHarnessStats();
 
   /*
    * NOTE: These methods should not be called by anything other than the
@@ -253,4 +258,16 @@
   static Offset arrayBaseOffsetTrapdoor(ObjectModel o) {
     return o.getArrayBaseOffset();
   }
+  public abstract boolean getCollectArrayletStats();
+  static boolean collectArrayletStatsTrapdoor(ObjectModel o) {
+    return o.getCollectArrayletStats();
+  }
+  public abstract boolean getCollectAccessStats();
+  static boolean collectAccessStatsTrapdoor(ObjectModel o) {
+    return o.getCollectAccessStats();
+  }
+  public abstract boolean getDoAnyTypesCow();
+  static boolean doAnyTypesCowTrapdoor(ObjectModel o) {
+    return o.getDoAnyTypesCow();
+  }
 }
diff -r 743a2cc2ed20 -r 058fdc3780ba MMTk/src/org/mmtk/vm/Statistics.java
--- a/MMTk/src/org/mmtk/vm/Statistics.java	Tue Aug 04 11:04:15 2009 +1000
+++ b/MMTk/src/org/mmtk/vm/Statistics.java	Mon Nov 16 09:21:21 2009 +1100
@@ -23,6 +23,9 @@
    */
   public abstract int getCollectionCount();
 
+  //jbs added arraylet
+  public abstract void printArrayletStatistics();
+  
   /**
    * Read cycle counter
    */
diff -r 743a2cc2ed20 -r 058fdc3780ba MMTk/src/org/mmtk/vm/VM.java
--- a/MMTk/src/org/mmtk/vm/VM.java	Tue Aug 04 11:04:15 2009 +1000
+++ b/MMTk/src/org/mmtk/vm/VM.java	Mon Nov 16 09:21:21 2009 +1100
@@ -78,6 +78,12 @@
   public static final int ALIGNMENT_VALUE;
   /** The offset from an array reference to element zero */
   public static final Offset ARRAY_BASE_OFFSET;
+  /** The log of the number of elements per arraylet */
+  public static final int LOG_ARRAYLET_ELEMENTS; 
+
+  public static final boolean COLLECT_ARRAYLET_STATS; 
+  public static final boolean COLLECT_ACCESS_STATS; 
+  public static final boolean DO_ANY_TYPES_COW; 
 
   /*
    * VM-specific functionality captured in a series of singleton classs
@@ -175,6 +181,10 @@
     MAX_BYTES_PADDING = Memory.maxBytesPaddingTrapdoor(memory);
     ALIGNMENT_VALUE = Memory.alignmentValueTrapdoor(memory);
     ARRAY_BASE_OFFSET = ObjectModel.arrayBaseOffsetTrapdoor(objectModel);
+    LOG_ARRAYLET_ELEMENTS = Memory.logArrayletElements(memory);
+    COLLECT_ARRAYLET_STATS = ObjectModel.collectArrayletStatsTrapdoor(objectModel);
+    COLLECT_ACCESS_STATS = ObjectModel.collectAccessStatsTrapdoor(objectModel);
+    DO_ANY_TYPES_COW = ObjectModel.doAnyTypesCowTrapdoor(objectModel);
   }
 
   /**
diff -r 743a2cc2ed20 -r 058fdc3780ba build.xml
--- a/build.xml	Tue Aug 04 11:04:15 2009 +1000
+++ b/build.xml	Mon Nov 16 09:21:21 2009 +1100
@@ -1975,7 +1975,7 @@
   <target name="create-bootimage-profile" depends="runtime">
 	<ant antfile="build/components/dacapo.xml" target="ensure" inheritall="false" inheritrefs="false"/>
 	<mkdir dir="${build.profiles}"/>
-	<exec executable="${dist.base}/rvm"
+	<exec executable="${dist.base}/rvm" failonerror="true"
     dir="${build.profiles}">
     <arg value="-X:base:edge_counters=true"/>
 	  <arg value="-X:base:edge_counter_file=${build.profiles}/profile.ec"/>
diff -r 743a2cc2ed20 -r 058fdc3780ba build/primordials/RVM.txt
--- a/build/primordials/RVM.txt	Tue Aug 04 11:04:15 2009 +1000
+++ b/build/primordials/RVM.txt	Mon Nov 16 09:21:21 2009 +1100
@@ -17,6 +17,7 @@
 [Lorg/vmmagic/unboxed/Offset;
 [Lorg/vmmagic/unboxed/Extent;
 [Lorg/vmmagic/unboxed/AddressArray;
+[Lorg/vmmagic/unboxed/WordArray;
 [Lorg/vmmagic/unboxed/ObjectReferenceArray;
 
 [Lorg/jikesrvm/ArchitectureSpecific$CodeArray;
diff -r 743a2cc2ed20 -r 058fdc3780ba build/tests.xml
--- a/build/tests.xml	Tue Aug 04 11:04:15 2009 +1000
+++ b/build/tests.xml	Mon Nov 16 09:21:21 2009 +1100
@@ -619,6 +619,7 @@
     <attribute name="maxHeapSize" default=""/>
     <attribute name="rvmArgs" default=""/>
     <attribute name="timeLimit" default=""/>
+    <attribute name="expectedSuffix" default=""/>
     <sequential>
       <rvm tag="@{tag}"
            class="@{class}"
@@ -635,7 +636,7 @@
 
       <diffCompareFiles tag="@{tag}"
    	   					execution="@{execution}"
-                       	expected="${main.java}/${test.@{tag}.expected.output.file}.expected"
+                       	expected="${main.java}/${test.@{tag}.expected.output.file}@{expectedSuffix}.expected"
                         actual="${test.@{tag}.default.sanitized.output.file}"/>
 
       <outputResults tag="@{tag}"/>
diff -r 743a2cc2ed20 -r 058fdc3780ba common/vmmagic/src/org/vmmagic/unboxed/WordArray.java
--- a/common/vmmagic/src/org/vmmagic/unboxed/WordArray.java	Tue Aug 04 11:04:15 2009 +1000
+++ b/common/vmmagic/src/org/vmmagic/unboxed/WordArray.java	Mon Nov 16 09:21:21 2009 +1100
@@ -25,6 +25,34 @@
   public void set(int index, Word v) {
   }
 
+  public byte getByte(int index) {
+    return 0;
+  }
+
+  public void setByte(int index, byte v) {
+  }
+
+  public char getChar(int index) {
+    return 0;
+  }
+
+  public void setChar(int index, char v) {
+  }
+
+  public int getInt(int index) {
+    return 0;
+  }
+
+  public void setInt(int index, int v) {
+  }
+
+  public long getLong(int index) {
+    return 0;
+  }
+
+  public void setLong(int index, long v) {
+  }
+
   public int length() {
     return 0;
   }
diff -r 743a2cc2ed20 -r 058fdc3780ba libraryInterface/Common/src/java/lang/VMCommonLibrarySupport.java
--- a/libraryInterface/Common/src/java/lang/VMCommonLibrarySupport.java	Tue Aug 04 11:04:15 2009 +1000
+++ b/libraryInterface/Common/src/java/lang/VMCommonLibrarySupport.java	Mon Nov 16 09:21:21 2009 +1100
@@ -27,6 +27,7 @@
 import org.vmmagic.pragma.Entrypoint;
 import org.vmmagic.pragma.NoInline;
 import org.vmmagic.unboxed.Offset;
+import org.vmmagic.unboxed.WordArray;
 
 /**
  * Common utilities for Jikes RVM implementations of the java.lang API
@@ -164,20 +165,21 @@
    * Get the value of an environment variable.
    */
   static String getenv(String envarName) {
-    byte[] buf = new byte[128]; // Modest amount of space for starters.
+    WordArray buf = MemoryManager.createNativeByteBuffer(128); // Modest amount of space for starters.
 
-    byte[] nameBytes = envarName.getBytes();
-
+    WordArray nameBytes = MemoryManager.cloneToNativeBuffer(envarName.getBytes());
+      
     // sysCall is uninterruptible so passing buf is safe
-    int len = sysCall.sysGetenv(nameBytes, buf, buf.length);
+    int len = sysCall.sysGetenv(nameBytes, buf, MemoryManager.nativeByteBufferLength(buf));
 
     if (len < 0)                // not set.
       return null;
 
-    if (len > buf.length) {
-      buf = new byte[len];
+    if (len > MemoryManager.nativeByteBufferLength(buf)) {
+      buf = MemoryManager.createNativeByteBuffer(len);
       sysCall.sysGetenv(nameBytes, buf, len);
     }
-    return new String(buf, 0, len);
+    byte[] tmp = MemoryManager.getByteArray(buf);
+    return new String(tmp, 0, len);
   }
 }
diff -r 743a2cc2ed20 -r 058fdc3780ba libraryInterface/GNUClasspath/CPL/src/gnu/java/lang/VMInstrumentationImpl.java
--- a/libraryInterface/GNUClasspath/CPL/src/gnu/java/lang/VMInstrumentationImpl.java	Tue Aug 04 11:04:15 2009 +1000
+++ b/libraryInterface/GNUClasspath/CPL/src/gnu/java/lang/VMInstrumentationImpl.java	Mon Nov 16 09:21:21 2009 +1100
@@ -15,9 +15,14 @@
 import java.lang.instrument.Instrumentation;
 import java.lang.instrument.ClassDefinition;
 
+import org.jikesrvm.HeapLayoutConstants;
 import org.jikesrvm.classloader.RVMType;
 import org.jikesrvm.classloader.RVMClass;
 import org.jikesrvm.classloader.RVMArray;
+import org.jikesrvm.mm.mminterface.MemoryManagerConstants;
+import org.jikesrvm.runtime.Magic;
+import org.mmtk.plan.Plan;
+import org.mmtk.policy.Space;
 
 
 /**
@@ -47,7 +52,11 @@
     if (cl.isArray()) {
       RVMArray vmArray = (RVMArray)vmType;
       int nelements = java.lang.reflect.Array.getLength(objectToSize);
-      return vmArray.getInstanceSize(nelements);
+      if (Magic.objectAsAddress(objectToSize).LT(HeapLayoutConstants.BOOT_IMAGE_DATA_END)) {
+        return vmArray.getBootImageContiguousInstanceSize(nelements);
+      } else {
+        return vmArray.getInstanceSize(nelements);
+      }
     } else {
       RVMClass vmClass = (RVMClass)vmType;
       return vmClass.getInstanceSize();
diff -r 743a2cc2ed20 -r 058fdc3780ba libraryInterface/GNUClasspath/CPL/src/java/lang/VMClassLoader.java
--- a/libraryInterface/GNUClasspath/CPL/src/java/lang/VMClassLoader.java	Tue Aug 04 11:04:15 2009 +1000
+++ b/libraryInterface/GNUClasspath/CPL/src/java/lang/VMClassLoader.java	Mon Nov 16 09:21:21 2009 +1100
@@ -262,12 +262,14 @@
   }
 
   @SuppressWarnings({"unchecked","unused"}) // TODO should this method be deleted ?
-  private static Map packageAssertionStatus() {
+  //jbs changed private
+  public static Map packageAssertionStatus() {
     return new HashMap();
   }
 
   @SuppressWarnings({"unchecked","unused"}) // TODO should this method be deleted ?
-  private static Map classAssertionStatus() {
+  //jbs changed private
+  public static Map classAssertionStatus() {
     return new HashMap();
   }
 
diff -r 743a2cc2ed20 -r 058fdc3780ba libraryInterface/GNUClasspath/LGPL/src/gnu/java/nio/VMChannel.java
--- a/libraryInterface/GNUClasspath/LGPL/src/gnu/java/nio/VMChannel.java	Tue Aug 04 11:04:15 2009 +1000
+++ b/libraryInterface/GNUClasspath/LGPL/src/gnu/java/nio/VMChannel.java	Mon Nov 16 09:21:21 2009 +1100
@@ -49,9 +49,12 @@
 import java.nio.MappedByteBuffer;
 
 import org.jikesrvm.VM;
+import org.jikesrvm.classloader.RVMArray;
 import org.jikesrvm.mm.mminterface.MemoryManager;
+import org.jikesrvm.runtime.Memory;
 import org.jikesrvm.scheduler.greenthreads.FileSystem;
 import org.vmmagic.pragma.NonMovingAllocation;
+import org.vmmagic.unboxed.WordArray;
 
 
 /**
@@ -170,11 +173,10 @@
    * A thread-local store of non-moving buffers.  Used to perform IO to
    * in cases where the actual user buffer is in a moving space.
    */
-  private static class LocalByteArray extends ThreadLocal<byte[]> {
+  private static class LocalByteArray extends ThreadLocal<WordArray> {
     private static final int INITIAL_BUFFER_SIZE = 8192;
-    @NonMovingAllocation
-    protected byte[] initialValue() {
-      return new byte[INITIAL_BUFFER_SIZE];
+    protected WordArray initialValue() {
+      return MemoryManager.createNonMovingNativeByteBuffer(INITIAL_BUFFER_SIZE);
     }
 
     /**
@@ -182,15 +184,14 @@
      * @param len Minimum length of the buffer
      * @return a new or recycled buffer
      */
-    @NonMovingAllocation
-    public byte[] get(int len) {
-      byte[] buf = get();
-      if (buf.length < len) {
+    public WordArray get(int len) {
+      WordArray buf = get();
+      if (MemoryManager.nativeByteBufferLength(buf) < len) {
         /* Allocate a new buffer by successive doubling of capacity */
-        int newCapacity = buf.length << 1;
+        int newCapacity = MemoryManager.nativeByteBufferLength(buf) << 1;
         while (newCapacity < len)
           newCapacity <<= 1;
-        buf = new byte[newCapacity];
+        buf = MemoryManager.createNonMovingNativeByteBuffer(newCapacity);
         set(buf);
       }
       return buf;
@@ -258,17 +259,20 @@
    * @throws IOException If an error occurs or dst is not a direct buffers.
    */
   private int read(byte[] dst, int pos, int len) throws IOException {
-    if (MemoryManager.willNeverMove(dst)) {
-      return read(nfd.getNativeFD(),dst,pos,len);
+    if (false && MemoryManager.willNeverMove(dst)) {
+      WordArray tmp = MemoryManager.createNativeByteBuffer(len);
+      int rtn = read(nfd.getNativeFD(), tmp, 0, len);
+      Memory.nativeMarshal(tmp, 0, dst, pos, len);
+      return rtn;
     } else {
-      byte[] buffer;
+      WordArray buffer;
       // Rebuffer the IO in a thread-local byte array
       buffer = localByteArray.get(len);
 
       /* perform the read */
-      int bytes = read(nfd.getNativeFD(),buffer,0,len);
+      int bytes = read(nfd.getNativeFD(), buffer, 0, len);
       if (bytes > 0)
-        System.arraycopy(buffer,0,dst,pos,bytes);
+        Memory.nativeMarshal(buffer, 0, dst, pos, bytes);
       return bytes;
     }
   }
@@ -283,7 +287,7 @@
    * @return Number of bytes read, or -1 for end of file.
    * @throws IOException
    */
-  private static int read(int fd, byte[] dst, int position, int len) throws IOException {
+  private static int read(int fd, WordArray dst, int position, int len) throws IOException {
     if (VM.VerifyAssertions) VM._assert(MemoryManager.willNeverMove(dst));
     int bytes = FileSystem.readBytes(fd,dst,position,len);
     if (bytes < 0) {
@@ -393,14 +397,14 @@
    * @throws IOException
    */
   public int write(byte[] src, int pos, int len) throws IOException {
-    if (MemoryManager.willNeverMove(src)) {
-      return write(nfd.getNativeFD(), src, pos, len);
+    if (false && MemoryManager.willNeverMove(src)) {
+      return write(nfd.getNativeFD(), MemoryManager.cloneToNativeBuffer(src), pos, len);
     } else {
-      byte[] buffer;
+      WordArray buffer;
       // Rebuffer the IO in a thread-local DirectBuffer
       buffer = localByteArray.get(len);
       if (VM.VerifyAssertions) VM._assert(MemoryManager.willNeverMove(buffer));
-      System.arraycopy(src, pos, buffer,0,len);
+      Memory.nativeMarshal(src, pos, buffer, 0, len);
       return write(nfd.getNativeFD(),buffer,0,len);
     }
   }
@@ -437,7 +441,7 @@
    * @return Number of bytes written.
    * @throws IOException
    */
-  private static int write(int fd, byte[] src, int pos, int len) throws IOException {
+  private static int write(int fd, WordArray src, int pos, int len) throws IOException {
     int bytes = FileSystem.writeBytes(fd,src,pos,len);
     if (bytes < 0)
       throw new IOException("Error code "+Integer.toString(bytes));
diff -r 743a2cc2ed20 -r 058fdc3780ba rvm/src/org/jikesrvm/CommandLineArgs.java
--- a/rvm/src/org/jikesrvm/CommandLineArgs.java	Tue Aug 04 11:04:15 2009 +1000
+++ b/rvm/src/org/jikesrvm/CommandLineArgs.java	Mon Nov 16 09:21:21 2009 +1100
@@ -15,6 +15,7 @@
 import java.io.File;
 import java.util.Arrays;
 import org.jikesrvm.adaptive.controller.Controller;
+import org.jikesrvm.classloader.RVMArray;
 import org.jikesrvm.classloader.RVMClassLoader;
 import org.jikesrvm.compilers.baseline.BaselineCompiler;
 import org.jikesrvm.compilers.baseline.BaselineOptions;
@@ -22,8 +23,11 @@
 import org.jikesrvm.mm.mminterface.MemoryManager;
 
 import static org.jikesrvm.runtime.SysCall.sysCall;
+
+import org.jikesrvm.runtime.Memory;
 import org.jikesrvm.scheduler.Scheduler;
 import org.jikesrvm.scheduler.greenthreads.GreenScheduler;
+import org.vmmagic.unboxed.WordArray;
 
 /**
  * Command line option processing.
@@ -756,7 +760,12 @@
    *         for argument to fit)
    */
   private static int sysArg(int argno, byte[] buf) {
-    return sysCall.sysArg(argno, buf, buf.length);
+    WordArray nativeBuf = MemoryManager.createNativeByteBuffer(buf.length);
+    int rtn = sysCall.sysArg(argno, nativeBuf, MemoryManager.nativeByteBufferLength(nativeBuf));
+    if (rtn != -1) {
+      Memory.nativeMarshal(nativeBuf, buf);
+    }
+    return rtn;
   }
 
   /**
@@ -768,7 +777,7 @@
    */
   public static float primitiveParseFloat(String arg) {
     byte[] b = stringToBytes("floating point", arg);
-    return sysCall.sysPrimitiveParseFloat(b);
+    return sysCall.sysPrimitiveParseFloat(MemoryManager.cloneToNativeBuffer(b));
   }
 
   /**
@@ -779,7 +788,7 @@
    */
   public static int primitiveParseInt(String arg) {
     byte[] b = stringToBytes("integer or byte", arg);
-    return sysCall.sysPrimitiveParseInt(b);
+    return sysCall.sysPrimitiveParseInt(MemoryManager.cloneToNativeBuffer(b));
   }
 
   /**
@@ -856,8 +865,8 @@
   }
 
   /** Convenience method for calling stringToBytes */
-  private static byte[] s2b(String arg) {
-    return stringToBytes(null, arg);
+  private static WordArray s2b(String arg) {
+    return MemoryManager.cloneToNativeBuffer(stringToBytes(null, arg));
   }
 
   /** Convert the string s (the "argument") to a null-terminated byte array.
diff -r 743a2cc2ed20 -r 058fdc3780ba rvm/src/org/jikesrvm/Services.java
--- a/rvm/src/org/jikesrvm/Services.java	Tue Aug 04 11:04:15 2009 +1000
+++ b/rvm/src/org/jikesrvm/Services.java	Mon Nov 16 09:21:21 2009 +1100
@@ -156,7 +156,7 @@
    */
   public static int sprintf(char[] dest, int destOffset, char[] src, int srcStart, int srcEnd) {
     for (int i = srcStart; i < srcEnd; ++i) {
-      char nextChar = getArrayNoBarrier(src, i);
+      char nextChar = getArrayNoGCBarrier(src, i);
       destOffset = sprintf(dest, destOffset, nextChar);
     }
     return destOffset;
@@ -169,7 +169,7 @@
     }
 
     if (destOffset < dest.length) {
-      setArrayNoBarrier(dest, destOffset, c);
+      setArrayNoGCBarrier(dest, destOffset, c);
     }
     return destOffset + 1;
   }
@@ -210,19 +210,19 @@
     char[] intBuffer = grabIntBuffer();
 
     nextDigit = (int) (l % 10);
-    nextChar = getArrayNoBarrier(hexDigitCharacter, negative ? -nextDigit : nextDigit);
-    setArrayNoBarrier(intBuffer, index--, nextChar);
+    nextChar = getArrayNoGCBarrier(hexDigitCharacter, negative ? -nextDigit : nextDigit);
+    setArrayNoGCBarrier(intBuffer, index--, nextChar);
     l = l / 10;
 
     while (l != 0) {
       nextDigit = (int) (l % 10);
-      nextChar = getArrayNoBarrier(hexDigitCharacter, negative ? -nextDigit : nextDigit);
-      setArrayNoBarrier(intBuffer, index--, nextChar);
+      nextChar = getArrayNoGCBarrier(hexDigitCharacter, negative ? -nextDigit : nextDigit);
+      setArrayNoGCBarrier(intBuffer, index--, nextChar);
       l = l / 10;
     }
 
     if (negative) {
-     setArrayNoBarrier(intBuffer, index--, '-');
+     setArrayNoGCBarrier(intBuffer, index--, '-');
     }
 
     int newOffset = sprintf(dest, offset, intBuffer, index + 1, INT_BUFFER_SIZE);
@@ -346,7 +346,7 @@
   }
 
   /**
-   * Sets an element of a char array without invoking any write
+   * Sets an element of a char array without invoking any GC write
    * barrier.  This method is called by the Log method, as it will be
    * used during garbage collection and needs to manipulate character
    * arrays without causing a write barrier operation.
@@ -355,22 +355,25 @@
    * @param index the index of the element to set
    * @param value the new value for the element
    */
-  public static void setArrayNoBarrier(char[] dst, int index, char value) {
-    if (VM.runningVM)
-      Magic.setCharAtOffset(dst, Offset.fromIntZeroExtend(index << LOG_BYTES_IN_CHAR), value);
-    else
+  public static void setArrayNoGCBarrier(char[] dst, int index, char value) {
+    if (VM.runningVM) {
+      if (MemoryManagerConstants.USE_PRIMITIVE_CHAR_ARRAYLETS)
+	MemoryManager.arrayStorePrimitiveCharWriteBarrier(dst, index, value); 
+      else
+        Magic.setCharAtOffset(dst, Offset.fromIntZeroExtend(index << LOG_BYTES_IN_CHAR), value);
+    } else
       dst[index] = value;
   }
 
   /**
-   * Gets an element of an Object array without invoking any read
+   * Gets an element of an Object array without invoking any GC read
    * barrier or performing bounds checks.
    *
    * @param src the source array
    * @param index the natural array index of the element to get
    * @return the new value of element
    */
-  public static Object getArrayNoBarrier(Object[] src, int index) {
+  public static Object getArrayNoGCBarrier(Object[] src, int index) {
     if (VM.runningVM)
       return Magic.getObjectAtOffset(src, Offset.fromIntZeroExtend(index << LOG_BYTES_IN_ADDRESS));
     else
@@ -385,9 +388,13 @@
    * @param index the natural array index of the element to get
    * @return the new value of element
    */
-  public static int getArrayNoBarrier(int[] src, int index) {
+  public static int getArrayNoGCBarrier(int[] src, int index) {
     if (VM.runningVM)
-      return Magic.getIntAtOffset(src, Offset.fromIntZeroExtend(index << LOG_BYTES_IN_INT));
+      if (MemoryManagerConstants.USE_PRIMITIVE_INT_ARRAYLETS) {
+        return MemoryManager.arrayLoadPrimitiveIntReadBarrier(src, index);
+      } else {
+        return Magic.getIntAtOffset(src, Offset.fromIntZeroExtend(index << LOG_BYTES_IN_INT));
+      }
     else
       return src[index];
   }
@@ -400,9 +407,13 @@
    * @param index the natural array index of the element to get
    * @return the new value of element
    */
-  public static char getArrayNoBarrier(char[] src, int index) {
+  public static char getArrayNoGCBarrier(char[] src, int index) {
     if (VM.runningVM)
-      return Magic.getCharAtOffset(src, Offset.fromIntZeroExtend(index << LOG_BYTES_IN_CHAR));
+      if (MemoryManagerConstants.USE_PRIMITIVE_CHAR_ARRAYLETS) {
+        return MemoryManager.arrayLoadPrimitiveCharReadBarrier(src, index); //jbs changed
+      } else {
+        return Magic.getCharAtOffset(src, Offset.fromIntZeroExtend(index << LOG_BYTES_IN_CHAR));
+      }
     else
       return src[index];
   }
@@ -415,7 +426,7 @@
    * @param index the natural array index of the element to get
    * @return the new value of element
    */
-  public static byte getArrayNoBarrier(byte[] src, int index) {
+  public static byte getArrayNoGCBarrier(byte[] src, int index) {
     if (VM.runningVM)
       return Magic.getByteAtOffset(src, Offset.fromIntZeroExtend(index));
     else
@@ -430,7 +441,7 @@
    * @param index the index of the element to get
    * @return the new value of element
    */
-  public static byte[] getArrayNoBarrier(byte[][] src, int index) {
+  public static byte[] getArrayNoGCBarrier(byte[][] src, int index) {
     if (VM.runningVM)
       return Magic.addressAsByteArray(Magic.objectAsAddress(Magic.getObjectAtOffset(src, Offset.fromIntZeroExtend(index << LOG_BYTES_IN_ADDRESS))));
     else
diff -r 743a2cc2ed20 -r 058fdc3780ba rvm/src/org/jikesrvm/VM.java
--- a/rvm/src/org/jikesrvm/VM.java	Tue Aug 04 11:04:15 2009 +1000
+++ b/rvm/src/org/jikesrvm/VM.java	Mon Nov 16 09:21:21 2009 +1100
@@ -29,6 +29,7 @@
 import org.jikesrvm.compilers.common.BootImageCompiler;
 import org.jikesrvm.compilers.common.RuntimeCompiler;
 import org.jikesrvm.mm.mminterface.MemoryManager;
+import org.jikesrvm.mm.mminterface.MemoryManagerConstants;
 import org.jikesrvm.runtime.BootRecord;
 import org.jikesrvm.runtime.DynamicLibrary;
 import org.jikesrvm.runtime.Entrypoints;
@@ -796,7 +797,12 @@
          *
          *  TODO: Convert this to use org.mmtk.vm.Barriers.getArrayNoBarrier
          */ {
-        write(Magic.getCharAtOffset(value, Offset.fromIntZeroExtend(i << LOG_BYTES_IN_CHAR)));
+        //jbs changed so doesn't use getCharAtOffset
+        if (MemoryManagerConstants.USE_PRIMITIVE_CHAR_ARRAYLETS) {
+          write(MemoryManager.arrayLoadPrimitiveCharReadBarrier(value, i));
+        } else {
+          write(Magic.getCharAtOffset(value, Offset.fromIntZeroExtend(i << LOG_BYTES_IN_CHAR)));
+        }
       } else {
         write(value[i]);
       }
diff -r 743a2cc2ed20 -r 058fdc3780ba rvm/src/org/jikesrvm/classloader/DynamicTypeCheck.java
--- a/rvm/src/org/jikesrvm/classloader/DynamicTypeCheck.java	Tue Aug 04 11:04:15 2009 +1000
+++ b/rvm/src/org/jikesrvm/classloader/DynamicTypeCheck.java	Mon Nov 16 09:21:21 2009 +1100
@@ -16,8 +16,8 @@
 import org.jikesrvm.mm.mminterface.MemoryManager;
 import org.jikesrvm.objectmodel.TIB;
 import org.jikesrvm.objectmodel.TIBLayoutConstants;
-import org.jikesrvm.runtime.Magic;
 import org.vmmagic.pragma.Uninterruptible;
+import org.vmmagic.unboxed.WordArray;
 
 /**
  * Data structures and code for fast dynamic type checking.
@@ -106,33 +106,33 @@
    * @param t a RVMType to create a superclass Id vector for
    * @return the superclass Id vector
    */
-  static short[] buildSuperclassIds(RVMType t) {
+  static WordArray buildSuperclassIds(RVMType t) {
     int depth = t.getTypeDepth();
-    short[] tsi;
+    WordArray tsi;
     if (t.isJavaLangObjectType()) {
       if (VM.VerifyAssertions) VM._assert(depth == 0);
-      tsi = MemoryManager.newNonMovingShortArray(1);
+      tsi = MemoryManager.createNonMovingNativeCharBuffer(1);
     } else {
       int size = MIN_SUPERCLASS_IDS_SIZE <= depth ? depth + 1 : MIN_SUPERCLASS_IDS_SIZE;
-      tsi = MemoryManager.newNonMovingShortArray(size);
+      tsi = MemoryManager.createNonMovingNativeCharBuffer(size);
       RVMType p;
       if (t.isArrayType() || t.asClass().isInterface()) {
         p = RVMType.JavaLangObjectType;
       } else {
         p = t.asClass().getSuperClass();
       }
-      short[] psi = p.getSuperclassIds();
+      WordArray psi = p.getSuperclassIds();
       for (int i = 0; i < depth; i++) {
-        tsi[i] = psi[i];
+        tsi.setChar(i, psi.getChar(i));
       }
     }
     int id = t.getId();
     if (VM.VerifyAssertions) VM._assert(id <= 0xFFFF); // when this fails, make superclassIds int[]
-    tsi[depth] = (short) id;
+    tsi.setChar(depth, (char) id);
     return tsi;
   }
 
-  private static int[] arrayDoesImplement;
+  private static WordArray arrayDoesImplement;
 
   /**
    * Create the doesImplement vector for a RVMArray.
@@ -141,15 +141,15 @@
    * @param t a RVMArray to create a doesImplement vector for
    * @return the doesImplement vector
    */
-  static int[] buildDoesImplement(RVMArray t) {
+  static WordArray buildDoesImplement(RVMArray t) {
     if (arrayDoesImplement == null) {
       int cloneIdx = RVMType.JavaLangCloneableType.getDoesImplementIndex();
       int serialIdx = RVMType.JavaIoSerializableType.getDoesImplementIndex();
       int size = Math.max(cloneIdx, serialIdx);
       size = Math.max(MIN_DOES_IMPLEMENT_SIZE, size + 1);
-      int[] tmp = MemoryManager.newNonMovingIntArray(size);
-      tmp[cloneIdx] = RVMType.JavaLangCloneableType.getDoesImplementBitMask();
-      tmp[serialIdx] |= RVMType.JavaIoSerializableType.getDoesImplementBitMask();
+      WordArray tmp = MemoryManager.createNonMovingNativeIntBuffer(size);
+      tmp.setInt(cloneIdx, RVMType.JavaLangCloneableType.getDoesImplementBitMask());
+      tmp.setInt(serialIdx, tmp.getInt(serialIdx) | RVMType.JavaIoSerializableType.getDoesImplementBitMask());
       arrayDoesImplement = tmp;
     }
     return arrayDoesImplement;
@@ -161,10 +161,10 @@
    * @param t a RVMClass to create a doesImplement vector for
    * @return the doesImplement vector
    */
-  static int[] buildDoesImplement(RVMClass t) {
+  static WordArray buildDoesImplement(RVMClass t) {
     if (t.isJavaLangObjectType()) {
       // object implements no interfaces.
-      return MemoryManager.newNonMovingIntArray(MIN_DOES_IMPLEMENT_SIZE);
+      return MemoryManager.createNonMovingNativeIntBuffer(MIN_DOES_IMPLEMENT_SIZE);
     }
 
     RVMClass[] superInterfaces = t.getDeclaredInterfaces();
@@ -179,26 +179,26 @@
     if (t.isInterface()) {
       size = Math.max(MIN_DOES_IMPLEMENT_SIZE, t.getDoesImplementIndex() + 1);
     } else {
-      size = t.getSuperClass().getDoesImplement().length;
+      size = MemoryManager.nativeIntBufferLength(t.getSuperClass().getDoesImplement());
     }
     for (RVMClass superInterface : superInterfaces) {
-      size = Math.max(size, superInterface.getDoesImplement().length);
+      size = Math.max(size, MemoryManager.nativeIntBufferLength(superInterface.getDoesImplement()));
     }
 
     // then create and populate it
-    int[] mine = MemoryManager.newNonMovingIntArray(size);
+    WordArray mine = MemoryManager.createNonMovingNativeIntBuffer(size);
     if (t.isInterface()) {
-      mine[t.getDoesImplementIndex()] = t.getDoesImplementBitMask();
+      mine.setInt(t.getDoesImplementIndex(), t.getDoesImplementBitMask());
     } else {
-      int[] parent = t.getSuperClass().getDoesImplement();
-      for (int j = 0; j < parent.length; j++) {
-        mine[j] |= parent[j];
+      WordArray parent = t.getSuperClass().getDoesImplement();
+      for (int j = 0; j < MemoryManager.nativeIntBufferLength(parent); j++) {
+        mine.setInt(j, mine.getInt(j) | parent.getInt(j));
       }
     }
     for (RVMClass superInterface : superInterfaces) {
-      int[] parent = superInterface.getDoesImplement();
-      for (int j = 0; j < parent.length; j++) {
-        mine[j] |= parent[j];
+      WordArray parent = superInterface.getDoesImplement();
+      for (int j = 0; j < MemoryManager.nativeIntBufferLength(parent); j++) {
+        mine.setInt(j, mine.getInt(j) | parent.getInt(j));
       }
     }
 
@@ -237,11 +237,11 @@
       VM._assert(rhsTIB != null);
       VM._assert(rhsTIB.getSuperclassIds() != null);
     }
-    short[] superclassIds = Magic.objectAsShortArray(rhsTIB.getSuperclassIds());
+    WordArray superclassIds = rhsTIB.getSuperclassIds();
     int LHSDepth = LHSclass.getTypeDepth();
-    if (LHSDepth >= superclassIds.length) return false;
+    if (LHSDepth >= MemoryManager.nativeCharBufferLength(superclassIds)) return false;
     int LHSId = LHSclass.getId();
-    return superclassIds[LHSDepth] == LHSId;
+    return superclassIds.getChar(LHSDepth) == LHSId;
   }
 
   /**
@@ -254,10 +254,10 @@
    *         or <code>false</code> if it is not
    */
   public static boolean instanceOfInterface(RVMClass LHSclass, TIB rhsTIB) {
-    int[] doesImplement = rhsTIB.getDoesImplement();
+    WordArray doesImplement = rhsTIB.getDoesImplement();
     int idx = LHSclass.getDoesImplementIndex();
     int mask = LHSclass.getDoesImplementBitMask();
-    return idx < doesImplement.length && ((doesImplement[idx] & mask) != 0);
+    return idx < MemoryManager.nativeIntBufferLength(doesImplement) && ((doesImplement.getInt(idx) & mask) != 0);
   }
 
   /**
diff -r 743a2cc2ed20 -r 058fdc3780ba rvm/src/org/jikesrvm/classloader/RVMArray.java
--- a/rvm/src/org/jikesrvm/classloader/RVMArray.java	Tue Aug 04 11:04:15 2009 +1000
+++ b/rvm/src/org/jikesrvm/classloader/RVMArray.java	Mon Nov 16 09:21:21 2009 +1100
@@ -12,6 +12,8 @@
  */
 package org.jikesrvm.classloader;
 
+import static org.jikesrvm.mm.mminterface.MemoryManagerConstants.*; 
+
 import org.jikesrvm.ArchitectureSpecific;
 import org.jikesrvm.VM;
 import org.jikesrvm.Constants;
@@ -23,13 +25,23 @@
 import org.jikesrvm.runtime.Memory;
 import org.jikesrvm.runtime.RuntimeEntrypoints;
 import org.jikesrvm.runtime.Statics;
+import org.jikesrvm.scheduler.Scheduler;
+import org.mmtk.plan.Plan;
+import org.mmtk.plan.generational.Gen;
+import org.mmtk.policy.Space;
+import org.mmtk.policy.arraylet.Arraylet;
 import org.vmmagic.pragma.Entrypoint;
 import org.vmmagic.pragma.Inline;
 import org.vmmagic.pragma.NoInline;
 import org.vmmagic.pragma.NonMoving;
 import org.vmmagic.pragma.Pure;
 import org.vmmagic.pragma.Uninterruptible;
+import org.vmmagic.unboxed.Address;
+import org.vmmagic.unboxed.Extent;
+import org.vmmagic.unboxed.ObjectReference;
 import org.vmmagic.unboxed.Offset;
+import org.vmmagic.unboxed.Word;
+import org.vmmagic.unboxed.WordArray;
 
 /**
  * Description of a java "array" type. <p>
@@ -44,6 +56,9 @@
 @NonMoving
 public final class RVMArray extends RVMType implements Constants, ClassLoaderConstants {
 
+	
+	//jbs added for debugging
+	//private static int arrayCopyCounter = 0;
   /*
    * We hold on to a number of commonly used arrays for easy access.
    */
@@ -55,6 +70,7 @@
   public static final RVMArray LongArray;
   public static final RVMArray FloatArray;
   public static final RVMArray DoubleArray;
+  public static final RVMArray WordArray;
   public static final RVMArray JavaLangObjectArray;
 
   static {
@@ -66,6 +82,7 @@
     ShortArray = (RVMArray) TypeReference.ShortArray.resolve();
     IntArray = (RVMArray) TypeReference.IntArray.resolve();
     LongArray = (RVMArray) TypeReference.LongArray.resolve();
+    WordArray = (RVMArray) TypeReference.WordArray.resolve();
     JavaLangObjectArray = (RVMArray) TypeReference.JavaLangObjectArray.resolve();
   }
 
@@ -99,6 +116,14 @@
   private final int alignment;
 
   /**
+   * Are instances of this type arrayletized? 
+   */
+  private final boolean arrayletized;
+
+  @Uninterruptible                                                                                                                          
+  public boolean isArrayletizable() { return arrayletized; } 
+
+  /**
    * Reference Count GC: is this type acyclic?
    */
   private final boolean acyclic;
@@ -181,6 +206,46 @@
   }
 
   /**
+   * The number of elements that are inlined into the spine.
+   */
+  @Uninterruptible
+  public int getFirstNElements() {
+    if (VM.VerifyAssertions) {
+      VM._assert(arrayletized);
+    }
+    if (elementType == RVMType.BooleanType) {
+      return MemoryManagerConstants.FIRSTN_BOOLEAN_ELEMS;
+    } else if (elementType == RVMType.ByteType) {
+      return MemoryManagerConstants.FIRSTN_BYTE_ELEMS;
+    } else if (elementType == RVMType.CharType) {
+      return MemoryManagerConstants.FIRSTN_CHAR_ELEMS;
+    } else if (elementType == RVMType.ShortType) {
+      return MemoryManagerConstants.FIRSTN_SHORT_ELEMS;
+    } else if (elementType == RVMType.IntType) {
+      return MemoryManagerConstants.FIRSTN_INT_ELEMS;
+    } else if (elementType == RVMType.LongType) {
+      return MemoryManagerConstants.FIRSTN_LONG_ELEMS;
+    } else if (elementType == RVMType.FloatType) {
+      return MemoryManagerConstants.FIRSTN_FLOAT_ELEMS;
+    } else if (elementType == RVMType.DoubleType) {
+      return MemoryManagerConstants.FIRSTN_DOUBLE_ELEMS;
+    } else {
+      return MemoryManagerConstants.FIRSTN_REF_ELEMS;
+    }
+  }
+
+  /**
+   * The number of elements in each arraylet.
+   */
+  @Uninterruptible
+  public int getLogArrayletElements() {
+    if (VM.VerifyAssertions) {
+      VM._assert(arrayletized);
+    }
+    return MemoryManagerConstants.LOG_ARRAYLET_BYTES - getLogElementSize();
+  }
+
+  /**
    * Calculate the size, in bytes, of an array element, log base 2.
    * @return log base 2 of array element size
    */
@@ -223,9 +288,56 @@
   @Pure
   @Uninterruptible
   public int getInstanceSize(int numelts) {
+    final int headerBytes = ObjectModel.computeArrayHeaderSize(this);
+    if (arrayletized) {
+      int firstN = getFirstNElements();
+      int logArrayletElements = getLogArrayletElements();
+      int arrayletizedElements = numelts - firstN;
+      if (arrayletizedElements > 0) {
+        int arrayletCount =  1 + (arrayletizedElements >> logArrayletElements);
+        int spineBytes = arrayletCount<<LOG_BYTES_IN_ADDRESS;
+        int danglingElements = arrayletizedElements & ((1<<logArrayletElements) - 1);
+        return headerBytes + spineBytes + ((firstN + danglingElements)<<getLogElementSize());
+      }
+    }
+    return headerBytes + (numelts << getLogElementSize());
+  }
+
+  @Inline
+  @Pure
+  @Uninterruptible
+  public int getContiguousInstanceSize(int numelts) {
     return ObjectModel.computeArrayHeaderSize(this) + (numelts << getLogElementSize());
   }
 
+  @Inline
+  @Pure
+  @Uninterruptible
+  public int getBootImageContiguousInstanceSize(int numelts) {
+    int size = 0;                                                                                                                           
+    if (MemoryManagerConstants.BOOT_IMAGE_IS_ARRAYLETIZED && arrayletized) {
+      int curr_firstN_value = FIRSTN_INT_ELEMS;
+      int curr_logArrayletElems = LOG_ELEMENTS_IN_INT_ARRAYLET;
+      if (getElementType().isShortType() || getElementType().isCharType()) {
+        curr_firstN_value = FIRSTN_SHORT_ELEMS;
+        curr_logArrayletElems = LOG_ELEMENTS_IN_SHORT_ARRAYLET;
+      } else if (getElementType().isLongType() || getElementType().isDoubleType()) {
+        curr_firstN_value = MemoryManagerConstants.FIRSTN_LONG_ELEMS;
+        curr_logArrayletElems = MemoryManagerConstants.LOG_ELEMENTS_IN_LONG_ARRAYLET;
+      } else if (getElementType().isByteType() || getElementType().isBooleanType()) {
+        curr_firstN_value = MemoryManagerConstants.FIRSTN_BYTE_ELEMS;
+        curr_logArrayletElems = MemoryManagerConstants.LOG_ELEMENTS_IN_BYTE_ARRAYLET;
+      }
+      int arrayletizedElements = numelts - curr_firstN_value; //FIRSTN_VALUE;                                                                                    
+      if (arrayletizedElements > 0) { 
+        int numArraylets = 1 + (arrayletizedElements >>> curr_logArrayletElems); //LOG_ELEMENTS_IN_ARRAYLET);                                                         
+        size = numArraylets<<LOG_BYTES_IN_ADDRESS; 
+      }                                                                                                                                     
+    }                                                                                                                                       
+    size += ObjectModel.computeArrayHeaderSize(this) + (numelts << getLogElementSize());                                                    
+    return size; 
+  }
+
   /**
    * Does this class override java.lang.Object.finalize()?
    */
@@ -423,6 +535,17 @@
     super(typeRef, typeRef.getDimensionality(), null);
     this.elementType = elementType;
     this.logElementSize = computeLogElementSize();
+    
+    this.arrayletized = !getTypeRef().isUnboxedArrayType() &&
+       ((USE_REFERENCE_ARRAYLETS && !elementType.isPrimitiveType()) || 
+        (USE_PRIMITIVE_SHORT_ARRAYLETS && getElementType().isShortType()) || 
+        (USE_PRIMITIVE_CHAR_ARRAYLETS && getElementType().isCharType()) || 
+        (USE_PRIMITIVE_LONG_ARRAYLETS && getElementType().isLongType()) || 
+        (USE_PRIMITIVE_DOUBLE_ARRAYLETS && getElementType().isDoubleType()) || 
+        (USE_PRIMITIVE_BYTE_ARRAYLETS && getElementType().isByteType()) || 
+        (USE_PRIMITIVE_BOOLEAN_ARRAYLETS && getElementType().isBooleanType()) || 
+        (USE_PRIMITIVE_INT_ARRAYLETS && getElementType().isIntType()) || 
+        (USE_PRIMITIVE_FLOAT_ARRAYLETS && getElementType().isFloatType())); 
     depth = 1;
 
     if (elementType.isArrayType()) {
@@ -487,7 +610,7 @@
    * @param doesImplement The calculated does implement array
    */
   @Uninterruptible
-  private void publishResolved(TIB allocatedTib, short[] superclassIds, int[] doesImplement) {
+  private void publishResolved(TIB allocatedTib, WordArray superclassIds, WordArray doesImplement) {
     Statics.setSlotContents(getTibOffset(), allocatedTib);
     allocatedTib.setType(this);
     allocatedTib.setSuperclassIds(superclassIds);
@@ -605,13 +728,26 @@
         (dstIdx + len) >= 0 &&
         (dstIdx + len) <= dst.length) {
       if (src != dst || srcIdx >= (dstIdx + BYTES_IN_ADDRESS)) {
-        Memory.arraycopy8Bit(src, srcIdx, dst, dstIdx, len);
+        if (USE_PRIMITIVE_BYTE_ARRAYLETS) {
+          if (!FAST_ARRAY_COPY) {
+            while (len-- != 0)
+              dst[dstIdx++] = src[srcIdx++];
+          } else
+            fastArrayletCopy(src, srcIdx, dst, dstIdx, len, false, DO_COPY_ON_WRITE_BYTE_ARRAYS, LOG_BYTES_IN_BYTE, FIRSTN_BYTE_ELEMS, LOG_ELEMENTS_IN_BYTE_ARRAYLET);
+        } else {
+          Memory.arraycopy8Bit(src, srcIdx, dst, dstIdx, len);
+        }
       } else {
         arraycopyOverlap(src, srcIdx, dst, dstIdx, len);
       }
     } else {
       failWithIndexOutOfBoundsException();
     }
+    //VM.sysWrite(" In arraycopy for bytes, copying length "); VM.sysWriteln(len);
+    if (MemoryManagerConstants.DO_COLLECT_SPACE_SAVING_STATS) {
+    	MemoryManagerConstants.NUM_PRIM_BYTES_ARRAYCOPY += (len); // * BYTES_IN_BYTE);
+    	MemoryManagerConstants.NUM_BYTE_ARRAYS_BYTES_COPIED += len;
+    }
   }
 
   // Outlined unlikely case of potentially overlapping subarrays
@@ -630,7 +766,74 @@
       }
     }
   }
+  
+  @Inline
+  @Uninterruptible
+  private static Address taintArraylet(Object array, int offset, int firstNBytes) {
+    if (VM.VerifyAssertions) VM._assert(offset >= firstNBytes);
+    int arrayletNumber = (offset - firstNBytes) >> LOG_ARRAYLET_BYTES;
+	  Offset arrayletPtrOffset = Offset.fromIntZeroExtend(firstNBytes + (arrayletNumber << LOG_BYTES_IN_ADDRESS));
+	  Address arraylet = Magic.getWordAtOffset(array, arrayletPtrOffset).toAddress();
 
+	  boolean isTainted = arraylet.toWord().and(MemoryManagerConstants.ARRAYLET_TAINT_WORD).NE(Word.zero());
+	  if (!isTainted) {
+	    if (MemoryManagerConstants.ENABLE_COW_ARRAYLET_INCOMING_PTR) {
+	      Arraylet.addIncomingPointer(arraylet);
+	    }
+	    arraylet = arraylet.plus(MemoryManagerConstants.ARRAYLET_TAINT_WORD.toExtent());
+	    Magic.setWordAtOffset(array, arrayletPtrOffset, arraylet.toWord());
+	  } else {
+	    if (MemoryManagerConstants.ENABLE_COW_ARRAYLET_INCOMING_PTR) {
+	      Arraylet.addIncomingPointer(arraylet.toWord().and(MemoryManagerConstants.ARRAYLET_TAINT_MASK).toAddress());
+	    }
+	  }
+	  return arraylet;
+  }
+  
+  @Inline
+  @Uninterruptible
+  private static void setArrayletPtr(Object array, int offset, Address newValue, int firstNBytes) {
+    if (VM.VerifyAssertions) VM._assert(offset >= firstNBytes);
+    int arrayletNumber = (offset - firstNBytes) >> LOG_ARRAYLET_BYTES;
+	  Offset arrayletPtrOffset = Offset.fromIntZeroExtend(firstNBytes + (arrayletNumber << LOG_BYTES_IN_ADDRESS));
+	  Magic.setWordAtOffset(array, arrayletPtrOffset, newValue.toWord());
+  }   
+
+  @Inline
+  @Uninterruptible
+  private static boolean isArraylet(Object array, int offset, int firstNBytes) {
+    return (offset >= firstNBytes);
+  }
+
+  @Inline
+  @Uninterruptible
+  private static Address getArrayletSlot(boolean isArraylet, Object array, int offset, boolean ensureWritable, boolean doCow, int firstNBytes) {
+    if (!isArraylet) {
+      return ObjectReference.fromObject(array).toAddress().plus(offset);
+    }
+    int arrayletNumber = (offset - firstNBytes) >> LOG_ARRAYLET_BYTES;
+    Offset arrayletPtrOffset = Offset.fromIntZeroExtend(firstNBytes + (arrayletNumber << LOG_BYTES_IN_ADDRESS));
+    Address arraylet = Magic.getWordAtOffset(array, arrayletPtrOffset).toAddress();
+    if (ensureWritable) {
+      // Ensure that the arraylet is writable
+      boolean isTainted = false;
+      if (doCow) {
+        isTainted = arraylet.toWord().and(MemoryManagerConstants.ARRAYLET_TAINT_WORD).NE(Word.zero());
+        if (isTainted) {
+          arraylet = MemoryManager.arrayletStoreTainted(array, arrayletPtrOffset, arraylet);
+        }
+      }
+      if (USE_ZERO_ARRAYLETS && !isTainted && arraylet.EQ(Magic.objectAsAddress(ObjectModel.zeroArraylet))) {
+        arraylet = MemoryManager.lazyAllocateArraylet(array, arrayletPtrOffset);
+      }
+    } else {
+      if (doCow) {
+        arraylet = arraylet.toWord().and(MemoryManagerConstants.ARRAYLET_TAINT_MASK).toAddress();
+      }
+    }
+    return arraylet.plus((offset - firstNBytes) & ((1 << LOG_ARRAYLET_BYTES) - 1));
+  }
+  
   /**
    * Perform an array copy for arrays of booleans.
    *
@@ -652,13 +855,26 @@
         (dstIdx + len) >= 0 &&
         (dstIdx + len) <= dst.length) {
       if (src != dst || srcIdx >= (dstIdx + BYTES_IN_ADDRESS / BYTES_IN_BOOLEAN)) {
-        Memory.arraycopy8Bit(src, srcIdx, dst, dstIdx, len);
+        if (USE_PRIMITIVE_BOOLEAN_ARRAYLETS) {
+          if (!FAST_ARRAY_COPY) {
+            while (len-- != 0)
+              dst[dstIdx++] = src[srcIdx++];
+          } else
+            fastArrayletCopy(src, srcIdx, dst, dstIdx, len, false, DO_COPY_ON_WRITE_BOOLEAN_ARRAYS, LOG_BYTES_IN_BOOLEAN, FIRSTN_BOOLEAN_ELEMS, LOG_ELEMENTS_IN_BOOLEAN_ARRAYLET);
+        } else {
+          Memory.arraycopy8Bit(src, srcIdx, dst, dstIdx, len);
+        }
       } else {
         arraycopyOverlap(src, srcIdx, dst, dstIdx, len);
       }
     } else {
       failWithIndexOutOfBoundsException();
     }
+    if (MemoryManagerConstants.DO_COLLECT_SPACE_SAVING_STATS) {
+    	MemoryManagerConstants.NUM_PRIM_BYTES_ARRAYCOPY += (len * BYTES_IN_BOOLEAN);
+
+    	MemoryManagerConstants.NUM_BOOLEAN_ARRAYS_BYTES_COPIED += (len * BYTES_IN_BOOLEAN);
+    }
   }
 
   // Outlined unlikely case of potentially overlapping subarrays
@@ -698,14 +914,28 @@
         (srcIdx + len) <= src.length &&
         (dstIdx + len) >= 0 &&
         (dstIdx + len) <= dst.length) {
+
       if (src != dst || srcIdx >= (dstIdx + BYTES_IN_ADDRESS / BYTES_IN_SHORT)) {
-        Memory.arraycopy16Bit(src, srcIdx, dst, dstIdx, len);
+        if (USE_PRIMITIVE_SHORT_ARRAYLETS) {
+          if (!FAST_ARRAY_COPY) {
+            while (len-- != 0)
+              dst[dstIdx++] = src[srcIdx++];
+          } else
+            fastArrayletCopy(src, srcIdx, dst, dstIdx, len, false, DO_COPY_ON_WRITE_SHORT_ARRAYS, LOG_BYTES_IN_SHORT, FIRSTN_SHORT_ELEMS, LOG_ELEMENTS_IN_SHORT_ARRAYLET);
+        } else {
+          Memory.arraycopy16Bit(src, srcIdx, dst, dstIdx, len);
+        }
       } else {
         arraycopyOverlap(src, srcIdx, dst, dstIdx, len);
       }
     } else {
       failWithIndexOutOfBoundsException();
     }
+    VM.sysWrite("Copying short array of length "); VM.sysWriteln(len);
+    if (MemoryManagerConstants.DO_COLLECT_SPACE_SAVING_STATS) {
+    	MemoryManagerConstants.NUM_PRIM_BYTES_ARRAYCOPY += (len * BYTES_IN_SHORT);
+    	MemoryManagerConstants.NUM_SHORT_ARRAYS_BYTES_COPIED += (len * BYTES_IN_SHORT);
+    }
   }
 
   // Outlined unlikely case of potentially overlapping subarrays
@@ -746,13 +976,25 @@
         (dstIdx + len) >= 0 &&
         (dstIdx + len) <= dst.length) {
       if (src != dst || srcIdx >= (dstIdx + BYTES_IN_ADDRESS / BYTES_IN_CHAR)) {
-        Memory.arraycopy16Bit(src, srcIdx, dst, dstIdx, len);
+        if (USE_PRIMITIVE_CHAR_ARRAYLETS) {
+          if (!FAST_ARRAY_COPY) {
+            while (len-- != 0)
+              dst[dstIdx++] = src[srcIdx++];
+          } else
+            fastArrayletCopy(src, srcIdx, dst, dstIdx, len, false, DO_COPY_ON_WRITE_CHAR_ARRAYS, LOG_BYTES_IN_CHAR, FIRSTN_CHAR_ELEMS, LOG_ELEMENTS_IN_CHAR_ARRAYLET);
+        } else {
+          Memory.arraycopy16Bit(src, srcIdx, dst, dstIdx, len);
+        }
       } else {
         arraycopyOverlap(src, srcIdx, dst, dstIdx, len);
       }
     } else {
       failWithIndexOutOfBoundsException();
     }
+    if (MemoryManagerConstants.DO_COLLECT_SPACE_SAVING_STATS) {
+    	MemoryManagerConstants.NUM_PRIM_BYTES_ARRAYCOPY += (len * BYTES_IN_CHAR);
+    	MemoryManagerConstants.NUM_CHAR_ARRAYS_BYTES_COPIED += (len * BYTES_IN_CHAR);
+    }
   }
 
   // Outlined unlikely case of potentially overlapping subarrays
@@ -771,7 +1013,7 @@
       }
     }
   }
-
+  
   /**
    * Perform an array copy for arrays of ints.
    *
@@ -793,13 +1035,25 @@
         (dstIdx + len) >= 0 &&
         (dstIdx + len) <= dst.length) {
       if (src != dst || srcIdx >= dstIdx) {
-        Memory.arraycopy32Bit(src, srcIdx, dst, dstIdx, len);
+        if (USE_PRIMITIVE_INT_ARRAYLETS) {
+          if (!FAST_ARRAY_COPY) {
+            while (len-- != 0)
+            dst[dstIdx++] = src[srcIdx++];
+          } else 
+            fastArrayletCopy(src, srcIdx, dst, dstIdx, len, false, DO_COPY_ON_WRITE_INT_ARRAYS, LOG_BYTES_IN_INT, FIRSTN_INT_ELEMS, LOG_ELEMENTS_IN_INT_ARRAYLET);
+        } else {
+          Memory.arraycopy32Bit(src, srcIdx, dst, dstIdx, len);
+        }
       } else {
         arraycopyOverlap(src, srcIdx, dst, dstIdx, len);
       }
     } else {
       failWithIndexOutOfBoundsException();
     }
+    if (MemoryManagerConstants.DO_COLLECT_SPACE_SAVING_STATS) {
+    	MemoryManagerConstants.NUM_PRIM_BYTES_ARRAYCOPY += (len * BYTES_IN_INT);
+    	MemoryManagerConstants.NUM_INT_ARRAYS_BYTES_COPIED += (len * BYTES_IN_INT);
+    }
   }
 
   // Outlined unlikely case of potentially overlapping subarrays
@@ -840,13 +1094,26 @@
         (dstIdx + len) >= 0 &&
         (dstIdx + len) <= dst.length) {
       if (src != dst || srcIdx > dstIdx) {
-        Memory.arraycopy32Bit(src, srcIdx, dst, dstIdx, len);
+        if (USE_PRIMITIVE_FLOAT_ARRAYLETS) {
+          if (!FAST_ARRAY_COPY) {
+            while (len-- != 0)
+              dst[dstIdx++] = src[srcIdx++];
+          } else 
+            fastArrayletCopy(src, srcIdx, dst, dstIdx, len, false, DO_COPY_ON_WRITE_FLOAT_ARRAYS, LOG_BYTES_IN_FLOAT, FIRSTN_FLOAT_ELEMS, LOG_ELEMENTS_IN_FLOAT_ARRAYLET);
+        } else {
+          Memory.arraycopy32Bit(src, srcIdx, dst, dstIdx, len);
+        }
       } else {
         arraycopyOverlap(src, srcIdx, dst, dstIdx, len);
       }
     } else {
       failWithIndexOutOfBoundsException();
     }
+    if (MemoryManagerConstants.DO_COLLECT_SPACE_SAVING_STATS) {
+    	MemoryManagerConstants.NUM_PRIM_BYTES_ARRAYCOPY += (len * BYTES_IN_FLOAT);
+
+    	MemoryManagerConstants.NUM_FLOAT_ARRAYS_BYTES_COPIED += (len * BYTES_IN_FLOAT);
+    }
   }
 
   // Outlined unlikely case of potentially overlapping subarrays
@@ -865,7 +1132,7 @@
       }
     }
   }
-
+  
   /**
    * Perform an array copy for arrays of longs.
    *
@@ -887,13 +1154,26 @@
         (dstIdx + len) >= 0 &&
         (dstIdx + len) <= dst.length) {
       if (src != dst || srcIdx > dstIdx) {
-        Memory.arraycopy64Bit(src, srcIdx, dst, dstIdx, len);
+        if (USE_PRIMITIVE_LONG_ARRAYLETS) {
+          if (!FAST_ARRAY_COPY) {
+            while (len-- != 0)
+              dst[dstIdx++] = src[srcIdx++];
+          } else
+            fastArrayletCopy(src, srcIdx, dst, dstIdx, len, false, DO_COPY_ON_WRITE_LONG_ARRAYS, LOG_BYTES_IN_LONG, FIRSTN_LONG_ELEMS, LOG_ELEMENTS_IN_LONG_ARRAYLET);
+        } else {
+          Memory.arraycopy64Bit(src, srcIdx, dst, dstIdx, len);
+        }
       } else {
         arraycopyOverlap(src, srcIdx, dst, dstIdx, len);
       }
     } else {
       failWithIndexOutOfBoundsException();
     }
+    if (MemoryManagerConstants.DO_COLLECT_SPACE_SAVING_STATS) {
+    	MemoryManagerConstants.NUM_PRIM_BYTES_ARRAYCOPY += (len * BYTES_IN_LONG);
+
+    	MemoryManagerConstants.NUM_LONG_ARRAYS_BYTES_COPIED += (len * BYTES_IN_LONG);
+    }
   }
 
   // Outlined unlikely case of potentially overlapping subarrays
@@ -912,7 +1192,7 @@
       }
     }
   }
-
+  
   /**
    * Perform an array copy for arrays of doubles.
    *
@@ -934,13 +1214,26 @@
         (dstIdx + len) >= 0 &&
         (dstIdx + len) <= dst.length) {
       if (src != dst || srcIdx > dstIdx) {
-        Memory.arraycopy64Bit(src, srcIdx, dst, dstIdx, len);
+        if (USE_PRIMITIVE_DOUBLE_ARRAYLETS) {
+          if (!FAST_ARRAY_COPY) {
+            while (len-- != 0)
+              dst[dstIdx++] = src[srcIdx++];
+          }  else
+            fastArrayletCopy(src, srcIdx, dst, dstIdx, len, false, DO_COPY_ON_WRITE_DOUBLE_ARRAYS, LOG_BYTES_IN_DOUBLE, FIRSTN_DOUBLE_ELEMS, LOG_ELEMENTS_IN_DOUBLE_ARRAYLET);
+        } else {
+          Memory.arraycopy64Bit(src, srcIdx, dst, dstIdx, len);
+        }
       } else {
         arraycopyOverlap(src, srcIdx, dst, dstIdx, len);
       }
     } else {
       failWithIndexOutOfBoundsException();
     }
+    if (MemoryManagerConstants.DO_COLLECT_SPACE_SAVING_STATS) {
+    	MemoryManagerConstants.NUM_PRIM_BYTES_ARRAYCOPY += (len * BYTES_IN_DOUBLE);
+    	MemoryManagerConstants.NUM_DOUBLE_ARRAYS_BYTES_COPIED += (len * BYTES_IN_DOUBLE);
+       
+    }
   }
 
   // Outlined unlikely case of potentially overlapping subarrays
@@ -960,6 +1253,84 @@
     }
   }
 
+  @Inline
+  private static void fastArrayletCopy(Object src, int srcIdx, Object dst, int dstIdx, int len, boolean doWriteBarrier, boolean doCow, int logElemSize, int firstNElems, int logElemsInArraylet) {
+    int srcOffset = srcIdx << logElemSize;
+    int dstOffset = dstIdx << logElemSize;
+    int bytes = len << logElemSize;
+    int firstNBytes = firstNElems << logElemSize;
+    
+    int remaining = bytes;
+    int srcContigRemaining = 0;
+    int dstContigRemaining = 0;
+    boolean srcIsArraylet = false;
+    boolean dstIsArraylet = false;
+
+    while (remaining > 0) {
+      if (srcContigRemaining == 0) {
+        srcIsArraylet = isArraylet(src, srcOffset, firstNBytes);
+        srcContigRemaining = getRemainingContigBytes(srcIsArraylet, srcOffset, firstNBytes);
+      }
+      if (dstContigRemaining == 0) {
+        dstIsArraylet = isArraylet(dst, dstOffset, firstNBytes);
+        dstContigRemaining = getRemainingContigBytes(dstIsArraylet, dstOffset, firstNBytes);
+      }
+      int advance = (srcContigRemaining > dstContigRemaining) ? dstContigRemaining : srcContigRemaining;
+      if (advance > remaining) advance = remaining;
+      
+      if (srcIsArraylet && dstIsArraylet && advance == ARRAYLET_BYTES) {
+        // Copy a full arraylet.
+        copyFullArraylet(src, srcOffset, srcIsArraylet, dst, dstOffset, dstIsArraylet, advance, doCow, doWriteBarrier, firstNBytes);
+      } else {
+        copyContiguousRegion(src, srcOffset, srcIsArraylet, dst, dstOffset, dstIsArraylet, advance, doCow, doWriteBarrier, firstNBytes);
+      }
+      
+      srcOffset += advance;
+      dstOffset += advance;
+      srcContigRemaining -= advance;
+      dstContigRemaining -= advance;
+      remaining -= advance;
+    }
+  }
+
+  @Uninterruptible
+  @Inline
+  private static void copyFullArraylet(Object src, int srcOffset, boolean srcIsArraylet, Object dst, int dstOffset, boolean dstIsArraylet, int bytes, boolean doCow, boolean doWriteBarrier, int firstNBytes) {
+    Address srcPtr = getArrayletSlot(srcIsArraylet, src, srcOffset, false, doCow, firstNBytes);
+    if (PERFORM_ZERO_ARRAYLET_ARRAYCOPY_OPT && srcPtr.EQ(Magic.objectAsAddress(ObjectModel.zeroArraylet))) {
+      if (MemoryManagerConstants.DO_COLLECT_SPACE_SAVING_STATS) {
+        MemoryManagerConstants.NUM_ZERO_ARRAYLET_ARRAYCOPY_OPT += MemoryManagerConstants.ARRAYLET_BYTES;
+      }
+      setArrayletPtr(dst, dstOffset, Magic.objectAsAddress(ObjectModel.zeroArraylet), firstNBytes);
+    } else if (doCow && srcPtr.GE(BOOT_IMAGE_END)) {
+      Address sharedArraylet = taintArraylet(src, srcOffset, firstNBytes);
+      setArrayletPtr(dst, dstOffset, sharedArraylet, firstNBytes);
+    } else { 
+      Address dstPtr = getArrayletSlot(dstIsArraylet, dst, dstOffset, true, doCow, firstNBytes);
+      if (doWriteBarrier && MemoryManager.arrayCopyWriteBarrier(src, srcPtr.diff(Magic.objectAsAddress(src)), dst, dstPtr.diff(Magic.objectAsAddress(dst)), bytes)) {
+        return;
+      }
+      Memory.memcopy(dstPtr, srcPtr, bytes);
+    }
+  }
+
+  @Uninterruptible
+  @Inline
+  private static void copyContiguousRegion(Object src, int srcOffset, boolean srcIsArraylet, Object dst, int dstOffset, boolean dstIsArraylet, int bytes, boolean doCow, boolean doWriteBarrier, int firstNBytes) {
+    Address srcPtr = getArrayletSlot(srcIsArraylet, src, srcOffset, false, doCow, firstNBytes);
+    Address dstPtr = getArrayletSlot(dstIsArraylet, dst, dstOffset, true, doCow, firstNBytes);
+    if (doWriteBarrier && MemoryManager.arrayCopyWriteBarrier(src, srcPtr.diff(Magic.objectAsAddress(src)), dst, dstPtr.diff(Magic.objectAsAddress(dst)), bytes)) {
+        return;
+    }
+
+    Memory.arraycopy8Bit(srcPtr, 0, dstPtr, 0, bytes);
+  }
+  
+  @Inline
+  private static int getRemainingContigBytes(boolean isArraylet, int offset, int firstNBytes) {
+    return isArraylet ? ARRAYLET_BYTES - ((offset - firstNBytes) & (ARRAYLET_BYTES - 1)) : firstNBytes - offset;
+  }
+  
   /**
    * Perform an array copy for arrays of objects.  This code must
    * ensure that write barriers are invoked as if the copy were
@@ -990,7 +1361,11 @@
     } else {
       failWithIndexOutOfBoundsException();
     }
+    if (MemoryManagerConstants.DO_COLLECT_SPACE_SAVING_STATS) {
+    	MemoryManagerConstants.NUM_REF_BYTES_ARRAYCOPY += (len * BYTES_IN_ADDRESS);
+    }
   }
+  
 
   /**
    * Perform an array copy for arrays of objects where the possibility
@@ -1013,12 +1388,21 @@
     Offset dstOffset = Offset.fromIntZeroExtend(dstIdx << LOG_BYTES_IN_ADDRESS);
     int bytes = len << LOG_BYTES_IN_ADDRESS;
 
-    if (!MemoryManagerConstants.NEEDS_READ_BARRIER && ((src != dst) || loToHi)) {
-      if (!MemoryManagerConstants.NEEDS_WRITE_BARRIER ||
-          !MemoryManager.arrayCopyWriteBarrier(src, srcOffset, dst, dstOffset, bytes)) {
-        Memory.alignedWordCopy(Magic.objectAsAddress(dst).plus(dstOffset),
-                                  Magic.objectAsAddress(src).plus(srcOffset),
-                                  bytes);
+    //jbs added arraylet
+    if (!NEEDS_READ_BARRIER  && ((src != dst) || loToHi)) {
+      if (USE_REFERENCE_ARRAYLETS) {
+        if (!FAST_ARRAY_COPY) {
+          while (len-- != 0)
+            dst[dstIdx++] = src[srcIdx++];
+        } else
+          fastArrayletCopy(src, srcIdx, dst, dstIdx, len, NEEDS_WRITE_BARRIER, DO_COPY_ON_WRITE_REF_ARRAYS, LOG_BYTES_IN_ADDRESS, FIRSTN_REF_ELEMS, LOG_ELEMENTS_IN_REF_ARRAYLET);
+      } else {
+        if (!MemoryManagerConstants.NEEDS_WRITE_BARRIER ||
+            !MemoryManager.arrayCopyWriteBarrier(src, srcOffset, dst, dstOffset, bytes)) {
+          Memory.alignedWordCopy(Magic.objectAsAddress(dst).plus(dstOffset),
+              Magic.objectAsAddress(src).plus(srcOffset),
+              bytes);
+        }
       }
     } else {
       // set up things according to the direction of the copy
@@ -1034,12 +1418,14 @@
       // perform the copy
       while (len-- != 0) {
         Object value;
-        if (MemoryManagerConstants.NEEDS_READ_BARRIER) {
+        //jbs added arraylet
+        if (MemoryManagerConstants.NEEDS_READ_BARRIER || MemoryManagerConstants.USE_REFERENCE_ARRAYLETS || MemoryManagerConstants.USE_OBJECT_ARRAY_ACCESS_BARRIER) {
           value = MemoryManager.arrayLoadReadBarrier(src, srcOffset.toInt() >> LOG_BYTES_IN_ADDRESS);
         } else {
           value = Magic.getObjectAtOffset(src, srcOffset);
         }
-        if (MemoryManagerConstants.NEEDS_WRITE_BARRIER) {
+        //jbs added arraylet
+        if (MemoryManagerConstants.NEEDS_WRITE_BARRIER || MemoryManagerConstants.USE_REFERENCE_ARRAYLETS || MemoryManagerConstants.USE_OBJECT_ARRAY_ACCESS_BARRIER) {
           MemoryManager.arrayStoreWriteBarrier(dst, dstOffset.toInt() >> LOG_BYTES_IN_ADDRESS, value);
         } else {
           Magic.setObjectAtOffset(dst, dstOffset, value);
diff -r 743a2cc2ed20 -r 058fdc3780ba rvm/src/org/jikesrvm/classloader/RVMClass.java
--- a/rvm/src/org/jikesrvm/classloader/RVMClass.java	Tue Aug 04 11:04:15 2009 +1000
+++ b/rvm/src/org/jikesrvm/classloader/RVMClass.java	Mon Nov 16 09:21:21 2009 +1100
@@ -31,10 +31,12 @@
 import org.jikesrvm.runtime.RuntimeEntrypoints;
 import org.jikesrvm.runtime.StackBrowser;
 import org.jikesrvm.runtime.Statics;
+import org.jikesrvm.scheduler.Scheduler;
 import org.vmmagic.pragma.NonMoving;
 import org.vmmagic.pragma.Pure;
 import org.vmmagic.pragma.Uninterruptible;
 import org.vmmagic.unboxed.Offset;
+import org.vmmagic.unboxed.WordArray;
 
 /**
  * Description of a java "class" type.<br/>
@@ -938,8 +940,9 @@
   public RVMClass[] getAllImplementedInterfaces() {
     if (VM.VerifyAssertions) VM._assert(isResolved());
     int count = 0;
-    int[] doesImplement = getDoesImplement();
-    for (int mask : doesImplement) {
+    WordArray doesImplement = getDoesImplement();
+    for (int i=0; i < MemoryManager.nativeIntBufferLength(doesImplement); i++) {
+      int mask = doesImplement.getInt(i);
       while (mask != 0) {
         count++;
         mask &= (mask - 1); // clear lsb 1 bit
@@ -947,8 +950,8 @@
     }
     if (count == 0) return emptyVMClass;
     RVMClass[] ans = new RVMClass[count];
-    for (int i = 0, idx = 0; i < doesImplement.length; i++) {
-      int mask = doesImplement[i];
+    for (int i = 0, idx = 0; i < MemoryManager.nativeIntBufferLength(doesImplement); i++) {
+      int mask = doesImplement.getInt(i);
       if (mask != 0) {
         for (int j = 0; j < 32; j++) {
           if ((mask & (1 << j)) != 0) {
@@ -1224,6 +1227,12 @@
    */
   static RVMClass readClass(TypeReference typeRef, DataInputStream input) throws ClassFormatError, IOException {
 
+	  //jbs debugging
+	  /*if (VM.runningVM) {
+	  VM.sysWrite("In RVMClass readClass, input address is "); VM.sysWrite(Magic.objectAsAddress(input.buf));
+	  VM.sysWriteln();
+	  //Scheduler.dumpStack();
+	  }*/
     if (classLoadingDisabled) {
       throw new RuntimeException("ClassLoading Disabled : " + typeRef);
     }
@@ -1881,7 +1890,7 @@
    * @param doesImplement The calculated does implement array
    */
   @Uninterruptible
-  private void publishResolved(TIB allocatedTib, short[] superclassIds, int[] doesImplement) {
+  private void publishResolved(TIB allocatedTib, WordArray superclassIds, WordArray doesImplement) {
     Statics.setSlotContents(getTibOffset(), allocatedTib);
     allocatedTib.setType(this);
     allocatedTib.setSuperclassIds(superclassIds);
diff -r 743a2cc2ed20 -r 058fdc3780ba rvm/src/org/jikesrvm/classloader/RVMClassLoader.java
--- a/rvm/src/org/jikesrvm/classloader/RVMClassLoader.java	Tue Aug 04 11:04:15 2009 +1000
+++ b/rvm/src/org/jikesrvm/classloader/RVMClassLoader.java	Mon Nov 16 09:21:21 2009 +1100
@@ -230,6 +230,7 @@
 
   // Names of special methods.
   //
+  public static final Atom HackArrayMethodName = Atom.findOrCreateAsciiAtom("hackArrayLoadReadBarrier");
   /** "<clinit>" */
   public static final Atom StandardClassInitializerMethodName = Atom.findOrCreateAsciiAtom("<clinit>");
   /** "()V" */
diff -r 743a2cc2ed20 -r 058fdc3780ba rvm/src/org/jikesrvm/classloader/RVMType.java
--- a/rvm/src/org/jikesrvm/classloader/RVMType.java	Tue Aug 04 11:04:15 2009 +1000
+++ b/rvm/src/org/jikesrvm/classloader/RVMType.java	Mon Nov 16 09:21:21 2009 +1100
@@ -25,6 +25,7 @@
 import org.vmmagic.pragma.NonMoving;
 import org.vmmagic.pragma.Uninterruptible;
 import org.vmmagic.unboxed.Offset;
+import org.vmmagic.unboxed.WordArray;
 
 /**
  * A description of a java type.
@@ -217,12 +218,12 @@
   /**
    * The superclass ids for this type.
    */
-  protected short[] superclassIds;
+  protected WordArray superclassIds;
 
   /**
    * The interface implementation array for this type.
    */
-  protected int[] doesImplement;
+  protected WordArray doesImplement;
 
   /**
    * Create an instance of a {@link RVMType}
@@ -500,7 +501,7 @@
    * get superclass id vector (@see DynamicTypeCheck)
    */
   @Uninterruptible
-  public final short[] getSuperclassIds() {
+  public final WordArray getSuperclassIds() {
     return superclassIds;
   }
 
@@ -508,7 +509,7 @@
    * get doesImplement vector (@see DynamicTypeCheck)
    */
   @Uninterruptible
-  public final int[] getDoesImplement() {
+  public final WordArray getDoesImplement() {
     return doesImplement;
   }
 
diff -r 743a2cc2ed20 -r 058fdc3780ba rvm/src/org/jikesrvm/classloader/TableBasedDynamicLinker.java
--- a/rvm/src/org/jikesrvm/classloader/TableBasedDynamicLinker.java	Tue Aug 04 11:04:15 2009 +1000
+++ b/rvm/src/org/jikesrvm/classloader/TableBasedDynamicLinker.java	Mon Nov 16 09:21:21 2009 +1100
@@ -16,8 +16,10 @@
 import org.jikesrvm.Constants;
 import org.jikesrvm.mm.mminterface.MemoryManager;
 import org.jikesrvm.runtime.Magic;
+import org.jikesrvm.runtime.Memory;
 import org.jikesrvm.runtime.RuntimeEntrypoints;
 import org.vmmagic.pragma.Entrypoint;
+import org.vmmagic.unboxed.WordArray;
 
 /**
  * Dynamic linking via indirection tables. <p>
@@ -44,12 +46,14 @@
    * member or whether the member needs linking.
    */
   @Entrypoint
-  private static int[] memberOffsets;
+  private static WordArray memberOffsets;
 
   static {
-    memberOffsets = MemoryManager.newContiguousIntArray(32000);
+    memberOffsets = MemoryManager.createNativeIntBuffer(32000);
     if (NEEDS_DYNAMIC_LINK != 0) {
-      java.util.Arrays.fill(memberOffsets, NEEDS_DYNAMIC_LINK);
+      for(int i=0; i < MemoryManager.nativeIntBufferLength(memberOffsets); i++) {
+        memberOffsets.setInt(i, NEEDS_DYNAMIC_LINK);
+      }
     }
   }
 
@@ -76,7 +80,7 @@
     RuntimeEntrypoints.initializeClassForDynamicLink(declaringClass);
     int offset = resolvedMember.getOffset().toInt();
     if (VM.VerifyAssertions) VM._assert(offset != NEEDS_DYNAMIC_LINK);
-    memberOffsets[ref.getId()] = offset;
+    memberOffsets.setInt(ref.getId(), offset);
     return offset;
   }
 
@@ -86,12 +90,20 @@
    * the given member reference.
    */
   static synchronized void ensureCapacity(int id) {
-    if (id >= memberOffsets.length) {
-      int oldLen = memberOffsets.length;
-      int[] tmp1 = MemoryManager.newContiguousIntArray((oldLen * 3) / 2);
-      System.arraycopy(memberOffsets, 0, tmp1, 0, oldLen);
+    int oldLen = MemoryManager.nativeIntBufferLength(memberOffsets);
+    if (id >= oldLen) {
+      WordArray tmp1 = MemoryManager.createNativeIntBuffer((oldLen * 3) / 2);
+      if (VM.runningVM) {
+        Memory.memcopy(Magic.objectAsAddress(tmp1), Magic.objectAsAddress(memberOffsets), oldLen << LOG_BYTES_IN_INT);
+      } else {
+        for(int i=0; i < oldLen; i++) {
+          tmp1.setInt(i, memberOffsets.getInt(i));
+        }
+      }
       if (NEEDS_DYNAMIC_LINK != 0) {
-        java.util.Arrays.fill(tmp1, oldLen, tmp1.length, NEEDS_DYNAMIC_LINK);
+        for(int i=oldLen; i < MemoryManager.nativeIntBufferLength(tmp1); i++) {
+          tmp1.setInt(i, NEEDS_DYNAMIC_LINK);
+        }
       }
       Magic.sync(); // be sure array initialization is visible before we publish the reference!
       memberOffsets = tmp1;
diff -r 743a2cc2ed20 -r 058fdc3780ba rvm/src/org/jikesrvm/compilers/baseline/BaselineCompiledMethod.java
--- a/rvm/src/org/jikesrvm/compilers/baseline/BaselineCompiledMethod.java	Tue Aug 04 11:04:15 2009 +1000
+++ b/rvm/src/org/jikesrvm/compilers/baseline/BaselineCompiledMethod.java	Mon Nov 16 09:21:21 2009 +1100
@@ -12,6 +12,7 @@
  */
 package org.jikesrvm.compilers.baseline;
 
+import org.jikesrvm.HeapLayoutConstants;
 import org.jikesrvm.VM;
 import org.jikesrvm.PrintLN;
 import org.jikesrvm.ArchitectureSpecific.BaselineConstants;
@@ -27,6 +28,7 @@
 import org.jikesrvm.compilers.common.ExceptionTable;
 import org.jikesrvm.runtime.DynamicLink;
 import org.jikesrvm.runtime.ExceptionDeliverer;
+import org.jikesrvm.runtime.Magic;
 import org.jikesrvm.runtime.StackBrowser;
 import org.vmmagic.pragma.SynchronizedObject;
 import org.vmmagic.pragma.Uninterruptible;
@@ -376,8 +378,21 @@
 
   public int size() {
     int size = TYPE.peekType().asClass().getInstanceSize();
-    if (bytecodeMap != null) size += RVMArray.ByteArray.getInstanceSize(bytecodeMap.length);
-    if (eTable != null) size += RVMArray.IntArray.getInstanceSize(eTable.length);
+    //jbs changed
+    if (bytecodeMap != null) { 
+    	if (Magic.objectAsAddress(bytecodeMap).LT(HeapLayoutConstants.BOOT_IMAGE_DATA_END)) {
+    		size += RVMArray.ByteArray.getBootImageContiguousInstanceSize(bytecodeMap.length);
+        } else {
+        	size += RVMArray.ByteArray.getInstanceSize(bytecodeMap.length);
+        }
+    }
+    if (eTable != null) {
+    	if (Magic.objectAsAddress(eTable).LT(HeapLayoutConstants.BOOT_IMAGE_DATA_END)) {
+    		size += RVMArray.IntArray.getBootImageContiguousInstanceSize(eTable.length);
+        } else {
+        	size += RVMArray.IntArray.getInstanceSize(eTable.length);
+        }
+    }
     if (referenceMaps != null) size += referenceMaps.size();
     return size;
   }
diff -r 743a2cc2ed20 -r 058fdc3780ba rvm/src/org/jikesrvm/compilers/baseline/BaselineCompiler.java
--- a/rvm/src/org/jikesrvm/compilers/baseline/BaselineCompiler.java	Tue Aug 04 11:04:15 2009 +1000
+++ b/rvm/src/org/jikesrvm/compilers/baseline/BaselineCompiler.java	Mon Nov 16 09:21:21 2009 +1100
@@ -244,6 +244,7 @@
       // determine if we are going to insert edge counters for this method
       if (options
           .EDGE_COUNTERS &&
+          method.getName() != org.jikesrvm.classloader.RVMClassLoader.HackArrayMethodName &&
           !method.getDeclaringClass().hasBridgeFromNativeAnnotation() &&
           (method.hasCondBranch() || method.hasSwitch())) {
         ((BaselineCompiledMethod) compiledMethod).setHasCounterArray(); // yes, we will inject counters for this method.
diff -r 743a2cc2ed20 -r 058fdc3780ba rvm/src/org/jikesrvm/compilers/baseline/BranchProfiles.java
--- a/rvm/src/org/jikesrvm/compilers/baseline/BranchProfiles.java	Tue Aug 04 11:04:15 2009 +1000
+++ b/rvm/src/org/jikesrvm/compilers/baseline/BranchProfiles.java	Mon Nov 16 09:21:21 2009 +1100
@@ -16,6 +16,8 @@
 import org.jikesrvm.classloader.BytecodeConstants;
 import org.jikesrvm.classloader.BytecodeStream;
 import org.jikesrvm.classloader.NormalMethod;
+import org.jikesrvm.mm.mminterface.MemoryManager;
+import org.vmmagic.unboxed.WordArray;
 
 /**
  * Profile data for all conditional branches (including switches)
@@ -60,9 +62,9 @@
     }
   }
 
-  BranchProfiles(NormalMethod m, int[] cs) {
+  BranchProfiles(NormalMethod m, WordArray cs) {
     method = m;
-    numCounters = cs.length;
+    numCounters = MemoryManager.nativeIntBufferLength(cs);
 
     // Originally we only allocate half of the number of edges for branch
     // profiles, like data = new BranchProfile[cs.length/2]
@@ -70,7 +72,7 @@
     // least two edges, supposingly. Then we found that the lookupswitch
     // bytecode could have only one edge, so the number of branch profiles
     // is not necessarily less than half of the number of edges.
-    BranchProfile[] data = new BranchProfile[cs.length];
+    BranchProfile[] data = new BranchProfile[MemoryManager.nativeIntBufferLength(cs)];
     BytecodeStream bcodes = m.getBytecodes();
     int dataIdx = 0;
     int countIdx = 0;
@@ -99,8 +101,8 @@
         case JBC_if_acmpne:
         case JBC_ifnull:
         case JBC_ifnonnull: {
-          int yea = cs[countIdx + EdgeCounts.TAKEN];
-          int nea = cs[countIdx + EdgeCounts.NOT_TAKEN];
+          int yea = cs.getInt(countIdx + EdgeCounts.TAKEN);
+          int nea = cs.getInt(countIdx + EdgeCounts.NOT_TAKEN);
           int offset = bcodes.getBranchOffset();
           boolean backwards = offset < 0;
           countIdx += 2;
@@ -137,7 +139,7 @@
     }
 
     // Make sure we are in sync
-    if (VM.VerifyAssertions) VM._assert(countIdx == cs.length);
+    if (VM.VerifyAssertions) VM._assert(countIdx == MemoryManager.nativeIntBufferLength(cs));
 
     if (dataIdx != data.length) {
       // We had a switch statment; shrink the array.
diff -r 743a2cc2ed20 -r 058fdc3780ba rvm/src/org/jikesrvm/compilers/baseline/EdgeCounts.java
--- a/rvm/src/org/jikesrvm/compilers/baseline/EdgeCounts.java	Tue Aug 04 11:04:15 2009 +1000
+++ b/rvm/src/org/jikesrvm/compilers/baseline/EdgeCounts.java	Mon Nov 16 09:21:21 2009 +1100
@@ -22,8 +22,10 @@
 import org.jikesrvm.Callbacks;
 import org.jikesrvm.classloader.MemberReference;
 import org.jikesrvm.classloader.NormalMethod;
+import org.jikesrvm.mm.mminterface.MemoryManager;
 import org.jikesrvm.runtime.Magic;
 import org.vmmagic.pragma.Entrypoint;
+import org.vmmagic.unboxed.WordArray;
 
 /**
  * A repository of edge counters for bytecode-level edge conditional branches.
@@ -50,8 +52,8 @@
    * number of times a particular branch event occurs.
    */
   @Entrypoint
-  private static int[][] data;
-
+  private static WordArray[] data;
+  
   public void notifyExit(int value) { dumpCounts(); }
 
   public static void boot(String inputFileName) {
@@ -74,17 +76,17 @@
 
   private static synchronized void allocateCounters(int id, int numEntries) {
     if (data == null) {
-      data = new int[id + 500][];
+      data = new WordArray[id + 500];
     }
     if (id >= data.length) {
       int newSize = data.length * 2;
       if (newSize <= id) newSize = id + 500;
-      int[][] tmp = new int[newSize][];
+      WordArray[] tmp = new WordArray[newSize];
       System.arraycopy(data, 0, tmp, 0, data.length);
       Magic.sync();
       data = tmp;
     }
-    data[id] = new int[numEntries];
+    data[id] = MemoryManager.createNativeIntBuffer(numEntries);
   }
 
   public static BranchProfiles getBranchProfiles(NormalMethod m) {
@@ -132,7 +134,7 @@
       VM.sysFail("Unable to open input edge counter file " + fn);
     }
     try {
-      int[] cur = null;
+      WordArray cur = null;
       int curIdx = 0;
       for (String s = in.readLine(); s != null; s = in.readLine()) {
         StringTokenizer parser = new StringTokenizer(s, " \t\n\r\f,{}");
@@ -149,12 +151,12 @@
           if (type.equals("switch")) {
             parser.nextToken(); // discard '<'
             for (String nt = parser.nextToken(); !nt.equals(">"); nt = parser.nextToken()) {
-              cur[curIdx++] = Integer.parseInt(nt);
+              cur.setInt(curIdx++, Integer.parseInt(nt));
             }
           } else if (type.equals("forwbranch") || type.equals("backbranch")) {
             parser.nextToken(); // discard '<'
-            cur[curIdx + TAKEN] = Integer.parseInt(parser.nextToken());
-            cur[curIdx + NOT_TAKEN] = Integer.parseInt(parser.nextToken());
+            cur.setInt(curIdx + TAKEN, Integer.parseInt(parser.nextToken()));
+            cur.setInt(curIdx + NOT_TAKEN, Integer.parseInt(parser.nextToken()));
             curIdx += 2;
           } else {
             VM.sysFail("Format error in edge counter input file");
diff -r 743a2cc2ed20 -r 058fdc3780ba rvm/src/org/jikesrvm/compilers/baseline/ReferenceMaps.java
--- a/rvm/src/org/jikesrvm/compilers/baseline/ReferenceMaps.java	Tue Aug 04 11:04:15 2009 +1000
+++ b/rvm/src/org/jikesrvm/compilers/baseline/ReferenceMaps.java	Mon Nov 16 09:21:21 2009 +1100
@@ -13,11 +13,14 @@
 package org.jikesrvm.compilers.baseline;
 
 import org.jikesrvm.ArchitectureSpecific.BaselineConstants;
+import org.jikesrvm.HeapLayoutConstants;
 import org.jikesrvm.VM;
 import org.jikesrvm.classloader.RVMArray;
 import org.jikesrvm.classloader.RVMMethod;
 import org.jikesrvm.classloader.NormalMethod;
 import org.jikesrvm.classloader.TypeReference;
+import org.jikesrvm.mm.mminterface.MemoryManagerConstants;
+import org.jikesrvm.runtime.Magic;
 import org.jikesrvm.scheduler.ProcessorLock;
 import org.vmmagic.pragma.Interruptible;
 import org.vmmagic.pragma.Uninterruptible;
@@ -378,11 +381,28 @@
   @Interruptible
   public int size() {
     int size = TypeReference.ReferenceMaps.peekType().asClass().getInstanceSize();
-    if (MCSites != null) size += RVMArray.IntArray.getInstanceSize(MCSites.length);
-    if (referenceMaps != null) size += RVMArray.ByteArray.getInstanceSize(referenceMaps.length);
+    if (MCSites != null) {
+    	if (Magic.objectAsAddress(MCSites).LT(HeapLayoutConstants.BOOT_IMAGE_DATA_END)) {
+    		size += RVMArray.IntArray.getBootImageContiguousInstanceSize(MCSites.length);
+        } else {
+        	size += RVMArray.IntArray.getInstanceSize(MCSites.length);
+        }
+    }
+    if (referenceMaps != null) {
+    	if (Magic.objectAsAddress(referenceMaps).LT(HeapLayoutConstants.BOOT_IMAGE_DATA_END)) {
+    		size += RVMArray.ByteArray.getBootImageContiguousInstanceSize(referenceMaps.length);
+        } else {
+    	size += RVMArray.ByteArray.getInstanceSize(referenceMaps.length);
+        }
+    }
     if (jsrInfo != null && jsrInfo.unusualReferenceMaps != null) {
+    	//jbs added arraylet
+        if (Magic.objectAsAddress(jsrInfo.unusualReferenceMaps).LT(HeapLayoutConstants.BOOT_IMAGE_DATA_END)) {
+      	  size += RVMArray.JavaLangObjectArray.getBootImageContiguousInstanceSize(jsrInfo.unusualReferenceMaps.length);
+        } else {
       size += RVMArray.JavaLangObjectArray.getInstanceSize(jsrInfo.unusualReferenceMaps.length);
     }
+    }
     return size;
   }
 
diff -r 743a2cc2ed20 -r 058fdc3780ba rvm/src/org/jikesrvm/compilers/baseline/SwitchBranchProfile.java
--- a/rvm/src/org/jikesrvm/compilers/baseline/SwitchBranchProfile.java	Tue Aug 04 11:04:15 2009 +1000
+++ b/rvm/src/org/jikesrvm/compilers/baseline/SwitchBranchProfile.java	Mon Nov 16 09:21:21 2009 +1100
@@ -12,6 +12,8 @@
  */
 package org.jikesrvm.compilers.baseline;
 
+import org.vmmagic.unboxed.WordArray;
+
 /**
  * Profile data for a branch instruction.
  */
@@ -29,11 +31,11 @@
    * @param start idx of first entry in cs
    * @param numEntries number of entries in cs for this switch
    */
-  SwitchBranchProfile(int _bci, int[] cs, int start, int numEntries) {
+  SwitchBranchProfile(int _bci, WordArray cs, int start, int numEntries) {
     super(_bci, sumCounts(cs, start, numEntries));
     counts = new float[numEntries];
     for (int i = 0; i < numEntries; i++) {
-      counts[i] = (float) cs[start + i];
+      counts[i] = (float) cs.getInt(start + i);
     }
   }
 
@@ -61,10 +63,10 @@
     return res + " >";
   }
 
-  private static float sumCounts(int[] counts, int start, int numEntries) {
+  private static float sumCounts(WordArray counts, int start, int numEntries) {
     float sum = 0.0f;
     for (int i = start; i < start + numEntries; i++) {
-      sum += (float) counts[i];
+      sum += (float) counts.getInt(i);
     }
     return sum;
   }
diff -r 743a2cc2ed20 -r 058fdc3780ba rvm/src/org/jikesrvm/compilers/baseline/ia32/Barriers.java
--- a/rvm/src/org/jikesrvm/compilers/baseline/ia32/Barriers.java	Tue Aug 04 11:04:15 2009 +1000
+++ b/rvm/src/org/jikesrvm/compilers/baseline/ia32/Barriers.java	Mon Nov 16 09:21:21 2009 +1100
@@ -27,12 +27,56 @@
  */
 class Barriers implements BaselineConstants {
 
+	
+	
   static void compileArrayStoreBarrier(Assembler asm) {
     // on entry java stack contains ...|target_array_ref|array_index|ref_to_store|
     BaselineCompilerImpl.genParameterRegisterLoad(asm, 3);
     asm.emitCALL_Abs(Magic.getTocPointer().plus(Entrypoints.arrayStoreWriteBarrierMethod.getOffset()));
   }
 
+  static void compileArrayStorePrimitiveShortBarrier(Assembler asm) {
+	  // on entry java stack contains ...|target_array_ref|array_index|ref_to_store|
+	  BaselineCompilerImpl.genParameterRegisterLoad(asm, 3);
+	  asm.emitCALL_Abs(Magic.getTocPointer().plus(Entrypoints.arrayStorePrimitiveShortWriteBarrierMethod.getOffset()));
+  }
+  
+  static void compileArrayStorePrimitiveCharBarrier(Assembler asm) {
+	  // on entry java stack contains ...|target_array_ref|array_index|ref_to_store|
+	  BaselineCompilerImpl.genParameterRegisterLoad(asm, 3);
+	  asm.emitCALL_Abs(Magic.getTocPointer().plus(Entrypoints.arrayStorePrimitiveCharWriteBarrierMethod.getOffset()));
+  }
+  
+  static void compileArrayStorePrimitiveByteBarrier(Assembler asm) {
+	  // on entry java stack contains ...|target_array_ref|array_index|ref_to_store|
+	  BaselineCompilerImpl.genParameterRegisterLoad(asm, 3);
+	  asm.emitCALL_Abs(Magic.getTocPointer().plus(Entrypoints.arrayStorePrimitiveByteWriteBarrierMethod.getOffset()));
+  }
+  
+  static void compileArrayStorePrimitiveFloatBarrier(Assembler asm) {
+	  // on entry java stack contains ...|target_array_ref|array_index|ref_to_store|
+	  BaselineCompilerImpl.genParameterRegisterLoad(asm, 3);
+	  asm.emitCALL_Abs(Magic.getTocPointer().plus(Entrypoints.arrayStorePrimitiveFloatWriteBarrierMethod.getOffset()));
+  }
+  
+  static void compileArrayStorePrimitiveIntBarrier(Assembler asm) {
+	  // on entry java stack contains ...|target_array_ref|array_index|ref_to_store|
+	  BaselineCompilerImpl.genParameterRegisterLoad(asm, 3);
+	  asm.emitCALL_Abs(Magic.getTocPointer().plus(Entrypoints.arrayStorePrimitiveIntWriteBarrierMethod.getOffset()));
+  }
+  
+  static void compileArrayStorePrimitiveLongBarrier(Assembler asm) {
+	  // on entry java stack contains ...|target_array_ref|array_index|ref_to_store|
+	  BaselineCompilerImpl.genParameterRegisterLoad(asm, 4);
+	  asm.emitCALL_Abs(Magic.getTocPointer().plus(Entrypoints.arrayStorePrimitiveLongWriteBarrierMethod.getOffset()));
+  }
+  
+  static void compileArrayStorePrimitiveDoubleBarrier(Assembler asm) {
+	  // on entry java stack contains ...|target_array_ref|array_index|ref_to_store|
+	  BaselineCompilerImpl.genParameterRegisterLoad(asm, 4);
+	  asm.emitCALL_Abs(Magic.getTocPointer().plus(Entrypoints.arrayStorePrimitiveDoubleWriteBarrierMethod.getOffset()));
+  }
+
   static void compilePutfieldBarrier(Assembler asm, GPR reg, int locationMetadata) {
     //  on entry java stack contains ...|target_ref|ref_to_store|
     //  SP[0] -> ref_to_store, SP[1] -> target_ref
@@ -83,6 +127,14 @@
     asm.emitCALL_Abs(Magic.getTocPointer().plus(Entrypoints.putstaticWriteBarrierMethod.getOffset()));
   }
 
+  static void compileHackArrayLoadBarrier(Assembler asm, boolean pushResult) {
+    // on entry java stack contains ...|target_array_ref|array_index|
+    // SP -> index, SP+4 -> target_ref
+    BaselineCompilerImpl.genParameterRegisterLoad(asm, 2);
+    asm.emitCALL_Abs(Magic.getTocPointer().plus(Entrypoints.hackArrayLoadReadBarrierMethod.getOffset()));
+    if (pushResult) asm.emitPUSH_Reg(T0);
+  }
+
   static void compileArrayLoadBarrier(Assembler asm, boolean pushResult) {
     // on entry java stack contains ...|target_array_ref|array_index|
     // SP -> index, SP+4 -> target_ref
@@ -91,6 +143,75 @@
     if (pushResult) asm.emitPUSH_Reg(T0);
   }
 
+  static void compileArrayLoadPrimitiveShortBarrier(Assembler asm, boolean pushResult) {
+	  // on entry java stack contains ...|target_array_ref|array_index|
+	  // SP -> index, SP+4 -> target_ref
+	  BaselineCompilerImpl.genParameterRegisterLoad(asm, 2);
+	  asm.emitCALL_Abs(Magic.getTocPointer().plus(Entrypoints.arrayLoadPrimitiveShortReadBarrierMethod.getOffset()));
+	  if (pushResult) asm.emitPUSH_Reg(T0);
+  }
+  
+  static void compileArrayLoadPrimitiveCharBarrier(Assembler asm, boolean pushResult) {
+	  // on entry java stack contains ...|target_array_ref|array_index|
+	  // SP -> index, SP+4 -> target_ref
+	  BaselineCompilerImpl.genParameterRegisterLoad(asm, 2);
+	  asm.emitCALL_Abs(Magic.getTocPointer().plus(Entrypoints.arrayLoadPrimitiveCharReadBarrierMethod.getOffset()));
+	  if (pushResult) asm.emitPUSH_Reg(T0);
+  }
+  
+  static void compileArrayLoadPrimitiveByteBarrier(Assembler asm, boolean pushResult) {
+	  // on entry java stack contains ...|target_array_ref|array_index|
+	  // SP -> index, SP+4 -> target_ref
+	  BaselineCompilerImpl.genParameterRegisterLoad(asm, 2);
+	  asm.emitCALL_Abs(Magic.getTocPointer().plus(Entrypoints.arrayLoadPrimitiveByteReadBarrierMethod.getOffset()));
+	  if (pushResult) asm.emitPUSH_Reg(T0);
+  }
+  
+  static void compileArrayLoadPrimitiveFloatBarrier(Assembler asm, boolean pushResult) {
+	  // on entry java stack contains ...|target_array_ref|array_index|
+	  // SP -> index, SP+4 -> target_ref
+	  BaselineCompilerImpl.genParameterRegisterLoad(asm, 2);
+	  asm.emitCALL_Abs(Magic.getTocPointer().plus(Entrypoints.arrayLoadPrimitiveFloatReadBarrierMethod.getOffset()));
+	  if (pushResult) asm.emitPUSH_Reg(T0); //shouldn't be true
+  }
+  
+  static void compileArrayLoadPrimitiveIntBarrier(Assembler asm, boolean pushResult) {
+	  // on entry java stack contains ...|target_array_ref|array_index|
+	  // SP -> index, SP+4 -> target_ref
+	  BaselineCompilerImpl.genParameterRegisterLoad(asm, 2);
+	  asm.emitCALL_Abs(Magic.getTocPointer().plus(Entrypoints.arrayLoadPrimitiveIntReadBarrierMethod.getOffset()));
+	  if (pushResult) asm.emitPUSH_Reg(T0);
+  }
+  
+  static void compileArrayLoadPrimitiveLongBarrier(Assembler asm, boolean pushResult) {
+	  // on entry java stack contains ...|target_array_ref|array_index|
+	  // SP -> index, SP+4 -> target_ref
+	  BaselineCompilerImpl.genParameterRegisterLoad(asm, 2);
+	  asm.emitCALL_Abs(Magic.getTocPointer().plus(Entrypoints.arrayLoadPrimitiveLongReadBarrierMethod.getOffset()));
+	  if (pushResult) {
+		  asm.emitPUSH_Reg(T0);
+		  asm.emitPUSH_Reg(T1);
+	  }
+  }
+  
+  static void compileArrayLoadPrimitiveDoubleBarrier(Assembler asm, boolean pushResult) {
+	  // on entry java stack contains ...|target_array_ref|array_index|
+	  // SP -> index, SP+4 -> target_ref
+	  BaselineCompilerImpl.genParameterRegisterLoad(asm, 2);
+	  asm.emitCALL_Abs(Magic.getTocPointer().plus(Entrypoints.arrayLoadPrimitiveDoubleReadBarrierMethod.getOffset()));
+	  if (pushResult) { //jbs should NOT be true
+		  //adjustStack(-2*WORDSIZE, true);
+	      if (SSE2_FULL) {
+	        asm.emitMOVLPD_RegInd_Reg(SP, XMM0);
+	      } else {
+	        asm.emitFSTP_RegInd_Reg_Quad(SP, FP0);
+	      }
+		//  asm.emitPUSH_Reg(T1);
+		 // asm.emitPUSH_Reg(T0);  //jbs switched for debugging...
+	  }
+  }
+  
+
   static void compileGetfieldBarrier(Assembler asm, GPR reg, int locationMetadata) {
     //  on entry java stack contains ...|target_ref|
     //  SP -> target_ref
diff -r 743a2cc2ed20 -r 058fdc3780ba rvm/src/org/jikesrvm/compilers/baseline/ia32/BaselineCompilerImpl.java
--- a/rvm/src/org/jikesrvm/compilers/baseline/ia32/BaselineCompilerImpl.java	Tue Aug 04 11:04:15 2009 +1000
+++ b/rvm/src/org/jikesrvm/compilers/baseline/ia32/BaselineCompilerImpl.java	Mon Nov 16 09:21:21 2009 +1100
@@ -12,6 +12,7 @@
  */
 package org.jikesrvm.compilers.baseline.ia32;
 
+import org.jikesrvm.HeapLayoutConstants;
 import org.jikesrvm.SizeConstants;
 import org.jikesrvm.VM;
 import org.jikesrvm.adaptive.AosEntrypoints;
@@ -58,7 +59,6 @@
  * BaselineCompilerImpl is the baseline compiler implementation for the IA32 architecture.
  */
 public abstract class BaselineCompilerImpl extends BaselineCompiler implements BaselineConstants, SizeConstants {
-
   static {
     // Force resolution of BaselineMagic before using in genMagic
     Object x = BaselineMagic.generateMagic(null, null, null, Offset.zero());
@@ -519,8 +519,65 @@
     asm.emitPOP_Reg(T0); // T0 is array index
     asm.emitPOP_Reg(S0); // S0 is array ref
     genBoundsCheck(asm, T0, S0); // T0 is index, S0 is address of array
-    // push [S0+T0<<2]
-    asm.emitPUSH_RegIdx(S0, T0, Assembler.WORD, NO_SLOT);
+    if (MemoryManagerConstants.USE_PRIMITIVE_INT_ARRAYLETS) {
+      if (MemoryManagerConstants.INLINE_BASELINE_INT_READ_BARRIER) {
+        ForwardReference fr, fr2 = null;   
+        //jbs S0 holds array, T0 holds index 
+
+        //if (MemoryManagerConstants.DO_FIRSTN_OPT) {  //we can actually get rid of this - if not true, firstn_value = 0
+        asm.emitCMP_Reg_Imm(T0, MemoryManagerConstants.FIRSTN_INT_ELEMS); 
+        // Jmp around trap if index is OK
+        asm.emitBranchLikelyNextInstruction();
+        fr = asm.forwardJcc(Assembler.LLT);
+        //}
+        //check if in boot image, jump to fr
+        //FIXME - not 64-bit safe right now
+        if (!MemoryManagerConstants.BOOT_IMAGE_IS_ARRAYLETIZED) {
+          asm.emitCMP_Reg_Imm(S0, org.jikesrvm.HeapLayoutConstants.BOOT_IMAGE_DATA_END.toInt());
+
+          //inline barrier - slow path index >= SPINE_FIRSTN_ELEMENTS
+          fr2 = asm.forwardJcc(Assembler.LLT);
+        }
+        //T0 = T0 - SPINE_FIRSTN_ELEMENTS;
+        //T0 = index - SPINE_FIRSTN
+        asm.emitSUB_Reg_Imm(T0, MemoryManagerConstants.FIRSTN_INT_ELEMS);
+        //need another register to store result 
+        //T1 = T0
+        asm.emitMOV_Reg_Reg(T1, T0);
+        //T1 = T1 >> LOG_ELEMENTS_IN_ARRAYLET;
+        //T1 is the index into arraylet indirection pointers
+        asm.emitSAR_Reg_Imm(T1, MemoryManagerConstants.LOG_ELEMENTS_IN_INT_ARRAYLET);
+        //T1 is arrayletIndirIndex in MemoryManager
+        //T1 = T1 + SPINE_FIRSTN_ELEMENTS
+        //"index" into the spine array with arraylet indirection
+        asm.emitADD_Reg_Imm(T1, MemoryManagerConstants.FIRSTN_INT_ELEMS);
+        //need to get arraylet indirection - load address, follow that 
+        //T1 = S0[T1 << 2];
+        //T1 is arraylet address
+        asm.emitMOV_Reg_RegIdx(S0, S0, T1, (short)LG_WORDSIZE, NO_SLOT);
+        //now S0 is base - check for zeroArraylet?
+        //jbs - note - need to check if firstN_value == arraylet_elements?
+        //T0 = T0 AND ARRAYLET_ELEMENT_MASK
+        asm.emitAND_Reg_Imm(T0, MemoryManagerConstants.INT_ARRAYLET_MASK);
+        fr.resolve(asm);
+        if (fr2 != null) {
+          fr2.resolve(asm);
+        }
+        //push [T1+T0<<2];
+
+        //asm.emitMOV_Reg_RegIdx(value, S0, T0, (short)LG_WORDSIZE, NO_SLOT);
+        asm.emitPUSH_RegIdx(S0, T0, (short)LG_WORDSIZE, NO_SLOT);
+        //asm.emitPOP_Reg(value);                 // pop result
+        //done
+      } else {
+        asm.emitPUSH_Reg(S0);
+        asm.emitPUSH_Reg(T0);
+        Barriers.compileArrayLoadPrimitiveIntBarrier(asm, true);
+      }
+    } else {
+      // push [S0+T0<<2]
+      asm.emitPUSH_RegIdx(S0, T0, Assembler.WORD, NO_SLOT);
+    }
   }
 
   /**
@@ -528,8 +585,22 @@
    */
   @Override
   protected final void emit_faload() {
-    // identical to iaload
-    emit_iaload();
+    asm.emitPOP_Reg(T0); // T0 is array index
+    asm.emitPOP_Reg(S0); // S0 is array ref
+    genBoundsCheck(asm, T0, S0); // T0 is index, S0 is address of array
+    if (MemoryManagerConstants.USE_PRIMITIVE_FLOAT_ARRAYLETS) {
+      asm.emitPUSH_Reg(S0);
+      asm.emitPUSH_Reg(T0);
+      Barriers.compileArrayLoadPrimitiveFloatBarrier(asm, false); //true);
+      adjustStack(-WORDSIZE, true);
+      if (SSE2_FULL) {
+        asm.emitMOVSS_RegInd_Reg(SP, XMM0);
+      } else {
+        asm.emitFSTP_RegInd_Reg(SP, FP0);
+      }
+    } else {
+      asm.emitPUSH_RegIdx(S0, T0, Assembler.WORD, NO_SLOT);
+    }
   }
 
   /**
@@ -540,11 +611,56 @@
     asm.emitPOP_Reg(T0); // T0 is array index
     asm.emitPOP_Reg(T1); // T1 is array ref
     genBoundsCheck(asm, T0, T1); // T0 is index, T1 is address of array
-    if (MemoryManagerConstants.NEEDS_READ_BARRIER) {
-      // rewind 2 args on stack
-      asm.emitPUSH_Reg(T1); // T1 is array ref
-      asm.emitPUSH_Reg(T0); // T0 is array index
-      Barriers.compileArrayLoadBarrier(asm, true);
+    if (MemoryManagerConstants.NEEDS_READ_BARRIER || MemoryManagerConstants.USE_REFERENCE_ARRAYLETS || MemoryManagerConstants.USE_OBJECT_ARRAY_ACCESS_BARRIER) {
+      if (MemoryManagerConstants.INLINE_BASELINE_REFERENCE_READ_BARRIER) {
+        ForwardReference fr, fr2 = null;
+        //if (MemoryManagerConstants.DO_FIRSTN_OPT) {  //we can actually get rid of this - if not true, firstn_value = 0
+        asm.emitCMP_Reg_Imm(T0, MemoryManagerConstants.FIRSTN_REF_ELEMS); 
+        // Jmp around trap if index is OK
+        asm.emitBranchLikelyNextInstruction();
+        fr = asm.forwardJcc(Assembler.LLT);
+        //}
+        //check if in boot image, jump to fr
+        //FIXME - not 64-bit safe right now
+        if (!MemoryManagerConstants.BOOT_IMAGE_IS_ARRAYLETIZED) {
+          asm.emitCMP_Reg_Imm(T1, org.jikesrvm.HeapLayoutConstants.BOOT_IMAGE_DATA_END.toInt());
+          //inline barrier - slow path index >= SPINE_FIRSTN_ELEMENTS
+          fr2 = asm.forwardJcc(Assembler.LLT);
+        }
+        //T0 = T0 - SPINE_FIRSTN_ELEMENTS;
+        //T0 = index - SPINE_FIRSTN
+        asm.emitSUB_Reg_Imm(T0, MemoryManagerConstants.FIRSTN_REF_ELEMS);
+        //need another register to store result 
+        //T1 = T0
+        asm.emitMOV_Reg_Reg(S0, T0);
+        //T1 = T1 >> LOG_ELEMENTS_IN_ARRAYLET;
+        //T1 is the index into arraylet indirection pointers
+        asm.emitSAR_Reg_Imm(S0, MemoryManagerConstants.LOG_ELEMENTS_IN_REF_ARRAYLET);
+        //T1 is arrayletIndirIndex in MemoryManager
+        //T1 = T1 + SPINE_FIRSTN_ELEMENTS
+        //"index" into the spine array with arraylet indirection
+        asm.emitADD_Reg_Imm(S0, MemoryManagerConstants.FIRSTN_REF_ELEMS);
+        //need to get arraylet indirection - load address, follow that 
+        //T1 = S0[T1 << 2];
+        //T1 is arraylet address
+        asm.emitMOV_Reg_RegIdx(T1, T1, S0, (short)LG_WORDSIZE, NO_SLOT);
+        //now S0 is base - check for zeroArraylet?
+        //jbs - note - need to check if firstN_value == arraylet_elements?
+        //T0 = T0 AND ARRAYLET_ELEMENT_MASK
+        asm.emitAND_Reg_Imm(T0, MemoryManagerConstants.REF_ARRAYLET_MASK);
+        fr.resolve(asm);
+        if (fr2 != null) {
+          fr2.resolve(asm);
+        }
+        //push [T1+T0<<2];
+        asm.emitPUSH_RegIdx(T1, T0, (short)LG_WORDSIZE, NO_SLOT);
+        //done
+      } else {
+        // rewind 2 args on stack
+        asm.emitPUSH_Reg(T1); // T1 is array ref
+        asm.emitPUSH_Reg(T0); // T0 is array index
+        Barriers.compileArrayLoadBarrier(asm, true);
+      }
     } else {
       asm.emitPUSH_RegIdx(T1, T0, (short)LG_WORDSIZE, NO_SLOT); // push [S0+T0*WORDSIZE]
     }
@@ -559,12 +675,87 @@
     asm.emitPOP_Reg(S0); // S0 is array ref
     genBoundsCheck(asm, T0, S0); // T0 is index, S0 is address of array
     // T1 = (int)[S0+T0<<1]
-    if (VM.BuildFor32Addr) {
-      asm.emitMOVZX_Reg_RegIdx_Word(T1, S0, T0, Assembler.SHORT, NO_SLOT);
-    } else {
-      asm.emitMOVZXQ_Reg_RegIdx_Word(T1, S0, T0, Assembler.SHORT, NO_SLOT);
-    }
-    asm.emitPUSH_Reg(T1);        // push short onto stack
+    if (MemoryManagerConstants.USE_PRIMITIVE_CHAR_ARRAYLETS) {
+      if (MemoryManagerConstants.INLINE_BASELINE_CHAR_READ_BARRIER) {
+        ForwardReference fr, fr2 = null;   
+        //jbs S0 holds array, T0 holds index 
+
+        //if (MemoryManagerConstants.DO_FIRSTN_OPT) {  //we can actually get rid of this - if not true, firstn_value = 0
+        asm.emitCMP_Reg_Imm(T0, MemoryManagerConstants.FIRSTN_SHORT_ELEMS); 
+        // Jmp around trap if index is OK
+        asm.emitBranchLikelyNextInstruction();
+        fr = asm.forwardJcc(Assembler.LLT);
+        //}
+        //check if in boot image, jump to fr
+        //FIXME - not 64-bit safe right now
+        if (!MemoryManagerConstants.BOOT_IMAGE_IS_ARRAYLETIZED) {
+          asm.emitCMP_Reg_Imm(S0, org.jikesrvm.HeapLayoutConstants.BOOT_IMAGE_DATA_END.toInt());
+
+          //inline barrier - slow path index >= SPINE_FIRSTN_ELEMENTS
+          fr2 = asm.forwardJcc(Assembler.LLT);
+        }
+        //T0 = T0 - SPINE_FIRSTN_ELEMENTS;
+        //T0 = index - SPINE_FIRSTN
+        asm.emitSUB_Reg_Imm(T0, MemoryManagerConstants.FIRSTN_SHORT_ELEMS);
+        //need another register to store result 
+        //T1 = T0
+        asm.emitMOV_Reg_Reg(T1, T0);
+        //T1 = T1 >> LOG_ELEMENTS_IN_ARRAYLET;
+        //T1 is the index into arraylet indirection pointers
+        asm.emitSAR_Reg_Imm(T1, MemoryManagerConstants.LOG_ELEMENTS_IN_SHORT_ARRAYLET);
+        //T1 is arrayletIndirIndex in MemoryManager
+        asm.emitSAL_Reg_Imm(T1, LG_WORDSIZE);
+        //T1 = T1 + SPINE_FIRSTN_ELEMENTS
+        //"index" into the spine array with arraylet indirection
+        asm.emitADD_Reg_Imm(T1, MemoryManagerConstants.FIRSTN_SHORT_BYTES);// MemoryManagerConstants.FIRSTN_SHORT_VALUE);
+        //need to get arraylet indirection - load address, follow that 
+        //T1 = S0[T1 << 2];
+        //T1 is arraylet address
+        //asm.emitMOV_Reg_RegIdx(S0, S0, T1, Assembler.SHORT, NO_SLOT);
+        /*if (VM.BuildFor32Addr) {
+    			asm.emitMOVZX_Reg_RegIdx_Word(S0, S0, T1, Assembler.SHORT, NO_SLOT);
+    		} else {
+    			asm.emitMOVZXQ_Reg_RegIdx_Word(S0, S0, T1, Assembler.SHORT, NO_SLOT);
+    		}*/
+        //jbs now T1 is offset off of S0 we need to load.
+        asm.emitADD_Reg_Reg(S0, T1);
+        asm.emitMOV_Reg_RegInd(S0, S0); 
+        //asm.emitMOV_Reg_RegDisp(S0, S0, T1);
+
+        //now S0 is base - check for zeroArraylet?
+        //jbs - note - need to check if firstN_value == arraylet_elements?
+        //T0 = T0 AND ARRAYLET_ELEMENT_MASK
+        asm.emitAND_Reg_Imm(T0, MemoryManagerConstants.SHORT_ARRAYLET_MASK);
+        fr.resolve(asm);
+        if (fr2 != null) {
+          fr2.resolve(asm);
+        }
+        //push [T1+T0<<2];
+
+        //asm.emitMOV_Reg_RegIdx(value, S0, T0, (short)LG_WORDSIZE, NO_SLOT);
+        //asm.emitPUSH_RegIdx(S0, T0, Assembler.SHORT, NO_SLOT);
+        //asm.emitPOP_Reg(value);                 // pop result
+        if (VM.BuildFor32Addr) {
+          asm.emitMOVZX_Reg_RegIdx_Word(T1, S0, T0, Assembler.SHORT, NO_SLOT);
+        } else {
+          asm.emitMOVZXQ_Reg_RegIdx_Word(T1, S0, T0, Assembler.SHORT, NO_SLOT);
+        }
+        asm.emitPUSH_Reg(T1);        // push short onto stack
+        //done
+      } else {
+        //asm.emitADD_Reg_Imm(SP, WORDSIZE * -2);     // rewind 2 args on stack
+        asm.emitPUSH_Reg(S0);
+        asm.emitPUSH_Reg(T0);
+        Barriers.compileArrayLoadPrimitiveCharBarrier(asm, true);
+      }
+    } else {
+      if (VM.BuildFor32Addr) {
+        asm.emitMOVZX_Reg_RegIdx_Word(T1, S0, T0, Assembler.SHORT, NO_SLOT);
+      } else {
+        asm.emitMOVZXQ_Reg_RegIdx_Word(T1, S0, T0, Assembler.SHORT, NO_SLOT);
+      }
+      asm.emitPUSH_Reg(T1);        // push short onto stack
+    }
   }
 
   /**
@@ -576,12 +767,88 @@
     asm.emitPOP_Reg(S0); // S0 is array ref
     genBoundsCheck(asm, T0, S0); // T0 is index, S0 is address of array
     // T1 = (int)[S0+T0<<1]
-    if (VM.BuildFor32Addr) {
-      asm.emitMOVSX_Reg_RegIdx_Word(T1, S0, T0, Assembler.SHORT, NO_SLOT);
-    } else {
-      asm.emitMOVSXQ_Reg_RegIdx_Word(T1, S0, T0, Assembler.SHORT, NO_SLOT);
-    }
-    asm.emitPUSH_Reg(T1);        // push short onto stack
+    //jbs changed arraylets
+    if (MemoryManagerConstants.USE_PRIMITIVE_SHORT_ARRAYLETS) {
+      //asm.emitADD_Reg_Imm(SP, WORDSIZE * -2);     // rewind 2 args on stack
+      if (MemoryManagerConstants.INLINE_BASELINE_CHAR_READ_BARRIER) {
+        ForwardReference fr, fr2 = null;   
+        //jbs S0 holds array, T0 holds index 
+
+        //if (MemoryManagerConstants.DO_FIRSTN_OPT) {  //we can actually get rid of this - if not true, firstn_value = 0
+        asm.emitCMP_Reg_Imm(T0, MemoryManagerConstants.FIRSTN_SHORT_ELEMS); 
+        // Jmp around trap if index is OK
+        asm.emitBranchLikelyNextInstruction();
+        fr = asm.forwardJcc(Assembler.LLT);
+        //}
+        //check if in boot image, jump to fr
+        //FIXME - not 64-bit safe right now
+        if (!MemoryManagerConstants.BOOT_IMAGE_IS_ARRAYLETIZED) {
+          asm.emitCMP_Reg_Imm(S0, org.jikesrvm.HeapLayoutConstants.BOOT_IMAGE_DATA_END.toInt());
+
+          //inline barrier - slow path index >= SPINE_FIRSTN_ELEMENTS
+          fr2 = asm.forwardJcc(Assembler.LLT);
+        }
+        //T0 = T0 - SPINE_FIRSTN_ELEMENTS;
+        //T0 = index - SPINE_FIRSTN
+        asm.emitSUB_Reg_Imm(T0, MemoryManagerConstants.FIRSTN_SHORT_ELEMS);
+        //need another register to store result 
+        //T1 = T0
+        asm.emitMOV_Reg_Reg(T1, T0);
+        //T1 = T1 >> LOG_ELEMENTS_IN_ARRAYLET;
+        //T1 is the index into arraylet indirection pointers
+        asm.emitSAR_Reg_Imm(T1, MemoryManagerConstants.LOG_ELEMENTS_IN_SHORT_ARRAYLET);
+        //T1 is arrayletIndirIndex in MemoryManager
+        asm.emitSAL_Reg_Imm(T1, LG_WORDSIZE);
+        //T1 = T1 + SPINE_FIRSTN_ELEMENTS
+        //"index" into the spine array with arraylet indirection
+        asm.emitADD_Reg_Imm(T1, MemoryManagerConstants.FIRSTN_SHORT_BYTES);// MemoryManagerConstants.FIRSTN_SHORT_VALUE);
+        //need to get arraylet indirection - load address, follow that 
+        //T1 = S0[T1 << 2];
+        //T1 is arraylet address
+        //asm.emitMOV_Reg_RegIdx(S0, S0, T1, Assembler.SHORT, NO_SLOT);
+        /*if (VM.BuildFor32Addr) {
+    			asm.emitMOVZX_Reg_RegIdx_Word(S0, S0, T1, Assembler.SHORT, NO_SLOT);
+    		} else {
+    			asm.emitMOVZXQ_Reg_RegIdx_Word(S0, S0, T1, Assembler.SHORT, NO_SLOT);
+    		}*/
+        //jbs now T1 is offset off of S0 we need to load.
+        asm.emitADD_Reg_Reg(S0, T1);
+        asm.emitMOV_Reg_RegInd(S0, S0); 
+        //asm.emitMOV_Reg_RegDisp(S0, S0, T1);
+
+        //now S0 is base - check for zeroArraylet?
+        //jbs - note - need to check if firstN_value == arraylet_elements?
+        //T0 = T0 AND ARRAYLET_ELEMENT_MASK
+        asm.emitAND_Reg_Imm(T0, MemoryManagerConstants.SHORT_ARRAYLET_MASK);
+        fr.resolve(asm);
+        if (fr2 != null) {
+          fr2.resolve(asm);
+        }
+        //push [T1+T0<<2];
+
+        //asm.emitMOV_Reg_RegIdx(value, S0, T0, (short)LG_WORDSIZE, NO_SLOT);
+        //asm.emitPUSH_RegIdx(S0, T0, Assembler.SHORT, NO_SLOT);
+        //asm.emitPOP_Reg(value);                 // pop result
+        if (VM.BuildFor32Addr) {
+          asm.emitMOVSX_Reg_RegIdx_Word(T1, S0, T0, Assembler.SHORT, NO_SLOT);
+        } else {
+          asm.emitMOVSXQ_Reg_RegIdx_Word(T1, S0, T0, Assembler.SHORT, NO_SLOT);
+        }
+        asm.emitPUSH_Reg(T1);        // push short onto stack
+        //done
+      } else {
+        asm.emitPUSH_Reg(S0);
+        asm.emitPUSH_Reg(T0);
+        Barriers.compileArrayLoadPrimitiveShortBarrier(asm, true);
+      }
+    } else {
+      if (VM.BuildFor32Addr) {
+        asm.emitMOVSX_Reg_RegIdx_Word(T1, S0, T0, Assembler.SHORT, NO_SLOT);
+      } else {
+        asm.emitMOVSXQ_Reg_RegIdx_Word(T1, S0, T0, Assembler.SHORT, NO_SLOT);
+      }
+      asm.emitPUSH_Reg(T1);        // push short onto stack
+    }
   }
 
   /**
@@ -592,13 +859,89 @@
     asm.emitPOP_Reg(T0); // T0 is array index
     asm.emitPOP_Reg(S0); // S0 is array ref
     genBoundsCheck(asm, T0, S0); // T0 is index, S0 is address of array
+    boolean arrayletize = true;
     // T1 = (int)[S0+T0<<1]
-    if (VM.BuildFor32Addr) {
-      asm.emitMOVSX_Reg_RegIdx_Byte(T1, S0, T0, Assembler.BYTE, NO_SLOT);
-    } else {
-      asm.emitMOVSXQ_Reg_RegIdx_Byte(T1, S0, T0, Assembler.BYTE, NO_SLOT);
-    }
-    asm.emitPUSH_Reg(T1);        // push byte onto stack
+    if (arrayletize && MemoryManagerConstants.USE_PRIMITIVE_BOOLEAN_ARRAYLETS || MemoryManagerConstants.USE_PRIMITIVE_BYTE_ARRAYLETS) {
+      //asm.emitADD_Reg_Imm(SP, WORDSIZE * -2);     // rewind 2 args on stack
+      if (MemoryManagerConstants.INLINE_BASELINE_BOOL_READ_BARRIER) {
+        ForwardReference fr, fr2 = null;   
+        //jbs S0 holds array, T0 holds index 
+
+        //if (MemoryManagerConstants.DO_FIRSTN_OPT) {  //we can actually get rid of this - if not true, firstn_value = 0
+        asm.emitCMP_Reg_Imm(T0, MemoryManagerConstants.FIRSTN_BYTE_ELEMS); 
+        // Jmp around trap if index is OK
+        asm.emitBranchLikelyNextInstruction();
+        fr = asm.forwardJcc(Assembler.LLT);
+        //}
+        //check if in boot image, jump to fr
+        //FIXME - not 64-bit safe right now
+        if (!MemoryManagerConstants.BOOT_IMAGE_IS_ARRAYLETIZED) {
+          asm.emitCMP_Reg_Imm(S0, org.jikesrvm.HeapLayoutConstants.BOOT_IMAGE_DATA_END.toInt());
+
+          //inline barrier - slow path index >= SPINE_FIRSTN_ELEMENTS
+          fr2 = asm.forwardJcc(Assembler.LLT);
+        }
+        //T0 = T0 - SPINE_FIRSTN_ELEMENTS;
+        //T0 = index - SPINE_FIRSTN
+        asm.emitSUB_Reg_Imm(T0, MemoryManagerConstants.FIRSTN_BYTE_ELEMS);
+        //need another register to store result 
+        //T1 = T0
+        asm.emitMOV_Reg_Reg(T1, T0);
+        //T1 = T1 >> LOG_ELEMENTS_IN_ARRAYLET;
+        //T1 is the index into arraylet indirection pointers
+        asm.emitSAR_Reg_Imm(T1, MemoryManagerConstants.LOG_ELEMENTS_IN_BYTE_ARRAYLET);
+        //T1 is arrayletIndirIndex in MemoryManager
+        asm.emitSAL_Reg_Imm(T1, LG_WORDSIZE);
+        //T1 = T1 + SPINE_FIRSTN_ELEMENTS
+        //"index" into the spine array with arraylet indirection
+        asm.emitADD_Reg_Imm(T1, MemoryManagerConstants.FIRSTN_BYTE_BYTES);// MemoryManagerConstants.FIRSTN_SHORT_VALUE);
+        //need to get arraylet indirection - load address, follow that 
+        //T1 = S0[T1 << 2];
+        //T1 is arraylet address
+        //asm.emitMOV_Reg_RegIdx(S0, S0, T1, Assembler.SHORT, NO_SLOT);
+        /*if (VM.BuildFor32Addr) {
+    			asm.emitMOVZX_Reg_RegIdx_Word(S0, S0, T1, Assembler.SHORT, NO_SLOT);
+    		} else {
+    			asm.emitMOVZXQ_Reg_RegIdx_Word(S0, S0, T1, Assembler.SHORT, NO_SLOT);
+    		}*/
+        //jbs now T1 is offset off of S0 we need to load.
+        asm.emitADD_Reg_Reg(S0, T1);
+        asm.emitMOV_Reg_RegInd(S0, S0); 
+        //asm.emitMOV_Reg_RegDisp(S0, S0, T1);
+
+        //now S0 is base - check for zeroArraylet?
+        //jbs - note - need to check if firstN_value == arraylet_elements?
+        //T0 = T0 AND ARRAYLET_ELEMENT_MASK
+        asm.emitAND_Reg_Imm(T0, MemoryManagerConstants.BYTE_ARRAYLET_MASK);
+        fr.resolve(asm);
+        if (fr2 != null) {
+          fr2.resolve(asm);
+        }
+        //push [T1+T0<<2];
+
+        //asm.emitMOV_Reg_RegIdx(value, S0, T0, (short)LG_WORDSIZE, NO_SLOT);
+        //asm.emitPUSH_RegIdx(S0, T0, Assembler.SHORT, NO_SLOT);
+        //asm.emitPOP_Reg(value);                 // pop result
+        if (VM.BuildFor32Addr) {
+          asm.emitMOVSX_Reg_RegIdx_Byte(T1, S0, T0, Assembler.BYTE, NO_SLOT);
+        } else {
+          asm.emitMOVSXQ_Reg_RegIdx_Byte(T1, S0, T0, Assembler.BYTE, NO_SLOT);
+        }
+        asm.emitPUSH_Reg(T1);        // push short onto stack
+        //done
+      } else {
+        asm.emitPUSH_Reg(S0);
+        asm.emitPUSH_Reg(T0);
+        Barriers.compileArrayLoadPrimitiveByteBarrier(asm, true);
+      }
+    } else {
+      if (VM.BuildFor32Addr) {
+        asm.emitMOVSX_Reg_RegIdx_Byte(T1, S0, T0, Assembler.BYTE, NO_SLOT);
+      } else {
+        asm.emitMOVSXQ_Reg_RegIdx_Byte(T1, S0, T0, Assembler.BYTE, NO_SLOT);
+      }
+      asm.emitPUSH_Reg(T1);        // push byte onto stack
+    }
   }
 
   /**
@@ -608,21 +951,49 @@
   protected final void emit_laload() {
     asm.emitPOP_Reg(T0); // T0 is array index
     asm.emitPOP_Reg(T1); // T1 is array ref
-    if (VM.BuildFor32Addr && SSE2_BASE) {
-      adjustStack(WORDSIZE*-2, true); // create space for result
-    }
     genBoundsCheck(asm, T0, T1); // T0 is index, T1 is address of array
-    if (VM.BuildFor32Addr) {
-      if (SSE2_BASE) {
-        asm.emitMOVQ_Reg_RegIdx(XMM0, T1, T0, Assembler.LONG, NO_SLOT);
-        asm.emitMOVQ_RegInd_Reg(SP, XMM0);
-      } else {
-        asm.emitPUSH_RegIdx(T1, T0, Assembler.LONG, ONE_SLOT); // load high part of desired long array element
-        asm.emitPUSH_RegIdx(T1, T0, Assembler.LONG, NO_SLOT);  // load low part of desired long array element
-      }
-    } else {
-      adjustStack(-WORDSIZE, true);
-      asm.emitPUSH_RegIdx(T1, T0, Assembler.LONG, NO_SLOT);  // load desired long array element
+    ForwardReference fr = null;
+    ForwardReference fr2 = null;
+    if (MemoryManagerConstants.USE_PRIMITIVE_LONG_ARRAYLETS) {
+      asm.emitCMP_Reg_Imm(T0, MemoryManagerConstants.FIRSTN_LONG_ELEMS); 
+      // Jmp around trap if index is OK
+      asm.emitBranchLikelyNextInstruction();
+      fr = asm.forwardJcc(Assembler.LLT);
+      //check if in boot image, jump to fr
+      //FIXME - not 64-bit safe right now
+      if (!MemoryManagerConstants.BOOT_IMAGE_IS_ARRAYLETIZED) {
+        asm.emitCMP_Reg_Imm(T1, org.jikesrvm.HeapLayoutConstants.BOOT_IMAGE_DATA_END.toInt());
+        //inline barrier - slow path index >= SPINE_FIRSTN_ELEMENTS
+        fr2 = asm.forwardJcc(Assembler.LLT);
+      }
+      //VM.sysWrite(" In primitiveLoadLongBarrier, got into barrier part "); VM.sysWriteln(MemoryManagerConstants.FIRSTN_LONG_ELEMS); 
+      //}
+      //asm.emitADD_Reg_Imm(SP, WORDSIZE * -2);     // rewind 2 args on stack
+      asm.emitPUSH_Reg(T1);
+      asm.emitPUSH_Reg(T0);
+      Barriers.compileArrayLoadPrimitiveLongBarrier(asm, true);
+    } else {
+      if (fr != null) {
+        fr.resolve(asm);
+      } 
+      if (fr2 != null) {
+        fr2.resolve(asm);
+      }
+      if (VM.BuildFor32Addr) {
+        if (SSE2_BASE) {
+          //jbs added line back here
+          adjustStack(WORDSIZE*-2, true); // create space for result
+
+          asm.emitMOVQ_Reg_RegIdx(XMM0, T1, T0, Assembler.LONG, NO_SLOT);
+          asm.emitMOVQ_RegInd_Reg(SP, XMM0);
+        } else {
+          asm.emitPUSH_RegIdx(T1, T0, Assembler.LONG, ONE_SLOT); // load high part of desired long array element
+          asm.emitPUSH_RegIdx(T1, T0, Assembler.LONG, NO_SLOT);  // load low part of desired long array element
+        }
+      } else {
+        adjustStack(-WORDSIZE, true);
+        asm.emitPUSH_RegIdx(T1, T0, Assembler.LONG, NO_SLOT);  // load desired long array element
+      }
     }
   }
 
@@ -631,8 +1002,57 @@
    */
   @Override
   protected final void emit_daload() {
-    // identical to laload
-    emit_laload();
+    asm.emitPOP_Reg(T0); // T0 is array index
+    asm.emitPOP_Reg(T1); // T1 is array ref
+    genBoundsCheck(asm, T0, T1); // T0 is index, T1 is address of array
+    //jbs changed arraylets
+    ForwardReference fr = null;
+    ForwardReference fr2 = null;
+    if (MemoryManagerConstants.USE_PRIMITIVE_DOUBLE_ARRAYLETS) {
+      asm.emitCMP_Reg_Imm(T0, MemoryManagerConstants.FIRSTN_DOUBLE_ELEMS); 
+      // Jmp around trap if index is OK
+      asm.emitBranchLikelyNextInstruction();
+      fr = asm.forwardJcc(Assembler.LLT);
+      //}
+      //check if in boot image, jump to fr
+      //FIXME - not 64-bit safe right now
+      if (!MemoryManagerConstants.BOOT_IMAGE_IS_ARRAYLETIZED) {
+        asm.emitCMP_Reg_Imm(T1, org.jikesrvm.HeapLayoutConstants.BOOT_IMAGE_DATA_END.toInt());
+        //inline barrier - slow path index >= SPINE_FIRSTN_ELEMENTS
+        fr2 = asm.forwardJcc(Assembler.LLT);
+      }
+      asm.emitPUSH_Reg(T1);
+      asm.emitPUSH_Reg(T0);
+      Barriers.compileArrayLoadPrimitiveDoubleBarrier(asm, false);
+      adjustStack(-2*WORDSIZE, true);
+      if (SSE2_FULL) {
+        asm.emitMOVLPD_RegInd_Reg(SP, XMM0);
+      } else {
+        asm.emitFSTP_RegInd_Reg_Quad(SP, FP0);
+      }
+    } else {
+      if (fr != null) {
+        fr.resolve(asm);
+      } 
+      if (fr2 != null) {
+        fr2.resolve(asm);
+      }
+      if (VM.BuildFor32Addr) {
+        if (SSE2_BASE) {
+          //jbs added line back here
+          adjustStack(WORDSIZE*-2, true); // create space for result
+
+          asm.emitMOVQ_Reg_RegIdx(XMM0, T1, T0, Assembler.LONG, NO_SLOT);
+          asm.emitMOVQ_RegInd_Reg(SP, XMM0);
+        } else {
+          asm.emitPUSH_RegIdx(T1, T0, Assembler.LONG, ONE_SLOT); // load high part of desired long array element
+          asm.emitPUSH_RegIdx(T1, T0, Assembler.LONG, NO_SLOT);  // load low part of desired long array element
+        }
+      } else {
+        adjustStack(-WORDSIZE, true);
+        asm.emitPUSH_RegIdx(T1, T0, Assembler.LONG, NO_SLOT);  // load desired long array element
+      }
+    }
   }
 
   /*
@@ -649,7 +1069,36 @@
     asm.emitPOP_Reg(T0); // T0 is array index
     asm.emitPOP_Reg(S0); // S0 is array ref
     genBoundsCheck(asm, T0, S0);                // T0 is index, S0 is address of array
-    asm.emitMOV_RegIdx_Reg(S0, T0, Assembler.WORD, NO_SLOT, T1); // [S0 + T0<<2] <- T1
+    //jbs changed arraylets
+    ForwardReference fr = null;
+    ForwardReference fr2 = null;
+    if (MemoryManagerConstants.USE_PRIMITIVE_INT_ARRAYLETS) {
+      asm.emitCMP_Reg_Imm(T0, MemoryManagerConstants.FIRSTN_INT_ELEMS); 
+      // Jmp around trap if index is OK
+      asm.emitBranchLikelyNextInstruction();
+      fr = asm.forwardJcc(Assembler.LLT);
+      //}
+      //check if in boot image, jump to fr
+      //FIXME - not 64-bit safe right now
+      if (!MemoryManagerConstants.BOOT_IMAGE_IS_ARRAYLETIZED) {
+        asm.emitCMP_Reg_Imm(S0, org.jikesrvm.HeapLayoutConstants.BOOT_IMAGE_DATA_END.toInt());
+
+        //inline barrier - slow path index >= SPINE_FIRSTN_ELEMENTS
+        fr2 = asm.forwardJcc(Assembler.LLT);
+      }
+      asm.emitPUSH_Reg(S0);
+      asm.emitPUSH_Reg(T0);
+      asm.emitPUSH_Reg(T1);
+      Barriers.compileArrayStorePrimitiveIntBarrier(asm); 	
+    } else {
+      if (fr != null) {
+        fr.resolve(asm);
+      } 
+      if (fr2 != null) {
+        fr2.resolve(asm);
+      }
+      asm.emitMOV_RegIdx_Reg(S0, T0, Assembler.WORD, NO_SLOT, T1); // [S0 + T0<<2] <- T1
+    }
   }
 
   /**
@@ -657,8 +1106,27 @@
    */
   @Override
   protected final void emit_fastore() {
-    // identical to iastore
-    emit_iastore();
+    Barriers.compileModifyCheck(asm, 8);
+    asm.emitPOP_Reg(T1); // T1 is the value
+    asm.emitPOP_Reg(T0); // T0 is array index
+    asm.emitPOP_Reg(S0); // S0 is array ref
+    genBoundsCheck(asm, T0, S0);         
+    if (MemoryManagerConstants.USE_PRIMITIVE_FLOAT_ARRAYLETS) {
+      asm.emitPUSH_Reg(S0);
+      asm.emitPUSH_Reg(T0);
+      asm.emitPUSH_Reg(T1);
+      if (NUM_PARAMETER_FPRS > 0) {
+        if (SSE2_FULL) {
+          asm.emitMOVSS_Reg_RegDisp(XMM0, SP, NO_SLOT);
+        } else {
+          asm.emitFLD_Reg_RegDisp(FP0, SP, NO_SLOT);
+        }
+      }
+      Barriers.compileArrayStorePrimitiveFloatBarrier(asm);
+    } else {
+      // T0 is index, S0 is address of array
+      asm.emitMOV_RegIdx_Reg(S0, T0, Assembler.WORD, NO_SLOT, T1); // [S0 + T0<<2] <- T1
+    }
   }
 
 
@@ -673,7 +1141,8 @@
     genParameterRegisterLoad(asm, 2);    // pass 2 parameter
     // call checkstore(array ref, value)
     asm.emitCALL_Abs(Magic.getTocPointer().plus(Entrypoints.checkstoreMethod.getOffset()));
-    if (MemoryManagerConstants.NEEDS_WRITE_BARRIER) {
+    //jbs added arraylet
+    if (MemoryManagerConstants.NEEDS_WRITE_BARRIER || MemoryManagerConstants.USE_REFERENCE_ARRAYLETS || MemoryManagerConstants.USE_OBJECT_ARRAY_ACCESS_BARRIER) {
       if (VM.BuildFor32Addr) {
         asm.emitMOV_Reg_RegDisp(T0, SP, ONE_SLOT);  // T0 is array index
         asm.emitMOV_Reg_RegDisp(S0, SP, TWO_SLOTS); // S0 is array ref
@@ -706,8 +1175,37 @@
     asm.emitPOP_Reg(T0); // T0 is array index
     asm.emitPOP_Reg(S0); // S0 is array ref
     genBoundsCheck(asm, T0, S0);        // T0 is index, S0 is address of array
-    // store halfword element into array i.e. [S0 +T0] <- T1 (halfword)
-    asm.emitMOV_RegIdx_Reg_Word(S0, T0, Assembler.SHORT, NO_SLOT, T1);
+    //jbs changed arraylets
+    ForwardReference fr = null;
+    ForwardReference fr2 = null;
+    if (MemoryManagerConstants.USE_PRIMITIVE_CHAR_ARRAYLETS) {
+	asm.emitCMP_Reg_Imm(T0, MemoryManagerConstants.FIRSTN_SHORT_ELEMS); 
+	// Jmp around trap if index is OK
+	asm.emitBranchLikelyNextInstruction();
+	fr = asm.forwardJcc(Assembler.LLT);
+		//}
+		//check if in boot image, jump to fr
+		//FIXME - not 64-bit safe right now
+	if (!MemoryManagerConstants.BOOT_IMAGE_IS_ARRAYLETIZED) {
+	    asm.emitCMP_Reg_Imm(S0, org.jikesrvm.HeapLayoutConstants.BOOT_IMAGE_DATA_END.toInt());
+	    
+	    //inline barrier - slow path index >= SPINE_FIRSTN_ELEMENTS
+	    fr2 = asm.forwardJcc(Assembler.LLT);
+	}
+      asm.emitPUSH_Reg(S0);
+      asm.emitPUSH_Reg(T0);
+      asm.emitPUSH_Reg(T1);
+      Barriers.compileArrayStorePrimitiveCharBarrier(asm); 	
+    } else {
+	if (fr != null) {
+	    fr.resolve(asm);
+	} 
+	if (fr2 != null) {
+	    fr2.resolve(asm);
+	}
+      // store halfword element into array i.e. [S0 +T0] <- T1 (halfword)
+      asm.emitMOV_RegIdx_Reg_Word(S0, T0, Assembler.SHORT, NO_SLOT, T1);
+    }
   }
 
   /**
@@ -715,8 +1213,42 @@
    */
   @Override
   protected final void emit_sastore() {
-    // identical to castore
-    emit_castore();
+    Barriers.compileModifyCheck(asm, 8);
+    asm.emitPOP_Reg(T1); // T1 is the value
+    asm.emitPOP_Reg(T0); // T0 is array index
+    asm.emitPOP_Reg(S0); // S0 is array ref
+    genBoundsCheck(asm, T0, S0);        // T0 is index, S0 is address of array
+ //jbs changed arraylet
+    ForwardReference fr = null;
+    ForwardReference fr2 = null;
+    if (MemoryManagerConstants.USE_PRIMITIVE_SHORT_ARRAYLETS) {
+	asm.emitCMP_Reg_Imm(T0, MemoryManagerConstants.FIRSTN_SHORT_ELEMS); 
+	// Jmp around trap if index is OK
+	asm.emitBranchLikelyNextInstruction();
+	fr = asm.forwardJcc(Assembler.LLT);
+	//}
+	//check if in boot image, jump to fr
+	//FIXME - not 64-bit safe right now
+	if (!MemoryManagerConstants.BOOT_IMAGE_IS_ARRAYLETIZED) {
+	    asm.emitCMP_Reg_Imm(S0, org.jikesrvm.HeapLayoutConstants.BOOT_IMAGE_DATA_END.toInt());
+	    
+	    //inline barrier - slow path index >= SPINE_FIRSTN_ELEMENTS
+	    fr2 = asm.forwardJcc(Assembler.LLT);
+	}
+      asm.emitPUSH_Reg(S0);
+      asm.emitPUSH_Reg(T0);
+      asm.emitPUSH_Reg(T1);
+      Barriers.compileArrayStorePrimitiveShortBarrier(asm);
+    } else {
+	if (fr != null) {
+	    fr.resolve(asm);
+	} 
+	if (fr2 != null) {
+	    fr2.resolve(asm);
+	}
+      // store halfword element into array i.e. [S0 +T0] <- T1 (halfword)
+      asm.emitMOV_RegIdx_Reg_Word(S0, T0, Assembler.SHORT, NO_SLOT, T1);
+    }
   }
 
   /**
@@ -729,7 +1261,37 @@
     asm.emitPOP_Reg(T0); // T0 is array index
     asm.emitPOP_Reg(S0); // S0 is array ref
     genBoundsCheck(asm, T0, S0);         // T0 is index, S0 is address of array
-    asm.emitMOV_RegIdx_Reg_Byte(S0, T0, Assembler.BYTE, NO_SLOT, T1); // [S0 + T0<<2] <- T1
+    // boolean arrayletize = true;
+ //jbs changed arraylet
+    ForwardReference fr = null;
+    ForwardReference fr2 = null;
+    if (/*arrayletize && */MemoryManagerConstants.USE_PRIMITIVE_BYTE_ARRAYLETS || MemoryManagerConstants.USE_PRIMITIVE_BOOLEAN_ARRAYLETS) {
+	asm.emitCMP_Reg_Imm(T0, MemoryManagerConstants.FIRSTN_BYTE_ELEMS); 
+	// Jmp around trap if index is OK
+	asm.emitBranchLikelyNextInstruction();
+	fr = asm.forwardJcc(Assembler.LLT);
+	//}
+	//check if in boot image, jump to fr
+	//FIXME - not 64-bit safe right now
+	if (!MemoryManagerConstants.BOOT_IMAGE_IS_ARRAYLETIZED) {
+	    asm.emitCMP_Reg_Imm(S0, org.jikesrvm.HeapLayoutConstants.BOOT_IMAGE_DATA_END.toInt());
+	    
+	    //inline barrier - slow path index >= SPINE_FIRSTN_ELEMENTS
+	    fr2 = asm.forwardJcc(Assembler.LLT);
+	}
+      asm.emitPUSH_Reg(S0);
+      asm.emitPUSH_Reg(T0);
+      asm.emitPUSH_Reg(T1);
+      Barriers.compileArrayStorePrimitiveByteBarrier(asm);
+    } else {
+	if (fr != null) {
+	    fr.resolve(asm);
+	} 
+	if (fr2 != null) {
+	    fr2.resolve(asm);
+	}
+      asm.emitMOV_RegIdx_Reg_Byte(S0, T0, Assembler.BYTE, NO_SLOT, T1); // [S0 + T0<<2] <- T1
+    }
   }
 
   /**
@@ -756,19 +1318,53 @@
       asm.emitPOP_Reg(S0);         // S0 is array ref
     }
     genBoundsCheck(asm, T0, S0);                   // T0 is index, S0 is address of array
-    if (VM.BuildFor32Addr) {
-      if (SSE2_BASE) {
-        asm.emitMOVQ_RegIdx_Reg(S0, T0, Assembler.LONG, NO_SLOT, XMM0); // [S0+T0<<<3] <- XMM0
-      } else {
-        // [S0 + T0<<3 + 0] <- T1 store low part into array
-        asm.emitMOV_RegIdx_Reg(S0, T0, Assembler.LONG, NO_SLOT, T1);
-        asm.emitMOV_Reg_RegDisp(T1, SP, ONE_SLOT); // high part of long value
-        // [S0 + T0<<3 + 4] <- T1 store high part into array
-        adjustStack(WORDSIZE*4, false); // remove index and ref from the stack
-        asm.emitMOV_RegIdx_Reg(S0, T0, Assembler.LONG, ONE_SLOT, T1);
-      }
-    } else {
-      asm.emitMOV_RegIdx_Reg_Quad(S0, T0, Assembler.LONG, NO_SLOT, T1); // [S0+T0<<<3] <- T1
+    //jbs changed arraylet
+    ForwardReference fr = null;
+    ForwardReference fr2 = null;
+    if (MemoryManagerConstants.USE_PRIMITIVE_LONG_ARRAYLETS) {
+      asm.emitCMP_Reg_Imm(T0, MemoryManagerConstants.FIRSTN_LONG_ELEMS); 
+      // Jmp around trap if index is OK
+      asm.emitBranchLikelyNextInstruction();
+      fr = asm.forwardJcc(Assembler.LLT);
+      //check if in boot image, jump to fr
+      //FIXME - not 64-bit safe right now
+      if (!MemoryManagerConstants.BOOT_IMAGE_IS_ARRAYLETIZED) {
+        asm.emitCMP_Reg_Imm(S0, org.jikesrvm.HeapLayoutConstants.BOOT_IMAGE_DATA_END.toInt());
+        //inline barrier - slow path index >= SPINE_FIRSTN_ELEMENTS
+        fr2 = asm.forwardJcc(Assembler.LLT);
+      }
+      asm.emitPUSH_Reg(S0);
+      asm.emitPUSH_Reg(T0);
+      if (! (VM.BuildFor32Addr && SSE2_BASE)) {
+        asm.emitPUSH_Reg(T1);
+      } else {
+        //jbs - need to do adjustStack??
+        adjustStack(WORDSIZE*-2, true); // create space for store value
+
+        asm.emitMOVQ_RegInd_Reg(SP, XMM0); //jbs unsure? .emitPUSH_Reg(XMM0);
+      }
+      Barriers.compileArrayStorePrimitiveLongBarrier(asm);
+    } else {
+      if (fr != null) {
+        fr.resolve(asm);
+      } 
+      if (fr2 != null) {
+        fr2.resolve(asm);
+      }
+      if (VM.BuildFor32Addr) {
+        if (SSE2_BASE) {
+          asm.emitMOVQ_RegIdx_Reg(S0, T0, Assembler.LONG, NO_SLOT, XMM0); // [S0+T0<<<3] <- XMM0
+        } else {
+          // [S0 + T0<<3 + 0] <- T1 store low part into array
+          asm.emitMOV_RegIdx_Reg(S0, T0, Assembler.LONG, NO_SLOT, T1);
+          asm.emitMOV_Reg_RegDisp(T1, SP, ONE_SLOT); // high part of long value
+          // [S0 + T0<<3 + 4] <- T1 store high part into array
+          adjustStack(WORDSIZE*4, false); // remove index and ref from the stack
+          asm.emitMOV_RegIdx_Reg(S0, T0, Assembler.LONG, ONE_SLOT, T1);
+        }
+      } else {
+        asm.emitMOV_RegIdx_Reg_Quad(S0, T0, Assembler.LONG, NO_SLOT, T1); // [S0+T0<<<3] <- T1
+      }
     }
   }
 
@@ -777,8 +1373,73 @@
    */
   @Override
   protected final void emit_dastore() {
-    // identical to lastore
-    emit_lastore();
+    Barriers.compileModifyCheck(asm, 3*WORDSIZE);
+    if (VM.BuildFor32Addr) {
+      if (SSE2_BASE) {
+        asm.emitMOVQ_Reg_RegInd(XMM0,SP); // XMM0 is the value
+        adjustStack(WORDSIZE*2, true);    // remove value from the stack
+        asm.emitPOP_Reg(T0); // T0 is array index
+        asm.emitPOP_Reg(S0); // S0 is array ref
+      } else {
+        asm.emitMOV_Reg_RegDisp(T0, SP, TWO_SLOTS);    // T0 is the array index
+        asm.emitMOV_Reg_RegDisp(S0, SP, THREE_SLOTS);  // S0 is the array ref
+        asm.emitMOV_Reg_RegInd(T1, SP);              // low part of long value
+      }
+    } else {
+      asm.emitPOP_Reg(T1);         // T1 is the value
+      adjustStack(WORDSIZE, true); // throw away slot
+      asm.emitPOP_Reg(T0);         // T0 is array index
+      asm.emitPOP_Reg(S0);         // S0 is array ref
+    }
+    genBoundsCheck(asm, T0, S0);                   // T0 is index, S0 is address of array
+ //jbs changed arraylet
+    ForwardReference fr = null;
+    ForwardReference fr2 = null;
+    if (MemoryManagerConstants.USE_PRIMITIVE_DOUBLE_ARRAYLETS) {
+	asm.emitCMP_Reg_Imm(T0, MemoryManagerConstants.FIRSTN_DOUBLE_ELEMS); 
+	// Jmp around trap if index is OK
+    	asm.emitBranchLikelyNextInstruction();
+    	fr = asm.forwardJcc(Assembler.LLT);
+	//}
+	//check if in boot image, jump to fr
+	//FIXME - not 64-bit safe right now
+    	if (!MemoryManagerConstants.BOOT_IMAGE_IS_ARRAYLETIZED) {
+	    asm.emitCMP_Reg_Imm(S0, org.jikesrvm.HeapLayoutConstants.BOOT_IMAGE_DATA_END.toInt());
+	    //inline barrier - slow path index >= SPINE_FIRSTN_ELEMENTS
+	    fr2 = asm.forwardJcc(Assembler.LLT);
+	}
+      asm.emitPUSH_Reg(S0);
+      asm.emitPUSH_Reg(T0);
+      //if (!(VM.BuildFor32Addr && SSE2_BASE)) {
+      //  asm.emitPUSH_Reg(T1);
+      //} else {
+        //jbs - need to do adjustStack??
+        adjustStack(WORDSIZE*-2, true); // create space for store value
+        //asm.emitMOVQ_RegInd_Reg(SP, XMM0); //jbs unsure? .emitPUSH_Reg(XMM0);
+      //}
+      Barriers.compileArrayStorePrimitiveDoubleBarrier(asm);
+    } else {
+	if (fr != null) {
+    		fr.resolve(asm);
+    	} 
+    	if (fr2 != null) {
+    		fr2.resolve(asm);
+    	}
+      if (VM.BuildFor32Addr) {
+        if (SSE2_BASE) {
+          asm.emitMOVQ_RegIdx_Reg(S0, T0, Assembler.LONG, NO_SLOT, XMM0); // [S0+T0<<<3] <- XMM0
+        } else {
+          // [S0 + T0<<3 + 0] <- T1 store low part into array
+          asm.emitMOV_RegIdx_Reg(S0, T0, Assembler.LONG, NO_SLOT, T1);
+          asm.emitMOV_Reg_RegDisp(T1, SP, ONE_SLOT); // high part of long value
+          // [S0 + T0<<3 + 4] <- T1 store high part into array
+          adjustStack(WORDSIZE*4, false); // remove index and ref from the stack
+          asm.emitMOV_RegIdx_Reg(S0, T0, Assembler.LONG, ONE_SLOT, T1);
+        }
+      } else {
+        asm.emitMOV_RegIdx_Reg_Quad(S0, T0, Assembler.LONG, NO_SLOT, T1); // [S0+T0<<<3] <- T1
+      }
+    }
   }
 
   /*
@@ -2426,6 +3087,7 @@
       fr.resolve(asm);
 
       // Increment counter for the appropriate case
+      
       incEdgeCounter(S0, T1, firstCounter);
     } else {
       asm.emitJCC_Cond_ImmOrLabel(Assembler.LGE, mTarget, bTarget);   // if not, goto default case
@@ -3161,6 +3823,7 @@
           }
 
           if (DynamicTypeCheck.MIN_DOES_IMPLEMENT_SIZE <= interfaceIndex) {
+            if (VM.VerifyAssertions) VM._assert(BYTES_IN_WORD == BYTES_IN_INT);
             // must do arraybounds check of implements bit vector
             if (JavaHeaderConstants.ARRAY_LENGTH_BYTES == 4) {
               asm.emitCMP_RegDisp_Imm(S0, ObjectModel.getArrayLengthOffset(), interfaceIndex);
@@ -3174,11 +3837,13 @@
           }
 
           // Test the appropriate bit and if set, branch around another trap imm
+          //jbs added arraylets
           if (interfaceIndex == 0) {
             asm.emitTEST_RegInd_Imm(S0, interfaceMask);
           } else {
             asm.emitTEST_RegDisp_Imm(S0, Offset.fromIntZeroExtend(interfaceIndex << LOG_BYTES_IN_INT), interfaceMask);
           }
+          
           asm.emitBranchLikelyNextInstruction();
           ForwardReference fr = asm.forwardJcc(Assembler.NE);
           asm.emitINT_Imm(RuntimeEntrypoints.TRAP_MUST_IMPLEMENT + RVM_TRAP_BASE);
@@ -3471,7 +4136,9 @@
     }
 
     // Test the appropriate bit and if set, branch around another trap imm
+    //jbs added arraylets
     asm.emitTEST_RegDisp_Imm(S0, Offset.fromIntZeroExtend(interfaceIndex << LOG_BYTES_IN_INT), interfaceMask);
+
     asm.emitBranchLikelyNextInstruction();
     ForwardReference fr = asm.forwardJcc(Assembler.NE);
     asm.emitINT_Imm(RuntimeEntrypoints.TRAP_CHECKCAST + RVM_TRAP_BASE);
@@ -3507,9 +4174,9 @@
     if (DynamicTypeCheck.MIN_SUPERCLASS_IDS_SIZE <= LHSDepth) {
       // must do arraybounds check of superclass display
       if (JavaHeaderConstants.ARRAY_LENGTH_BYTES == 4) {
-        asm.emitCMP_RegDisp_Imm(S0, ObjectModel.getArrayLengthOffset(), LHSDepth);
-      } else {
-        asm.emitCMP_RegDisp_Imm_Quad(S0, ObjectModel.getArrayLengthOffset(), LHSDepth);
+        asm.emitCMP_RegDisp_Imm(S0, ObjectModel.getArrayLengthOffset(), LHSDepth >> (LOG_BYTES_IN_WORD - LOG_BYTES_IN_CHAR));
+      } else {
+        asm.emitCMP_RegDisp_Imm_Quad(S0, ObjectModel.getArrayLengthOffset(), LHSDepth >> (LOG_BYTES_IN_WORD - LOG_BYTES_IN_CHAR));
       }
       asm.emitBranchLikelyNextInstruction();
       ForwardReference fr = asm.forwardJcc(Assembler.LGT);
@@ -3518,6 +4185,7 @@
     }
 
     // Load id from display at required depth and compare against target id.
+    //jbs added arraylets
     asm.emitMOVZX_Reg_RegDisp_Word(S0, S0, Offset.fromIntZeroExtend(LHSDepth << LOG_BYTES_IN_SHORT));
     asm.emitCMP_Reg_Imm(S0, LHSId);
     asm.emitBranchLikelyNextInstruction();
@@ -3603,7 +4271,9 @@
     }
 
     // Test the implements bit and push true if it is set
+    //jbs added arraylets
     asm.emitTEST_RegDisp_Imm(S0, Offset.fromIntZeroExtend(interfaceIndex << LOG_BYTES_IN_INT), interfaceMask);
+
     ForwardReference notMatched = asm.forwardJcc(Assembler.EQ);
     asm.emitPUSH_Imm(1);
     ForwardReference done = asm.forwardJMP();
@@ -3645,9 +4315,9 @@
     if (DynamicTypeCheck.MIN_SUPERCLASS_IDS_SIZE <= LHSDepth) {
       // must do arraybounds check of superclass display
       if (JavaHeaderConstants.ARRAY_LENGTH_BYTES == 4) {
-        asm.emitCMP_RegDisp_Imm(S0, ObjectModel.getArrayLengthOffset(), LHSDepth);
-      } else {
-        asm.emitCMP_RegDisp_Imm_Quad(S0, ObjectModel.getArrayLengthOffset(), LHSDepth);
+        asm.emitCMP_RegDisp_Imm(S0, ObjectModel.getArrayLengthOffset(), LHSDepth >> (LOG_BYTES_IN_WORD - LOG_BYTES_IN_CHAR));
+      } else {
+        asm.emitCMP_RegDisp_Imm_Quad(S0, ObjectModel.getArrayLengthOffset(), LHSDepth >> (LOG_BYTES_IN_WORD - LOG_BYTES_IN_CHAR));
       }
       outOfBounds = asm.forwardJcc(Assembler.LLE);
     }
@@ -3840,10 +4510,14 @@
 
       if (!VM.runningTool && ((BaselineCompiledMethod) compiledMethod).hasCounterArray()) {
         // use (nonvolatile) EBX to hold base of this method's counter array
-        if (MemoryManagerConstants.NEEDS_READ_BARRIER) {
+    	  //jbs added arraylet
+        if (MemoryManagerConstants.NEEDS_READ_BARRIER || MemoryManagerConstants.USE_REFERENCE_ARRAYLETS || MemoryManagerConstants.USE_OBJECT_ARRAY_ACCESS_BARRIER_ON_EDGE_COUNTS) {
           asm.emitPUSH_Abs(Magic.getTocPointer().plus(Entrypoints.edgeCountersField.getOffset()));
           asm.emitPUSH_Imm(getEdgeCounterIndex());
-          Barriers.compileArrayLoadBarrier(asm, false);
+          if (VM.BuildWithBaseBootImageCompiler && VM.BuildForAdaptiveSystem && MemoryManagerConstants.USE_REFERENCE_ARRAYLETS) 
+            Barriers.compileHackArrayLoadBarrier(asm, false);
+          else
+            Barriers.compileArrayLoadBarrier(asm, false);
           if (VM.BuildFor32Addr) {
             asm.emitMOV_Reg_Reg(EBX, T0);
           } else {
@@ -4032,6 +4706,20 @@
     }
   }
 
+  private void emitSaveRegisters() {
+	  asm.emitPUSH_Reg(S0);
+	  asm.emitPUSH_Reg(S1);
+	  asm.emitPUSH_Reg(T0);
+	  asm.emitPUSH_Reg(T1);
+  }
+
+  private void emitRestoreRegisters() {
+	  asm.emitPOP_Reg(T1);
+	  asm.emitPOP_Reg(T0);
+	  asm.emitPOP_Reg(S1);
+	  asm.emitPOP_Reg(S0);
+  }
+
   /**
    * Generate code to increment edge counter
    * @param scratch register to use as scratch
@@ -4041,20 +4729,22 @@
   @Inline(value=Inline.When.ArgumentsAreConstant, arguments={1,2})
   private void incEdgeCounter(GPR scratch, GPR idx, int counterIdx) {
     if (VM.VerifyAssertions) VM._assert(((BaselineCompiledMethod) compiledMethod).hasCounterArray());
-    if (idx == null) {
+
+    if (idx == null)
       asm.emitMOV_Reg_RegDisp(scratch, EBX, Offset.fromIntZeroExtend(counterIdx << LOG_BYTES_IN_INT));
-    } else {
+    else
       asm.emitMOV_Reg_RegIdx(scratch, EBX, idx, Assembler.WORD, Offset.fromIntZeroExtend(counterIdx << LOG_BYTES_IN_INT));
-    }
+    
     asm.emitADD_Reg_Imm(scratch, 1);
     // Don't write back result if it would make the counter negative (ie
     // saturate at 0x7FFFFFFF)
     ForwardReference fr1 = asm.forwardJcc(Assembler.S);
-    if (idx == null) {
+    
+    if (idx == null)
       asm.emitMOV_RegDisp_Reg(EBX, Offset.fromIntSignExtend(counterIdx << LOG_BYTES_IN_INT), scratch);
-    } else {
+    else
       asm.emitMOV_RegIdx_Reg(EBX, idx, Assembler.WORD, Offset.fromIntSignExtend(counterIdx << LOG_BYTES_IN_INT), scratch);
-    }
+    
     fr1.resolve(asm);
   }
 
@@ -4398,7 +5088,22 @@
       int id = compiledMethod.getId();
       InvocationCounts.allocateCounter(id);
       asm.emitMOV_Reg_Abs(ECX, Magic.getTocPointer().plus(AosEntrypoints.invocationCountsField.getOffset()));
-      asm.emitSUB_RegDisp_Imm(ECX, Offset.fromIntZeroExtend(compiledMethod.getId() << 2), 1);
+      //jbs added
+      if (MemoryManagerConstants.USE_PRIMITIVE_INT_ARRAYLETS) {
+
+        asm.emitPUSH_Reg(ECX);
+        asm.emitPUSH_Imm(compiledMethod.getId());
+        Barriers.compileArrayLoadPrimitiveIntBarrier(asm, false);
+        //result is in T0 because passed false (dont' push result) above
+        //asm.emitPOP_Reg(T0); // T0 is results of load of array at compiledMethod.getId()
+        asm.emitSUB_Reg_Imm(T0, 1);
+        asm.emitPUSH_Reg(ECX);
+        asm.emitPUSH_Imm(compiledMethod.getId());
+        asm.emitPUSH_Reg(T0); //value to store
+        Barriers.compileArrayStorePrimitiveIntBarrier(asm);
+      } else {
+        asm.emitSUB_RegDisp_Imm(ECX, Offset.fromIntZeroExtend(compiledMethod.getId() << 2), 1);
+      }
       ForwardReference notTaken = asm.forwardJcc(Assembler.GT);
       asm.emitPUSH_Imm(id);
       genParameterRegisterLoad(asm, 1);
diff -r 743a2cc2ed20 -r 058fdc3780ba rvm/src/org/jikesrvm/compilers/baseline/ia32/BaselineMagic.java
--- a/rvm/src/org/jikesrvm/compilers/baseline/ia32/BaselineMagic.java	Tue Aug 04 11:04:15 2009 +1000
+++ b/rvm/src/org/jikesrvm/compilers/baseline/ia32/BaselineMagic.java	Mon Nov 16 09:21:21 2009 +1100
@@ -754,13 +754,17 @@
       // Store at offset
       if (VM.BuildFor32Addr) {
         asm.emitPOP_Reg(T0);                          // T0 = offset
-        asm.emitADD_Reg_RegDisp(T0, SP, THREE_SLOTS); // T0 = base+offset
+        asm.emitADD_Reg_RegDisp(T0, SP, TWO_SLOTS);  // T0 = base+offset
+        //jbs bug fix - added above line and took out below (dframpton)
+        //asm.emitADD_Reg_RegDisp(T0, SP, THREE_SLOTS); // T0 = base+offset
         asm.emitPOP_RegInd(T0);                       // [T0]   <- value low
         asm.emitPOP_RegDisp(T0, ONE_SLOT);            // [T0+4] <- value high
         asm.emitPOP_Reg(T0);                          // throw away slot
       } else {
         asm.emitPOP_Reg(T0);                               // offset
-        asm.emitADD_Reg_RegDisp_Quad(T0, SP, THREE_SLOTS); // T0 = base+offset
+        asm.emitADD_Reg_RegDisp_Quad(T0, SP, TWO_SLOTS); // T0 = base+offset
+        //jbs bug fix - added above line and took out below (dframpton)
+        //asm.emitADD_Reg_RegDisp_Quad(T0, SP, THREE_SLOTS); // T0 = base+offset
         asm.emitPOP_RegInd(T0);                            // T0 <- value
         asm.emitPOP_Reg(T0);                               // throw away slot
         asm.emitPOP_Reg(T0);                               // throw away slot
@@ -1024,6 +1028,7 @@
     generators.put(getMethodReference(Magic.class, MagicNames.objectAsType, Object.class, RVMType.class), g);
     generators.put(getMethodReference(Magic.class, MagicNames.objectAsShortArray, Object.class, short[].class), g);
     generators.put(getMethodReference(Magic.class, MagicNames.objectAsIntArray, Object.class, int[].class), g);
+    generators.put(getMethodReference(Magic.class, MagicNames.objectAsWordArray, Object.class, WordArray.class), g);
     generators.put(getMethodReference(Magic.class, MagicNames.objectAsProcessor, Object.class, Processor.class), g);
     generators.put(getMethodReference(Magic.class, MagicNames.processorAsGreenProcessor, Processor.class, GreenProcessor.class), g);
     generators.put(getMethodReference(Magic.class, MagicNames.objectAsThread, Object.class, RVMThread.class), g);
@@ -1544,7 +1549,7 @@
     if (VALIDATE_OBJECT_REFERENCES) {
       g = new LateReferenceCheckDecorator(NO_SLOT, g);
     }
-    generators.put(getMethodReference(Magic.class, MagicNames.invokeMethodReturningObject, CodeArray.class, WordArray.class, double[].class, byte[].class, WordArray.class, Object.class), g);
+    generators.put(getMethodReference(Magic.class, MagicNames.invokeMethodReturningObject, CodeArray.class, WordArray.class, WordArray.class, WordArray.class, WordArray.class, Object.class), g);
   }
 
   /**
@@ -1560,7 +1565,7 @@
   }
   static {
     MagicGenerator g = new InvokeMethodReturningVoid();
-    generators.put(getMethodReference(Magic.class, MagicNames.invokeMethodReturningVoid, CodeArray.class, WordArray.class, double[].class, byte[].class, WordArray.class, void.class), g);
+    generators.put(getMethodReference(Magic.class, MagicNames.invokeMethodReturningVoid, CodeArray.class, WordArray.class, WordArray.class, WordArray.class, WordArray.class, void.class), g);
   }
 
   /**
@@ -1577,7 +1582,7 @@
   }
   static {
     MagicGenerator g = new InvokeMethodReturningInt();
-    generators.put(getMethodReference(Magic.class, MagicNames.invokeMethodReturningInt, CodeArray.class, WordArray.class, double[].class, byte[].class, WordArray.class, int.class), g);
+    generators.put(getMethodReference(Magic.class, MagicNames.invokeMethodReturningInt, CodeArray.class, WordArray.class, WordArray.class, WordArray.class, WordArray.class, int.class), g);
   }
 
   /**
@@ -1595,7 +1600,7 @@
   }
   static {
     MagicGenerator g = new InvokeMethodReturningLong();
-    generators.put(getMethodReference(Magic.class, MagicNames.invokeMethodReturningLong, CodeArray.class, WordArray.class, double[].class, byte[].class, WordArray.class, long.class), g);
+    generators.put(getMethodReference(Magic.class, MagicNames.invokeMethodReturningLong, CodeArray.class, WordArray.class, WordArray.class, WordArray.class, WordArray.class, long.class), g);
   }
 
   /**
@@ -1617,7 +1622,7 @@
   }
   static {
     MagicGenerator g = new InvokeMethodReturningFloat();
-    generators.put(getMethodReference(Magic.class, MagicNames.invokeMethodReturningFloat, CodeArray.class, WordArray.class, double[].class, byte[].class, WordArray.class, float.class), g);
+    generators.put(getMethodReference(Magic.class, MagicNames.invokeMethodReturningFloat, CodeArray.class, WordArray.class, WordArray.class, WordArray.class, WordArray.class, float.class), g);
   }
 
   /**
@@ -1639,7 +1644,7 @@
   }
   static {
     MagicGenerator g = new InvokeMethodReturningDouble();
-    generators.put(getMethodReference(Magic.class, MagicNames.invokeMethodReturningDouble, CodeArray.class, WordArray.class, double[].class, byte[].class, WordArray.class, double.class), g);
+    generators.put(getMethodReference(Magic.class, MagicNames.invokeMethodReturningDouble, CodeArray.class, WordArray.class, WordArray.class, WordArray.class, WordArray.class, double.class), g);
   }
 
   /**
@@ -1856,6 +1861,25 @@
   }
 
   /**
+   * Get a 16bit element from a runtime table
+   * @see org.jikesrvm.objectmodel.RuntimeTable#get(int)
+   */
+  private static final class Load16_Array extends MagicGenerator {
+    @Override
+    void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) {
+      asm.emitPOP_Reg(T0);          // T0 is array index
+      asm.emitPOP_Reg(S0);          // S0 is array ref
+      // push [S0+T0<<2]
+      asm.emitMOVZX_Reg_RegIdx_Word(T1, S0, T0, Assembler.SHORT, NO_SLOT);
+      asm.emitPUSH_Reg(T1);
+    }
+  }
+  static {
+    MagicGenerator g = new Load16_Array();
+    generators.put(getMethodReference(WordArray.class, MagicNames.addressArrayGetChar, int.class, char.class), g);
+  }
+
+  /**
    * Get a 32bit element from a runtime table
    * @see org.jikesrvm.objectmodel.RuntimeTable#get(int)
    */
@@ -1864,11 +1888,15 @@
     void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) {
       asm.emitPOP_Reg(T0);          // T0 is array index
       asm.emitPOP_Reg(S0);          // S0 is array ref
-      BaselineCompilerImpl.genBoundsCheck(asm, T0, S0); // T0 is index, S0 is address of array
       // push [S0+T0<<2]
       asm.emitPUSH_RegIdx(S0, T0, Assembler.WORD, NO_SLOT);
     }
   }
+  static {
+    MagicGenerator g = new Load32_Array();
+    generators.put(getMethodReference(WordArray.class, MagicNames.addressArrayGetInt, int.class, int.class), g);
+  }
+
   /**
    * Get a 64bit element from a runtime table
    * @see org.jikesrvm.objectmodel.RuntimeTable#get(int)
@@ -1878,12 +1906,15 @@
     void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) {
       asm.emitPOP_Reg(T0);          // T0 is array index
       asm.emitPOP_Reg(S0);          // S0 is array ref
-      BaselineCompilerImpl.genBoundsCheck(asm, T0, S0); // T0 is index, S0 is address of array
       // push [S0+T0<<3]
       asm.emitPUSH_RegIdx(S0, T0, Assembler.LONG, NO_SLOT);
     }
   }
   static {
+    MagicGenerator g = new Load64_Array();
+    generators.put(getMethodReference(WordArray.class, MagicNames.addressArrayGetLong, int.class, long.class), g);
+  }
+  static {
     MagicGenerator g = VM.BuildFor32Addr ? new Load32_Array() : new Load64_Array();
     Class<?>[] unboxedTypes = new Class<?>[] { AddressArray.class,
         ExtentArray.class, FunctionTable.class, IMT.class,
@@ -1907,15 +1938,34 @@
     void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) {
       asm.emitPOP_Reg(T0); // T0 is array index
       asm.emitPOP_Reg(S0); // S0 is array ref
-      BaselineCompilerImpl.genBoundsCheck(asm, T0, S0); // T0 is index, S0 is address of array
       // T1 = (int)[S0+T0<<1]
-      asm.emitMOVSX_Reg_RegIdx_Byte(T1, S0, T0, Assembler.BYTE, NO_SLOT);
+      asm.emitMOVZX_Reg_RegIdx_Byte(T1, S0, T0, Assembler.BYTE, NO_SLOT);
       asm.emitPUSH_Reg(T1);        // push byte onto stack
     }
   }
   static {
     MagicGenerator g = new LoadByte_Array();
     generators.put(getMethodReference(CodeArray.class, MagicNames.addressArrayGet, int.class, byte.class), g);
+    generators.put(getMethodReference(WordArray.class, MagicNames.addressArrayGetByte, int.class, byte.class), g);
+  }
+
+  /**
+   * Store a 16bit element to a runtime table
+   * @see org.jikesrvm.objectmodel.RuntimeTable#set(int, Object)
+   */
+  private static final class Store16_Array extends MagicGenerator {
+    @Override
+    void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) {
+      Barriers.compileModifyCheck(asm, 8);
+      asm.emitPOP_Reg(T1); // T1 is the value
+      asm.emitPOP_Reg(T0); // T0 is array index
+      asm.emitPOP_Reg(S0); // S0 is array ref
+      asm.emitMOV_RegIdx_Reg_Word(S0, T0, Assembler.SHORT, NO_SLOT, T1); // [S0 + T0<<2] <- T1
+    }
+  }
+  static {
+    MagicGenerator g = new Store16_Array();
+    generators.put(getMethodReference(WordArray.class, MagicNames.addressArraySetChar, int.class, char.class, void.class), g);
   }
 
   /**
@@ -1929,10 +1979,14 @@
       asm.emitPOP_Reg(T1); // T1 is the value
       asm.emitPOP_Reg(T0); // T0 is array index
       asm.emitPOP_Reg(S0); // S0 is array ref
-      BaselineCompilerImpl.genBoundsCheck(asm, T0, S0);            // T0 is index, S0 is address of array
       asm.emitMOV_RegIdx_Reg(S0, T0, Assembler.WORD, NO_SLOT, T1); // [S0 + T0<<2] <- T1
     }
   }
+  static {
+    MagicGenerator g = new Store32_Array();
+    generators.put(getMethodReference(WordArray.class, MagicNames.addressArraySetInt, int.class, int.class, void.class), g);
+  }
+  
   /**
    * Store a 64bit element to a runtime table
    * @see org.jikesrvm.objectmodel.RuntimeTable#set(int, Object)
@@ -1941,14 +1995,31 @@
     @Override
     void generateMagic(Assembler asm, MethodReference m, RVMMethod cm, Offset sd) {
       Barriers.compileModifyCheck(asm, 8);
-      asm.emitPOP_Reg(T1); // T1 is the value
-      asm.emitPOP_Reg(T0); // T0 is array index
-      asm.emitPOP_Reg(S0); // S0 is array ref
-      BaselineCompilerImpl.genBoundsCheck(asm, T0, S0);                 // T0 is index, S0 is address of array
-      asm.emitMOV_RegIdx_Reg_Quad(S0, T0, Assembler.LONG, NO_SLOT, T1); // [S0 + T0<<2] <- T1
+      if (SSE2_BASE) {
+        asm.emitMOVQ_Reg_RegInd(XMM0,SP); // XMM0 is the value
+        asm.emitPOP_Reg(S0); // discard
+        asm.emitPOP_Reg(S0); // discard
+        asm.emitPOP_Reg(T0); // T0 is array index
+        asm.emitPOP_Reg(S0); // S0 is array ref
+        asm.emitMOVQ_RegIdx_Reg(S0, T0, Assembler.LONG, NO_SLOT, XMM0); // [S0+T0<<<3] <- XMM0
+      } else {
+        asm.emitMOV_Reg_RegDisp(T0, SP, TWO_SLOTS);    // T0 is the array index
+        asm.emitMOV_Reg_RegDisp(S0, SP, THREE_SLOTS);  // S0 is the array ref
+        asm.emitMOV_Reg_RegInd(T1, SP);              // low part of long value
+        // [S0 + T0<<3 + 0] <- T1 store low part into array
+        asm.emitMOV_RegIdx_Reg(S0, T0, Assembler.LONG, NO_SLOT, T1);
+        asm.emitMOV_Reg_RegDisp(T1, SP, ONE_SLOT); // high part of long value
+        // [S0 + T0<<3 + 4] <- T1 store high part into array
+        asm.emitADD_Reg_Imm(SP, WORDSIZE*4); // remove index and ref from the stack
+        asm.emitMOV_RegIdx_Reg(S0, T0, Assembler.LONG, ONE_SLOT, T1);
+      }
     }
   }
   static {
+    MagicGenerator g = new Store64_Array();
+    generators.put(getMethodReference(WordArray.class, MagicNames.addressArraySetLong, int.class, long.class, void.class), g);
+  }
+  static {
     MagicGenerator g = VM.BuildFor32Addr ? new Store32_Array() : new Store64_Array();
     Class<?>[] unboxedTypes = new Class<?>[] { AddressArray.class,
         ExtentArray.class, FunctionTable.class, IMT.class,
@@ -1974,13 +2045,13 @@
       asm.emitPOP_Reg(T1); // T1 is the value
       asm.emitPOP_Reg(T0); // T0 is array index
       asm.emitPOP_Reg(S0); // S0 is array ref
-      BaselineCompilerImpl.genBoundsCheck(asm, T0, S0);                // T0 is index, S0 is address of array
       asm.emitMOV_RegIdx_Reg_Byte(S0, T0, Assembler.BYTE, NO_SLOT, T1); // [S0 + T0<<2] <- T1
     }
   }
   static {
     MagicGenerator g = new StoreByte_Array();
     generators.put(getMethodReference(CodeArray.class, MagicNames.addressArraySet, int.class, byte.class, void.class), g);
+    generators.put(getMethodReference(WordArray.class, MagicNames.addressArraySetByte, int.class, byte.class, void.class), g);
   }
 
   /**
diff -r 743a2cc2ed20 -r 058fdc3780ba rvm/src/org/jikesrvm/compilers/baseline/ppc/Barriers.java
--- a/rvm/src/org/jikesrvm/compilers/baseline/ppc/Barriers.java	Tue Aug 04 11:04:15 2009 +1000
+++ b/rvm/src/org/jikesrvm/compilers/baseline/ppc/Barriers.java	Mon Nov 16 09:21:21 2009 +1100
@@ -12,9 +12,11 @@
  */
 package org.jikesrvm.compilers.baseline.ppc;
 
+//import org.jikesrvm.compilers.baseline.ia32.BaselineCompilerImpl;
 import org.jikesrvm.compilers.common.assembler.ppc.Assembler;
 import org.jikesrvm.ppc.BaselineConstants;
 import org.jikesrvm.runtime.Entrypoints;
+import org.jikesrvm.runtime.Magic;
 import org.vmmagic.unboxed.Offset;
 
 /**
@@ -31,7 +33,70 @@
     asm.emitMTCTR(S0);
     asm.emitBCCTRL();  // MemoryManager.arrayStoreWriteBarrier(Object ref, int index, Object value)
   }
-
+  
+  //jbs added
+  //on entry T0, T1, and T2 already contain the appropriate values
+  static void compileArrayStorePrimitiveIntBarrier(BaselineCompilerImpl comp) {
+	  Assembler asm = comp.asm;
+	  asm.emitLAddrToc(S0, Entrypoints.arrayStorePrimitiveIntWriteBarrierMethod.getOffset());
+	  asm.emitMTCTR(S0);
+	  asm.emitBCCTRL();  // MemoryManager.arrayStoreWriteBarrier(Object ref, int index, Object value)
+  }
+  
+  //jbs added
+  //on entry T0, T1, and T2 already contain the appropriate values
+  static void compileArrayStorePrimitiveFloatBarrier(BaselineCompilerImpl comp) {
+	  Assembler asm = comp.asm;
+	  asm.emitLAddrToc(S0, Entrypoints.arrayStorePrimitiveFloatWriteBarrierMethod.getOffset());
+	  asm.emitMTCTR(S0);
+	  asm.emitBCCTRL();  // MemoryManager.arrayStoreWriteBarrier(Object ref, int index, Object value)
+  }
+  
+  //jbs added
+  //on entry T0, T1, and T2 already contain the appropriate values
+  static void compileArrayStorePrimitiveByteBarrier(BaselineCompilerImpl comp) {
+	  Assembler asm = comp.asm;
+	  asm.emitLAddrToc(S0, Entrypoints.arrayStorePrimitiveByteWriteBarrierMethod.getOffset());
+	  asm.emitMTCTR(S0);
+	  asm.emitBCCTRL();  // MemoryManager.arrayStoreWriteBarrier(Object ref, int index, Object value)
+  }
+  
+  //jbs added
+  //on entry T0, T1, and T2 already contain the appropriate values
+  static void compileArrayStorePrimitiveCharBarrier(BaselineCompilerImpl comp) {
+	  Assembler asm = comp.asm;
+	  asm.emitLAddrToc(S0, Entrypoints.arrayStorePrimitiveCharWriteBarrierMethod.getOffset());
+	  asm.emitMTCTR(S0);
+	  asm.emitBCCTRL();  // MemoryManager.arrayStoreWriteBarrier(Object ref, int index, Object value)
+  }
+  
+  //jbs added
+  //on entry T0, T1, and T2 already contain the appropriate values
+  static void compileArrayStorePrimitiveShortBarrier(BaselineCompilerImpl comp) {
+	  Assembler asm = comp.asm;
+	  asm.emitLAddrToc(S0, Entrypoints.arrayStorePrimitiveShortWriteBarrierMethod.getOffset());
+	  asm.emitMTCTR(S0);
+	  asm.emitBCCTRL();  // MemoryManager.arrayStoreWriteBarrier(Object ref, int index, Object value)
+  }
+  
+  //jbs added
+  //on entry T0, T1, T2, T3 already contain the appropriate values
+  static void compileArrayStorePrimitiveLongBarrier(BaselineCompilerImpl comp) {
+	  Assembler asm = comp.asm;
+	  asm.emitLAddrToc(S0, Entrypoints.arrayStorePrimitiveLongWriteBarrierMethod.getOffset());
+	  asm.emitMTCTR(S0);
+	  asm.emitBCCTRL();  // MemoryManager.arrayStoreWriteBarrier(Object ref, int index, Object value)
+  }
+  
+  //jbs added
+  //on entry T0, T1, and F0 already contain the appropriate values
+  static void compileArrayStorePrimitiveDoubleBarrier(BaselineCompilerImpl comp) {
+	  Assembler asm = comp.asm;
+	  asm.emitLAddrToc(S0, Entrypoints.arrayStorePrimitiveDoubleWriteBarrierMethod.getOffset());
+	  asm.emitMTCTR(S0);
+	  asm.emitBCCTRL();  // MemoryManager.arrayStoreWriteBarrier(Object ref, int index, Object value)
+  }
+  
   //  on entry java stack contains ...|target_ref|ref_to_store|
   // T1 already contains the offset of the field on entry
   static void compilePutfieldBarrier(BaselineCompilerImpl comp, int locationMetadata) {
@@ -79,6 +144,15 @@
     asm.emitLVAL(T2, locationMetadata);
     asm.emitBCCTRL();  // MemoryManager.putstaticWriteBarrier(T0,T1)
   }
+  
+  //jbs added arraylet
+  //on entry T0, T1 already contain the appropriate values
+  static void compileHackArrayLoadBarrier(BaselineCompilerImpl comp) {
+	  Assembler asm = comp.asm;
+	    asm.emitLAddrToc(S0, Entrypoints.hackArrayLoadReadBarrierMethod.getOffset());
+	    asm.emitMTCTR(S0);
+	    asm.emitBCCTRL();  // MemoryManager.hackArrayLoadReadBarrier(T0,T1)
+  }  
 
   // on entry T0, T1 already contain the appropriate values
   static void compileArrayLoadBarrier(BaselineCompilerImpl comp) {
@@ -87,6 +161,69 @@
     asm.emitMTCTR(S0);
     asm.emitBCCTRL();  // MemoryManager.arrayLoadReadBarrier(T0,T1)
   }
+  
+  //jbs added arraylet
+  //on entry T0, T1 already contain the appropriate values
+  static void compileArrayLoadPrimitiveIntBarrier(BaselineCompilerImpl comp) {
+    Assembler asm = comp.asm;
+    asm.emitLAddrToc(S0, Entrypoints.arrayLoadPrimitiveIntReadBarrierMethod.getOffset());
+    asm.emitMTCTR(S0);
+    asm.emitBCCTRL();  // MemoryManager.arrayLoadReadBarrier(T0,T1)
+  }
+  
+  //jbs added arraylet
+  //on entry T0, T1 already contain the appropriate values
+  static void compileArrayLoadPrimitiveFloatBarrier(BaselineCompilerImpl comp) {
+	  Assembler asm = comp.asm;
+	  asm.emitLAddrToc(S0, Entrypoints.arrayLoadPrimitiveFloatReadBarrierMethod.getOffset());
+	  asm.emitMTCTR(S0);
+	  asm.emitBCCTRL();  // MemoryManager.arrayLoadReadBarrier(T0,T1)
+  }
+  
+  //jbs added arraylet
+  //on entry T0, T1 already contain the appropriate values
+  static void compileArrayLoadPrimitiveByteBarrier(BaselineCompilerImpl comp) {
+	  Assembler asm = comp.asm;
+	  asm.emitLAddrToc(S0, Entrypoints.arrayLoadPrimitiveByteReadBarrierMethod.getOffset());
+	  asm.emitMTCTR(S0);
+	  asm.emitBCCTRL();  // MemoryManager.arrayLoadReadBarrier(T0,T1)
+  }
+  
+  //jbs added arraylet
+  //on entry T0, T1 already contain the appropriate values
+  static void compileArrayLoadPrimitiveCharBarrier(BaselineCompilerImpl comp) {
+	  Assembler asm = comp.asm;
+	  asm.emitLAddrToc(S0, Entrypoints.arrayLoadPrimitiveCharReadBarrierMethod.getOffset());
+	  asm.emitMTCTR(S0);
+	  asm.emitBCCTRL();  // MemoryManager.arrayLoadReadBarrier(T0,T1)
+  }
+  
+  //jbs added arraylet
+  //on entry T0, T1 already contain the appropriate values
+  static void compileArrayLoadPrimitiveShortBarrier(BaselineCompilerImpl comp) {
+	  Assembler asm = comp.asm;
+	  asm.emitLAddrToc(S0, Entrypoints.arrayLoadPrimitiveShortReadBarrierMethod.getOffset());
+	  asm.emitMTCTR(S0);
+	  asm.emitBCCTRL();  // MemoryManager.arrayLoadReadBarrier(T0,T1)
+  }
+  
+  //jbs added arraylet
+  //on entry T0, T1 already contain the appropriate values
+  static void compileArrayLoadPrimitiveLongBarrier(BaselineCompilerImpl comp) {
+	  Assembler asm = comp.asm;
+	  asm.emitLAddrToc(S0, Entrypoints.arrayLoadPrimitiveLongReadBarrierMethod.getOffset());
+	  asm.emitMTCTR(S0);
+	  asm.emitBCCTRL();  // MemoryManager.arrayLoadReadBarrier(T0,T1)
+  }
+  
+  //jbs added arraylet
+  //on entry T0, T1 already contain the appropriate values
+  static void compileArrayLoadPrimitiveDoubleBarrier(BaselineCompilerImpl comp) {
+	  Assembler asm = comp.asm;
+	  asm.emitLAddrToc(S0, Entrypoints.arrayLoadPrimitiveDoubleReadBarrierMethod.getOffset());
+	  asm.emitMTCTR(S0);
+	  asm.emitBCCTRL();  // MemoryManager.arrayLoadReadBarrier(T0,T1)
+  }
 
   //  on entry java stack contains ...|source_ref|
   // T1 already contains the offset of the field on entry
diff -r 743a2cc2ed20 -r 058fdc3780ba rvm/src/org/jikesrvm/compilers/baseline/ppc/BaselineCompilerImpl.java
--- a/rvm/src/org/jikesrvm/compilers/baseline/ppc/BaselineCompilerImpl.java	Tue Aug 04 11:04:15 2009 +1000
+++ b/rvm/src/org/jikesrvm/compilers/baseline/ppc/BaselineCompilerImpl.java	Mon Nov 16 09:21:21 2009 +1100
@@ -885,9 +885,14 @@
   @Override
   protected final void emit_iaload() {
     genBoundsCheck();
-    asm.emitSLWI(T1, T1, LOG_BYTES_IN_INT);  // convert index to offset
-    asm.emitLIntX(T2, T0, T1);  // load desired int array element
-    pushInt(T2);
+    if (MemoryManagerConstants.USE_PRIMITIVE_INT_ARRAYLETS) {
+    	Barriers.compileArrayLoadPrimitiveIntBarrier(this);
+    	pushInt(T0);
+    } else {
+      asm.emitSLWI(T1, T1, LOG_BYTES_IN_INT);  // convert index to offset
+      asm.emitLIntX(T2, T0, T1);  // load desired int array element
+      pushInt(T2);
+    }
   }
 
   /**
@@ -896,9 +901,14 @@
   @Override
   protected final void emit_laload() {
     genBoundsCheck();
-    asm.emitSLWI(T1, T1, LOG_BYTES_IN_LONG);  // convert index to offset
-    asm.emitLFDX(F0, T0, T1);  // load desired (long) array element
-    pushLongAsDouble(F0);
+    if (MemoryManagerConstants.USE_PRIMITIVE_LONG_ARRAYLETS) {
+      Barriers.compileArrayLoadPrimitiveLongBarrier(this);
+      pushLong(T0, VM.BuildFor64Addr ? T0 : (T0 + 1));
+    } else {
+      asm.emitSLWI(T1, T1, LOG_BYTES_IN_LONG);  // convert index to offset
+      asm.emitLFDX(F0, T0, T1);  // load desired (long) array element
+      pushLongAsDouble(F0);
+    }
   }
 
   /**
@@ -907,11 +917,14 @@
   @Override
   protected final void emit_faload() {
     genBoundsCheck();
-    asm.emitSLWI(T1, T1, LOG_BYTES_IN_FLOAT);  // convert index to offset
-    asm.emitLWZX(T2, T0, T1);  // load desired (float) array element
-    pushInt(T2);  //LFSX not implemented yet
-//    asm.emitLFSX  (F0, T0, T1);  // load desired (float) array element
-//    pushFloat(F0);
+    if (MemoryManagerConstants.USE_PRIMITIVE_FLOAT_ARRAYLETS) {
+      Barriers.compileArrayLoadPrimitiveFloatBarrier(this);
+      pushFloat(F0);
+    } else {
+      asm.emitSLWI(T1, T1, LOG_BYTES_IN_FLOAT);  // convert index to offset
+      asm.emitLWZX(T2, T0, T1);  // load desired (float) array element
+      pushInt(T2);
+    }
   }
 
   /**
@@ -920,9 +933,14 @@
   @Override
   protected final void emit_daload() {
     genBoundsCheck();
-    asm.emitSLWI(T1, T1, LOG_BYTES_IN_DOUBLE);  // convert index to offset
-    asm.emitLFDX(F0, T0, T1);  // load desired (double) array element
-    pushDouble(F0);
+    if (MemoryManagerConstants.USE_PRIMITIVE_DOUBLE_ARRAYLETS) {
+      Barriers.compileArrayLoadPrimitiveDoubleBarrier(this);
+      pushDouble(F0);
+    } else {
+      asm.emitSLWI(T1, T1, LOG_BYTES_IN_DOUBLE);  // convert index to offset
+      asm.emitLFDX(F0, T0, T1);  // load desired (double) array element
+      pushDouble(F0);
+    }
   }
 
   /**
@@ -931,13 +949,62 @@
   @Override
   protected final void emit_aaload() {
     genBoundsCheck();
-    if (MemoryManagerConstants.NEEDS_READ_BARRIER) {
-      Barriers.compileArrayLoadBarrier(this);
-      pushAddr(T0);
-    } else {
-      asm.emitSLWI(T1, T1, LOG_BYTES_IN_ADDRESS);  // convert index to offset
-      asm.emitLAddrX(T2, T0, T1);  // load desired (ref) array element
-      pushAddr(T2);
+    if (MemoryManagerConstants.NEEDS_READ_BARRIER ||
+    		MemoryManagerConstants.USE_OBJECT_ARRAY_ACCESS_BARRIER) {
+    	if (MemoryManagerConstants.DO_BASELINE_READ_BARRIER_OPT) {
+    		// TODO: Assuming boot image arraylets for now!
+    		ForwardReference fr = null, fr2 = null;
+    		int AB = T0;
+    		if (MemoryManagerConstants.DO_FIRSTN_OPT) {
+    			// Are we inside first N?
+    			asm.emitCMPI(T1, MemoryManagerConstants.FIRSTN_REF_ELEMS);
+    			// Yes: jump to fast path: base T0, index T1
+    			fr = asm.emitForwardBC(LT);
+    		}
+    		if (!MemoryManagerConstants.BOOT_IMAGE_IS_ARRAYLETIZED) {
+    			// Are we not arrayletizing the boot image.
+    			asm.emitLVALAddr(T2,
+    					org.jikesrvm.HeapLayoutConstants.BOOT_IMAGE_DATA_END);
+    			// Are we in the boot image
+    			asm.emitCMP(T0, T2);
+    			fr2 = asm.emitForwardBC(LT);
+    		}
+    		if (MemoryManagerConstants.DO_FIRSTN_OPT) {
+    			// No: subtract N
+    			asm.emitADDI(T1, -MemoryManagerConstants.FIRSTN_REF_ELEMS, T1);
+    			// No: T2: pointer to first arraylet.
+    			asm.emitADDI(T2, MemoryManagerConstants.FIRSTN_REF_ELEMS <<
+    					LOG_BYTES_IN_ADDRESS, T0);
+    			AB = T2;
+    		}
+    		// calculate arraylet pointer index
+    		asm.emitSRAWI(T3, T1,  MemoryManagerConstants.LOG_ELEMENTS_IN_REF_ARRAYLET);
+    		// convert from index to offset
+    		asm.emitSLWI(T3, T3, LOG_BYTES_IN_ADDRESS);
+    		// load indirect arraylet pointer
+    		asm.emitLAddrX(T0, AB, T3);
+    		// T0 is now arraylet (base)
+
+    		// mask out the arraylet index
+    		asm.emitANDI(T1, T1, MemoryManagerConstants.REF_ARRAYLET_MASK);
+
+    		if (fr != null) {
+    		// T0 is base, T1 is index
+    			fr.resolve(asm);
+    		}
+    		if (fr2 != null) fr2.resolve(asm);
+
+    		asm.emitSLWI(T1, T1, LOG_BYTES_IN_ADDRESS);  // convert index to offset
+    		asm.emitLAddrX(T2, T0, T1);  // load desired (ref) array element
+    		pushAddr(T2);
+    	} else {
+    		Barriers.compileArrayLoadBarrier(this);
+    		pushAddr(T0);
+    	}
+    } else {
+    	asm.emitSLWI(T1, T1, LOG_BYTES_IN_ADDRESS);  // convert index to offset
+    	asm.emitLAddrX(T2, T0, T1);  // load desired (ref) array element
+    	pushAddr(T2);
     }
   }
 
@@ -947,9 +1014,14 @@
   @Override
   protected final void emit_baload() {
     genBoundsCheck();
-    asm.emitLBZX(T2, T0, T1);  // no load byte algebraic ...
-    asm.emitEXTSB(T2, T2);
-    pushInt(T2);
+    if (MemoryManagerConstants.USE_PRIMITIVE_BYTE_ARRAYLETS) {
+      Barriers.compileArrayLoadPrimitiveByteBarrier(this);
+      pushInt(T0);
+    } else {
+      asm.emitLBZX(T2, T0, T1);  // no load byte algebraic ...
+      asm.emitEXTSB(T2, T2);
+      pushInt(T2);
+    }
   }
 
   /**
@@ -958,9 +1030,14 @@
   @Override
   protected final void emit_caload() {
     genBoundsCheck();
-    asm.emitSLWI(T1, T1, LOG_BYTES_IN_CHAR);  // convert index to offset
-    asm.emitLHZX(T2, T0, T1);  // load desired (char) array element
-    pushInt(T2);
+    if (MemoryManagerConstants.USE_PRIMITIVE_CHAR_ARRAYLETS) {
+      Barriers.compileArrayLoadPrimitiveCharBarrier(this);
+      pushInt(T0);
+    } else {
+      asm.emitSLWI(T1, T1, LOG_BYTES_IN_CHAR);  // convert index to offset
+      asm.emitLHZX(T2, T0, T1);  // load desired (char) array element
+      pushInt(T2);
+    }
   }
 
   /**
@@ -969,9 +1046,14 @@
   @Override
   protected final void emit_saload() {
     genBoundsCheck();
-    asm.emitSLWI(T1, T1, LOG_BYTES_IN_SHORT);  // convert index to offset
-    asm.emitLHAX(T2, T0, T1);  // load desired (short) array element
-    pushInt(T2);
+    if (MemoryManagerConstants.USE_PRIMITIVE_SHORT_ARRAYLETS) {
+      Barriers.compileArrayLoadPrimitiveShortBarrier(this);
+      pushInt(T0);
+    } else {
+      asm.emitSLWI(T1, T1, LOG_BYTES_IN_SHORT);  // convert index to offset
+      asm.emitLHAX(T2, T0, T1);  // load desired (short) array element
+      pushInt(T2);
+    }
   }
 
   /*
@@ -985,8 +1067,12 @@
   protected final void emit_iastore() {
     popInt(T2);      // T2 is value to store
     genBoundsCheck();
-    asm.emitSLWI(T1, T1, LOG_BYTES_IN_INT);  // convert index to offset
-    asm.emitSTWX(T2, T0, T1);  // store int value in array
+    if (MemoryManagerConstants.USE_PRIMITIVE_INT_ARRAYLETS) {
+      Barriers.compileArrayStorePrimitiveIntBarrier(this); 
+    } else {
+      asm.emitSLWI(T1, T1, LOG_BYTES_IN_INT);  // convert index to offset
+      asm.emitSTWX(T2, T0, T1);  // store int value in array
+    }
   }
 
   /**
@@ -994,10 +1080,16 @@
    */
   @Override
   protected final void emit_lastore() {
-    popLongAsDouble(F0);                    // F0 is value to store
-    genBoundsCheck();
-    asm.emitSLWI(T1, T1, LOG_BYTES_IN_LONG);  // convert index to offset
-    asm.emitSTFDX(F0, T0, T1);  // store long value in array
+    if (MemoryManagerConstants.USE_PRIMITIVE_LONG_ARRAYLETS) {
+      popLong(T2, T3);                    // F0 is value to store
+      genBoundsCheck();
+      Barriers.compileArrayStorePrimitiveLongBarrier(this); 
+    } else {
+      popLongAsDouble(F0);
+      genBoundsCheck();
+      asm.emitSLWI(T1, T1, LOG_BYTES_IN_LONG);  // convert index to offset
+      asm.emitSTFDX(F0, T0, T1);  // store long value in array
+    }
   }
 
   /**
@@ -1005,10 +1097,16 @@
    */
   @Override
   protected final void emit_fastore() {
-    popInt(T2);      // T2 is value to store
-    genBoundsCheck();
-    asm.emitSLWI(T1, T1, LOG_BYTES_IN_FLOAT);  // convert index to offset
-    asm.emitSTWX(T2, T0, T1);  // store float value in array
+    if (MemoryManagerConstants.USE_PRIMITIVE_FLOAT_ARRAYLETS) {
+      popFloat(F0);
+      genBoundsCheck();
+      Barriers.compileArrayStorePrimitiveFloatBarrier(this); 
+    } else {
+      popInt(T2);      // T2 is value to store
+      genBoundsCheck();
+      asm.emitSLWI(T1, T1, LOG_BYTES_IN_FLOAT);  // convert index to offset
+      asm.emitSTWX(T2, T0, T1);  // store float value in array
+    }
   }
 
   /**
@@ -1018,8 +1116,12 @@
   protected final void emit_dastore() {
     popDouble(F0);         // F0 is value to store
     genBoundsCheck();
-    asm.emitSLWI(T1, T1, LOG_BYTES_IN_DOUBLE);  // convert index to offset
-    asm.emitSTFDX(F0, T0, T1);  // store double value in array
+    if (MemoryManagerConstants.USE_PRIMITIVE_DOUBLE_ARRAYLETS) {
+      Barriers.compileArrayStorePrimitiveDoubleBarrier(this); 
+    } else {
+      asm.emitSLWI(T1, T1, LOG_BYTES_IN_DOUBLE);  // convert index to offset
+      asm.emitSTFDX(F0, T0, T1);  // store double value in array
+    }
   }
 
   /**
@@ -1034,7 +1136,7 @@
     asm.emitBCCTRL();   // checkstore(arrayref, value)
     popAddr(T2);        // T2 is value to store
     genBoundsCheck();
-    if (MemoryManagerConstants.NEEDS_WRITE_BARRIER) {
+    if (MemoryManagerConstants.NEEDS_WRITE_BARRIER || MemoryManagerConstants.USE_OBJECT_ARRAY_ACCESS_BARRIER) {
       Barriers.compileArrayStoreBarrier(this);
     } else {
       asm.emitSLWI(T1, T1, LOG_BYTES_IN_ADDRESS);  // convert index to offset
@@ -1049,7 +1151,11 @@
   protected final void emit_bastore() {
     popInt(T2);      // T2 is value to store
     genBoundsCheck();
-    asm.emitSTBX(T2, T0, T1);  // store byte value in array
+    if (MemoryManagerConstants.USE_PRIMITIVE_BYTE_ARRAYLETS) {
+      Barriers.compileArrayStorePrimitiveByteBarrier(this); 
+    } else {
+      asm.emitSTBX(T2, T0, T1);  // store byte value in array
+    }
   }
 
   /**
@@ -1059,8 +1165,12 @@
   protected final void emit_castore() {
     popInt(T2);      // T2 is value to store
     genBoundsCheck();
-    asm.emitSLWI(T1, T1, LOG_BYTES_IN_CHAR);  // convert index to offset
-    asm.emitSTHX(T2, T0, T1);  // store char value in array
+    if (MemoryManagerConstants.USE_PRIMITIVE_CHAR_ARRAYLETS) {
+      Barriers.compileArrayStorePrimitiveCharBarrier(this); 
+    } else {
+      asm.emitSLWI(T1, T1, LOG_BYTES_IN_CHAR);  // convert index to offset
+      asm.emitSTHX(T2, T0, T1);  // store char value in array
+    }
   }
 
   /**
@@ -1070,8 +1180,12 @@
   protected final void emit_sastore() {
     popInt(T2);      // T2 is value to store
     genBoundsCheck();
-    asm.emitSLWI(T1, T1, LOG_BYTES_IN_SHORT);  // convert index to offset
-    asm.emitSTHX(T2, T0, T1);  // store short value in array
+    if (MemoryManagerConstants.USE_PRIMITIVE_SHORT_ARRAYLETS) {
+      Barriers.compileArrayStorePrimitiveShortBarrier(this); 
+    } else {
+      asm.emitSLWI(T1, T1, LOG_BYTES_IN_SHORT);  // convert index to offset
+      asm.emitSTHX(T2, T0, T1);  // store short value in array
+    }
   }
 
   /*
@@ -3152,7 +3266,7 @@
     if (DynamicTypeCheck.MIN_SUPERCLASS_IDS_SIZE <= LHSDepth) {
       // must do arraybounds check of superclass display
       asm.emitLIntOffset(T1, T0, ObjectModel.getArrayLengthOffset()); // T1 gets array length
-      asm.emitLVAL(T2, LHSDepth);
+      asm.emitLVAL(T2, LHSDepth >> (LOG_BYTES_IN_WORD - LOG_BYTES_IN_CHAR));
       asm.emitCMPL(T2, T1);
       ForwardReference fr1 = asm.emitForwardBC(LT);      // if in bounds, jump around trap.  TODO: would like to encode "y" bit that this branch is expected to be takem.
       asm.emitTWI(31, 12, TrapConstants.CHECKCAST_TRAP); // encoding of TRAP_ALWAYS CHECKCAST
@@ -3275,7 +3389,7 @@
     if (DynamicTypeCheck.MIN_SUPERCLASS_IDS_SIZE <= LHSDepth) {
       // must do arraybounds check of superclass display
       asm.emitLIntOffset(T1, T0, ObjectModel.getArrayLengthOffset()); // T1 gets array length
-      asm.emitLVAL(T2, LHSDepth);
+      asm.emitLVAL(T2, LHSDepth >> (LOG_BYTES_IN_WORD - LOG_BYTES_IN_CHAR));
       asm.emitCMPL(T1, T2);
       outOfBounds = asm.emitForwardBC(LE);
     }
@@ -3720,10 +3834,13 @@
    * @param reg The register to hold the counter array.
    */
   private void loadCounterArray(int reg) {
-    if (MemoryManagerConstants.NEEDS_READ_BARRIER) {
+    if (MemoryManagerConstants.NEEDS_READ_BARRIER || MemoryManagerConstants.USE_OBJECT_ARRAY_ACCESS_BARRIER_ON_EDGE_COUNTS) {
       asm.emitLAddrToc(T0, Entrypoints.edgeCountersField.getOffset());
       asm.emitLVAL(T1, getEdgeCounterIndex());
-      Barriers.compileArrayLoadBarrier(this);
+      if (VM.BuildWithBaseBootImageCompiler && VM.BuildForAdaptiveSystem && MemoryManagerConstants.USE_REFERENCE_ARRAYLETS) 
+        Barriers.compileHackArrayLoadBarrier(this);
+      else
+        Barriers.compileArrayLoadBarrier(this);
       if (reg != T0) {
         asm.emitORI(reg, T0, 0);
       }
@@ -4569,18 +4686,71 @@
       emit_resolved_newarray(type);
     } else if (methodName == MagicNames.addressArrayLength) {
       emit_arraylength();
+    } else if (methodName == MagicNames.addressArrayGetByte) {
+      popInt(T1);      // T1 is array index
+      popAddr(T0);     // T0 is array ref
+      asm.emitLBZX(T2, T0, T1);
+      asm.emitEXTSB(T2, T2);
+      pushInt(T2);
+    } else if (methodName == MagicNames.addressArrayGetChar) {
+      popInt(T1);      // T1 is array index
+      popAddr(T0);     // T0 is array ref
+      asm.emitSLWI(T1, T1, LOG_BYTES_IN_CHAR);  // convert index to offset
+      asm.emitLHZX(T2, T0, T1);  // load desired (char) array element
+      pushInt(T2);
+    } else if (methodName == MagicNames.addressArrayGetInt) {
+      popInt(T1);      // T1 is array index
+      popAddr(T0);     // T0 is array ref
+      asm.emitSLWI(T1, T1, LOG_BYTES_IN_INT);  // convert index to offset
+      asm.emitLIntX(T2, T0, T1);  // load desired int array element
+      pushInt(T2);
+    } else if (methodName == MagicNames.addressArrayGetLong) {
+      popInt(T1);      // T1 is array index
+      popAddr(T0);     // T0 is array ref
+      asm.emitSLWI(T1, T1, LOG_BYTES_IN_LONG);  // convert index to offset
+      asm.emitLFDX(F0, T0, T1);  // load desired (long) array element
+      pushLongAsDouble(F0);
     } else if (methodName == MagicNames.addressArrayGet) {
       if (VM.BuildFor32Addr || methodToBeCalled.getType() == TypeReference.CodeArray) {
-        emit_iaload();
+        genBoundsCheck();
+        asm.emitSLWI(T1, T1, LOG_BYTES_IN_INT);  // convert index to offset
+        asm.emitLIntX(T2, T0, T1);  // load desired int array element
+        pushInt(T2);
       } else {
         genBoundsCheck();
         asm.emitSLDI(T1, T1, LOG_BYTES_IN_ADDRESS);  // convert index to offset
         asm.emitLAddrX(T2, T0, T1);  // load desired array element
         pushAddr(T2);
       }
+    } else if (methodName == MagicNames.addressArraySetByte) {
+      popInt(T2);      // T2 is value to store
+      popInt(T1);      // T1 is array index
+      popAddr(T0);     // T0 is array ref
+      asm.emitSTBX(T2, T0, T1);  // store byte value in array
+    } else if (methodName == MagicNames.addressArraySetChar) {
+      popInt(T2);      // T2 is value to store
+      popInt(T1);      // T1 is array index
+      popAddr(T0);     // T0 is array ref
+      asm.emitSLWI(T1, T1, LOG_BYTES_IN_CHAR);  // convert index to offset
+      asm.emitSTHX(T2, T0, T1);  // store char value in array
+    } else if (methodName == MagicNames.addressArraySetInt) {
+      popInt(T2);      // T2 is value to store
+      popInt(T1);      // T1 is array index
+      popAddr(T0);     // T0 is array ref
+      asm.emitSLWI(T1, T1, LOG_BYTES_IN_INT);  // convert index to offset
+      asm.emitSTWX(T2, T0, T1);  // store int value in array
+    } else if (methodName == MagicNames.addressArraySetLong) {
+      popLongAsDouble(F0);                    // F0 is value to store
+      popInt(T1);      // T1 is array index
+      popAddr(T0);     // T0 is array ref
+      asm.emitSLWI(T1, T1, LOG_BYTES_IN_LONG);  // convert index to offset
+      asm.emitSTFDX(F0, T0, T1);  // store long value in array
     } else if (methodName == MagicNames.addressArraySet) {
       if (VM.BuildFor32Addr || methodToBeCalled.getType() == TypeReference.CodeArray) {
-        emit_iastore();
+        popInt(T2);      // T2 is value to store
+        genBoundsCheck();
+        asm.emitSLWI(T1, T1, LOG_BYTES_IN_INT);  // convert index to offset
+        asm.emitSTWX(T2, T0, T1);  // store int value in array
       } else {
         popAddr(T2);                                   // T2 is value to store
         genBoundsCheck();
@@ -4805,6 +4975,7 @@
                methodName == MagicNames.objectAsType ||
                methodName == MagicNames.objectAsShortArray ||
                methodName == MagicNames.objectAsIntArray ||
+               methodName == MagicNames.objectAsWordArray ||
                methodName == MagicNames.objectAsProcessor ||
                methodName == MagicNames.processorAsGreenProcessor ||
                methodName == MagicNames.objectAsThread ||
diff -r 743a2cc2ed20 -r 058fdc3780ba rvm/src/org/jikesrvm/compilers/baseline/ppc/BaselineExceptionDeliverer.java
--- a/rvm/src/org/jikesrvm/compilers/baseline/ppc/BaselineExceptionDeliverer.java	Tue Aug 04 11:04:15 2009 +1000
+++ b/rvm/src/org/jikesrvm/compilers/baseline/ppc/BaselineExceptionDeliverer.java	Mon Nov 16 09:21:21 2009 +1100
@@ -104,7 +104,7 @@
     for (int i = bcm.getLastFloatStackRegister(); i >= FIRST_FLOAT_LOCAL_REGISTER; --i) {
       frameOffset = frameOffset.minus(BYTES_IN_DOUBLE);
       long temp = Magic.getLongAtOffset(Magic.addressAsObject(fp), frameOffset);
-      registers.fprs[i] = Magic.longBitsAsDouble(temp);
+      registers.fprs.setLong(i, temp);
     }
 
     for (int i = bcm.getLastFixedStackRegister(); i >= FIRST_FIXED_LOCAL_REGISTER; --i) {
diff -r 743a2cc2ed20 -r 058fdc3780ba rvm/src/org/jikesrvm/compilers/opt/bc2ir/BC2IR.java
--- a/rvm/src/org/jikesrvm/compilers/opt/bc2ir/BC2IR.java	Tue Aug 04 11:04:15 2009 +1000
+++ b/rvm/src/org/jikesrvm/compilers/opt/bc2ir/BC2IR.java	Mon Nov 16 09:21:21 2009 +1100
@@ -3377,9 +3377,9 @@
     // Avoid upcasts of magic types to regular j.l.Objects
 //    if (VM.VerifyAssertions && (type == TypeReference.JavaLangObject))
 //      VM._assert(!r.getType().isMagicType());
-    if (VM.VerifyAssertions) {
+    if (false && VM.VerifyAssertions) {
       if ((type == TypeReference.JavaLangObject) &&
-          (r.getType().isMagicType()) &&
+          (r.getType().isMagicType() && !r.getType().isWordArrayType()) &&
           !gc.method.getDeclaringClass().getTypeRef().isMagicType()) {
         throw new OptimizingCompilerException.IllegalUpcast(r.getType());
       }
diff -r 743a2cc2ed20 -r 058fdc3780ba rvm/src/org/jikesrvm/compilers/opt/bc2ir/GenerateMagic.java
--- a/rvm/src/org/jikesrvm/compilers/opt/bc2ir/GenerateMagic.java	Tue Aug 04 11:04:15 2009 +1000
+++ b/rvm/src/org/jikesrvm/compilers/opt/bc2ir/GenerateMagic.java	Mon Nov 16 09:21:21 2009 +1100
@@ -213,6 +213,95 @@
       Instruction s = GuardedUnary.create(ARRAYLENGTH, t, op1, bc2ir.getCurrentGuard());
       bc2ir.push(t.copyD2U());
       bc2ir.appendInstruction(s);
+    } else if (methodName == MagicNames.addressArrayGetByte || 
+               methodName == MagicNames.addressArrayGetChar ||
+               methodName == MagicNames.addressArrayGetInt ||
+               methodName == MagicNames.addressArrayGetLong) {
+      TypeReference elementType = meth.getReturnType();
+      Operand index = bc2ir.popInt();
+      Operand ref = bc2ir.popRef();
+      RegisterOperand result = gc.temps.makeTemp(elementType);
+      
+      if (elementType == TypeReference.Byte) {
+        bc2ir.appendInstruction(Load.create(BYTE_LOAD,
+                                            result,
+                                            ref,
+                                            index,
+                                            new LocationOperand(elementType),
+                                            new TrueGuardOperand()));
+      } else { 
+        RegisterOperand offsetI = gc.temps.makeTempInt();
+        RegisterOperand offset = gc.temps.makeTempOffset();
+        Operator op;
+        int logSize;
+        if (elementType == TypeReference.Char) {
+          op = USHORT_LOAD;
+          logSize = 1;
+        } else if (elementType == TypeReference.Int) {
+          op = INT_LOAD;
+          logSize = 2;
+        } else if (elementType == TypeReference.Long) {
+          op = LONG_LOAD;
+          logSize = 3;
+        } else {
+          throw MagicNotImplementedException.UNEXPECTED("Unexpected type");
+        }
+        bc2ir.appendInstruction(Binary.create(INT_SHL, offsetI, index, new IntConstantOperand(logSize)));
+        bc2ir.appendInstruction(Unary.create(INT_2ADDRZerExt, offset, offsetI.copy()));
+        bc2ir.appendInstruction(Load.create(op,
+                                            result,
+                                            ref,
+                                            offset.copy(),
+                                            new LocationOperand(elementType),
+                                            new TrueGuardOperand()));
+      }
+      if (methodName == MagicNames.addressArrayGetLong) {
+        bc2ir.pushDual(result.copyD2U());
+      } else {
+        bc2ir.push(result.copyD2U());
+      }
+    } else if (methodName == MagicNames.addressArraySetByte || 
+        methodName == MagicNames.addressArraySetChar ||
+        methodName == MagicNames.addressArraySetInt ||
+        methodName == MagicNames.addressArraySetLong) {
+      TypeReference elementType = meth.getParameterTypes()[1];
+      Operand val = (methodName == MagicNames.addressArraySetLong) ? bc2ir.popLong() : bc2ir.pop();
+      Operand index = bc2ir.popInt();
+      Operand ref = bc2ir.popRef();
+
+      if (elementType == TypeReference.Byte) {
+        bc2ir.appendInstruction(Store.create(BYTE_STORE,
+            val,
+            ref,
+            index,
+            new LocationOperand(elementType),
+            new TrueGuardOperand()));
+      } else { 
+        RegisterOperand offsetI = gc.temps.makeTempInt();
+        RegisterOperand offset = gc.temps.makeTempOffset();
+        Operator op;
+        int logSize;
+        if (elementType == TypeReference.Char) {
+          op = SHORT_STORE;
+          logSize = 1;
+        } else if (elementType == TypeReference.Int) {
+          op = INT_STORE;
+          logSize = 2;
+        } else if (elementType == TypeReference.Long) {
+          op = LONG_STORE;
+          logSize = 3;
+        } else {
+          throw MagicNotImplementedException.UNEXPECTED("Unexpected type");
+        }
+        bc2ir.appendInstruction(Binary.create(INT_SHL, offsetI, index, new IntConstantOperand(logSize)));
+        bc2ir.appendInstruction(Unary.create(INT_2ADDRZerExt, offset, offsetI.copy()));
+        bc2ir.appendInstruction(Store.create(op,
+            val,
+            ref,
+            offset.copy(),
+            new LocationOperand(elementType),
+            new TrueGuardOperand()));
+      }
     } else if (methodName == MagicNames.addressArrayGet) {
       TypeReference elementType = meth.getReturnType();
       if (meth.getType() == TypeReference.ProcessorTable) {
@@ -540,6 +629,10 @@
       RegisterOperand reg = gc.temps.makeTemp(TypeReference.ShortArray);
       bc2ir.appendInstruction(Move.create(REF_MOVE, reg, bc2ir.popRef()));
       bc2ir.push(reg.copyD2U());
+    } else if (methodName == MagicNames.objectAsWordArray) {
+      RegisterOperand reg = gc.temps.makeTemp(TypeReference.WordArray);
+      bc2ir.appendInstruction(Move.create(REF_MOVE, reg, bc2ir.popRef()));
+      bc2ir.push(reg.copyD2U());
     } else if (methodName == MagicNames.objectAsIntArray) {
       RegisterOperand reg = gc.temps.makeTemp(TypeReference.IntArray);
       bc2ir.appendInstruction(Move.create(REF_MOVE, reg, bc2ir.popRef()));
diff -r 743a2cc2ed20 -r 058fdc3780ba rvm/src/org/jikesrvm/compilers/opt/bc2ir/GenerationContext.java
--- a/rvm/src/org/jikesrvm/compilers/opt/bc2ir/GenerationContext.java	Tue Aug 04 11:04:15 2009 +1000
+++ b/rvm/src/org/jikesrvm/compilers/opt/bc2ir/GenerationContext.java	Mon Nov 16 09:21:21 2009 +1100
@@ -359,8 +359,10 @@
         RegisterOperand objPtr = receiver.asRegister();
         if (ClassLoaderProxy.includesType(child.method.getDeclaringClass().getTypeRef(), objPtr.getType()) != YES) {
           // narrow type of actual to match formal static type implied by method
-          objPtr.setType(child.method.getDeclaringClass().getTypeRef());
+        	//jbs changed to make eclipse work - setType and clearPreciseType swapped order
           objPtr.clearPreciseType(); // Can be precise but not assignable if enough classes aren't loaded
+        	objPtr.setType(child.method.getDeclaringClass().getTypeRef());
+          //objPtr.clearPreciseType(); // Can be precise but not assignable if enough classes aren't loaded
           objPtr.setDeclaredType();
         }
         local = child.makeLocal(localNum, objPtr);
diff -r 743a2cc2ed20 -r 058fdc3780ba rvm/src/org/jikesrvm/compilers/opt/escape/SimpleEscape.java
--- a/rvm/src/org/jikesrvm/compilers/opt/escape/SimpleEscape.java	Tue Aug 04 11:04:15 2009 +1000
+++ b/rvm/src/org/jikesrvm/compilers/opt/escape/SimpleEscape.java	Mon Nov 16 09:21:21 2009 +1100
@@ -62,6 +62,8 @@
 import static org.jikesrvm.compilers.opt.ir.Operators.DOUBLE_STORE_opcode;
 import static org.jikesrvm.compilers.opt.ir.Operators.FLOAT_ALOAD_opcode;
 import static org.jikesrvm.compilers.opt.ir.Operators.FLOAT_ASTORE_opcode;
+import static org.jikesrvm.compilers.opt.ir.Operators.FLOAT_LOAD_opcode; //jbs added arraylet
+import static org.jikesrvm.compilers.opt.ir.Operators.FLOAT_STORE_opcode; //jbs added arraylet
 import static org.jikesrvm.compilers.opt.ir.Operators.GETFIELD_opcode;
 import static org.jikesrvm.compilers.opt.ir.Operators.GETSTATIC_opcode;
 import static org.jikesrvm.compilers.opt.ir.Operators.GET_CAUGHT_EXCEPTION_opcode;
@@ -413,6 +415,7 @@
       case INT_LOAD_opcode:
       case LONG_LOAD_opcode:
       case DOUBLE_LOAD_opcode:
+      case FLOAT_LOAD_opcode:
       case REF_LOAD_opcode:
         // all is OK, unless we load this register from memory
         Operand result = ResultCarrier.getResult(inst);
@@ -432,6 +435,7 @@
       case REF_STORE_opcode:
       case INT_STORE_opcode:
       case LONG_STORE_opcode:
+      case FLOAT_STORE_opcode:
       case DOUBLE_STORE_opcode:
         // as long as we don't store this operand elsewhere, all
         // is OK. TODO: add more smarts.
@@ -609,6 +613,7 @@
       case INT_LOAD_opcode:
       case LONG_LOAD_opcode:
       case DOUBLE_LOAD_opcode:
+      case FLOAT_LOAD_opcode:
       case REF_LOAD_opcode:
         // all is OK, unless we load this register from memory
         Operand result = ResultCarrier.getResult(inst);
@@ -629,6 +634,7 @@
       case INT_STORE_opcode:
       case LONG_STORE_opcode:
       case DOUBLE_STORE_opcode:
+      case FLOAT_STORE_opcode:
         // as long as we don't store this operand elsewhere, all
         // is OK. TODO: add more smarts.
         value = Store.getValue(inst);
diff -r 743a2cc2ed20 -r 058fdc3780ba rvm/src/org/jikesrvm/compilers/opt/hir2lir/DynamicTypeCheckExpansion.java
--- a/rvm/src/org/jikesrvm/compilers/opt/hir2lir/DynamicTypeCheckExpansion.java	Tue Aug 04 11:04:15 2009 +1000
+++ b/rvm/src/org/jikesrvm/compilers/opt/hir2lir/DynamicTypeCheckExpansion.java	Mon Nov 16 09:21:21 2009 +1100
@@ -12,6 +12,9 @@
  */
 package org.jikesrvm.compilers.opt.hir2lir;
 
+import gnu.javax.swing.text.html.parser.support.low.Constants;
+
+import org.jikesrvm.SizeConstants;
 import org.jikesrvm.VM;
 import org.jikesrvm.classloader.RVMArray;
 import org.jikesrvm.classloader.RVMClass;
@@ -341,7 +344,7 @@
     failBlock.appendInstruction(raiseError);
 
     Operand RHStib = getTIB(s, ir, ref, guard);
-    RegisterOperand doesImpl = InsertUnary(s, ir, GET_DOES_IMPLEMENT_FROM_TIB, TypeReference.IntArray, RHStib);
+    RegisterOperand doesImpl = InsertUnary(s, ir, GET_DOES_IMPLEMENT_FROM_TIB, TypeReference.WordArray, RHStib);
 
     if (DynamicTypeCheck.MIN_DOES_IMPLEMENT_SIZE <= interfaceIndex) {
       RegisterOperand doesImplLength =
@@ -520,7 +523,7 @@
               InsertUnary(curBlock.lastInstruction(),
                           ir,
                           GET_SUPERCLASS_IDS_FROM_TIB,
-                          TypeReference.ShortArray,
+                          TypeReference.WordArray,
                           rhsTIB.copy());
           RegisterOperand lhsElemDepth =
               getField(curBlock.lastInstruction(), ir, lhsElemType, Entrypoints.depthField, TG());
@@ -531,10 +534,17 @@
                                  TypeReference.Int,
                                  rhsSuperclassIds.copyD2U(),
                                  TG());
+          RegisterOperand rhsSuperclassIdsChars =
+            insertBinary(curBlock.lastInstruction(),
+                         ir,
+                         INT_SHL,
+                         TypeReference.Int,
+                         rhsSuperclassIdsLength.copyD2U(),
+                         IC(SizeConstants.LOG_BYTES_IN_WORD - SizeConstants.LOG_BYTES_IN_CHAR));
           curBlock.appendInstruction(IfCmp.create(INT_IFCMP,
                                                   guardResult.copyRO(),
                                                   lhsElemDepth,
-                                                  rhsSuperclassIdsLength,
+                                                  rhsSuperclassIdsChars.copyD2U(),
                                                   ConditionOperand.GREATER_EQUAL(),
                                                   trapBlock.makeJumpTarget(),
                                                   BranchProfileOperand.never()));
@@ -543,36 +553,27 @@
 
           RegisterOperand lhsElemId =
               getField(curBlock.lastInstruction(), ir, lhsElemType.copyD2U(), Entrypoints.idField, TG());
-          RegisterOperand refCandidate = ir.regpool.makeTemp(TypeReference.Short);
-          LocationOperand loc = new LocationOperand(TypeReference.Short);
-          if (LOWER_ARRAY_ACCESS) {
-            RegisterOperand lhsDepthOffset =
-                insertBinary(curBlock.lastInstruction(),
-                             ir,
-                             INT_SHL,
-                             TypeReference.Int,
-                             lhsElemDepth.copyD2U(),
-                             IC(1));
-            lhsDepthOffset =
-                InsertUnary(curBlock.lastInstruction(),
-                            ir,
-                            INT_2ADDRZerExt,
-                            TypeReference.Offset,
-                            lhsDepthOffset.copy());
-            curBlock.appendInstruction(Load.create(USHORT_LOAD,
-                                                   refCandidate,
-                                                   rhsSuperclassIds,
-                                                   lhsDepthOffset,
-                                                   loc,
-                                                   TG()));
-          } else {
-            curBlock.appendInstruction(ALoad.create(USHORT_ALOAD,
-                                                    refCandidate,
-                                                    rhsSuperclassIds,
-                                                    lhsElemDepth.copyRO(),
-                                                    loc,
-                                                    TG()));
-          }
+          RegisterOperand refCandidate = ir.regpool.makeTemp(TypeReference.Char);
+          LocationOperand loc = new LocationOperand(TypeReference.Char);
+          RegisterOperand lhsDepthOffset =
+              insertBinary(curBlock.lastInstruction(),
+                           ir,
+                           INT_SHL,
+                           TypeReference.Int,
+                           lhsElemDepth.copyD2U(),
+                           IC(1));
+          lhsDepthOffset =
+              InsertUnary(curBlock.lastInstruction(),
+                          ir,
+                          INT_2ADDRZerExt,
+                          TypeReference.Offset,
+                          lhsDepthOffset.copy());
+          curBlock.appendInstruction(Load.create(USHORT_LOAD,
+                                                 refCandidate,
+                                                 rhsSuperclassIds,
+                                                 lhsDepthOffset,
+                                                 loc,
+                                                 TG()));
           curBlock.appendInstruction(IfCmp.create(INT_IFCMP,
                                                   guardResult.copyRO(),
                                                   refCandidate.copyD2U(),
@@ -636,7 +637,7 @@
           int interfaceIndex = LHSclass.getDoesImplementIndex();
           int interfaceMask = LHSclass.getDoesImplementBitMask();
           RegisterOperand doesImpl =
-              InsertUnary(s, ir, GET_DOES_IMPLEMENT_FROM_TIB, TypeReference.IntArray, RHStib);
+              InsertUnary(s, ir, GET_DOES_IMPLEMENT_FROM_TIB, TypeReference.WordArray, RHStib);
           RegisterOperand entry =
               InsertLoadOffset(s,
                                ir,
@@ -658,6 +659,10 @@
           if (DynamicTypeCheck.MIN_DOES_IMPLEMENT_SIZE <= interfaceIndex) {
             RegisterOperand doesImplLength =
                 InsertGuardedUnary(s, ir, ARRAYLENGTH, TypeReference.Int, doesImpl.copy(), TG());
+            if ((SizeConstants.LOG_BYTES_IN_WORD - SizeConstants.LOG_BYTES_IN_INT) != 0) {
+              doesImplLength = insertBinary(s, ir, INT_SHL, TypeReference.Int, doesImplLength.copyD2U(),
+                  IC(SizeConstants.LOG_BYTES_IN_WORD - SizeConstants.LOG_BYTES_IN_INT));
+            }
             RegisterOperand boundscheck = ir.regpool.makeTempInt();
             //save to use the cheaper ADDR version of BOOLEAN_CMP
             s.insertBefore(BooleanCmp.create(BOOLEAN_CMP_ADDR,
@@ -690,15 +695,15 @@
             int LHSDepth = LHSclass.getTypeDepth();
             int LHSId = LHSclass.getId();
             RegisterOperand superclassIds =
-                InsertUnary(s, ir, GET_SUPERCLASS_IDS_FROM_TIB, TypeReference.ShortArray, RHStib);
+                InsertUnary(s, ir, GET_SUPERCLASS_IDS_FROM_TIB, TypeReference.WordArray, RHStib);
             RegisterOperand refCandidate =
                 InsertLoadOffset(s,
                                  ir,
                                  USHORT_LOAD,
-                                 TypeReference.Short,
+                                 TypeReference.Char,
                                  superclassIds,
                                  Offset.fromIntZeroExtend(LHSDepth << 1),
-                                 new LocationOperand(TypeReference.Short),
+                                 new LocationOperand(TypeReference.Char),
                                  TG());
             //save to use the cheaper ADDR version of BOOLEAN_CMP
             s.insertBefore(BooleanCmp.create(BOOLEAN_CMP_ADDR,
@@ -710,6 +715,8 @@
             if (DynamicTypeCheck.MIN_SUPERCLASS_IDS_SIZE <= LHSDepth) {
               RegisterOperand superclassIdsLength =
                   InsertGuardedUnary(s, ir, ARRAYLENGTH, TypeReference.Int, superclassIds.copyD2U(), TG());
+              superclassIdsLength = insertBinary(s, ir, INT_SHL, TypeReference.Int, superclassIdsLength.copyD2U(),
+                    IC(SizeConstants.LOG_BYTES_IN_WORD - SizeConstants.LOG_BYTES_IN_CHAR));
               RegisterOperand boundscheck = ir.regpool.makeTempInt();
               //save to use the cheaper ADDR version of BOOLEAN_CMP
               s.insertBefore(BooleanCmp.create(BOOLEAN_CMP_ADDR,
@@ -849,11 +856,15 @@
           int interfaceIndex = LHSclass.getDoesImplementIndex();
           int interfaceMask = LHSclass.getDoesImplementBitMask();
           RegisterOperand doesImpl =
-              InsertUnary(continueAt, ir, GET_DOES_IMPLEMENT_FROM_TIB, TypeReference.IntArray, RHStib);
+              InsertUnary(continueAt, ir, GET_DOES_IMPLEMENT_FROM_TIB, TypeReference.WordArray, RHStib);
 
           if (DynamicTypeCheck.MIN_DOES_IMPLEMENT_SIZE <= interfaceIndex) {
             RegisterOperand doesImplLength =
                 InsertGuardedUnary(continueAt, ir, ARRAYLENGTH, TypeReference.Int, doesImpl.copyD2U(), TG());
+            if ((SizeConstants.LOG_BYTES_IN_WORD - SizeConstants.LOG_BYTES_IN_INT) != 0) {
+              doesImplLength = insertBinary(s, ir, INT_SHL, TypeReference.Int, doesImplLength.copyD2U(),
+                  IC(SizeConstants.LOG_BYTES_IN_WORD - SizeConstants.LOG_BYTES_IN_INT));
+            }
             Instruction lengthCheck =
                 IfCmp.create(INT_IFCMP,
                              oldGuard,
@@ -908,10 +919,12 @@
             int LHSDepth = LHSclass.getTypeDepth();
             int LHSId = LHSclass.getId();
             RegisterOperand superclassIds =
-                InsertUnary(continueAt, ir, GET_SUPERCLASS_IDS_FROM_TIB, TypeReference.ShortArray, RHStib);
+                InsertUnary(continueAt, ir, GET_SUPERCLASS_IDS_FROM_TIB, TypeReference.WordArray, RHStib);
             if (DynamicTypeCheck.MIN_SUPERCLASS_IDS_SIZE <= LHSDepth) {
               RegisterOperand superclassIdsLength =
                   InsertGuardedUnary(continueAt, ir, ARRAYLENGTH, TypeReference.Int, superclassIds.copyD2U(), TG());
+              superclassIdsLength = insertBinary(continueAt, ir, INT_SHL, TypeReference.Int, superclassIdsLength.copyD2U(),
+                  IC(SizeConstants.LOG_BYTES_IN_WORD - SizeConstants.LOG_BYTES_IN_CHAR));
               Instruction lengthCheck =
                   IfCmp.create(INT_IFCMP,
                                oldGuard,
@@ -932,10 +945,10 @@
                 InsertLoadOffset(continueAt,
                                  ir,
                                  USHORT_LOAD,
-                                 TypeReference.Short,
+                                 TypeReference.Char,
                                  superclassIds,
                                  Offset.fromIntZeroExtend(LHSDepth << 1),
-                                 new LocationOperand(TypeReference.Short),
+                                 new LocationOperand(TypeReference.Char),
                                  TG());
             continueAt.insertBefore(IfCmp.create(INT_IFCMP,
                                                  oldGuard,
diff -r 743a2cc2ed20 -r 058fdc3780ba rvm/src/org/jikesrvm/compilers/opt/hir2lir/ExpandRuntimeServices.java
--- a/rvm/src/org/jikesrvm/compilers/opt/hir2lir/ExpandRuntimeServices.java	Tue Aug 04 11:04:15 2009 +1000
+++ b/rvm/src/org/jikesrvm/compilers/opt/hir2lir/ExpandRuntimeServices.java	Mon Nov 16 09:21:21 2009 +1100
@@ -18,6 +18,21 @@
 import static org.jikesrvm.compilers.opt.ir.Operators.GETFIELD_opcode;
 import static org.jikesrvm.compilers.opt.ir.Operators.GETSTATIC_opcode;
 import static org.jikesrvm.compilers.opt.ir.Operators.INT_ASTORE;
+import static org.jikesrvm.compilers.opt.ir.Operators.SHORT_ALOAD_opcode;
+import static org.jikesrvm.compilers.opt.ir.Operators.SHORT_ASTORE_opcode;
+import static org.jikesrvm.compilers.opt.ir.Operators.LONG_ALOAD_opcode;
+import static org.jikesrvm.compilers.opt.ir.Operators.LONG_ASTORE_opcode; 
+import static org.jikesrvm.compilers.opt.ir.Operators.DOUBLE_ALOAD_opcode;
+import static org.jikesrvm.compilers.opt.ir.Operators.DOUBLE_ASTORE_opcode;
+import static org.jikesrvm.compilers.opt.ir.Operators.FLOAT_ALOAD_opcode;
+import static org.jikesrvm.compilers.opt.ir.Operators.FLOAT_ASTORE_opcode;
+import static org.jikesrvm.compilers.opt.ir.Operators.BYTE_ALOAD_opcode;
+import static org.jikesrvm.compilers.opt.ir.Operators.UBYTE_ALOAD_opcode;
+import static org.jikesrvm.compilers.opt.ir.Operators.BYTE_ASTORE_opcode;
+import static org.jikesrvm.compilers.opt.ir.Operators.USHORT_ALOAD_opcode;
+import static org.jikesrvm.compilers.opt.ir.Operators.INT_ALOAD_opcode;
+import static org.jikesrvm.compilers.opt.ir.Operators.INT_ASTORE_opcode;
+
 import static org.jikesrvm.compilers.opt.ir.Operators.MONITORENTER_opcode;
 import static org.jikesrvm.compilers.opt.ir.Operators.MONITOREXIT_opcode;
 import static org.jikesrvm.compilers.opt.ir.Operators.NEWARRAY_UNRESOLVED_opcode;
@@ -272,12 +287,36 @@
             // Step 2: Assign the dimension values to dimArray
             for (int i = 0; i < dimensions; i++) {
               LocationOperand loc = new LocationOperand(TypeReference.Int);
+             /* if (MemoryManagerConstants.USE_PRIMITIVE_INT_ARRAYLETS) {
+              	//jbs - FYI - next if might be unnecessary for longs, but was for shorts to distinguish from chars
+              	  //if (ALoad.getArray(inst).getType().peekType().isArrayType() && ALoad.getArray(inst).getType().peekType().asArray().isArrayletizable()) {// .getArrayElementType().isShortType()) {
+                  	  
+                  RVMMethod target = Entrypoints.arrayStorePrimitiveIntWriteBarrierMethod;
+                  Instruction wb =
+                      Call.create3(CALL,
+                                   null,
+                                   IRTools.AC(target.getOffset()),
+                                   MethodOperand.STATIC(target),
+                                   IRTools.TG(), //AStore.getClearGuard(inst),
+                                   dimArray.copyD2U(), //AStore.getArray(inst).copy(),
+                                   IRTools.IC(i), //AStore.getIndex(inst).copy(),
+                                   Multianewarray.getClearDimension(inst, i)); //AStore.getValue(inst).copy());
+                  wb.bcIndex = RUNTIME_SERVICES_BCI;
+                  //wb.position = inst.position;
+                  inst.insertBefore(wb);
+                  //next = wb.prevInstructionInCodeOrder();
+                  if (ir.options.INLINE_WRITE_BARRIER) {
+                    inline(wb, ir, true);
+                  }
+              	  //}
+                } else {*/
               inst.insertBefore(AStore.create(INT_ASTORE,
                                 Multianewarray.getClearDimension(inst, i),
                                 dimArray.copyD2U(),
                                 IRTools.IC(i),
                                 loc,
                                 IRTools.TG()));
+                //}
             }
             // Step 3. Plant call to OptLinker.newArrayArray
             RVMMethod target = Entrypoints.optNewArrayArrayMethod;
@@ -371,8 +410,173 @@
         }
         break;
 
+        case SHORT_ASTORE_opcode: {
+          if (MemoryManagerConstants.USE_PRIMITIVE_SHORT_ARRAYLETS || MemoryManagerConstants.USE_PRIMITIVE_CHAR_ARRAYLETS) {
+            if (ALoad.getArray(inst).getType().peekType().isArrayType() && ALoad.getArray(inst).getType().peekType().asArray().isArrayletizable()) {// .getArrayElementType().isShortType()) {
+
+              RVMMethod target; 
+              if (ALoad.getArray(inst).getType().peekType().asArray().getElementType().isShortType())
+                target = Entrypoints.arrayStorePrimitiveShortWriteBarrierMethod;
+              else
+                target = Entrypoints.arrayStorePrimitiveCharWriteBarrierMethod;
+
+              Instruction wb =
+                Call.create3(CALL,
+                             null,
+                             IRTools.AC(target.getOffset()),
+                             MethodOperand.STATIC(target),
+                             AStore.getClearGuard(inst),
+                             AStore.getArray(inst).copy(),
+                             AStore.getIndex(inst).copy(),
+                             AStore.getValue(inst).copy());
+              wb.bcIndex = RUNTIME_SERVICES_BCI;
+              wb.position = inst.position;
+              inst.replace(wb);
+              next = wb.prevInstructionInCodeOrder();
+              if (ir.options.INLINE_WRITE_BARRIER) {
+                inline(wb, ir, true);
+              }
+            }
+          }
+        }
+        break;
+        
+        
+        case BYTE_ASTORE_opcode: {
+          if (MemoryManagerConstants.USE_PRIMITIVE_BYTE_ARRAYLETS) {
+	      // if (ALoad.getArray(inst).getType().peekType().isArrayType() && ALoad.getArray(inst).getType().peekType().asArray().isArrayletizable()) {// .getArrayElementType().isShortType()) {
+
+              RVMMethod target = Entrypoints.arrayStorePrimitiveByteWriteBarrierMethod;
+              Instruction wb =
+                Call.create3(CALL,
+                             null,
+                             IRTools.AC(target.getOffset()),
+                             MethodOperand.STATIC(target),
+                             AStore.getClearGuard(inst),
+                             AStore.getArray(inst).copy(),
+                             AStore.getIndex(inst).copy(),
+                             AStore.getValue(inst).copy());
+              wb.bcIndex = RUNTIME_SERVICES_BCI;
+              wb.position = inst.position;
+              inst.replace(wb);
+              next = wb.prevInstructionInCodeOrder();
+              if (ir.options.INLINE_WRITE_BARRIER) {
+                inline(wb, ir, true);
+              }
+	      // }
+          }
+        }
+        break;
+
+        case FLOAT_ASTORE_opcode: {
+          if (MemoryManagerConstants.USE_PRIMITIVE_FLOAT_ARRAYLETS) {
+            //jbs - FYI - next if might be unnecessary for longs, but was for shorts to distinguish from chars
+            //if (ALoad.getArray(inst).getType().peekType().isArrayType() && ALoad.getArray(inst).getType().peekType().asArray().isArrayletizable()) {// .getArrayElementType().isShortType()) {
+
+              RVMMethod target = Entrypoints.arrayStorePrimitiveFloatWriteBarrierMethod;
+              Instruction wb =
+                Call.create3(CALL,
+                             null,
+                             IRTools.AC(target.getOffset()),
+                             MethodOperand.STATIC(target),
+                             AStore.getClearGuard(inst),
+                             AStore.getArray(inst).copy(),
+                             AStore.getIndex(inst).copy(),
+                             AStore.getValue(inst).copy());
+              wb.bcIndex = RUNTIME_SERVICES_BCI;
+              wb.position = inst.position;
+              inst.replace(wb);
+              next = wb.prevInstructionInCodeOrder();
+              if (ir.options.INLINE_WRITE_BARRIER) {
+                inline(wb, ir, true);
+              }
+	      //}
+          }
+        }
+        break;
+
+        case INT_ASTORE_opcode: {
+          if (MemoryManagerConstants.USE_PRIMITIVE_INT_ARRAYLETS) {
+            //jbs - FYI - next if might be unnecessary for longs, but was for shorts to distinguish from chars
+	      //    if (ALoad.getArray(inst).getType().peekType().isArrayType() && ALoad.getArray(inst).getType().peekType().asArray().isArrayletizable()) {// .getArrayElementType().isShortType()) {
+
+              RVMMethod target = Entrypoints.arrayStorePrimitiveIntWriteBarrierMethod;
+              Instruction wb =
+                Call.create3(CALL,
+                             null,
+                             IRTools.AC(target.getOffset()),
+                             MethodOperand.STATIC(target),
+                             AStore.getClearGuard(inst),
+                             AStore.getArray(inst).copy(),
+                             AStore.getIndex(inst).copy(),
+                             AStore.getValue(inst).copy());
+              wb.bcIndex = RUNTIME_SERVICES_BCI;
+              wb.position = inst.position;
+              inst.replace(wb);
+              next = wb.prevInstructionInCodeOrder();
+              if (ir.options.INLINE_WRITE_BARRIER) {
+                inline(wb, ir, true);
+              }
+	      // }
+          }
+        }
+        break;
+
+        case LONG_ASTORE_opcode: {
+          if (MemoryManagerConstants.USE_PRIMITIVE_LONG_ARRAYLETS) {
+	      // if (ALoad.getArray(inst).getType().peekType().isArrayType() && ALoad.getArray(inst).getType().peekType().asArray().isArrayletizable()) {// .getArrayElementType().isShortType()) {
+
+              RVMMethod target = Entrypoints.arrayStorePrimitiveLongWriteBarrierMethod;
+              Instruction wb =
+                Call.create3(CALL,
+                             null,
+                             IRTools.AC(target.getOffset()),
+                             MethodOperand.STATIC(target),
+                             AStore.getClearGuard(inst),
+                             AStore.getArray(inst).copy(),
+                             AStore.getIndex(inst).copy(),
+                             AStore.getValue(inst).copy());
+              wb.bcIndex = RUNTIME_SERVICES_BCI;
+              wb.position = inst.position;
+              inst.replace(wb);
+              next = wb.prevInstructionInCodeOrder();
+              if (ir.options.INLINE_WRITE_BARRIER) {
+                inline(wb, ir, true);
+              }
+	      //}
+          }
+        }
+        break;
+        
+        case DOUBLE_ASTORE_opcode: {
+          if (MemoryManagerConstants.USE_PRIMITIVE_DOUBLE_ARRAYLETS) {
+	      // if (ALoad.getArray(inst).getType().peekType().isArrayType() && ALoad.getArray(inst).getType().peekType().asArray().isArrayletizable()) {// .getArrayElementType().isShortType()) {
+
+              RVMMethod target = Entrypoints.arrayStorePrimitiveDoubleWriteBarrierMethod;
+              Instruction wb =
+                  Call.create3(CALL,
+                               null,
+                               IRTools.AC(target.getOffset()),
+                               MethodOperand.STATIC(target),
+                               AStore.getClearGuard(inst),
+                               AStore.getArray(inst).copy(),
+                               AStore.getIndex(inst).copy(),
+                               AStore.getValue(inst).copy());
+              wb.bcIndex = RUNTIME_SERVICES_BCI;
+              wb.position = inst.position;
+              inst.replace(wb);
+              next = wb.prevInstructionInCodeOrder();
+              if (ir.options.INLINE_WRITE_BARRIER) {
+                inline(wb, ir, true);
+              }
+	      //	  }
+            }
+          }
+          break;
+        
         case REF_ASTORE_opcode: {
-          if (MemoryManagerConstants.NEEDS_WRITE_BARRIER) {
+        	//jbs added arraylet
+          if (MemoryManagerConstants.NEEDS_WRITE_BARRIER || MemoryManagerConstants.USE_REFERENCE_ARRAYLETS || MemoryManagerConstants.USE_OBJECT_ARRAY_ACCESS_BARRIER) {
             RVMMethod target = Entrypoints.arrayStoreWriteBarrierMethod;
             Instruction wb =
                 Call.create3(CALL,
@@ -394,8 +598,212 @@
         }
         break;
 
+        case SHORT_ALOAD_opcode: {
+          if (MemoryManagerConstants.USE_PRIMITIVE_SHORT_ARRAYLETS || MemoryManagerConstants.USE_PRIMITIVE_CHAR_ARRAYLETS) {
+            if (ALoad.getArray(inst).getType().peekType().isArrayType() && ALoad.getArray(inst).getType().peekType().asArray().isArrayletizable()) {// .getArrayElementType().isShortType()) {
+
+              RVMMethod target; 
+              if (ALoad.getArray(inst).getType().peekType().asArray().getElementType().isShortType()) {
+                target = Entrypoints.arrayLoadPrimitiveShortReadBarrierMethod;
+              } else {
+                target = Entrypoints.arrayLoadPrimitiveCharReadBarrierMethod;
+              }
+
+              Instruction rb =
+                Call.create2(CALL,
+                           ALoad.getClearResult(inst),
+                           IRTools.AC(target.getOffset()),
+                           MethodOperand.STATIC(target),
+                           ALoad.getClearGuard(inst),
+                           ALoad.getArray(inst).copy(),
+                           ALoad.getIndex(inst).copy());
+
+              rb.bcIndex = RUNTIME_SERVICES_BCI;
+              rb.position = inst.position;
+              inst.replace(rb);
+              next = rb.prevInstructionInCodeOrder();
+              inline(rb, ir, true);
+            }
+          }
+        }
+        break;
+
+        case USHORT_ALOAD_opcode: {
+          if (MemoryManagerConstants.USE_PRIMITIVE_CHAR_ARRAYLETS) {
+            if (ALoad.getArray(inst).getType().peekType().isArrayType() && ALoad.getArray(inst).getType().peekType().asArray().isArrayletizable()) {// .getArrayElementType().isShortType()) {
+
+              RVMMethod target; 
+              target = Entrypoints.arrayLoadPrimitiveCharReadBarrierMethod;
+              Instruction rb =
+                Call.create2(CALL,
+                           ALoad.getClearResult(inst),
+                           IRTools.AC(target.getOffset()),
+                           MethodOperand.STATIC(target),
+                           ALoad.getClearGuard(inst),
+                           ALoad.getArray(inst).copy(),
+                           ALoad.getIndex(inst).copy());
+
+              rb.bcIndex = RUNTIME_SERVICES_BCI;
+              rb.position = inst.position;
+              inst.replace(rb);
+              next = rb.prevInstructionInCodeOrder();
+              inline(rb, ir, true);
+            }
+          }
+        }
+        break;
+
+        case UBYTE_ALOAD_opcode: {
+          if (MemoryManagerConstants.USE_PRIMITIVE_BYTE_ARRAYLETS) {
+	      // if (ALoad.getArray(inst).getType().peekType().isArrayType() && ALoad.getArray(inst).getType().peekType().asArray().isArrayletizable()) {// .getArrayElementType().isShortType()) {
+
+              RVMMethod target = Entrypoints.arrayLoadPrimitiveByteReadBarrierMethod;
+
+              Instruction rb =
+                Call.create2(CALL,
+                             ALoad.getClearResult(inst),
+                             IRTools.AC(target.getOffset()),
+                             MethodOperand.STATIC(target),
+                             ALoad.getClearGuard(inst),
+                             ALoad.getArray(inst).copy(),
+                             ALoad.getIndex(inst).copy());
+
+              rb.bcIndex = RUNTIME_SERVICES_BCI;
+              rb.position = inst.position;
+              inst.replace(rb);
+              next = rb.prevInstructionInCodeOrder();
+              inline(rb, ir, true);
+	      // }
+          }
+        }
+        break;
+        
+        case BYTE_ALOAD_opcode: {
+          if (MemoryManagerConstants.USE_PRIMITIVE_BYTE_ARRAYLETS) {
+	      //  if (ALoad.getArray(inst).getType().peekType().isArrayType() && ALoad.getArray(inst).getType().peekType().asArray().isArrayletizable()) {// .getArrayElementType().isShortType()) {
+
+              RVMMethod target = Entrypoints.arrayLoadPrimitiveByteReadBarrierMethod;
+
+              Instruction rb =
+                Call.create2(CALL,
+                           ALoad.getClearResult(inst),
+                           IRTools.AC(target.getOffset()),
+                           MethodOperand.STATIC(target),
+                           ALoad.getClearGuard(inst),
+                           ALoad.getArray(inst).copy(),
+                           ALoad.getIndex(inst).copy());
+            
+              rb.bcIndex = RUNTIME_SERVICES_BCI;
+              rb.position = inst.position;
+              inst.replace(rb);
+              next = rb.prevInstructionInCodeOrder();
+              inline(rb, ir, true);
+	      // }
+          }
+        }
+        break;
+        
+        case FLOAT_ALOAD_opcode: {
+          if (MemoryManagerConstants.USE_PRIMITIVE_FLOAT_ARRAYLETS) {
+	      // if (ALoad.getArray(inst).getType().peekType().isArrayType() && ALoad.getArray(inst).getType().peekType().asArray().isArrayletizable()) {// .getArrayElementType().isShortType()) {
+
+              RVMMethod target = Entrypoints.arrayLoadPrimitiveFloatReadBarrierMethod;
+              Instruction rb =
+                Call.create2(CALL,
+                           ALoad.getClearResult(inst),
+                           IRTools.AC(target.getOffset()),
+                           MethodOperand.STATIC(target),
+                           ALoad.getClearGuard(inst),
+                           ALoad.getArray(inst).copy(),
+                           ALoad.getIndex(inst).copy());
+
+              rb.bcIndex = RUNTIME_SERVICES_BCI;
+              rb.position = inst.position;
+              inst.replace(rb);
+              next = rb.prevInstructionInCodeOrder();
+              inline(rb, ir, true);
+	      // }
+          }
+        }
+        break;
+        
+        case INT_ALOAD_opcode: {
+          if (MemoryManagerConstants.USE_PRIMITIVE_INT_ARRAYLETS) {
+	      // if (ALoad.getArray(inst).getType().peekType().isArrayType() && ALoad.getArray(inst).getType().peekType().asArray().isArrayletizable()) {// .getArrayElementType().isShortType()) {
+
+              RVMMethod target = Entrypoints.arrayLoadPrimitiveIntReadBarrierMethod;
+
+              Instruction rb =
+                Call.create2(CALL,
+                           ALoad.getClearResult(inst),
+                           IRTools.AC(target.getOffset()),
+                           MethodOperand.STATIC(target),
+                           ALoad.getClearGuard(inst),
+                           ALoad.getArray(inst).copy(),
+                           ALoad.getIndex(inst).copy());
+            
+              rb.bcIndex = RUNTIME_SERVICES_BCI;
+              rb.position = inst.position;
+              inst.replace(rb);
+              next = rb.prevInstructionInCodeOrder();
+              inline(rb, ir, true);
+	      // }
+          }
+        }
+        break;
+
+        case LONG_ALOAD_opcode: {
+          if (MemoryManagerConstants.USE_PRIMITIVE_LONG_ARRAYLETS) {
+	      // if (ALoad.getArray(inst).getType().peekType().isArrayType() && ALoad.getArray(inst).getType().peekType().asArray().isArrayletizable()) {// .getArrayElementType().isShortType()) {
+
+              RVMMethod target = Entrypoints.arrayLoadPrimitiveLongReadBarrierMethod;
+
+              Instruction rb =
+                Call.create2(CALL,
+                           ALoad.getClearResult(inst),
+                           IRTools.AC(target.getOffset()),
+                           MethodOperand.STATIC(target),
+                           ALoad.getClearGuard(inst),
+                           ALoad.getArray(inst).copy(),
+                           ALoad.getIndex(inst).copy());
+
+              rb.bcIndex = RUNTIME_SERVICES_BCI;
+              rb.position = inst.position;
+              inst.replace(rb);
+              next = rb.prevInstructionInCodeOrder();
+              inline(rb, ir, true);
+	      //}
+          }
+        }
+        break;
+
+        case DOUBLE_ALOAD_opcode: {
+          if (MemoryManagerConstants.USE_PRIMITIVE_DOUBLE_ARRAYLETS) {
+	      //if (ALoad.getArray(inst).getType().peekType().isArrayType() && ALoad.getArray(inst).getType().peekType().asArray().isArrayletizable()) {// .getArrayElementType().isShortType()) {
+
+              RVMMethod target = Entrypoints.arrayLoadPrimitiveDoubleReadBarrierMethod;
+
+              Instruction rb =
+              Call.create2(CALL,
+                           ALoad.getClearResult(inst),
+                           IRTools.AC(target.getOffset()),
+                           MethodOperand.STATIC(target),
+                           ALoad.getClearGuard(inst),
+                           ALoad.getArray(inst).copy(),
+                           ALoad.getIndex(inst).copy());
+
+              rb.bcIndex = RUNTIME_SERVICES_BCI;
+              rb.position = inst.position;
+              inst.replace(rb);
+              next = rb.prevInstructionInCodeOrder();
+              inline(rb, ir, true);
+	      //}
+          }
+        }
+        break;
+        
         case REF_ALOAD_opcode: {
-          if (MemoryManagerConstants.NEEDS_READ_BARRIER) {
+          if (MemoryManagerConstants.NEEDS_READ_BARRIER || MemoryManagerConstants.USE_REFERENCE_ARRAYLETS ||  MemoryManagerConstants.USE_OBJECT_ARRAY_ACCESS_BARRIER) {
             RVMMethod target = Entrypoints.arrayLoadReadBarrierMethod;
             Instruction rb =
               Call.create2(CALL,
diff -r 743a2cc2ed20 -r 058fdc3780ba rvm/src/org/jikesrvm/compilers/opt/runtimesupport/OptCompiledMethod.java
--- a/rvm/src/org/jikesrvm/compilers/opt/runtimesupport/OptCompiledMethod.java	Tue Aug 04 11:04:15 2009 +1000
+++ b/rvm/src/org/jikesrvm/compilers/opt/runtimesupport/OptCompiledMethod.java	Mon Nov 16 09:21:21 2009 +1100
@@ -16,6 +16,7 @@
 
 import org.jikesrvm.ArchitectureSpecific;
 import org.jikesrvm.ArchitectureSpecificOpt;
+import org.jikesrvm.HeapLayoutConstants;
 import org.jikesrvm.VM;
 import org.jikesrvm.PrintLN;
 import org.jikesrvm.classloader.RVMArray;
@@ -241,8 +242,20 @@
   public int size() {
     int size = TypeReference.ExceptionTable.peekType().asClass().getInstanceSize();
     size += _mcMap.size();
-    if (eTable != null) size += RVMArray.IntArray.getInstanceSize(eTable.length);
-    if (patchMap != null) size += RVMArray.IntArray.getInstanceSize(patchMap.length);
+    if (eTable != null) { 
+    	if (Magic.objectAsAddress(eTable).LT(HeapLayoutConstants.BOOT_IMAGE_DATA_END)) {
+    		size += RVMArray.IntArray.getBootImageContiguousInstanceSize(eTable.length);
+        } else {
+    	size += RVMArray.IntArray.getInstanceSize(eTable.length);
+        }
+    }
+    if (patchMap != null) {
+    	if (Magic.objectAsAddress(patchMap).LT(HeapLayoutConstants.BOOT_IMAGE_DATA_END)) {
+    		size += RVMArray.IntArray.getBootImageContiguousInstanceSize(patchMap.length);
+        } else {
+    	size += RVMArray.IntArray.getInstanceSize(patchMap.length);
+        }
+    }
     return size;
   }
 
diff -r 743a2cc2ed20 -r 058fdc3780ba rvm/src/org/jikesrvm/compilers/opt/runtimesupport/OptMachineCodeMap.java
--- a/rvm/src/org/jikesrvm/compilers/opt/runtimesupport/OptMachineCodeMap.java	Tue Aug 04 11:04:15 2009 +1000
+++ b/rvm/src/org/jikesrvm/compilers/opt/runtimesupport/OptMachineCodeMap.java	Mon Nov 16 09:21:21 2009 +1100
@@ -14,6 +14,7 @@
 
 import java.util.ArrayList;
 import org.jikesrvm.ArchitectureSpecific;
+import org.jikesrvm.HeapLayoutConstants;
 import org.jikesrvm.VM;
 import org.jikesrvm.Constants;
 import org.jikesrvm.adaptive.database.callgraph.CallSite;
@@ -31,6 +32,7 @@
 import org.jikesrvm.compilers.opt.ir.IR;
 import org.jikesrvm.compilers.opt.ir.Instruction;
 import org.jikesrvm.compilers.opt.ir.operand.MethodOperand;
+import org.jikesrvm.runtime.Magic;
 import org.vmmagic.pragma.Inline;
 import org.vmmagic.pragma.Uninterruptible;
 import org.vmmagic.unboxed.Offset;
@@ -693,9 +695,27 @@
    */
   int size() {
     int size = TYPE.peekType().asClass().getInstanceSize();
-    if (MCInformation != null) size += RVMArray.IntArray.getInstanceSize(MCInformation.length);
-    if (inlineEncoding != null) size += RVMArray.IntArray.getInstanceSize(inlineEncoding.length);
-    if (gcMaps != null) size += RVMArray.IntArray.getInstanceSize(gcMaps.length);
+    if (MCInformation != null) {
+    	if (Magic.objectAsAddress(MCInformation).LT(HeapLayoutConstants.BOOT_IMAGE_DATA_END)) {
+    		size += RVMArray.IntArray.getBootImageContiguousInstanceSize(MCInformation.length);
+        } else {
+    	size += RVMArray.IntArray.getInstanceSize(MCInformation.length);
+        }
+    }
+    if (inlineEncoding != null) {
+    	if (Magic.objectAsAddress(inlineEncoding).LT(HeapLayoutConstants.BOOT_IMAGE_DATA_END)) {
+    		size += RVMArray.IntArray.getBootImageContiguousInstanceSize(inlineEncoding.length);
+        } else {
+        	size += RVMArray.IntArray.getInstanceSize(inlineEncoding.length);
+        }
+    }
+    if (gcMaps != null) {
+    	if (Magic.objectAsAddress(gcMaps).LT(HeapLayoutConstants.BOOT_IMAGE_DATA_END)) {
+    		size += RVMArray.IntArray.getBootImageContiguousInstanceSize(gcMaps.length);
+        } else {
+        	size += RVMArray.IntArray.getInstanceSize(gcMaps.length);
+        }
+    }
     return size;
   }
 
diff -r 743a2cc2ed20 -r 058fdc3780ba rvm/src/org/jikesrvm/compilers/opt/runtimesupport/ppc/OptExceptionDeliverer.java
--- a/rvm/src/org/jikesrvm/compilers/opt/runtimesupport/ppc/OptExceptionDeliverer.java	Tue Aug 04 11:04:15 2009 +1000
+++ b/rvm/src/org/jikesrvm/compilers/opt/runtimesupport/ppc/OptExceptionDeliverer.java	Mon Nov 16 09:21:21 2009 +1100
@@ -87,7 +87,7 @@
       frameOffset = frameOffset.plus(7).toWord().and(Word.fromIntSignExtend(~7)).toOffset();
       for (int i = firstFloat; i < 32; i++) {
         long temp = Magic.getLongAtOffset(Magic.addressAsObject(fp), frameOffset);
-        registers.fprs[i] = Magic.longBitsAsDouble(temp);
+        registers.fprs.setLong(i, temp);
         frameOffset = frameOffset.plus(BYTES_IN_DOUBLE);
       }
     }
diff -r 743a2cc2ed20 -r 058fdc3780ba rvm/src/org/jikesrvm/ia32/MachineReflection.java
--- a/rvm/src/org/jikesrvm/ia32/MachineReflection.java	Tue Aug 04 11:04:15 2009 +1000
+++ b/rvm/src/org/jikesrvm/ia32/MachineReflection.java	Mon Nov 16 09:21:21 2009 +1100
@@ -16,6 +16,7 @@
 import org.jikesrvm.Constants;
 import org.jikesrvm.classloader.RVMMethod;
 import org.jikesrvm.classloader.TypeReference;
+import org.jikesrvm.mm.mminterface.MemoryManager;
 import org.jikesrvm.runtime.Magic;
 import org.vmmagic.pragma.UnpreemptibleNoWarn;
 import org.vmmagic.unboxed.Word;
@@ -94,9 +95,9 @@
   @UnpreemptibleNoWarn("GC is disabled as Objects are turned into Words."+
     "avoid preemption but still allow calls to preemptible unboxing routines")
   public static void packageParameters(RVMMethod method, Object thisArg, Object[] otherArgs, WordArray GPRs,
-                                       double[] FPRs, byte[] FPRmeta, WordArray Parameters) {
+                                       WordArray FPRs, WordArray FPRmeta, WordArray Parameters) {
     int GPR = 0;
-    int FPR = ArchConstants.SSE2_FULL ? 0 : FPRs.length;
+    int FPR = ArchConstants.SSE2_FULL ? 0 : MemoryManager.nativeLongBufferLength(FPRs);
     int parameter = 0;
 
     int gp = NUM_PARAMETER_GPRS; // 0, 1, 2
@@ -138,11 +139,11 @@
         if (fp > 0) {
           fp--;
           if (ArchConstants.SSE2_FULL) {
-            FPRs[FPR] = (Float)otherArgs[i];
-            FPRmeta[FPR] = 0x0;
+            FPRs.setLong(FPR, Double.doubleToLongBits((Float)otherArgs[i]));
+            FPRmeta.setByte(FPR, (byte)0);
             FPR++;
           } else {
-            FPRs[--FPR] = (Float)otherArgs[i];
+            FPRs.setLong(--FPR, Double.doubleToLongBits((Float)otherArgs[i]));
           }
         }
         float f = (Float)otherArgs[i];
@@ -151,11 +152,11 @@
         if (fp > 0) {
           fp--;
           if (ArchConstants.SSE2_FULL) {
-            FPRs[FPR] = (Double)otherArgs[i];
-            FPRmeta[FPR] = 0x1;
+            FPRs.setLong(FPR, Double.doubleToLongBits((Double)otherArgs[i]));
+            FPRmeta.setByte(FPR, (byte)1);
             FPR++;
           } else {
-            FPRs[--FPR] = (Double)otherArgs[i];
+            FPRs.setLong(--FPR, Double.doubleToLongBits((Double)otherArgs[i]));
           }
         }
         double d = (Double)otherArgs[i];
diff -r 743a2cc2ed20 -r 058fdc3780ba rvm/src/org/jikesrvm/ia32/Registers.java
--- a/rvm/src/org/jikesrvm/ia32/Registers.java	Tue Aug 04 11:04:15 2009 +1000
+++ b/rvm/src/org/jikesrvm/ia32/Registers.java	Mon Nov 16 09:21:21 2009 +1100
@@ -35,9 +35,9 @@
   @Untraced
   public final WordArray gprs; // general purpose registers
   @Untraced
-  public final double[] fprs; // floating point registers
-  public final WordArray gprsShadow;
-  public final double[] fprsShadow;
+  public final WordArray fprs; // floating point registers
+  public final Object gprsShadow;
+  public final Object fprsShadow;
   public Address ip;     // instruction address register
   public Address fp;     // frame pointer
 
@@ -47,8 +47,8 @@
   public boolean inuse; // do exception registers currently contain live values?
 
   public Registers() {
-    gprs = gprsShadow = MemoryManager.newNonMovingWordArray(NUM_GPRS);
-    fprs = fprsShadow = MemoryManager.newNonMovingDoubleArray(NUM_FPRS);
+    gprsShadow = gprs = MemoryManager.newNonMovingWordArray(NUM_GPRS);
+    fprsShadow = fprs = MemoryManager.newNonMovingWordArray(NUM_FPRS * 2);
   }
 
   /**
diff -r 743a2cc2ed20 -r 058fdc3780ba rvm/src/org/jikesrvm/jni/JNIFunctions.java
--- a/rvm/src/org/jikesrvm/jni/JNIFunctions.java	Tue Aug 04 11:04:15 2009 +1000
+++ b/rvm/src/org/jikesrvm/jni/JNIFunctions.java	Mon Nov 16 09:21:21 2009 +1100
@@ -12,6 +12,7 @@
  */
 package org.jikesrvm.jni;
 
+import java.lang.reflect.Array;
 import java.lang.reflect.Constructor;
 import java.lang.reflect.Field;
 import java.lang.reflect.Method;
@@ -3834,7 +3835,7 @@
 
     try {
       final char[] contents = new char[len];
-      Memory.memcopy(Magic.objectAsAddress(contents), uchars, len * 2);
+      Memory.nativeMarshal(uchars, 0, contents, 0, len);
       return env.pushJNIRef(java.lang.JikesRVMSupport.newStringWithoutCopy(contents, 0, len));
     } catch (Throwable unexpected) {
       if (traceJNI) unexpected.printStackTrace(System.err);
@@ -3882,15 +3883,13 @@
     int len = java.lang.JikesRVMSupport.getStringLength(str);
 
     // alloc non moving buffer in C heap for a copy of string contents
-    Address copyBuffer = sysCall.sysMalloc(len * 2);
+    Address copyBuffer = sysCall.sysMalloc(len << LOG_BYTES_IN_CHAR);
     if (copyBuffer.isZero()) {
       env.recordException(new OutOfMemoryError());
       return Address.zero();
     }
     try {
-      Address strBase = Magic.objectAsAddress(strChars);
-      Address srcBase = strBase.plus(strOffset * 2);
-      Memory.memcopy(copyBuffer, srcBase, len * 2);
+      Memory.nativeMarshal(strChars, strOffset, copyBuffer, 0, len);
 
       /* Set caller's isCopy boolean to true, if we got a valid (non-null)
          address */
@@ -4335,8 +4334,7 @@
         env.recordException(new OutOfMemoryError());
         return Address.zero();
       }
-
-      Memory.memcopy(copyBuffer, Magic.objectAsAddress(sourceArray), size);
+      Memory.nativeMarshal(sourceArray, copyBuffer);
 
       /* Set caller's isCopy boolean to true, if we got a valid (non-null)
          address */
@@ -4367,7 +4365,7 @@
       byte[] sourceArray = (byte[]) env.getJNIRef(arrayJREF);
       int size = sourceArray.length;
 
-      if (MemoryManager.willNeverMove(sourceArray)) {
+      if (Memory.isNativeFormat(sourceArray) && MemoryManager.willNeverMove(sourceArray)) {
         /* return a direct pointer */
         JNIGenericHelpers.setBoolStar(isCopyAddress, false);
         return Magic.objectAsAddress(sourceArray);
@@ -4379,8 +4377,7 @@
           env.recordException(new OutOfMemoryError());
           return Address.zero();
         }
-
-        Memory.memcopy(copyBuffer, Magic.objectAsAddress(sourceArray), size);
+        Memory.nativeMarshal(sourceArray, copyBuffer);
 
         /* Set caller's isCopy boolean to true, if we got a valid (non-null)
            address */
@@ -4412,18 +4409,17 @@
       char[] sourceArray = (char[]) env.getJNIRef(arrayJREF);
       int size = sourceArray.length;
 
-      if (MemoryManager.willNeverMove(sourceArray)) {
-        JNIGenericHelpers.setBoolStar(isCopyAddress, false);
-        return Magic.objectAsAddress(sourceArray);
-      } else {
-        // alloc non moving buffer in C heap for a copy of string contents
-        Address copyBuffer = sysCall.sysMalloc(size * BYTES_IN_CHAR);
-        if (copyBuffer.isZero()) {
-          env.recordException(new OutOfMemoryError());
-          return Address.zero();
-        }
-
-        Memory.memcopy(copyBuffer, Magic.objectAsAddress(sourceArray), size * BYTES_IN_CHAR);
+      if (Memory.isNativeFormat(sourceArray) && MemoryManager.willNeverMove(sourceArray)) {
+        JNIGenericHelpers.setBoolStar(isCopyAddress, false);
+        return Magic.objectAsAddress(sourceArray);
+      } else {
+        // alloc non moving buffer in C heap for a copy of string contents
+        Address copyBuffer = sysCall.sysMalloc(size << LOG_BYTES_IN_CHAR);
+        if (copyBuffer.isZero()) {
+          env.recordException(new OutOfMemoryError());
+          return Address.zero();
+        }
+        Memory.nativeMarshal(sourceArray, copyBuffer);
 
         /* Set caller's isCopy boolean to true, if we got a valid (non-null)
          address */
@@ -4455,18 +4451,17 @@
       short[] sourceArray = (short[]) env.getJNIRef(arrayJREF);
       int size = sourceArray.length;
 
-      if (MemoryManager.willNeverMove(sourceArray)) {
-        JNIGenericHelpers.setBoolStar(isCopyAddress, false);
-        return Magic.objectAsAddress(sourceArray);
-      } else {
-        // alloc non moving buffer in C heap for a copy of string contents
-        Address copyBuffer = sysCall.sysMalloc(size * BYTES_IN_SHORT);
-        if (copyBuffer.isZero()) {
-          env.recordException(new OutOfMemoryError());
-          return Address.zero();
-        }
-
-        Memory.memcopy(copyBuffer, Magic.objectAsAddress(sourceArray), size * BYTES_IN_SHORT);
+      if (Memory.isNativeFormat(sourceArray) && MemoryManager.willNeverMove(sourceArray)) {
+        JNIGenericHelpers.setBoolStar(isCopyAddress, false);
+        return Magic.objectAsAddress(sourceArray);
+      } else {
+        // alloc non moving buffer in C heap for a copy of string contents
+        Address copyBuffer = sysCall.sysMalloc(size << LOG_BYTES_IN_SHORT);
+        if (copyBuffer.isZero()) {
+          env.recordException(new OutOfMemoryError());
+          return Address.zero();
+        }
+        Memory.nativeMarshal(sourceArray, copyBuffer);
 
         /* Set caller's isCopy boolean to true, if we got a valid (non-null)
          address */
@@ -4498,7 +4493,7 @@
       int[] sourceArray = (int[]) env.getJNIRef(arrayJREF);
       int size = sourceArray.length;
 
-      if (MemoryManager.willNeverMove(sourceArray)) {
+      if (Memory.isNativeFormat(sourceArray) && MemoryManager.willNeverMove(sourceArray)) {
         JNIGenericHelpers.setBoolStar(isCopyAddress, false);
         return Magic.objectAsAddress(sourceArray);
       } else {
@@ -4508,7 +4503,7 @@
           env.recordException(new OutOfMemoryError());
           return Address.zero();
         }
-        Memory.memcopy(copyBuffer, Magic.objectAsAddress(sourceArray), size << LOG_BYTES_IN_INT);
+        Memory.nativeMarshal(sourceArray, copyBuffer);
 
         /* Set caller's isCopy boolean to true, if we got a valid (non-null)
          address */
@@ -4540,7 +4535,7 @@
       long[] sourceArray = (long[]) env.getJNIRef(arrayJREF);
       int size = sourceArray.length;
 
-      if (MemoryManager.willNeverMove(sourceArray)) {
+      if (Memory.isNativeFormat(sourceArray) && MemoryManager.willNeverMove(sourceArray)) {
         JNIGenericHelpers.setBoolStar(isCopyAddress, false);
         return Magic.objectAsAddress(sourceArray);
       } else {
@@ -4550,7 +4545,7 @@
           env.recordException(new OutOfMemoryError());
           return Address.zero();
         }
-        Memory.memcopy(copyBuffer, Magic.objectAsAddress(sourceArray), size << LOG_BYTES_IN_LONG);
+        Memory.nativeMarshal(sourceArray, copyBuffer);
 
         /* Set caller's isCopy boolean to true, if we got a valid (non-null)
          address */
@@ -4582,7 +4577,7 @@
       float[] sourceArray = (float[]) env.getJNIRef(arrayJREF);
       int size = sourceArray.length;
 
-      if (MemoryManager.willNeverMove(sourceArray)) {
+      if (Memory.isNativeFormat(sourceArray) && MemoryManager.willNeverMove(sourceArray)) {
         JNIGenericHelpers.setBoolStar(isCopyAddress, false);
         return Magic.objectAsAddress(sourceArray);
       } else {
@@ -4592,8 +4587,7 @@
           env.recordException(new OutOfMemoryError());
           return Address.zero();
         }
-
-        Memory.memcopy(copyBuffer, Magic.objectAsAddress(sourceArray), size << LOG_BYTES_IN_FLOAT);
+        Memory.nativeMarshal(sourceArray, copyBuffer);
 
         /* Set caller's isCopy boolean to true, if we got a valid (non-null)
          address */
@@ -4625,7 +4619,7 @@
       double[] sourceArray = (double[]) env.getJNIRef(arrayJREF);
       int size = sourceArray.length;
 
-      if (MemoryManager.willNeverMove(sourceArray)) {
+      if (Memory.isNativeFormat(sourceArray) && MemoryManager.willNeverMove(sourceArray)) {
         JNIGenericHelpers.setBoolStar(isCopyAddress, false);
         return Magic.objectAsAddress(sourceArray);
       } else {
@@ -4635,7 +4629,7 @@
           env.recordException(new OutOfMemoryError());
           return Address.zero();
         }
-        Memory.memcopy(copyBuffer, Magic.objectAsAddress(sourceArray), size << LOG_BYTES_IN_DOUBLE);
+        Memory.nativeMarshal(sourceArray, copyBuffer);
 
         /* Set caller's isCopy boolean to true, if we got a valid (non-null)
          address */
@@ -4727,7 +4721,7 @@
 
         // mode 0 and mode 1:  copy back the buffer
         if ((releaseMode == 0 || releaseMode == 1) && size != 0) {
-          Memory.memcopy(Magic.objectAsAddress(sourceArray), copyBufferAddress, size);
+          Memory.nativeMarshal(copyBufferAddress, sourceArray);
         }
 
         // mode 0 and mode 2:  free the buffer
@@ -4768,7 +4762,7 @@
 
         // mode 0 and mode 1:  copy back the buffer
         if ((releaseMode == 0 || releaseMode == 1) && size != 0) {
-          Memory.memcopy(Magic.objectAsAddress(sourceArray), copyBufferAddress, size << LOG_BYTES_IN_CHAR);
+          Memory.nativeMarshal(copyBufferAddress, sourceArray);
         }
 
         // mode 0 and mode 2:  free the buffer
@@ -4806,7 +4800,7 @@
 
         // mode 0 and mode 1:  copy back the buffer
         if ((releaseMode == 0 || releaseMode == 1) && size != 0) {
-          Memory.memcopy(Magic.objectAsAddress(sourceArray), copyBufferAddress, size << LOG_BYTES_IN_SHORT);
+          Memory.nativeMarshal(copyBufferAddress, sourceArray);
         }
 
         // mode 0 and mode 2:  free the buffer
@@ -4844,7 +4838,7 @@
 
         // mode 0 and mode 1:  copy back the buffer
         if (releaseMode == 0 || releaseMode == 1) {
-          Memory.memcopy(Magic.objectAsAddress(sourceArray), copyBufferAddress, size << LOG_BYTES_IN_INT);
+          Memory.nativeMarshal(copyBufferAddress, sourceArray);
         }
 
         // mode 0 and mode 2:  free the buffer
@@ -4882,7 +4876,7 @@
 
         // mode 0 and mode 1:  copy back the buffer
         if (releaseMode == 0 || releaseMode == 1) {
-          Memory.memcopy(Magic.objectAsAddress(sourceArray), copyBufferAddress, size << LOG_BYTES_IN_LONG);
+          Memory.nativeMarshal(copyBufferAddress, sourceArray);
         }
 
         // mode 0 and mode 2:  free the buffer
@@ -4920,7 +4914,7 @@
 
         // mode 0 and mode 1:  copy back the buffer
         if (releaseMode == 0 || releaseMode == 1) {
-          Memory.memcopy(Magic.objectAsAddress(sourceArray), copyBufferAddress, size << LOG_BYTES_IN_FLOAT);
+          Memory.nativeMarshal(copyBufferAddress, sourceArray);
         }
 
         // mode 0 and mode 2:  free the buffer
@@ -4958,7 +4952,7 @@
 
         // mode 0 and mode 1:  copy back the buffer
         if (releaseMode == 0 || releaseMode == 1) {
-          Memory.memcopy(Magic.objectAsAddress(sourceArray), copyBufferAddress, size << LOG_BYTES_IN_DOUBLE);
+          Memory.nativeMarshal(copyBufferAddress, sourceArray);
         }
 
         // mode 0 and mode 2:  free the buffer
@@ -4993,7 +4987,7 @@
         env.recordException(new ArrayIndexOutOfBoundsException());
         return;
       }
-      Memory.memcopy(bufAddress, Magic.objectAsAddress(sourceArray).plus(startIndex), length);
+      Memory.nativeMarshal(sourceArray, startIndex, bufAddress, 0, length);
     } catch (Throwable unexpected) {
       if (traceJNI) unexpected.printStackTrace(System.err);
       env.recordException(unexpected);
@@ -5022,7 +5016,7 @@
         return;
       }
 
-      Memory.memcopy(bufAddress, Magic.objectAsAddress(sourceArray).plus(startIndex), length);
+      Memory.nativeMarshal(sourceArray, startIndex, bufAddress, 0, length);
     } catch (Throwable unexpected) {
       if (traceJNI) unexpected.printStackTrace(System.err);
       env.recordException(unexpected);
@@ -5051,9 +5045,7 @@
         return;
       }
 
-      Memory.memcopy(bufAddress,
-                        Magic.objectAsAddress(sourceArray).plus(startIndex << LOG_BYTES_IN_CHAR),
-                        length << LOG_BYTES_IN_CHAR);
+      Memory.nativeMarshal(sourceArray, startIndex, bufAddress, 0, length);
     } catch (Throwable unexpected) {
       if (traceJNI) unexpected.printStackTrace(System.err);
       env.recordException(unexpected);
@@ -5082,9 +5074,7 @@
         return;
       }
 
-      Memory.memcopy(bufAddress,
-                        Magic.objectAsAddress(sourceArray).plus(startIndex << LOG_BYTES_IN_SHORT),
-                        length << LOG_BYTES_IN_SHORT);
+      Memory.nativeMarshal(sourceArray, startIndex, bufAddress, 0, length);
     } catch (Throwable unexpected) {
       if (traceJNI) unexpected.printStackTrace(System.err);
       env.recordException(unexpected);
@@ -5113,9 +5103,7 @@
         return;
       }
 
-      Memory.memcopy(bufAddress,
-                        Magic.objectAsAddress(sourceArray).plus(startIndex << LOG_BYTES_IN_INT),
-                        length << LOG_BYTES_IN_INT);
+      Memory.nativeMarshal(sourceArray, startIndex, bufAddress, 0, length);
     } catch (Throwable unexpected) {
       if (traceJNI) unexpected.printStackTrace(System.err);
       env.recordException(unexpected);
@@ -5144,9 +5132,7 @@
         return;
       }
 
-      Memory.memcopy(bufAddress,
-                        Magic.objectAsAddress(sourceArray).plus(startIndex << LOG_BYTES_IN_LONG),
-                        length << LOG_BYTES_IN_LONG);
+      Memory.nativeMarshal(sourceArray, startIndex, bufAddress, 0, length);
     } catch (Throwable unexpected) {
       if (traceJNI) unexpected.printStackTrace(System.err);
       env.recordException(unexpected);
@@ -5175,9 +5161,7 @@
         return;
       }
 
-      Memory.memcopy(bufAddress,
-                        Magic.objectAsAddress(sourceArray).plus(startIndex << LOG_BYTES_IN_FLOAT),
-                        length << LOG_BYTES_IN_FLOAT);
+      Memory.nativeMarshal(sourceArray, startIndex, bufAddress, 0, length);
     } catch (Throwable unexpected) {
       if (traceJNI) unexpected.printStackTrace(System.err);
       env.recordException(unexpected);
@@ -5206,9 +5190,7 @@
         return;
       }
 
-      Memory.memcopy(bufAddress,
-                        Magic.objectAsAddress(sourceArray).plus(startIndex << LOG_BYTES_IN_DOUBLE),
-                        length << LOG_BYTES_IN_DOUBLE);
+      Memory.nativeMarshal(sourceArray, startIndex, bufAddress, 0, length);
     } catch (Throwable unexpected) {
       if (traceJNI) unexpected.printStackTrace(System.err);
       env.recordException(unexpected);
@@ -5237,7 +5219,7 @@
         return;
       }
 
-      Memory.memcopy(Magic.objectAsAddress(destinationArray).plus(startIndex), bufAddress, length);
+      Memory.nativeMarshal(bufAddress, 0, destinationArray, startIndex, length);
     } catch (Throwable unexpected) {
       if (traceJNI) unexpected.printStackTrace(System.err);
       env.recordException(unexpected);
@@ -5266,7 +5248,7 @@
         return;
       }
 
-      Memory.memcopy(Magic.objectAsAddress(destinationArray).plus(startIndex), bufAddress, length);
+      Memory.nativeMarshal(bufAddress, 0, destinationArray, startIndex, length);
     } catch (Throwable unexpected) {
       if (traceJNI) unexpected.printStackTrace(System.err);
       env.recordException(unexpected);
@@ -5295,9 +5277,7 @@
         return;
       }
 
-      Memory.memcopy(Magic.objectAsAddress(destinationArray).plus(startIndex << LOG_BYTES_IN_CHAR),
-                        bufAddress,
-                        length << LOG_BYTES_IN_CHAR);
+      Memory.nativeMarshal(bufAddress, 0, destinationArray, startIndex, length);
     } catch (Throwable unexpected) {
       if (traceJNI) unexpected.printStackTrace(System.err);
       env.recordException(unexpected);
@@ -5326,9 +5306,7 @@
         return;
       }
 
-      Memory.memcopy(Magic.objectAsAddress(destinationArray).plus(startIndex << LOG_BYTES_IN_SHORT),
-                        bufAddress,
-                        length << LOG_BYTES_IN_SHORT);
+      Memory.nativeMarshal(bufAddress, 0, destinationArray, startIndex, length);
     } catch (Throwable unexpected) {
       if (traceJNI) unexpected.printStackTrace(System.err);
       env.recordException(unexpected);
@@ -5357,9 +5335,7 @@
         return;
       }
 
-      Memory.memcopy(Magic.objectAsAddress(destinationArray).plus(startIndex << LOG_BYTES_IN_INT),
-                        bufAddress,
-                        length << LOG_BYTES_IN_INT);
+      Memory.nativeMarshal(bufAddress, 0, destinationArray, startIndex, length);
     } catch (Throwable unexpected) {
       if (traceJNI) unexpected.printStackTrace(System.err);
       env.recordException(unexpected);
@@ -5388,9 +5364,7 @@
         return;
       }
 
-      Memory.memcopy(Magic.objectAsAddress(destinationArray).plus(startIndex << LOG_BYTES_IN_LONG),
-                        bufAddress,
-                        length << LOG_BYTES_IN_LONG);
+      Memory.nativeMarshal(bufAddress, 0, destinationArray, startIndex, length);
     } catch (Throwable unexpected) {
       if (traceJNI) unexpected.printStackTrace(System.err);
       env.recordException(unexpected);
@@ -5419,9 +5393,7 @@
         return;
       }
 
-      Memory.memcopy(Magic.objectAsAddress(destinationArray).plus(startIndex << LOG_BYTES_IN_FLOAT),
-                        bufAddress,
-                        length << LOG_BYTES_IN_FLOAT);
+      Memory.nativeMarshal(bufAddress, 0, destinationArray, startIndex, length);
     } catch (Throwable unexpected) {
       if (traceJNI) unexpected.printStackTrace(System.err);
       env.recordException(unexpected);
@@ -5450,9 +5422,7 @@
         return;
       }
 
-      Memory.memcopy(Magic.objectAsAddress(destinationArray).plus(startIndex << LOG_BYTES_IN_DOUBLE),
-                        bufAddress,
-                        length << LOG_BYTES_IN_DOUBLE);
+      Memory.nativeMarshal(bufAddress, 0, destinationArray, startIndex, length);
     } catch (Throwable unexpected) {
       if (traceJNI) unexpected.printStackTrace(System.err);
       env.recordException(unexpected);
@@ -5795,10 +5765,7 @@
         env.recordException(new StringIndexOutOfBoundsException());
         return;
       }
-      Address strBase = Magic.objectAsAddress(strChars);
-      Address srcBase = strBase.plus(strOffset * 2).plus(start * 2);
-      Memory.memcopy(buf, srcBase, len * 2);
-
+      Memory.nativeMarshal(strChars, start, buf, 0, len);
     } catch (Throwable unexpected) {
       if (traceJNI) unexpected.printStackTrace(System.err);
       env.recordException(unexpected);
@@ -5853,18 +5820,139 @@
     try {
       Object primitiveArray = env.getJNIRef(arrayJREF);
 
-      // not an array, return null
-      if (!primitiveArray.getClass().isArray()) {
+      if (primitiveArray instanceof byte[]) {
+        byte[] array = (byte[])primitiveArray;
+        if (Memory.isNativeFormat(array)) {
+          JNIGenericHelpers.setBoolStar(isCopyAddress, false);
+          VM.disableGC(true);
+          return Magic.objectAsAddress(primitiveArray);
+        } else {
+          Address copyBuffer = sysCall.sysMalloc(array.length << LOG_BYTES_IN_BYTE);
+          if (copyBuffer.isZero()) {
+            env.recordException(new OutOfMemoryError());
+            return Address.zero();
+          }
+          Memory.nativeMarshal(array, copyBuffer);
+          JNIGenericHelpers.setBoolStar(isCopyAddress, true);
+          return copyBuffer;
+        }
+      } else if (primitiveArray instanceof boolean[]) {
+        boolean[] array = (boolean[])primitiveArray;
+        if (Memory.isNativeFormat(array)) {
+          JNIGenericHelpers.setBoolStar(isCopyAddress, false);
+          VM.disableGC(true);
+          return Magic.objectAsAddress(primitiveArray);
+        } else {
+          Address copyBuffer = sysCall.sysMalloc(array.length << LOG_BYTES_IN_BOOLEAN);
+          if (copyBuffer.isZero()) {
+            env.recordException(new OutOfMemoryError());
+            return Address.zero();
+          }
+          Memory.nativeMarshal(array, copyBuffer);
+          JNIGenericHelpers.setBoolStar(isCopyAddress, true);
+          return copyBuffer;
+        }
+      } else if (primitiveArray instanceof char[]) {
+        char[] array = (char[])primitiveArray;
+        if (Memory.isNativeFormat(array)) {
+          JNIGenericHelpers.setBoolStar(isCopyAddress, false);
+          VM.disableGC(true);
+          return Magic.objectAsAddress(primitiveArray);
+        } else {
+          Address copyBuffer = sysCall.sysMalloc(array.length << LOG_BYTES_IN_CHAR);
+          if (copyBuffer.isZero()) {
+            env.recordException(new OutOfMemoryError());
+            return Address.zero();
+          }
+          Memory.nativeMarshal(array, copyBuffer);
+          JNIGenericHelpers.setBoolStar(isCopyAddress, true);
+          return copyBuffer;
+        }
+      } else if (primitiveArray instanceof short[]) {
+        short[] array = (short[])primitiveArray;
+        if (Memory.isNativeFormat(array)) {
+          JNIGenericHelpers.setBoolStar(isCopyAddress, false);
+          VM.disableGC(true);
+          return Magic.objectAsAddress(primitiveArray);
+        } else {
+          Address copyBuffer = sysCall.sysMalloc(array.length << LOG_BYTES_IN_SHORT);
+          if (copyBuffer.isZero()) {
+            env.recordException(new OutOfMemoryError());
+            return Address.zero();
+          }
+          Memory.nativeMarshal(array, copyBuffer);
+          JNIGenericHelpers.setBoolStar(isCopyAddress, true);
+          return copyBuffer;
+        }
+      } else if (primitiveArray instanceof int[]) {
+        int[] array = (int[])primitiveArray;
+        if (Memory.isNativeFormat(array)) {
+          JNIGenericHelpers.setBoolStar(isCopyAddress, false);
+          VM.disableGC(true);
+          return Magic.objectAsAddress(primitiveArray);
+        } else {
+          Address copyBuffer = sysCall.sysMalloc(array.length << LOG_BYTES_IN_INT);
+          if (copyBuffer.isZero()) {
+            env.recordException(new OutOfMemoryError());
+            return Address.zero();
+          }
+          Memory.nativeMarshal(array, copyBuffer);
+          JNIGenericHelpers.setBoolStar(isCopyAddress, true);
+          return copyBuffer;
+        }
+      } else if (primitiveArray instanceof float[]) {
+        float[] array = (float[])primitiveArray;
+        if (Memory.isNativeFormat(array)) {
+          JNIGenericHelpers.setBoolStar(isCopyAddress, false);
+          VM.disableGC(true);
+          return Magic.objectAsAddress(primitiveArray);
+        } else {
+          Address copyBuffer = sysCall.sysMalloc(array.length << LOG_BYTES_IN_FLOAT);
+          if (copyBuffer.isZero()) {
+            env.recordException(new OutOfMemoryError());
+            return Address.zero();
+          }
+          Memory.nativeMarshal(array, copyBuffer);
+          JNIGenericHelpers.setBoolStar(isCopyAddress, true);
+          return copyBuffer;
+        }
+      } else if (primitiveArray instanceof long[]) {
+        long[] array = (long[])primitiveArray;
+        if (Memory.isNativeFormat(array)) {
+          JNIGenericHelpers.setBoolStar(isCopyAddress, false);
+          VM.disableGC(true);
+          return Magic.objectAsAddress(primitiveArray);
+        } else {
+          Address copyBuffer = sysCall.sysMalloc(array.length << LOG_BYTES_IN_LONG);
+          if (copyBuffer.isZero()) {
+            env.recordException(new OutOfMemoryError());
+            return Address.zero();
+          }
+          Memory.nativeMarshal(array, copyBuffer);
+          JNIGenericHelpers.setBoolStar(isCopyAddress, true);
+          return copyBuffer;
+        }
+      } else if (primitiveArray instanceof double[]) {
+        double[] array = (double[])primitiveArray;
+        if (Memory.isNativeFormat(array)) {
+          JNIGenericHelpers.setBoolStar(isCopyAddress, false);
+          VM.disableGC(true);
+          return Magic.objectAsAddress(primitiveArray);
+        } else {
+          Address copyBuffer = sysCall.sysMalloc(array.length << LOG_BYTES_IN_DOUBLE);
+          if (copyBuffer.isZero()) {
+            env.recordException(new OutOfMemoryError());
+            return Address.zero();
+          }
+          Memory.nativeMarshal(array, copyBuffer);
+          JNIGenericHelpers.setBoolStar(isCopyAddress, true);
+          return copyBuffer;
+        }
+      } else {
+        // not an array, return null
         return Address.zero();
       }
-
-      /* Set caller's isCopy boolean to false, if we got a valid (non-null)
-         address */
-      JNIGenericHelpers.setBoolStar(isCopyAddress, false);
-
-      // For array of primitive, return the object address, which is the array itself
-      VM.disableGC(true);
-      return Magic.objectAsAddress(primitiveArray);
+      
     } catch (Throwable unexpected) {
       if (traceJNI) unexpected.printStackTrace(System.err);
       env.recordException(unexpected);
@@ -5890,7 +5978,128 @@
     RuntimeEntrypoints.checkJNICountDownToGC();
 
     try {
-      VM.enableGC(true);
+      Object primitiveArray = env.getJNIRef(arrayJREF);
+      if (primitiveArray instanceof byte[]) {
+        byte[] array = (byte[])primitiveArray;
+        if (Memory.isNativeFormat(array)) {
+          VM.enableGC(true);
+        } else {
+          // mode 0 and mode 1:  copy back the buffer
+          if ((mode == 0 || mode == 1) && array.length != 0) {
+            Memory.nativeMarshal(arrayCopyAddress, array);
+          }
+
+          // mode 0 and mode 2:  free the buffer
+          if (mode == 0 || mode == 2) {
+            sysCall.sysFree(arrayCopyAddress);
+          }
+        }
+      } else if (primitiveArray instanceof boolean[]) {
+        boolean[] array = (boolean[])primitiveArray;
+        if (Memory.isNativeFormat(array)) {
+          VM.enableGC(true);
+        } else {
+          // mode 0 and mode 1:  copy back the buffer
+          if ((mode == 0 || mode == 1) && array.length != 0) {
+            Memory.nativeMarshal(arrayCopyAddress, array);
+          }
+
+          // mode 0 and mode 2:  free the buffer
+          if (mode == 0 || mode == 2) {
+            sysCall.sysFree(arrayCopyAddress);
+          }
+        }
+      } else if (primitiveArray instanceof char[]) {
+        char[] array = (char[])primitiveArray;
+        if (Memory.isNativeFormat(array)) {
+          VM.enableGC(true);
+        } else {
+          // mode 0 and mode 1:  copy back the buffer
+          if ((mode == 0 || mode == 1) && array.length != 0) {
+            Memory.nativeMarshal(arrayCopyAddress, array);
+          }
+
+          // mode 0 and mode 2:  free the buffer
+          if (mode == 0 || mode == 2) {
+            sysCall.sysFree(arrayCopyAddress);
+          }
+        }
+      } else if (primitiveArray instanceof short[]) {
+        short[] array = (short[])primitiveArray;
+        if (Memory.isNativeFormat(array)) {
+          VM.enableGC(true);
+        } else {
+          // mode 0 and mode 1:  copy back the buffer
+          if ((mode == 0 || mode == 1) && array.length != 0) {
+            Memory.nativeMarshal(arrayCopyAddress, array);
+          }
+
+          // mode 0 and mode 2:  free the buffer
+          if (mode == 0 || mode == 2) {
+            sysCall.sysFree(arrayCopyAddress);
+          }
+        }
+      } else if (primitiveArray instanceof int[]) {
+        int[] array = (int[])primitiveArray;
+        if (Memory.isNativeFormat(array)) {
+          VM.enableGC(true);
+        } else {
+          // mode 0 and mode 1:  copy back the buffer
+          if ((mode == 0 || mode == 1) && array.length != 0) {
+            Memory.nativeMarshal(arrayCopyAddress, array);
+          }
+
+          // mode 0 and mode 2:  free the buffer
+          if (mode == 0 || mode == 2) {
+            sysCall.sysFree(arrayCopyAddress);
+          }
+        }
+      } else if (primitiveArray instanceof float[]) {
+        float[] array = (float[])primitiveArray;
+        if (Memory.isNativeFormat(array)) {
+          VM.enableGC(true);
+        } else {
+          // mode 0 and mode 1:  copy back the buffer
+          if ((mode == 0 || mode == 1) && array.length != 0) {
+            Memory.nativeMarshal(arrayCopyAddress, array);
+          }
+
+          // mode 0 and mode 2:  free the buffer
+          if (mode == 0 || mode == 2) {
+            sysCall.sysFree(arrayCopyAddress);
+          }
+        }
+      } else if (primitiveArray instanceof long[]) {
+        long[] array = (long[])primitiveArray;
+        if (Memory.isNativeFormat(array)) {
+          VM.enableGC(true);
+        } else {
+          // mode 0 and mode 1:  copy back the buffer
+          if ((mode == 0 || mode == 1) && array.length != 0) {
+            Memory.nativeMarshal(arrayCopyAddress, array);
+          }
+
+          // mode 0 and mode 2:  free the buffer
+          if (mode == 0 || mode == 2) {
+            sysCall.sysFree(arrayCopyAddress);
+          }
+        }
+      } else if (primitiveArray instanceof double[]) {
+        double[] array = (double[])primitiveArray;
+        if (Memory.isNativeFormat(array)) {
+          VM.enableGC(true);
+        } else {
+          // mode 0 and mode 1:  copy back the buffer
+          if ((mode == 0 || mode == 1) && array.length != 0) {
+            Memory.nativeMarshal(arrayCopyAddress, array);
+          }
+
+          // mode 0 and mode 2:  free the buffer
+          if (mode == 0 || mode == 2) {
+            sysCall.sysFree(arrayCopyAddress);
+          }
+        }
+      }
     } catch (Throwable unexpected) {
       if (traceJNI) unexpected.printStackTrace(System.err);
       env.recordException(unexpected);
@@ -5911,17 +6120,44 @@
     if (traceJNI) VM.sysWrite("JNI called: GetStringCritical \n");
     RuntimeEntrypoints.checkJNICountDownToGC();
 
-    String str = (String) env.getJNIRef(strJREF);
-    char[] strChars = java.lang.JikesRVMSupport.getBackingCharArray(str);
-    int strOffset = java.lang.JikesRVMSupport.getStringOffset(str);
-
-    /* Set caller's isCopy boolean to false, if we got a valid (non-null)
-       address */
-    JNIGenericHelpers.setBoolStar(isCopyAddress, false);
-
-    VM.disableGC(true);
-    Address strBase = Magic.objectAsAddress(strChars);
-    return strBase.plus(strOffset * 2);
+    try {
+      String str = (String) env.getJNIRef(strJREF);
+      char[] strChars = java.lang.JikesRVMSupport.getBackingCharArray(str);
+      int strOffset = java.lang.JikesRVMSupport.getStringOffset(str);
+      int strLen = java.lang.JikesRVMSupport.getStringLength(str);
+      
+      if (Memory.isNativeFormat(strChars)) {
+        /* Set caller's isCopy boolean to false */
+        JNIGenericHelpers.setBoolStar(isCopyAddress, false);
+  
+        VM.disableGC(true);
+        return Magic.objectAsAddress(strChars).plus(strOffset << LOG_BYTES_IN_CHAR);
+      } else {
+        // alloc non moving buffer in C heap for a copy of string contents
+        Address copyBuffer = sysCall.sysMalloc(strLen << LOG_BYTES_IN_CHAR);
+        if (copyBuffer.isZero()) {
+          env.recordException(new OutOfMemoryError());
+          return Address.zero();
+        }
+        try {
+          Memory.nativeMarshal(strChars, strOffset, copyBuffer, 0, strLen);
+    
+          /* Set caller's isCopy boolean to true */
+          JNIGenericHelpers.setBoolStar(isCopyAddress, true);
+    
+          return copyBuffer;
+        } catch (Throwable unexpected) {
+          sysCall.sysFree(copyBuffer);
+          if (traceJNI) unexpected.printStackTrace(System.err);
+          env.recordException(unexpected);
+          return Address.zero();
+        }
+      }
+    } catch (Throwable unexpected) {
+      if (traceJNI) unexpected.printStackTrace(System.err);
+      env.recordException(unexpected);
+      return Address.zero();
+    }
   }
 
   /**
@@ -5939,7 +6175,17 @@
     RuntimeEntrypoints.checkJNICountDownToGC();
 
     try {
-      VM.enableGC(true);
+      String str = (String) env.getJNIRef(strJREF);
+      char[] strChars = java.lang.JikesRVMSupport.getBackingCharArray(str);
+      int strOffset = java.lang.JikesRVMSupport.getStringOffset(str);
+      int strLen = java.lang.JikesRVMSupport.getStringLength(str);
+
+      if (Memory.isNativeFormat(strChars)) {
+        VM.enableGC(true);
+      } else {
+        Memory.nativeMarshal(carray, 0, strChars, strOffset, strLen);
+        sysCall.sysFree(carray);
+      }
     } catch (Throwable unexpected) {
       if (traceJNI) unexpected.printStackTrace(System.err);
       env.recordException(unexpected);
diff -r 743a2cc2ed20 -r 058fdc3780ba rvm/src/org/jikesrvm/jni/JNIGenericHelpers.java
--- a/rvm/src/org/jikesrvm/jni/JNIGenericHelpers.java	Tue Aug 04 11:04:15 2009 +1000
+++ b/rvm/src/org/jikesrvm/jni/JNIGenericHelpers.java	Mon Nov 16 09:21:21 2009 +1100
@@ -100,7 +100,7 @@
 
     int length = strlen(stringAddress);
     byte[] contents = new byte[length];
-    Memory.memcopy(Magic.objectAsAddress(contents), stringAddress, length);
+    Memory.nativeMarshal(stringAddress, contents);
 
     return contents;
   }
diff -r 743a2cc2ed20 -r 058fdc3780ba rvm/src/org/jikesrvm/mm/mminterface/CollectorThread.java
--- a/rvm/src/org/jikesrvm/mm/mminterface/CollectorThread.java	Tue Aug 04 11:04:15 2009 +1000
+++ b/rvm/src/org/jikesrvm/mm/mminterface/CollectorThread.java	Mon Nov 16 09:21:21 2009 +1100
@@ -41,6 +41,7 @@
 import org.vmmagic.pragma.UnpreemptibleNoWarn;
 import org.vmmagic.unboxed.Address;
 import org.vmmagic.unboxed.Offset;
+import org.vmmagic.unboxed.WordArray;
 
 /**
  * System thread used to perform garbage collections.
@@ -107,7 +108,7 @@
   public static final int GC_ORDINAL_BASE = 1;
 
   /** array of size 1 to count arriving collector threads */
-  static final int[] participantCount;
+  static final WordArray participantCount;
 
   /** maps processor id to assoicated collector thread */
   static CollectorThread[] collectorThreads;
@@ -164,7 +165,7 @@
    */
   static {
     handshake = new Handshake();
-    participantCount = new int[1]; // counter for threads starting a collection
+    participantCount = WordArray.create(1); // counter for threads starting a collection
   }
 
   /**
@@ -175,7 +176,7 @@
    * @param processorAffinity The processor with which this thread is
    * associated.
    */
-  CollectorThread(byte[] stack, boolean isActive, GreenProcessor processorAffinity) {
+  CollectorThread(WordArray stack, boolean isActive, GreenProcessor processorAffinity) {
     super(stack, myName);
     makeDaemon(true); // this is redundant, but harmless
     this.isActive          = isActive;
@@ -241,7 +242,7 @@
    */
   @Interruptible
   public static CollectorThread createActiveCollectorThread(GreenProcessor processorAffinity) {
-    byte[] stack = MemoryManager.newStack(ArchitectureSpecific.StackframeLayoutConstants.STACK_SIZE_COLLECTOR, true);
+    WordArray stack = MemoryManager.newStack(ArchitectureSpecific.StackframeLayoutConstants.STACK_SIZE_COLLECTOR, true);
     return new CollectorThread(stack, true, processorAffinity);
   }
 
@@ -257,7 +258,7 @@
    * @return a new non-particpating collector thread
    */
   @Interruptible
-  static CollectorThread createPassiveCollectorThread(byte[] stack, GreenProcessor processorAffinity) {
+  static CollectorThread createPassiveCollectorThread(WordArray stack, GreenProcessor processorAffinity) {
     return new CollectorThread(stack, false, processorAffinity);
   }
 
@@ -306,7 +307,7 @@
    */
   @Uninterruptible
   public static int numCollectors() {
-    return (participantCount[0]);
+    return participantCount.getInt(0);
   }
 
   /**
diff -r 743a2cc2ed20 -r 058fdc3780ba rvm/src/org/jikesrvm/mm/mminterface/ConcurrentCollectorThread.java
--- a/rvm/src/org/jikesrvm/mm/mminterface/ConcurrentCollectorThread.java	Tue Aug 04 11:04:15 2009 +1000
+++ b/rvm/src/org/jikesrvm/mm/mminterface/ConcurrentCollectorThread.java	Mon Nov 16 09:21:21 2009 +1100
@@ -22,6 +22,7 @@
 import org.vmmagic.pragma.NonMoving;
 import org.vmmagic.pragma.Uninterruptible;
 import org.vmmagic.pragma.Unpreemptible;
+import org.vmmagic.unboxed.WordArray;
 
 /**
  * Threads that perform collector work while mutators are active. these
@@ -61,7 +62,7 @@
    * @param processorAffinity The processor with which this thread is
    * associated.
    */
-  ConcurrentCollectorThread(byte[] stack, GreenProcessor processorAffinity) {
+  ConcurrentCollectorThread(WordArray stack, GreenProcessor processorAffinity) {
     super(stack, myName);
     makeDaemon(true); // this is redundant, but harmless
     this.processorAffinity = processorAffinity;
@@ -89,7 +90,7 @@
    */
   @Interruptible
   public static ConcurrentCollectorThread createConcurrentCollectorThread(GreenProcessor processorAffinity) {
-    byte[] stack = MemoryManager.newStack(ArchitectureSpecific.StackframeLayoutConstants.STACK_SIZE_COLLECTOR, true);
+    WordArray stack = MemoryManager.newStack(ArchitectureSpecific.StackframeLayoutConstants.STACK_SIZE_COLLECTOR, true);
     return new ConcurrentCollectorThread(stack, processorAffinity);
   }
 
diff -r 743a2cc2ed20 -r 058fdc3780ba rvm/src/org/jikesrvm/mm/mminterface/Handshake.java
--- a/rvm/src/org/jikesrvm/mm/mminterface/Handshake.java	Tue Aug 04 11:04:15 2009 +1000
+++ b/rvm/src/org/jikesrvm/mm/mminterface/Handshake.java	Mon Nov 16 09:21:21 2009 +1100
@@ -142,7 +142,7 @@
 
     /* reset counter for collector threads arriving to participate in
      * the collection */
-    CollectorThread.participantCount[0] = 0;
+    CollectorThread.participantCount.setInt(0, 0);
 
     /* reset rendezvous counters to 0, the decision about which
      * collector threads will participate has moved to the run method
diff -r 743a2cc2ed20 -r 058fdc3780ba rvm/src/org/jikesrvm/mm/mminterface/MemoryManager.java
--- a/rvm/src/org/jikesrvm/mm/mminterface/MemoryManager.java	Tue Aug 04 11:04:15 2009 +1000
+++ b/rvm/src/org/jikesrvm/mm/mminterface/MemoryManager.java	Mon Nov 16 09:21:21 2009 +1100
@@ -12,10 +12,13 @@
  */
 package org.jikesrvm.mm.mminterface;
 
+import static org.jikesrvm.mm.mminterface.MemoryManagerConstants.*;
+
 import java.lang.ref.PhantomReference;
 import java.lang.ref.SoftReference;
 import java.lang.ref.WeakReference;
 import org.jikesrvm.ArchitectureSpecific.CodeArray;
+import org.jikesrvm.Constants;
 import org.jikesrvm.VM;
 import org.jikesrvm.HeapLayoutConstants;
 import org.jikesrvm.classloader.RVMArray;
@@ -39,20 +42,25 @@
 import org.jikesrvm.options.OptionSet;
 import org.jikesrvm.runtime.BootRecord;
 import org.jikesrvm.runtime.Magic;
+import org.jikesrvm.runtime.Memory;
 import org.jikesrvm.scheduler.ProcessorTable;
 import org.mmtk.plan.Plan;
+import org.mmtk.plan.generational.Gen;
 import org.mmtk.policy.Space;
-import org.mmtk.utility.Constants;
-import org.mmtk.utility.Memory;
+import org.mmtk.policy.arraylet.Arraylet;
+import org.mmtk.policy.arraylet.ArrayletSpace;
+//import org.mmtk.utility.Memory;
 import org.mmtk.utility.alloc.Allocator;
 import org.mmtk.utility.gcspy.GCspy;
 import org.mmtk.utility.heap.HeapGrowthManager;
 import org.mmtk.utility.heap.Mmapper;
 import org.mmtk.utility.options.Options;
+import org.mmtk.utility.statistics.EventCounter;
 import org.vmmagic.pragma.Entrypoint;
 import org.vmmagic.pragma.Inline;
 import org.vmmagic.pragma.Interruptible;
 import org.vmmagic.pragma.NoInline;
+import org.vmmagic.pragma.NonMovingAllocation;
 import org.vmmagic.pragma.Pure;
 import org.vmmagic.pragma.Uninterruptible;
 import org.vmmagic.pragma.Unpreemptible;
@@ -63,6 +71,13 @@
 import org.vmmagic.unboxed.Offset;
 import org.vmmagic.unboxed.Word;
 import org.vmmagic.unboxed.WordArray;
+import static org.mmtk.utility.Constants.AALOAD_READ_BARRIER;
+import static org.mmtk.utility.Constants.AASTORE_WRITE_BARRIER;
+import static org.mmtk.utility.Constants.GETFIELD_READ_BARRIER;
+import static org.mmtk.utility.Constants.PUTFIELD_WRITE_BARRIER;
+import static org.mmtk.utility.Constants.GETSTATIC_READ_BARRIER;
+import static org.mmtk.utility.Constants.PUTSTATIC_WRITE_BARRIER;
+import static org.mmtk.utility.Constants.MIN_ALIGNMENT;
 
 /**
  * The interface that the MMTk memory manager presents to Jikes RVM
@@ -85,6 +100,7 @@
    * Hash the interface been booted yet?
    */
   private static boolean booted = false;
+  
 
   /***********************************************************************
    *
@@ -226,11 +242,416 @@
   public static void putstaticWriteBarrier(Offset offset, Object value, int locationMetadata) {
     ObjectReference src = ObjectReference.fromObject(Magic.getJTOC());
     Selected.Mutator.get().writeBarrier(src,
-                                        src.toAddress().plus(offset),
-                                        ObjectReference.fromObject(value),
-                                        offset.toWord(),
-                                        Word.fromIntZeroExtend(locationMetadata),
-                                        PUTSTATIC_WRITE_BARRIER);
+        src.toAddress().plus(offset),
+        ObjectReference.fromObject(value),
+        offset.toWord(),
+        Word.fromIntZeroExtend(locationMetadata),
+        PUTSTATIC_WRITE_BARRIER);
+  }
+  
+  /**
+   * Store a byte to an array
+   * 
+   * @param array The array object to which the byte is to be stored
+   * @param index The array index at which the byte is to be stored
+   * @param value The value to be stored
+   */
+  @Entrypoint
+  public static void arrayStorePrimitiveByteWriteBarrier(Object array, int index, byte value) {
+    if ((BOOT_IMAGE_IS_ARRAYLETIZED || ObjectReference.fromObject(array).toAddress().GE(HeapLayoutConstants.BOOT_IMAGE_DATA_END)) &&
+        (!DO_FIRSTN_OPT || (index >= FIRSTN_BYTE_ELEMS)))  {                                                 
+      arrayletStoreByte(array, index, value);
+    } else {
+      Magic.setByteAtOffset(array, Offset.fromIntZeroExtend(index << LOG_BYTES_IN_BYTE), value);
+      if (DO_COLLECT_ARRAY_ACCESS_STATS) primWbFast++;
+    }
+  }
+  
+  /**
+   * Perform an arrayletized store to a byte array.  This code must find the 
+   * appropriate arraylet and store the value to the appropriate slot within
+   * that arraylet.  If we're using lazy allocation or zero compression, the
+   * target arraylet may be the zero arraylet, so if we're storing an non-zero
+   * value, we need to instantiate a new arraylet.
+   * 
+   * @param array The array to which the store is to be made
+   * @param index The array index at which the byte is to be stored
+   * @param value The value to be stored
+   */
+  private static void arrayletStoreByte(Object array, int index, byte value) { 
+	  if (DO_COLLECT_ARRAY_ACCESS_STATS) primWbSlow++;
+	  int arrayletNumber = (index - FIRSTN_BYTE_ELEMS)>>LOG_ELEMENTS_IN_BYTE_ARRAYLET;
+    Offset arrayletPtrOffset = Offset.fromIntZeroExtend(FIRSTN_BYTE_BYTES + (arrayletNumber<<LOG_BYTES_IN_ADDRESS));
+    Address arraylet = Magic.getWordAtOffset(array, arrayletPtrOffset).toAddress();
+    //boolean seenArraylet = false;
+    boolean isTainted = false; 
+    if (DO_COPY_ON_WRITE_BYTE_ARRAYS || DO_COPY_ON_WRITE_BOOLEAN_ARRAYS) { 
+    	isTainted = arraylet.toWord().and(MemoryManagerConstants.ARRAYLET_TAINT_WORD).NE(Word.zero());
+    }
+  	if (isTainted) {
+  		arraylet = arrayletStoreTainted(array, arrayletPtrOffset, arraylet);
+  	}
+  	
+  	if (USE_ZERO_ARRAYLETS && arraylet.EQ(Magic.objectAsAddress(ObjectModel.zeroArraylet))) {
+  		if (value == 0)
+  			return;
+  		arraylet = lazyAllocateArraylet(array, arrayletPtrOffset);
+  	}
+  
+    int arrayletIndex = (index - FIRSTN_BYTE_ELEMS) & BYTE_ARRAYLET_MASK;
+    arraylet.store(value,  Offset.fromIntZeroExtend(arrayletIndex<<LOG_BYTES_IN_BYTE));
+  }
+
+  @NoInline
+  public static Address arrayletStoreTainted(Object array, Offset arrayletPtrOffset, Address arraylet) {
+    Address sourceArraylet = arraylet.toWord().and(MemoryManagerConstants.ARRAYLET_TAINT_MASK).toAddress();
+    if (MemoryManagerConstants.ENABLE_COW_ARRAYLET_INCOMING_PTR) {
+      int numPtrs = Arraylet.subIncomingPointer(sourceArraylet);
+      if (numPtrs < 0) {
+        Magic.setWordAtOffset(array, arrayletPtrOffset, sourceArraylet.toWord());
+        return sourceArraylet;
+      }
+    }
+
+    Address basePtr = Magic.objectAsAddress(array).plus(arrayletPtrOffset);
+    Address destArraylet = arrayStoreAllocateArraylet(array);
+    Memory.memcopy(destArraylet, sourceArraylet, ARRAYLET_BYTES);
+    do {
+      Address existingArraylet = basePtr.prepareAddress();
+      if (existingArraylet.NE(arraylet)) 
+        return existingArraylet;
+    } while (!basePtr.attempt(arraylet, destArraylet));
+
+    return destArraylet;
+  }
+ 
+  @NoInline 
+  private static Address arrayletStoreTaintedWithGCBarrier(Object array, Offset arrayletPtrOffset, Address arraylet) {
+    Address sourceArraylet = arraylet.toWord().and(MemoryManagerConstants.ARRAYLET_TAINT_MASK).toAddress();
+    if (MemoryManagerConstants.ENABLE_COW_ARRAYLET_INCOMING_PTR) {
+      int numPtrs = Arraylet.subIncomingPointer(sourceArraylet);
+      if (numPtrs < 0) {
+        Magic.setWordAtOffset(array, arrayletPtrOffset, sourceArraylet.toWord());
+        return sourceArraylet;
+      }
+    }
+
+    Address basePtr = Magic.objectAsAddress(array).plus(arrayletPtrOffset);
+    Address destArraylet = arrayStoreAllocateArraylet(array);
+    if (!MemoryManager.arrayCopyWriteBarrier(array, sourceArraylet.diff(Magic.objectAsAddress(array)), array, destArraylet.diff(Magic.objectAsAddress(array)), ARRAYLET_BYTES)) {
+      Memory.memcopy(destArraylet, sourceArraylet, ARRAYLET_BYTES);
+    }
+    do {
+      Address existingArraylet = basePtr.prepareAddress();
+      if (existingArraylet.NE(arraylet)) 
+        return existingArraylet;
+    } while (!basePtr.attempt(arraylet, destArraylet));
+
+    return destArraylet;
+  }  
+
+  /**
+   * Store a char to an array
+   * 
+   * @param array The array object to which the char is to be stored
+   * @param index The array index at which the char is to be stored
+   * @param value The value to be stored
+   */
+  @Entrypoint
+  public static void arrayStorePrimitiveCharWriteBarrier(Object array, int index, char value) {
+    if ((BOOT_IMAGE_IS_ARRAYLETIZED || ObjectReference.fromObject(array).toAddress().GE(HeapLayoutConstants.BOOT_IMAGE_DATA_END)) &&
+        (!DO_FIRSTN_OPT || (index >= FIRSTN_CHAR_ELEMS)))                                                   
+      arrayletStoreChar(array, index, value);
+    else {
+      Magic.setCharAtOffset(array, Offset.fromIntZeroExtend(index << LOG_BYTES_IN_CHAR), value);
+      if (DO_COLLECT_ARRAY_ACCESS_STATS) primWbFast++;
+    }
+  }
+  
+  /**
+   * Perform an arrayletized store to a char array.  This code must find the 
+   * appropriate arraylet and store the value to the appropriate slot within
+   * that arraylet.  If we're using lazy allocation or zero compression, the
+   * target arraylet may be the zero arraylet, so if we're storing an non-zero
+   * value, we need to instantiate a new arraylet.
+   * 
+   * @param array The array to which the store is to be made
+   * @param index The array index at which the char is to be stored
+   * @param value The value to be stored
+   */
+  private static void arrayletStoreChar(Object array, int index, char value) { 
+	  if (DO_COLLECT_ARRAY_ACCESS_STATS) primWbSlow++;
+    int arrayletNumber = (index - FIRSTN_CHAR_ELEMS)>>LOG_ELEMENTS_IN_CHAR_ARRAYLET;
+    Offset arrayletPtrOffset = Offset.fromIntZeroExtend(FIRSTN_CHAR_BYTES + (arrayletNumber<<LOG_BYTES_IN_ADDRESS));
+    Address arraylet = Magic.getWordAtOffset(array, arrayletPtrOffset).toAddress();
+    boolean isTainted = false; 
+    if (DO_COPY_ON_WRITE_CHAR_ARRAYS) { 
+    	isTainted = arraylet.toWord().and(MemoryManagerConstants.ARRAYLET_TAINT_WORD).NE(Word.zero());
+    }
+  	if (isTainted) {
+  		arraylet = arrayletStoreTainted(array, arrayletPtrOffset, arraylet);
+  	}
+  	if (USE_ZERO_ARRAYLETS && arraylet.EQ(Magic.objectAsAddress(ObjectModel.zeroArraylet))) {
+  		if (value == 0)
+  			return;
+  		arraylet = lazyAllocateArraylet(array, arrayletPtrOffset);
+  	}
+    int arrayletIndex = (index - FIRSTN_CHAR_ELEMS) & CHAR_ARRAYLET_MASK;
+    arraylet.store(value,  Offset.fromIntZeroExtend(arrayletIndex<<LOG_BYTES_IN_CHAR));
+  }
+
+  /**
+   * Store a short to an array
+   * 
+   * @param array The array object to which the short is to be stored
+   * @param index The array index at which the short is to be stored
+   * @param value The value to be stored
+   */
+  @Entrypoint
+  public static void arrayStorePrimitiveShortWriteBarrier(Object array, int index, short value) {
+    if ((BOOT_IMAGE_IS_ARRAYLETIZED || ObjectReference.fromObject(array).toAddress().GE(HeapLayoutConstants.BOOT_IMAGE_DATA_END)) &&
+        (!DO_FIRSTN_OPT || (index >= FIRSTN_SHORT_ELEMS)))                                                   
+      arrayletStoreShort(array, index, value);
+    else {
+     // Magic.setShortAtOffset(array, Offset.fromIntZeroExtend(index << LOG_BYTES_IN_SHORT), value);
+      ObjectReference.fromObject(array).toAddress().store(value, Offset.fromIntZeroExtend(index << LOG_BYTES_IN_SHORT));
+      if (DO_COLLECT_ARRAY_ACCESS_STATS) primWbFast++;
+    }
+  }
+  
+  /**
+   * Perform an arrayletized store to a short array.  This code must find the 
+   * appropriate arraylet and store the value to the appropriate slot within
+   * that arraylet.  If we're using lazy allocation or zero compression, the
+   * target arraylet may be the zero arraylet, so if we're storing an non-zero
+   * value, we need to instantiate a new arraylet.
+   * 
+   * @param array The array to which the store is to be made
+   * @param index The array index at which the short is to be stored
+   * @param value The value to be stored
+   */
+  private static void arrayletStoreShort(Object array, int index, short value) { 
+	  if (DO_COLLECT_ARRAY_ACCESS_STATS) primWbSlow++;
+    int arrayletNumber = (index - FIRSTN_SHORT_ELEMS)>>LOG_ELEMENTS_IN_SHORT_ARRAYLET;
+    Offset arrayletPtrOffset = Offset.fromIntZeroExtend(FIRSTN_SHORT_BYTES + (arrayletNumber<<LOG_BYTES_IN_ADDRESS));
+    Address arraylet = Magic.getWordAtOffset(array, arrayletPtrOffset).toAddress();
+    boolean isTainted = false; 
+    if (DO_COPY_ON_WRITE_SHORT_ARRAYS) { 
+    	isTainted = arraylet.toWord().and(MemoryManagerConstants.ARRAYLET_TAINT_WORD).NE(Word.zero());
+    }
+    if (isTainted) {
+      arraylet = arrayletStoreTainted(array, arrayletPtrOffset, arraylet);
+    }
+    if (USE_ZERO_ARRAYLETS && arraylet.EQ(Magic.objectAsAddress(ObjectModel.zeroArraylet))) {
+      if (value == 0)
+        return;
+      arraylet = lazyAllocateArraylet(array, arrayletPtrOffset);
+    }
+
+    int arrayletIndex = (index - FIRSTN_SHORT_ELEMS) & SHORT_ARRAYLET_MASK;
+    arraylet.store(value,  Offset.fromIntZeroExtend(arrayletIndex<<LOG_BYTES_IN_SHORT));
+  }
+
+  /**
+   * Store a int to an array
+   * 
+   * @param array The array object to which the int is to be stored
+   * @param index The array index at which the int is to be stored
+   * @param value The value to be stored
+   */
+  @Entrypoint
+  public static void arrayStorePrimitiveIntWriteBarrier(Object array, int index, int value) {
+    if (INSANITY) sanityCheckSpine(array);
+    if ((BOOT_IMAGE_IS_ARRAYLETIZED || ObjectReference.fromObject(array).toAddress().GE(HeapLayoutConstants.BOOT_IMAGE_DATA_END)) &&
+        (!DO_FIRSTN_OPT || (index >= FIRSTN_INT_ELEMS)))                                                   
+      arrayletStoreInt(array, index, value);
+    else {
+      Magic.setIntAtOffset(array, Offset.fromIntZeroExtend(index << LOG_BYTES_IN_INT), value);
+      if (DO_COLLECT_ARRAY_ACCESS_STATS) primWbFast++;
+    }
+  }
+  
+  /**
+   * Perform an arrayletized store to a int array.  This code must find the 
+   * appropriate arraylet and store the value to the appropriate slot within
+   * that arraylet.  If we're using lazy allocation or zero compression, the
+   * target arraylet may be the zero arraylet, so if we're storing an non-zero
+   * value, we need to instantiate a new arraylet.
+   * 
+   * @param array The array to which the store is to be made
+   * @param index The array index at which the int is to be stored
+   * @param value The value to be stored
+   */
+  private static void arrayletStoreInt(Object array, int index, int value) { 
+	  if (DO_COLLECT_ARRAY_ACCESS_STATS) primWbSlow++;
+    int arrayletNumber = (index - FIRSTN_INT_ELEMS)>>LOG_ELEMENTS_IN_INT_ARRAYLET;
+    Offset arrayletPtrOffset = Offset.fromIntZeroExtend(FIRSTN_INT_BYTES + (arrayletNumber<<LOG_BYTES_IN_ADDRESS));
+    Address arraylet = Magic.getWordAtOffset(array, arrayletPtrOffset).toAddress();
+    boolean isTainted = false; 
+    if (DO_COPY_ON_WRITE_INT_ARRAYS) { 
+    	isTainted = arraylet.toWord().and(MemoryManagerConstants.ARRAYLET_TAINT_WORD).NE(Word.zero());
+    }
+    if (isTainted) {
+      arraylet = arrayletStoreTainted(array, arrayletPtrOffset, arraylet);
+    }
+    if (USE_ZERO_ARRAYLETS && arraylet.EQ(Magic.objectAsAddress(ObjectModel.zeroArraylet))) {
+      if (value == 0)
+        return;
+      arraylet = lazyAllocateArraylet(array, arrayletPtrOffset);
+    }
+    int arrayletIndex = (index - FIRSTN_INT_ELEMS) & INT_ARRAYLET_MASK;
+    arraylet.store(value,  Offset.fromIntZeroExtend(arrayletIndex<<LOG_BYTES_IN_INT));
+  }
+
+  /**
+   * Store a float to an array
+   * 
+   * @param array The array object to which the float is to be stored
+   * @param index The array index at which the float is to be stored
+   * @param value The value to be stored
+   */
+  @Entrypoint
+  public static void arrayStorePrimitiveFloatWriteBarrier(Object array, int index, float value) {
+    if ((BOOT_IMAGE_IS_ARRAYLETIZED || ObjectReference.fromObject(array).toAddress().GE(HeapLayoutConstants.BOOT_IMAGE_DATA_END)) &&
+        (!DO_FIRSTN_OPT || (index >= FIRSTN_FLOAT_ELEMS)))                                                   
+      arrayletStoreFloat(array, index, value);
+    else {
+     // Magic.setFloatAtOffset(array, Offset.fromIntZeroExtend(index << LOG_BYTES_IN_FLOAT), value);
+      ObjectReference.fromObject(array).toAddress().store(value, Offset.fromIntZeroExtend(index << LOG_BYTES_IN_FLOAT));
+      if (DO_COLLECT_ARRAY_ACCESS_STATS) primWbFast++;
+    }
+  }
+  
+  /**
+   * Perform an arrayletized store to a float array.  This code must find the 
+   * appropriate arraylet and store the value to the appropriate slot within
+   * that arraylet.  If we're using lazy allocation or zero compression, the
+   * target arraylet may be the zero arraylet, so if we're storing an non-zero
+   * value, we need to instantiate a new arraylet.
+   * 
+   * @param array The array to which the store is to be made
+   * @param index The array index at which the float is to be stored
+   * @param value The value to be stored
+   */
+  private static void arrayletStoreFloat(Object array, int index, float value) { 
+	  if (DO_COLLECT_ARRAY_ACCESS_STATS) primWbSlow++;
+    int arrayletNumber = (index - FIRSTN_FLOAT_ELEMS)>>LOG_ELEMENTS_IN_FLOAT_ARRAYLET;
+    Offset arrayletPtrOffset = Offset.fromIntZeroExtend(FIRSTN_FLOAT_BYTES + (arrayletNumber<<LOG_BYTES_IN_ADDRESS));
+    Address arraylet = Magic.getWordAtOffset(array, arrayletPtrOffset).toAddress();
+    boolean isTainted = false; 
+    if (DO_COPY_ON_WRITE_FLOAT_ARRAYS) { 
+    	isTainted = arraylet.toWord().and(MemoryManagerConstants.ARRAYLET_TAINT_WORD).NE(Word.zero());
+    }
+  	if (isTainted) {
+  		arraylet = arrayletStoreTainted(array, arrayletPtrOffset, arraylet);
+  	}
+    if (USE_ZERO_ARRAYLETS && arraylet.EQ(Magic.objectAsAddress(ObjectModel.zeroArraylet))) {
+  		if (value == 0)
+  			return;
+  		arraylet = lazyAllocateArraylet(array, arrayletPtrOffset);
+  	}
+    int arrayletIndex = (index - FIRSTN_FLOAT_ELEMS) & FLOAT_ARRAYLET_MASK;
+    arraylet.store(value,  Offset.fromIntZeroExtend(arrayletIndex<<LOG_BYTES_IN_FLOAT));
+  }
+
+  /**
+   * Store a double to an array
+   * 
+   * @param array The array object to which the double is to be stored
+   * @param index The array index at which the double is to be stored
+   * @param value The value to be stored
+   */
+  @Entrypoint
+  public static void arrayStorePrimitiveDoubleWriteBarrier(Object array, int index, double value) {
+    if ((BOOT_IMAGE_IS_ARRAYLETIZED || ObjectReference.fromObject(array).toAddress().GE(HeapLayoutConstants.BOOT_IMAGE_DATA_END)) &&
+        (!DO_FIRSTN_OPT || (index >= FIRSTN_DOUBLE_ELEMS)))                                                   
+      arrayletStoreDouble(array, index, value);
+    else {
+      Magic.setDoubleAtOffset(array, Offset.fromIntZeroExtend(index << LOG_BYTES_IN_DOUBLE), value);
+      if (DO_COLLECT_ARRAY_ACCESS_STATS) primWbFast++;
+    }
+  }
+  
+  /**
+   * Perform an arrayletized store to a double array.  This code must find the 
+   * appropriate arraylet and store the value to the appropriate slot within
+   * that arraylet.  If we're using lazy allocation or zero compression, the
+   * target arraylet may be the zero arraylet, so if we're storing an non-zero
+   * value, we need to instantiate a new arraylet.
+   * 
+   * @param array The array to which the store is to be made
+   * @param index The array index at which the double is to be stored
+   * @param value The value to be stored
+   */
+  private static void arrayletStoreDouble(Object array, int index, double value) { 
+	  if (DO_COLLECT_ARRAY_ACCESS_STATS) primWbSlow++;
+    int arrayletNumber = (index - FIRSTN_DOUBLE_ELEMS)>>LOG_ELEMENTS_IN_DOUBLE_ARRAYLET;
+    Offset arrayletPtrOffset = Offset.fromIntZeroExtend(FIRSTN_DOUBLE_BYTES + (arrayletNumber<<LOG_BYTES_IN_ADDRESS));
+    Address arraylet = Magic.getWordAtOffset(array, arrayletPtrOffset).toAddress();
+    boolean isTainted = false; 
+    if (DO_COPY_ON_WRITE_DOUBLE_ARRAYS) { 
+    	isTainted = arraylet.toWord().and(MemoryManagerConstants.ARRAYLET_TAINT_WORD).NE(Word.zero());
+    }
+  	if (isTainted) {
+  		arraylet = arrayletStoreTainted(array, arrayletPtrOffset, arraylet);
+  	}
+    if (USE_ZERO_ARRAYLETS && arraylet.EQ(Magic.objectAsAddress(ObjectModel.zeroArraylet))) {
+  		if (value == 0)
+  			return;
+  		arraylet = lazyAllocateArraylet(array, arrayletPtrOffset);
+  	}
+    int arrayletIndex = (index - FIRSTN_DOUBLE_ELEMS) & DOUBLE_ARRAYLET_MASK;
+    arraylet.store(value,  Offset.fromIntZeroExtend(arrayletIndex<<LOG_BYTES_IN_DOUBLE));
+  }
+
+  /**
+   * Store a long to an array
+   * 
+   * @param array The array object to which the long is to be stored
+   * @param index The array index at which the long is to be stored
+   * @param value The value to be stored
+   */
+  @Entrypoint
+  public static void arrayStorePrimitiveLongWriteBarrier(Object array, int index, long value) {
+    if ((BOOT_IMAGE_IS_ARRAYLETIZED || ObjectReference.fromObject(array).toAddress().GE(HeapLayoutConstants.BOOT_IMAGE_DATA_END)) &&
+        (!DO_FIRSTN_OPT || (index >= FIRSTN_LONG_ELEMS)))                                                   
+      arrayletStoreLong(array, index, value);
+    else {
+      Magic.setLongAtOffset(array, Offset.fromIntZeroExtend(index << LOG_BYTES_IN_LONG), value);
+      if (DO_COLLECT_ARRAY_ACCESS_STATS) primWbFast++;
+    }
+  }
+  
+  /**
+   * Perform an arrayletized store to a long array.  This code must find the 
+   * appropriate arraylet and store the value to the appropriate slot within
+   * that arraylet.  If we're using lazy allocation or zero compression, the
+   * target arraylet may be the zero arraylet, so if we're storing an non-zero
+   * value, we need to instantiate a new arraylet.
+   * 
+   * @param array The array to which the store is to be made
+   * @param index The array index at which the long is to be stored
+   * @param value The value to be stored
+   */
+  private static void arrayletStoreLong(Object array, int index, long value) { 
+	  if (DO_COLLECT_ARRAY_ACCESS_STATS) primWbSlow++;
+    int arrayletNumber = (index - FIRSTN_LONG_ELEMS)>>LOG_ELEMENTS_IN_LONG_ARRAYLET;
+    Offset arrayletPtrOffset = Offset.fromIntZeroExtend(FIRSTN_LONG_BYTES + (arrayletNumber<<LOG_BYTES_IN_ADDRESS));
+    Address arraylet = Magic.getWordAtOffset(array, arrayletPtrOffset).toAddress();
+    boolean isTainted = false; 
+    if (DO_COPY_ON_WRITE_LONG_ARRAYS) { 
+    	isTainted = arraylet.toWord().and(MemoryManagerConstants.ARRAYLET_TAINT_WORD).NE(Word.zero());
+    }
+  	if (isTainted) {
+  		arraylet = arrayletStoreTainted(array, arrayletPtrOffset, arraylet);
+  	}
+    if (USE_ZERO_ARRAYLETS && arraylet.EQ(Magic.objectAsAddress(ObjectModel.zeroArraylet))) {
+  		if (value == 0)
+  			return;
+  		arraylet = lazyAllocateArraylet(array, arrayletPtrOffset);
+  	}
+    int arrayletIndex = (index - FIRSTN_LONG_ELEMS) & LONG_ARRAYLET_MASK;
+    arraylet.store(value,  Offset.fromIntZeroExtend(arrayletIndex<<LOG_BYTES_IN_LONG));
   }
 
   /**
@@ -243,20 +664,197 @@
    * example a[index].
    * @param value the object that is the target of the new reference.
    */
-  @Inline
   @Entrypoint
   public static void arrayStoreWriteBarrier(Object ref, int index, Object value) {
     ObjectReference array = ObjectReference.fromObject(ref);
-    Offset offset = Offset.fromIntZeroExtend(index << LOG_BYTES_IN_ADDRESS);
-    Selected.Mutator.get().writeBarrier(array,
-                                        array.toAddress().plus(offset),
-                                        ObjectReference.fromObject(value),
-                                        offset.toWord(),
-                                        Word.zero(),
-                                        // don't know metadata
-                                        AASTORE_WRITE_BARRIER);
+    ObjectReference target = ObjectReference.fromObject(value);    
+    if (USE_REFERENCE_ARRAYLETS && ((BOOT_IMAGE_IS_ARRAYLETIZED || array.toAddress().GE(HeapLayoutConstants.BOOT_IMAGE_DATA_END)) && (!DO_FIRSTN_OPT || (index >= FIRSTN_INT_ELEMS)))) {                                                    
+      arrayletizedArrayStore(ref, index, target, true);                                                                                         
+    } else {       
+    	if (DO_COLLECT_ARRAY_ACCESS_STATS) refWbFast++;
+      Offset offset = Offset.fromIntZeroExtend(index << LOG_BYTES_IN_ADDRESS);                                                              
+      if (NEEDS_WRITE_BARRIER)                                                                                                                
+        Selected.Mutator.get().writeBarrier(array, array.toAddress().plus(offset), target, offset.toWord(), array.toAddress().toWord(), AASTORE_WRITE_BARRIER);                                                                                                           
+      else                                                                                                                                    
+        array.toAddress().store(target, offset);  
+    }  
+  }
+  
+  /**
+   * Perform an arrayletized store to an object array.  This code must find the 
+   * appropriate arraylet and store the value to the appropriate slot within
+   * that arraylet.  If we're using lazy allocation or zero compression, the
+   * target arraylet may be the zero arraylet, so if we're storing an non-zero
+   * value, we need to instantiate a new arraylet.
+   * 
+   * @param array The array to which the store is to be made
+   * @param index The array index at which the object is to be stored
+   * @param value The value to be stored
+   */
+  public static void arrayletizedArrayStore(Object ref, int index, ObjectReference value, boolean doGCBarrier) {
+	  if (DO_COLLECT_ARRAY_ACCESS_STATS) refWbSlow++;
+	  int arrayletNumber = (index - FIRSTN_REF_ELEMS)>>LOG_ELEMENTS_IN_REF_ARRAYLET;
+    ObjectReference array = ObjectReference.fromObject(ref);
+    Offset arrayletPtrOffset = Offset.fromIntZeroExtend(FIRSTN_REF_BYTES + (arrayletNumber<<LOG_BYTES_IN_ADDRESS));
+    Address arrayletPtr = Magic.objectAsAddress(ref).plus(arrayletPtrOffset);
+    Address arraylet = arrayletPtr.loadAddress();
+    boolean isTainted = false;
+    if (DO_COPY_ON_WRITE_REF_ARRAYS) { 
+    	isTainted = arraylet.toWord().and(MemoryManagerConstants.ARRAYLET_TAINT_WORD).NE(Word.zero());
+    }
+  	if (isTainted) {
+  		arraylet = arrayletStoreTaintedWithGCBarrier(ref, arrayletPtrOffset, arraylet);
+  	} else  if (USE_ZERO_ARRAYLETS && arraylet.EQ(Magic.objectAsAddress(ObjectModel.zeroArraylet))) {
+  		if (value.isNull())
+  			return; // found that target is null - don't need to perform store - zeroArraylet already zero
+  		arraylet = lazyAllocateArraylet(ref, arrayletPtrOffset);
+  	}
+    int arrayletIndex = (index - FIRSTN_REF_ELEMS) & REF_ARRAYLET_MASK;
+    Offset offset = Offset.fromIntZeroExtend(arrayletIndex << LOG_BYTES_IN_ADDRESS);   
+    if (NEEDS_WRITE_BARRIER && doGCBarrier)                                                                                                                
+      Selected.Mutator.get().writeBarrier(array, arraylet.plus(offset), value, offset.toWord(), arraylet.toWord(), AASTORE_WRITE_BARRIER);                                                                                                           
+    else                                                                                                                                    
+      arraylet.store(value, offset);  
   }
 
+  private static Address arrayStoreAllocateArraylet(Object array) {
+    Selected.Mutator mutator = Selected.Mutator.get();
+    int allocator = Plan.ALLOC_ARRAYLET;
+    int arraylet_bytes = ARRAYLET_BYTES;
+    Address region = mutator.alloc(arraylet_bytes, 0, 0, allocator, -1);
+    if (DO_COLLECT_SPACE_SAVING_STATS) {
+      ARRAYLET_BYTES_ALLOCATED += arraylet_bytes;
+    }
+    if (!Gen.inNursery(array)) {
+      //need to mark arraylet unless it'll be marked at next nursery collection
+      ArrayletSpace.markArraylet(region);
+    }
+    return region;
+  }
+  
+  @Inline
+  private static Address arrayStoreAllocateArraylet(boolean isNursery) {
+    Selected.Mutator mutator = Selected.Mutator.get();
+    int allocator = Plan.ALLOC_ARRAYLET;
+    int arraylet_bytes = ARRAYLET_BYTES;
+    Address region = mutator.alloc(arraylet_bytes, 0, 0, allocator, -1);
+    if (DO_COLLECT_SPACE_SAVING_STATS) {
+      ARRAYLET_BYTES_ALLOCATED += arraylet_bytes;
+    }
+    if (!isNursery)
+      //need to mark arraylet unless it'll be marked at next nursery collection
+      ArrayletSpace.markArraylet(region);
+    return region;
+  }
+
+  public static Address lazyAllocateArraylet(Object array, Offset arrayletPtrOffset) {
+    final Address ZERO_ARRAYLET = Magic.objectAsAddress(ObjectModel.zeroArraylet);
+    Address basePtr = Magic.objectAsAddress(array).plus(arrayletPtrOffset);
+
+    Address newArraylet = arrayStoreAllocateArraylet(array);
+    do {
+      Address existingArraylet = basePtr.prepareAddress();
+      if (existingArraylet.NE(ZERO_ARRAYLET)) 
+        return existingArraylet;  // new arraylet thrown away; will get GC'd soon enough
+    } while (!basePtr.attempt(ZERO_ARRAYLET, newArraylet));
+    
+    return newArraylet;
+  }
+  
+  @Inline                                                                                                                                   
+  private static Address getArrayletBase(Address array, int index) {                                                                           
+    int arrayletIndex;                                                                                                                      
+    if (!DO_FIRSTN_OPT) // || DO_FIRSTN_DUP_OPT)                                                                                                
+      arrayletIndex = (index >> LOG_ELEMENTS_IN_INT_ARRAYLET);                                                                         
+    else                                                                                                                                    
+      arrayletIndex = FIRSTN_INT_ELEMS + ((index - FIRSTN_INT_ELEMS) >> LOG_ELEMENTS_IN_INT_ARRAYLET);                                                        
+    Offset offset = Offset.fromIntZeroExtend(arrayletIndex<<LOG_BYTES_IN_ADDRESS);                                                          
+    Address basePtr = array.plus(offset);                                                           
+    if (DO_COPY_ON_WRITE_REF_ARRAYS) basePtr = basePtr.toWord().and(MemoryManagerConstants.ARRAYLET_TAINT_MASK).toAddress();
+    return basePtr.loadAddress();                                                                                                           
+  } 
+
+  
+  @Inline                                                                                                                                   
+  public static int getArrayletIndex(int index, int logElementSize) {                                                                                                  
+    int curr_firstN_value = FIRSTN_INT_ELEMS;
+    int curr_arrayletMask = REF_ARRAYLET_MASK;
+    if (logElementSize == LOG_BYTES_IN_SHORT) {
+      curr_firstN_value = FIRSTN_SHORT_ELEMS;
+      curr_arrayletMask = SHORT_ARRAYLET_MASK;
+    } else if (logElementSize == LOG_BYTES_IN_LONG) {
+      curr_firstN_value = FIRSTN_LONG_ELEMS;
+      curr_arrayletMask = LONG_ARRAYLET_MASK;
+    } else if (logElementSize == LOG_BYTES_IN_BYTE) {
+      curr_firstN_value = FIRSTN_BYTE_ELEMS;
+      curr_arrayletMask = BYTE_ARRAYLET_MASK;
+    }
+    if (DO_FIRSTN_OPT)                                                         
+      index -= curr_firstN_value;                                                                                                                
+
+    return index & curr_arrayletMask;                                                                                                           
+  } 
+
+  @Inline
+  public static int getArraySpineNumDangling(int numelts, int logElementSize) {
+    int curr_firstN_value = FIRSTN_INT_ELEMS;
+    int curr_arrayletMask = REF_ARRAYLET_MASK;
+    if (logElementSize == LOG_BYTES_IN_SHORT) {
+      curr_firstN_value = FIRSTN_SHORT_ELEMS;
+      curr_arrayletMask = SHORT_ARRAYLET_MASK;
+    } else if (logElementSize == LOG_BYTES_IN_LONG) {
+      curr_firstN_value = FIRSTN_LONG_ELEMS;
+      curr_arrayletMask = LONG_ARRAYLET_MASK;
+    } else if (logElementSize == LOG_BYTES_IN_BYTE) {
+      curr_firstN_value = FIRSTN_BYTE_ELEMS;
+      curr_arrayletMask = BYTE_ARRAYLET_MASK;
+    }
+    numelts -= curr_firstN_value;
+    return (numelts & curr_arrayletMask);
+  }
+  
+  public static Address getArrayletizedSlotForStore(Address array, int index) {                                                              
+    Address base = array;           
+    if (USE_REFERENCE_ARRAYLETS && ((BOOT_IMAGE_IS_ARRAYLETIZED || (array).GE(HeapLayoutConstants.BOOT_IMAGE_DATA_END)) && (!DO_FIRSTN_OPT || (index >= FIRSTN_INT_ELEMS)))) {  
+      base = getArrayletBase(array, index);           
+      index = getArrayletIndex(index, LOG_BYTES_IN_ADDRESS);                               
+
+    }
+    Offset offset = Offset.fromIntZeroExtend(index<<LOG_BYTES_IN_ADDRESS);                                                                  
+    return base.plus(offset);                                                                                                               
+  }
+
+  @Inline                                                                                                                                   
+  public static void initializeDanglingPointer(ObjectReference array, int elements, int logElementSize) {
+    int curr_firstN_value = FIRSTN_INT_ELEMS;
+    int curr_logArrayletElems = LOG_ELEMENTS_IN_INT_ARRAYLET;
+    int curr_firstN_bytes = FIRSTN_INT_BYTES;
+    if (logElementSize == LOG_BYTES_IN_SHORT) {
+      curr_firstN_value = FIRSTN_SHORT_ELEMS;
+      curr_logArrayletElems = LOG_ELEMENTS_IN_SHORT_ARRAYLET;
+      curr_firstN_bytes = FIRSTN_SHORT_BYTES;
+    } else if (logElementSize == LOG_BYTES_IN_LONG) {
+      curr_firstN_value = FIRSTN_LONG_ELEMS;
+      curr_logArrayletElems = LOG_ELEMENTS_IN_LONG_ARRAYLET;
+      curr_firstN_bytes = FIRSTN_LONG_BYTES;
+    } else if (logElementSize == LOG_BYTES_IN_BYTE) {
+      curr_firstN_value = FIRSTN_BYTE_ELEMS;
+      curr_logArrayletElems = LOG_ELEMENTS_IN_BYTE_ARRAYLET;
+      curr_firstN_bytes = FIRSTN_BYTE_BYTES;
+    }
+    int arrayletizedElements = elements - curr_firstN_value;                                                                                     
+    if (arrayletizedElements > 0) { 
+      int numArraylets = 1 + (arrayletizedElements >> curr_logArrayletElems);
+      Address arrayletCursor = array.toAddress(); 
+      int baseOfArrayletElems = 0;
+      if (DO_FIRSTN_OPT) {
+        baseOfArrayletElems = curr_firstN_bytes;
+      }
+      arrayletCursor = arrayletCursor.plus(Offset.fromIntZeroExtend(baseOfArrayletElems + ((numArraylets - 1)<<LOG_BYTES_IN_ADDRESS)));
+      arrayletCursor.store(arrayletCursor.plus(BYTES_IN_ADDRESS));
+    }
+  }
+  
   /**
    * Take appropriate write barrier actions when a series of
    * references are copied (i.e. in an array copy).
@@ -305,6 +903,42 @@
                                               Word.fromIntZeroExtend(locationMetadata),
                                               GETFIELD_READ_BARRIER).toObject();
   }
+ 
+  /**
+   * Take appropriate read barrier actions for loading a reference
+   * from an array.
+   *
+   * @param ref the array containing the reference.
+   * @param index the index into the array were the reference resides.
+   * @return the value read from the array
+   */
+  @Entrypoint 
+  public static Object arrayLoadReadBarrier(Object ref, int index) {
+    ObjectReference array = ObjectReference.fromObject(ref);
+    if (USE_REFERENCE_ARRAYLETS && (BOOT_IMAGE_IS_ARRAYLETIZED || array.toAddress().GE(HeapLayoutConstants.BOOT_IMAGE_DATA_END)) &&
+        (!DO_FIRSTN_OPT || (index >= FIRSTN_REF_ELEMS)))
+      return arrayletizedReferenceArrayLoad(array, index);
+    else {
+    	if (DO_COLLECT_ARRAY_ACCESS_STATS) refRbFast++;
+      Offset offset = Offset.fromIntZeroExtend(index << LOG_BYTES_IN_ADDRESS);                                                              
+      if (NEEDS_READ_BARRIER)
+        return Selected.Mutator.get().readBarrier(array, array.toAddress().plus(offset), offset.toWord(), array.toAddress().toWord(),  AALOAD_READ_BARRIER).toObject();                                                                   
+      else
+        return array.toAddress().loadObjectReference(offset).toObject();
+    }
+  }
+  
+  private static Object arrayletizedReferenceArrayLoad(ObjectReference array, int index) {
+	  if (DO_COLLECT_ARRAY_ACCESS_STATS) refRbSlow++;
+    int arrayletNumber = (index - FIRSTN_REF_ELEMS)>>LOG_ELEMENTS_IN_REF_ARRAYLET;
+    Address arraylet = array.toAddress().plus(FIRSTN_REF_BYTES + (arrayletNumber<<LOG_BYTES_IN_ADDRESS)).loadAddress();
+    if (DO_COPY_ON_WRITE_REF_ARRAYS) arraylet = arraylet.toWord().and(MemoryManagerConstants.ARRAYLET_TAINT_MASK).toAddress();
+    if (DO_ZERO_ARRAY_COMPRESSION && arraylet.EQ(Magic.objectAsAddress(ObjectModel.zeroArraylet)))
+      return ObjectReference.nullReference().toObject();  //we know it's zero - short circuit to save doing load
+
+    int arrayletIndex = (index - FIRSTN_REF_ELEMS) & REF_ARRAYLET_MASK;
+    return arraylet.loadObjectReference(Offset.fromIntZeroExtend(arrayletIndex<<LOG_BYTES_IN_ADDRESS)).toObject();
+  }
 
   /**
    * Take appropriate read barrier actions for loading a reference
@@ -316,17 +950,319 @@
    */
   @Inline
   @Entrypoint
-  public static Object arrayLoadReadBarrier(Object ref, int index) {
-    ObjectReference array = ObjectReference.fromObject(ref);
-    Offset offset = Offset.fromIntZeroExtend(index << LOG_BYTES_IN_ADDRESS);
-    return Selected.Mutator.get().readBarrier(array,
-                                              array.toAddress().plus(offset),
-                                              offset.toWord(),
-                                              Word.zero(), // don't know metadata
-                                              AALOAD_READ_BARRIER).toObject();
+  public static Object hackArrayLoadReadBarrier(Object ref, int index) {
+    ObjectReference array =  ObjectReference.fromObject(ref);
+    Address base = array.toAddress();
+    int aIndex = index;
+    if (USE_REFERENCE_ARRAYLETS && ((BOOT_IMAGE_IS_ARRAYLETIZED || array.toAddress().GE(HeapLayoutConstants.BOOT_IMAGE_DATA_END)) && (!DO_FIRSTN_OPT || (index >= FIRSTN_INT_ELEMS)))) {   
+    	 if (DO_COLLECT_ARRAY_ACCESS_STATS) refRbSlow++;
+    	int arrayletIndex;   
+      if (!DO_FIRSTN_OPT)
+        arrayletIndex = (index >> LOG_ELEMENTS_IN_INT_ARRAYLET);  
+      else                                           
+        arrayletIndex = FIRSTN_INT_ELEMS + ((index - FIRSTN_INT_ELEMS) >> LOG_ELEMENTS_IN_INT_ARRAYLET);                                                        
+      Offset offset = Offset.fromIntZeroExtend(arrayletIndex<<LOG_BYTES_IN_ADDRESS);                                                          
+      Address basePtr = array.toAddress().plus(offset);                                                           
+      base = basePtr.loadAddress();   
+      if (DO_COPY_ON_WRITE_REF_ARRAYS)
+    	  base = base.toWord().and(MemoryManagerConstants.ARRAYLET_TAINT_MASK).toAddress();
+      if (base.EQ(Magic.objectAsAddress(ObjectModel.zeroArraylet))) {
+        return ObjectReference.nullReference().toObject();  
+      }
+      if (DO_FIRSTN_OPT)                                                         
+        aIndex -= FIRSTN_INT_ELEMS;                                                                                                                
+      aIndex = aIndex & REF_ARRAYLET_MASK;                                                                                                           
+    } else if (DO_COLLECT_ARRAY_ACCESS_STATS) refRbFast++;
+    Offset offset = Offset.fromIntZeroExtend(aIndex << LOG_BYTES_IN_ADDRESS); 
+    return base.loadObjectReference(offset).toObject();
+  }  
+
+
+  /**
+   * Load a byte from an array
+   * 
+   * @param array The array object from which the byte is to be loaded
+   * @param index The array index from which the byte is to be loaded
+   * @return The value read
+   */  
+ @Entrypoint
+  public static byte arrayLoadPrimitiveByteReadBarrier(Object array, int index) {
+    if ((BOOT_IMAGE_IS_ARRAYLETIZED || ObjectReference.fromObject(array).toAddress().GE(HeapLayoutConstants.BOOT_IMAGE_DATA_END)) &&
+        (!DO_FIRSTN_OPT || (index >= FIRSTN_BYTE_ELEMS)))
+      return arrayletLoadByte(array, index);
+    else           {
+    	 if (DO_COLLECT_ARRAY_ACCESS_STATS) primRbFast++; 
+      return Magic.getByteAtOffset(array, Offset.fromIntZeroExtend(index << LOG_BYTES_IN_BYTE)); 
+    }
   }
 
   /**
+   * Perform an arrayletized load from a byte array.  This code must find the 
+   * appropriate arraylet and load the value from the appropriate slot within
+   * that arraylet.
+   * 
+   * @param array The array from which the load is to be made
+   * @param index The array index from which the byte is to be loaded
+   * @return The value read
+   */
+  private static byte arrayletLoadByte(Object array, int index) {
+	  if (DO_COLLECT_ARRAY_ACCESS_STATS) primRbSlow++;
+    int arrayletNumber = (index - FIRSTN_BYTE_ELEMS)>>LOG_ELEMENTS_IN_BYTE_ARRAYLET;
+    Offset arrayletPtrOffset = Offset.fromIntZeroExtend(FIRSTN_BYTE_BYTES + (arrayletNumber<<LOG_BYTES_IN_ADDRESS));
+    Address arraylet = Magic.getWordAtOffset(array, arrayletPtrOffset).toAddress();
+    if (MemoryManagerConstants.DO_COPY_ON_WRITE_BYTE_ARRAYS || MemoryManagerConstants.DO_COPY_ON_WRITE_BOOLEAN_ARRAYS) arraylet = arraylet.toWord().and(MemoryManagerConstants.ARRAYLET_TAINT_MASK).toAddress();
+    
+    if (DO_ZERO_ARRAYLET_RETURN_SHORTCUT && arraylet.EQ(Magic.objectAsAddress(ObjectModel.zeroArraylet)))
+      return 0;
+
+    int arrayletIndex = (index - FIRSTN_BYTE_ELEMS) & BYTE_ARRAYLET_MASK;
+    return arraylet.loadByte(Offset.fromIntZeroExtend(arrayletIndex<<LOG_BYTES_IN_BYTE));
+  }
+ 
+  /**
+   * Load a char from an array
+   * 
+   * @param array The array object from which the char is to be loaded
+   * @param index The array index from which the char is to be loaded
+   * @return The value read
+   */  
+ @Entrypoint
+  public static char arrayLoadPrimitiveCharReadBarrier(Object array, int index) {
+    if ((BOOT_IMAGE_IS_ARRAYLETIZED || ObjectReference.fromObject(array).toAddress().GE(HeapLayoutConstants.BOOT_IMAGE_DATA_END)) &&
+        (!DO_FIRSTN_OPT || (index >= FIRSTN_CHAR_ELEMS)))
+      return arrayletLoadChar(array, index);
+    else {
+    	if (DO_COLLECT_ARRAY_ACCESS_STATS) primRbFast++; 
+    	return Magic.getCharAtOffset(array, Offset.fromIntZeroExtend(index << LOG_BYTES_IN_CHAR));
+    }
+  }
+
+  /**
+   * Perform an arrayletized load from a char array.  This code must find the 
+   * appropriate arraylet and load the value from the appropriate slot within
+   * that arraylet.
+   * 
+   * @param array The array from which the load is to be made
+   * @param index The array index from which the char is to be loaded
+   * @return The value read
+   */
+  private static char arrayletLoadChar(Object array, int index) {
+	  if (DO_COLLECT_ARRAY_ACCESS_STATS) primRbSlow++; 
+    int arrayletNumber = (index - FIRSTN_CHAR_ELEMS)>>LOG_ELEMENTS_IN_CHAR_ARRAYLET;
+    Offset arrayletPtrOffset = Offset.fromIntZeroExtend(FIRSTN_CHAR_BYTES + (arrayletNumber<<LOG_BYTES_IN_ADDRESS));
+    Address arraylet = Magic.getWordAtOffset(array, arrayletPtrOffset).toAddress();
+    if (MemoryManagerConstants.DO_COPY_ON_WRITE_CHAR_ARRAYS) arraylet = arraylet.toWord().and(MemoryManagerConstants.ARRAYLET_TAINT_MASK).toAddress();
+    if (DO_ZERO_ARRAYLET_RETURN_SHORTCUT && arraylet.EQ(Magic.objectAsAddress(ObjectModel.zeroArraylet)))
+      return 0;
+
+    int arrayletIndex = (index - FIRSTN_CHAR_ELEMS) & CHAR_ARRAYLET_MASK;
+    return arraylet.loadChar(Offset.fromIntZeroExtend(arrayletIndex<<LOG_BYTES_IN_CHAR));
+  }
+ 
+  /**
+   * Load a short from an array
+   * 
+   * @param array The array object from which the short is to be loaded
+   * @param index The array index from which the short is to be loaded
+   * @return The value read
+   */  
+ @Entrypoint
+  public static short arrayLoadPrimitiveShortReadBarrier(Object array, int index) {
+    if ((BOOT_IMAGE_IS_ARRAYLETIZED || ObjectReference.fromObject(array).toAddress().GE(HeapLayoutConstants.BOOT_IMAGE_DATA_END)) &&
+        (!DO_FIRSTN_OPT || (index >= FIRSTN_SHORT_ELEMS)))
+      return arrayletLoadShort(array, index);
+    else {
+    	if (DO_COLLECT_ARRAY_ACCESS_STATS) primRbFast++; 
+     return Magic.getShortAtOffset(array, Offset.fromIntZeroExtend(index << LOG_BYTES_IN_SHORT));
+    }
+  }
+
+  /**
+   * Perform an arrayletized load from a short array.  This code must find the 
+   * appropriate arraylet and load the value from the appropriate slot within
+   * that arraylet.
+   * 
+   * @param array The array from which the load is to be made
+   * @param index The array index from which the short is to be loaded
+   * @return The value read
+   */
+  private static short arrayletLoadShort(Object array, int index) {
+	  if (DO_COLLECT_ARRAY_ACCESS_STATS) primRbSlow++; 
+    int arrayletNumber = (index - FIRSTN_SHORT_ELEMS)>>LOG_ELEMENTS_IN_SHORT_ARRAYLET;
+    Offset arrayletPtrOffset = Offset.fromIntZeroExtend(FIRSTN_SHORT_BYTES + (arrayletNumber<<LOG_BYTES_IN_ADDRESS));
+    Address arraylet = Magic.getWordAtOffset(array, arrayletPtrOffset).toAddress();
+    if (MemoryManagerConstants.DO_COPY_ON_WRITE_SHORT_ARRAYS || MemoryManagerConstants.DO_COPY_ON_WRITE_CHAR_ARRAYS) arraylet = arraylet.toWord().and(MemoryManagerConstants.ARRAYLET_TAINT_MASK).toAddress();
+    if (DO_ZERO_ARRAYLET_RETURN_SHORTCUT && arraylet.EQ(Magic.objectAsAddress(ObjectModel.zeroArraylet)))
+      return 0;
+
+    int arrayletIndex = (index - FIRSTN_SHORT_ELEMS) & SHORT_ARRAYLET_MASK;
+    return arraylet.loadShort(Offset.fromIntZeroExtend(arrayletIndex<<LOG_BYTES_IN_SHORT));
+  }
+ 
+  /**
+   * Load a int from an array
+   * 
+   * @param array The array object from which the int is to be loaded
+   * @param index The array index from which the int is to be loaded
+   * @return The value read
+   */  
+ @Entrypoint
+  public static int arrayLoadPrimitiveIntReadBarrier(Object array, int index) {
+   if (INSANITY) sanityCheckSpine(array);
+   if ((BOOT_IMAGE_IS_ARRAYLETIZED || ObjectReference.fromObject(array).toAddress().GE(HeapLayoutConstants.BOOT_IMAGE_DATA_END)) &&
+        (!DO_FIRSTN_OPT || (index >= FIRSTN_INT_ELEMS)))
+      return arrayletLoadInt(array, index);
+    else {
+    	if (DO_COLLECT_ARRAY_ACCESS_STATS) primRbFast++; 
+    	return Magic.getIntAtOffset(array, Offset.fromIntZeroExtend(index << LOG_BYTES_IN_INT));
+    }
+  }
+
+  /**
+   * Perform an arrayletized load from a int array.  This code must find the 
+   * appropriate arraylet and load the value from the appropriate slot within
+   * that arraylet.
+   * 
+   * @param array The array from which the load is to be made
+   * @param index The array index from which the int is to be loaded
+   * @return The value read
+   */
+  private static int arrayletLoadInt(Object array, int index) {
+	  if (DO_COLLECT_ARRAY_ACCESS_STATS) primRbSlow++; 
+    int arrayletNumber = (index - FIRSTN_INT_ELEMS)>>LOG_ELEMENTS_IN_INT_ARRAYLET;
+    Offset arrayletPtrOffset = Offset.fromIntZeroExtend(FIRSTN_INT_BYTES + (arrayletNumber<<LOG_BYTES_IN_ADDRESS));
+    Address arraylet = Magic.getWordAtOffset(array, arrayletPtrOffset).toAddress();
+    if (MemoryManagerConstants.DO_COPY_ON_WRITE_INT_ARRAYS) arraylet = arraylet.toWord().and(MemoryManagerConstants.ARRAYLET_TAINT_MASK).toAddress();
+    if (DO_ZERO_ARRAYLET_RETURN_SHORTCUT && arraylet.EQ(Magic.objectAsAddress(ObjectModel.zeroArraylet)))
+      return 0;
+
+    int arrayletIndex = (index - FIRSTN_INT_ELEMS) & INT_ARRAYLET_MASK;
+    return arraylet.loadInt(Offset.fromIntZeroExtend(arrayletIndex<<LOG_BYTES_IN_INT));
+  }
+ 
+  /**
+   * Load a float from an array
+   * 
+   * @param array The array object from which the float is to be loaded
+   * @param index The array index from which the float is to be loaded
+   * @return The value read
+   */  
+ @Entrypoint
+  public static float arrayLoadPrimitiveFloatReadBarrier(Object array, int index) {
+    if ((BOOT_IMAGE_IS_ARRAYLETIZED || ObjectReference.fromObject(array).toAddress().GE(HeapLayoutConstants.BOOT_IMAGE_DATA_END)) &&
+        (!DO_FIRSTN_OPT || (index >= FIRSTN_FLOAT_ELEMS)))
+      return arrayletLoadFloat(array, index);
+    else          {
+    	if (DO_COLLECT_ARRAY_ACCESS_STATS) primRbFast++;   
+      // return Magic.getFloatAtOffset(array, Offset.fromIntZeroExtend(index << LOG_BYTES_IN_FLOAT));
+      return ObjectReference.fromObject(array).toAddress().loadFloat(Offset.fromIntZeroExtend(index << LOG_BYTES_IN_FLOAT));
+    }
+  }
+
+  /**
+   * Perform an arrayletized load from a float array.  This code must find the 
+   * appropriate arraylet and load the value from the appropriate slot within
+   * that arraylet.
+   * 
+   * @param array The array from which the load is to be made
+   * @param index The array index from which the float is to be loaded
+   * @return The value read
+   */
+  private static float arrayletLoadFloat(Object array, int index) {
+	  if (DO_COLLECT_ARRAY_ACCESS_STATS) primRbSlow++; 
+    int arrayletNumber = (index - FIRSTN_FLOAT_ELEMS)>>LOG_ELEMENTS_IN_FLOAT_ARRAYLET;
+    Offset arrayletPtrOffset = Offset.fromIntZeroExtend(FIRSTN_FLOAT_BYTES + (arrayletNumber<<LOG_BYTES_IN_ADDRESS));
+    Address arraylet = Magic.getWordAtOffset(array, arrayletPtrOffset).toAddress();
+    if (MemoryManagerConstants.DO_COPY_ON_WRITE_FLOAT_ARRAYS) arraylet = arraylet.toWord().and(MemoryManagerConstants.ARRAYLET_TAINT_MASK).toAddress();
+    if (DO_ZERO_ARRAYLET_RETURN_SHORTCUT && arraylet.EQ(Magic.objectAsAddress(ObjectModel.zeroArraylet)))
+      return 0;
+
+    int arrayletIndex = (index - FIRSTN_FLOAT_ELEMS) & FLOAT_ARRAYLET_MASK;
+    return arraylet.loadFloat(Offset.fromIntZeroExtend(arrayletIndex<<LOG_BYTES_IN_FLOAT));
+  }
+ 
+  /**
+   * Load a double from an array
+   * 
+   * @param array The array object from which the double is to be loaded
+   * @param index The array index from which the double is to be loaded
+   * @return The value read
+   */  
+ @Entrypoint
+  public static double arrayLoadPrimitiveDoubleReadBarrier(Object array, int index) {
+    if ((BOOT_IMAGE_IS_ARRAYLETIZED || ObjectReference.fromObject(array).toAddress().GE(HeapLayoutConstants.BOOT_IMAGE_DATA_END)) &&
+        (!DO_FIRSTN_OPT || (index >= FIRSTN_DOUBLE_ELEMS)))
+      return arrayletLoadDouble(array, index);
+    else           {
+    	if (DO_COLLECT_ARRAY_ACCESS_STATS) primRbFast++; 
+    	return Magic.getDoubleAtOffset(array, Offset.fromIntZeroExtend(index << LOG_BYTES_IN_DOUBLE));
+    }
+  }
+
+  /**
+   * Perform an arrayletized load from a double array.  This code must find the 
+   * appropriate arraylet and load the value from the appropriate slot within
+   * that arraylet.
+   * 
+   * @param array The array from which the load is to be made
+   * @param index The array index from which the double is to be loaded
+   * @return The value read
+   */
+  private static double arrayletLoadDouble(Object array, int index) {
+	  if (DO_COLLECT_ARRAY_ACCESS_STATS) primRbSlow++; 
+    int arrayletNumber = (index - FIRSTN_DOUBLE_ELEMS)>>LOG_ELEMENTS_IN_DOUBLE_ARRAYLET;
+    Offset arrayletPtrOffset = Offset.fromIntZeroExtend(FIRSTN_DOUBLE_BYTES + (arrayletNumber<<LOG_BYTES_IN_ADDRESS));
+    Address arraylet = Magic.getWordAtOffset(array, arrayletPtrOffset).toAddress();
+    if (MemoryManagerConstants.DO_COPY_ON_WRITE_DOUBLE_ARRAYS) arraylet = arraylet.toWord().and(MemoryManagerConstants.ARRAYLET_TAINT_MASK).toAddress();
+    if (DO_ZERO_ARRAYLET_RETURN_SHORTCUT && arraylet.EQ(Magic.objectAsAddress(ObjectModel.zeroArraylet)))
+      return 0;
+
+    int arrayletIndex = (index - FIRSTN_DOUBLE_ELEMS) & DOUBLE_ARRAYLET_MASK;
+    return arraylet.loadDouble(Offset.fromIntZeroExtend(arrayletIndex<<LOG_BYTES_IN_DOUBLE));
+  }
+ 
+  /**
+   * Load a long from an array
+   * 
+   * @param array The array object from which the long is to be loaded
+   * @param index The array index from which the long is to be loaded
+   * @return The value read
+   */  
+ @Entrypoint
+  public static long arrayLoadPrimitiveLongReadBarrier(Object array, int index) {
+    if ((BOOT_IMAGE_IS_ARRAYLETIZED || ObjectReference.fromObject(array).toAddress().GE(HeapLayoutConstants.BOOT_IMAGE_DATA_END)) &&
+        (!DO_FIRSTN_OPT || (index >= FIRSTN_LONG_ELEMS)))
+      return arrayletLoadLong(array, index);
+    else      {
+    	if (DO_COLLECT_ARRAY_ACCESS_STATS) primRbFast++; 
+    	return Magic.getLongAtOffset(array, Offset.fromIntZeroExtend(index << LOG_BYTES_IN_LONG));
+    }
+  }
+
+  /**
+   * Perform an arrayletized load from a long array.  This code must find the 
+   * appropriate arraylet and load the value from the appropriate slot within
+   * that arraylet.
+   * 
+   * @param array The array from which the load is to be made
+   * @param index The array index from which the long is to be loaded
+   * @return The value read
+   */
+  private static long arrayletLoadLong(Object array, int index) {
+	  if (DO_COLLECT_ARRAY_ACCESS_STATS) primRbSlow++; 
+    int arrayletNumber = (index - FIRSTN_LONG_ELEMS)>>LOG_ELEMENTS_IN_LONG_ARRAYLET;
+    Offset arrayletPtrOffset = Offset.fromIntZeroExtend(FIRSTN_LONG_BYTES + (arrayletNumber<<LOG_BYTES_IN_ADDRESS));
+    Address arraylet = Magic.getWordAtOffset(array, arrayletPtrOffset).toAddress();
+    if (MemoryManagerConstants.DO_COPY_ON_WRITE_LONG_ARRAYS) arraylet = arraylet.toWord().and(MemoryManagerConstants.ARRAYLET_TAINT_MASK).toAddress();
+    if (DO_ZERO_ARRAYLET_RETURN_SHORTCUT && arraylet.EQ(Magic.objectAsAddress(ObjectModel.zeroArraylet)))
+      return 0;
+
+    int arrayletIndex = (index - FIRSTN_LONG_ELEMS) & LONG_ARRAYLET_MASK;
+    return arraylet.loadLong(Offset.fromIntZeroExtend(arrayletIndex<<LOG_BYTES_IN_LONG));
+  }
+
+
+  /**
    * Read barrier for getstatic operations.
    *
    * @param offset the offset of the field to be modified
@@ -550,7 +1486,7 @@
    * <code>b</code>
    */
   @Interruptible
-  private static boolean isPrefix(String a, byte[] b) {
+  public static boolean isPrefix(String a, byte[] b) {
     int aLen = a.length();
     if (aLen > b.length) {
       return false;
@@ -585,7 +1521,7 @@
       if (isPrefix("Lorg/jikesrvm/mm/mmtk/ReferenceProcessor", clsBA))
         return Plan.ALLOC_DEFAULT;
       if (isPrefix("Lorg/mmtk/", clsBA) ||
-          isPrefix("Lorg/jikesrvm/mm/", clsBA) ||
+          (isPrefix("Lorg/jikesrvm/mm/", clsBA) && !isPrefix("Lorg/jikesrvm/mm/mminterface/MemoryManager", clsBA))||
           isPrefix("Lorg/jikesrvm/mm/mminterface/GCMapIteratorGroup", clsBA)) {
         return Plan.ALLOC_IMMORTAL;
       }
@@ -655,6 +1591,7 @@
     Address region = allocateSpace(mutator, size, align, offset, allocator, site);
     Object result = ObjectModel.initializeScalar(region, tib, size);
     mutator.postAlloc(ObjectReference.fromObject(result), ObjectReference.fromObject(tib), size, allocator);
+    if (DO_COLLECT_SPACE_SAVING_STATS) {MemoryManagerConstants.NUM_ALLOC_BYTES_SCALAR += (size - ObjectModel.computeScalarHeaderSize(null)); }
     return result;
   }
 
@@ -664,7 +1601,7 @@
    *
    * @param numElements number of array elements
    * @param logElementSize size in bytes of an array element, log base 2.
-   * @param headerSize size in bytes of array header
+   * @param headerBytes size in bytes of array header
    * @param tib type information block for array object
    * @param allocator int that encodes which allocator should be used
    * @param align the alignment requested; must be a power of 2.
@@ -676,17 +1613,137 @@
    */
   @Inline
   @Unpreemptible
-  public static Object allocateArray(int numElements, int logElementSize, int headerSize, TIB tib, int allocator,
-                                     int align, int offset, int site) {
+  public static Object allocateArray(int numElements, int logElementSize, int headerBytes, TIB tib, int allocator,
+      int align, int offset, int site) {
     int elemBytes = numElements << logElementSize;
+    int requiredBytes = elemBytes + headerBytes;
+    int apparentBytes = requiredBytes;
     if ((elemBytes >>> logElementSize) != numElements) {
       /* asked to allocate more than Integer.MAX_VALUE bytes */
       throwLargeArrayOutOfMemoryError();
     }
-    int size = elemBytes + headerSize;
-    return allocateArrayInternal(numElements, size, tib, allocator, align, offset, site);
+    RVMArray type = tib.getType().asArray();
+    boolean arrayletize = type.isArrayletizable(); 
+    
+    if (DO_COLLECT_SPACE_SAVING_STATS) {
+    	if (type.getElementType().isPrimitiveType())  {
+    		NUM_ALLOC_ARRAYS++;
+    		NUM_ALLOC_BYTES_ARRAYS += elemBytes;
+    	}
+    	else if (type.getElementType().isReferenceType())  {
+    		NUM_ALLOC_REF_ARRAYS++;
+    		NUM_ALLOC_REF_BYTES_ARRAYS += elemBytes;
+    	}
+    }
+
+    int firstN = 0;
+    int arrayletCount = 0;
+    if (arrayletize) {
+      firstN = type.getFirstNElements();
+      int logArrayletElements = type.getLogArrayletElements();
+      int arrayletizedElements = numElements - firstN;
+      if (DO_COLLECT_SPACE_SAVING_STATS) {
+    	  if (type.getElementType().isPrimitiveType())  {
+    		  NUM_ALLOC_ARRAYLETIZABLE++;
+    		  NUM_ALLOC_BYTES_ARRAYLETIZABLE += elemBytes;
+    	  }
+    	  else if (type.getElementType().isReferenceType())  {
+    		  NUM_ALLOC_REF_ARRAYLETIZABLE++; 
+    		  NUM_ALLOC_REF_BYTES_ARRAYLETIZABLE += elemBytes;
+    	  }
+      }
+      if (arrayletizedElements > 0) {
+        arrayletCount =  arrayletizedElements >> logArrayletElements;
+        int arrayletBytes = (arrayletCount << LOG_ARRAYLET_BYTES);
+        requiredBytes -= arrayletBytes;  // we don't ask for this space now
+        arrayletCount++; //acount for dangling
+        int spineBytes = arrayletCount<<LOG_BYTES_IN_ADDRESS;
+        requiredBytes += spineBytes;     // we need to include this space
+        if (!DO_PRETENURE_LARGE_ARRAYS)
+          apparentBytes = requiredBytes;
+        if (DO_COLLECT_SPACE_SAVING_STATS) {
+        	if (type.getElementType().isPrimitiveType())  {
+        		NUM_ALLOC_ZRAYS++;
+        		NUM_ALLOC_BYTES_ZRAYS += elemBytes;
+        	}
+        	else if (type.getElementType().isReferenceType())  {
+        		NUM_ALLOC_REF_ZRAYS++;
+        		NUM_ALLOC_REF_BYTES_ZRAYS += elemBytes;
+        	}
+        }
+      }
+    }
+    
+    Object rtn = allocateArrayInternal(numElements, requiredBytes, tib, allocator, align, offset, site, apparentBytes);
+
+    if (arrayletCount > 0)
+      installArrayletPointers(rtn, firstN, logElementSize, arrayletCount);
+
+    return rtn;
+  }
+  
+  private static void installArrayletPointers(Object array, int firstN, int logElementSize, int arrayletCount) {
+    // install arraylet pointers
+    Offset spinePointerOffset = Offset.fromIntZeroExtend(firstN << logElementSize);
+    Address arraylet = Magic.objectAsAddress(ObjectModel.zeroArraylet);
+    for(int j = 0; j < arrayletCount - 1; j++) {
+      if (!DO_ARRAYLET_LAZY_ALLOC)
+        arraylet = arrayStoreAllocateArraylet(Gen.inNursery(array));
+      if (DO_COLLECT_SPACE_SAVING_STATS)
+        ARRAYLET_BYTES_REQUESTED += ARRAYLET_BYTES;
+      Magic.setWordAtOffset(array, spinePointerOffset, arraylet.toWord());
+      spinePointerOffset = spinePointerOffset.plus(BYTES_IN_ADDRESS);
+    }
+    Address dangling = ObjectReference.fromObject(array).toAddress().plus(spinePointerOffset.plus(BYTES_IN_ADDRESS));
+    Magic.setWordAtOffset(array, spinePointerOffset, dangling.toWord());
   }
 
+  private static final boolean INSANITY = false;
+  private static void sanityCheckSpine(Object o) {
+    RVMArray type = ObjectModel.getTIB(o).getType().asArray();
+    
+    int N = ObjectModel.getArrayLength(o);
+    int firstN = type.getFirstNElements();
+    int logES = type.getLogElementSize();
+    int logAE = type.getLogArrayletElements();
+    boolean inBI = !ObjectReference.fromObject(o).toAddress().GE(HeapLayoutConstants.BOOT_IMAGE_DATA_END);
+    
+    Address spineCursor = Magic.objectAsAddress(o).plus(firstN << logES);
+    int arrayletCount = (N-firstN) >> logAE;
+    
+    for(int i=0; i < arrayletCount; i++) {
+      Address arraylet = spineCursor.loadAddress();
+      boolean isZero =  arraylet.EQ(Magic.objectAsAddress(ObjectModel.zeroArraylet));
+      boolean isNull = arraylet.isZero();
+      boolean ainBI = !arraylet.GE(HeapLayoutConstants.BOOT_IMAGE_DATA_END);
+      boolean isArraylet = !isZero && !isNull && !inBI && Space.isInSpace(Plan.ARRAYLET, arraylet);
+      if (!(isZero || isNull || isArraylet || inBI && ainBI)) {
+        VM.sysWriteln(Magic.objectAsAddress(o));
+        VM.sysWriteln(arraylet);
+        DebugUtil.dumpRef(ObjectReference.fromObject(o));
+        DebugUtil.dumpRef(arraylet.toObjectReference());
+        VM._assert(false);
+      }
+      spineCursor = spineCursor.plus(BYTES_IN_ADDRESS);
+    }
+
+    if (N >= firstN){
+      if (!inBI) {
+        Address dangla = spineCursor.loadAddress();
+        if (!dangla.isZero()) {
+          if (dangla.NE(spineCursor.plus(BYTES_IN_ADDRESS))) {
+            VM.sysWriteln(Magic.objectAsAddress(o));
+            VM.sysWriteln(dangla);
+            DebugUtil.dumpRef(ObjectReference.fromObject(o));
+          }
+          VM._assert(dangla.EQ(spineCursor.plus(BYTES_IN_ADDRESS)));
+        }
+      } else {
+        VM._assert(!spineCursor.loadAddress().GE(HeapLayoutConstants.BOOT_IMAGE_DATA_END));
+        VM._assert(!spineCursor.loadAddress().LT(HeapLayoutConstants.BOOT_IMAGE_DATA_START));
+      }
+    }
+  }
 
   /**
    * Throw an out of memory error due to an array allocation request that is
@@ -703,7 +1760,7 @@
    * Allocate an array object.
    *
    * @param numElements The number of element bytes
-   * @param size size in bytes of array header
+   * @param bytes size in bytes of array header
    * @param tib type information block for array object
    * @param allocator int that encodes which allocator should be used
    * @param align the alignment requested; must be a power of 2.
@@ -714,13 +1771,13 @@
    * See also: bytecode 0xbc ("newarray") and 0xbd ("anewarray")
    */
   @Inline
-  private static Object allocateArrayInternal(int numElements, int size, TIB tib, int allocator,
-                                              int align, int offset, int site) {
+  private static Object allocateArrayInternal(int numElements, int bytes, TIB tib, int allocator,
+                                              int align, int offset, int site, int requestedBytes) {
     Selected.Mutator mutator = Selected.Mutator.get();
-    allocator = mutator.checkAllocator(org.jikesrvm.runtime.Memory.alignUp(size, MIN_ALIGNMENT), align, allocator);
-    Address region = allocateSpace(mutator, size, align, offset, allocator, site);
-    Object result = ObjectModel.initializeArray(region, tib, numElements, size);
-    mutator.postAlloc(ObjectReference.fromObject(result), ObjectReference.fromObject(tib), size, allocator);
+    allocator = mutator.checkAllocator(org.jikesrvm.runtime.Memory.alignUp(requestedBytes, MIN_ALIGNMENT), align, allocator);
+    Address region = allocateSpace(mutator, bytes, align, offset, allocator, site);
+    Object result = ObjectModel.initializeArray(region, tib, numElements, bytes);
+    mutator.postAlloc(ObjectReference.fromObject(result), ObjectReference.fromObject(tib), bytes, allocator);
     return result;
   }
 
@@ -746,7 +1803,7 @@
     region = mutator.alloc(bytes, align, offset, allocator, site);
 
     /* TODO: if (Stats.GATHER_MARK_CONS_STATS) Plan.cons.inc(bytes); */
-    if (CHECK_MEMORY_IS_ZEROED) Memory.assertIsZeroed(region, bytes);
+    if (CHECK_MEMORY_IS_ZEROED) org.mmtk.utility.Memory.assertIsZeroed(region, bytes);
 
     return region;
   }
@@ -772,7 +1829,7 @@
     region = collector.allocCopy(from, bytes, align, offset, allocator);
 
     /* TODO: if (Stats.GATHER_MARK_CONS_STATS) Plan.mark.inc(bytes); */
-    if (CHECK_MEMORY_IS_ZEROED) Memory.assertIsZeroed(region, bytes);
+    if (CHECK_MEMORY_IS_ZEROED) org.mmtk.utility.Memory.assertIsZeroed(region, bytes);
 
     return region;
   }
@@ -826,18 +1883,18 @@
    */
   @Inline
   @Unpreemptible
-  public static byte[] newStack(int bytes, boolean immortal) {
+  public static WordArray newStack(int bytes, boolean immortal) {
     if (!VM.runningVM) {
-      return new byte[bytes];
+      return createNativeByteBuffer(bytes);
     } else {
-      RVMArray stackType = RVMArray.ByteArray;
+      RVMArray stackType = RVMArray.WordArray;
       int headerSize = ObjectModel.computeArrayHeaderSize(stackType);
       int align = ObjectModel.getAlignment(stackType);
       int offset = ObjectModel.getOffsetForAlignment(stackType, false);
       int width = stackType.getLogElementSize();
       TIB stackTib = stackType.getTypeInformationBlock();
 
-      return (byte[]) allocateArray(bytes,
+      return (WordArray) allocateArray((bytes + (BYTES_IN_WORD - 1)) >> LOG_BYTES_IN_WORD,
                                     width,
                                     headerSize,
                                     stackTib,
@@ -1082,6 +2139,130 @@
     ObjectModel.setTIB(array, realTib);
     return array;
   }
+  
+  @Inline
+  @Unpreemptible
+  public static WordArray createNativeByteBuffer(int size) {
+    return WordArray.create((size + (BYTES_IN_WORD - 1)) >> LOG_BYTES_IN_WORD);
+  }
+
+  @Inline
+  @Interruptible
+  public static WordArray cloneToNativeBuffer(byte[] value) {
+    WordArray rtn = WordArray.create((value.length + (BYTES_IN_WORD - 1)) >> LOG_BYTES_IN_WORD);
+    Memory.nativeMarshal(value, rtn);
+    return rtn;
+  }
+  
+  @Inline
+  @Interruptible
+  public static byte[] getByteArray(WordArray value) {
+    byte[] rtn = new byte[nativeByteBufferLength(value)];
+    Memory.nativeMarshal(value, rtn);
+    return rtn;
+  }
+  
+  @Inline
+  @Unpreemptible
+  public static WordArray createNativeCharBuffer(int size) {
+    return WordArray.create((size + ((BYTES_IN_WORD >> 1) - 1)) >> (LOG_BYTES_IN_WORD - 1));
+  }
+
+  @Inline
+  @Unpreemptible
+  public static WordArray createNativeIntBuffer(int size) {
+    return WordArray.create((size + ((BYTES_IN_WORD >> 2) - 1)) >> (LOG_BYTES_IN_WORD - 2));
+  }
+
+  @Inline
+  @Interruptible
+  public static WordArray cloneToNativeBuffer(int[] value) {
+    WordArray rtn = WordArray.create((value.length + ((BYTES_IN_WORD >> 2) - 1)) >> (LOG_BYTES_IN_WORD - 2));
+    Memory.nativeMarshal(value, rtn);
+    return rtn;
+  }
+
+  @Inline
+  @Interruptible
+  public static int[] getIntArray(WordArray value) {
+    int[] rtn = new int[nativeIntBufferLength(value)];
+    Memory.nativeMarshal(value, rtn);
+    return rtn;
+  }
+
+  @Inline
+  @Unpreemptible
+  public static WordArray createNativeLongBuffer(int size) {
+    if (VM.VerifyAssertions) VM._assert(LOG_BYTES_IN_LONG >= LOG_BYTES_IN_WORD);
+    return WordArray.create(size << (LOG_BYTES_IN_LONG - LOG_BYTES_IN_WORD));
+  }
+
+  @Inline
+  @Interruptible
+  public static WordArray createNativeBuffer(long[] value) {
+    if (VM.VerifyAssertions) VM._assert(LOG_BYTES_IN_LONG >= LOG_BYTES_IN_WORD);
+    WordArray rtn = WordArray.create(value.length << (LOG_BYTES_IN_LONG - LOG_BYTES_IN_WORD));
+    Memory.nativeMarshal(value, rtn);
+    return rtn;
+  }
+
+  @Inline
+  @Interruptible
+  public static long[] getLongArray(WordArray value) {
+    long[] rtn = new long[nativeLongBufferLength(value)];
+    Memory.nativeMarshal(value, rtn);
+    return rtn;
+  }
+
+  @Inline
+  @Unpreemptible
+  @NonMovingAllocation
+  public static WordArray createNonMovingNativeByteBuffer(int size) {
+    return WordArray.create((size + (BYTES_IN_WORD - 1)) >> LOG_BYTES_IN_WORD);
+  }
+
+  @Inline
+  @Unpreemptible
+  @NonMovingAllocation
+  public static WordArray createNonMovingNativeCharBuffer(int size) {
+    return WordArray.create((size + ((BYTES_IN_WORD >> 1) - 1)) >> (LOG_BYTES_IN_WORD - 1));
+  }
+
+  @Inline
+  @Unpreemptible
+  @NonMovingAllocation
+  public static WordArray createNonMovingNativeIntBuffer(int size) {
+    return WordArray.create((size + ((BYTES_IN_WORD >> 2) - 1)) >> (LOG_BYTES_IN_WORD - 2));
+  }
+
+  @Inline
+  @Unpreemptible
+  @NonMovingAllocation
+  public static WordArray createNonMovingNativeLongBuffer(int size) {
+    if (VM.VerifyAssertions) VM._assert(LOG_BYTES_IN_LONG >= LOG_BYTES_IN_WORD);
+    return WordArray.create(size << (LOG_BYTES_IN_LONG - LOG_BYTES_IN_WORD));
+  }
+
+  @Inline
+  public static int nativeByteBufferLength(WordArray wa) {
+    return wa.length() << LOG_BYTES_IN_WORD;
+  }
+
+  @Inline
+  public static int nativeCharBufferLength(WordArray wa) {
+    return wa.length() << (LOG_BYTES_IN_WORD - 1);
+  }
+
+  @Inline
+  public static int nativeIntBufferLength(WordArray wa) {
+    return wa.length() << (LOG_BYTES_IN_WORD - 2);
+  }
+  
+  @Inline
+  public static int nativeLongBufferLength(WordArray wa) {
+    if (VM.VerifyAssertions) VM._assert(LOG_BYTES_IN_LONG >= LOG_BYTES_IN_WORD);
+    return wa.length() >>> (LOG_BYTES_IN_LONG - LOG_BYTES_IN_WORD);
+  }
 
   /**
    *  Will this object move (allows us to optimize some JNI calls)
@@ -1305,16 +2486,5 @@
     return Space.MAX_SPACES;
   }
 
-  /**
-   * Allocate a contiguous int array
-   * @param n The number of ints
-   * @return The contiguous int array
-   */
-  @Inline
-  @Interruptible
-  public static int[] newContiguousIntArray(int n) {
-    return new int[n];
-  }
-
 }
 
diff -r 743a2cc2ed20 -r 058fdc3780ba rvm/src/org/jikesrvm/mm/mminterface/MemoryManagerConstants.java
--- a/rvm/src/org/jikesrvm/mm/mminterface/MemoryManagerConstants.java	Tue Aug 04 11:04:15 2009 +1000
+++ b/rvm/src/org/jikesrvm/mm/mminterface/MemoryManagerConstants.java	Mon Nov 16 09:21:21 2009 +1100
@@ -13,6 +13,9 @@
 package org.jikesrvm.mm.mminterface;
 
 import org.jikesrvm.SizeConstants;
+import org.mmtk.policy.MarkSweepSpace; //jbs added
+import org.vmmagic.unboxed.Word; //jbs added
+import org.mmtk.utility.statistics.EventCounter;
 
 /**
  * This class merely exposes the MMTk constants into the Jikes RVM
@@ -48,5 +51,224 @@
   /** True if the selected plan moves code */
   public static final boolean MOVES_CODE = false;
 
+  public static final boolean USE_ARRAYLETS = true;   // not sure this works if false    
+
+  public static final boolean USE_REFERENCE_ARRAYLETS         = true;
+  public static final boolean USE_PRIMITIVE_BYTE_ARRAYLETS    = true;
+  public static final boolean USE_PRIMITIVE_SHORT_ARRAYLETS   = true;
+  public static final boolean USE_PRIMITIVE_CHAR_ARRAYLETS    = true;
+  public static final boolean USE_PRIMITIVE_INT_ARRAYLETS     = true;
+  public static final boolean USE_PRIMITIVE_FLOAT_ARRAYLETS   = true;
+  public static final boolean USE_PRIMITIVE_LONG_ARRAYLETS    = true;
+  public static final boolean USE_PRIMITIVE_DOUBLE_ARRAYLETS  = true;
+  public static final boolean USE_PRIMITIVE_BOOLEAN_ARRAYLETS = USE_PRIMITIVE_BYTE_ARRAYLETS;
+  public static final boolean USE_PRIMITIVE_ARRAYLETS = USE_PRIMITIVE_SHORT_ARRAYLETS || USE_PRIMITIVE_LONG_ARRAYLETS || USE_PRIMITIVE_DOUBLE_ARRAYLETS || USE_PRIMITIVE_FLOAT_ARRAYLETS || USE_PRIMITIVE_BOOLEAN_ARRAYLETS || USE_PRIMITIVE_BYTE_ARRAYLETS || USE_PRIMITIVE_CHAR_ARRAYLETS || USE_PRIMITIVE_INT_ARRAYLETS;
+
+  /* Key configuration and optimization parameters */
+  public static final int     LOG_ARRAYLET_BYTES            = 10; //7; //8;//12;
+  public static final int     LOG_DEFAULT_FIRSTN_BYTES      = 12; //7; //12;
+
+  public static final boolean DO_FIRSTN_OPT                    = true;
+  public static final boolean DO_ARRAYLET_LAZY_ALLOC           = true; 
+  public static final boolean DO_ZERO_ARRAY_COMPRESSION        = true;
+  public static final boolean FAST_ARRAY_COPY                  = true;
+  public static final boolean DO_COPY_ON_WRITE_ALLTYPES_ARRAYS = false;
+
+  public static final boolean PERFORM_ZERO_ARRAYLET_ARRAYCOPY_OPT = DO_COPY_ON_WRITE_ALLTYPES_ARRAYS && true; //working - to measure need STATS on too
+  public static final boolean ENABLE_COW_ARRAYLET_INCOMING_PTR =  DO_COPY_ON_WRITE_ALLTYPES_ARRAYS && false;
+
+  public static final boolean INLINE_BASELINE_READ_BARRIERS = false; //for COW and access_stats this needs to be false
+  public static final boolean BOOT_IMAGE_IS_ARRAYLETIZED    = true;  
+  public static final boolean DO_PRETENURE_LARGE_ARRAYS     = false;  //no longer supported
+  public static final boolean DO_COLLECT_SPACE_SAVING_STATS = false;
+  public static final boolean DO_COLLECT_ARRAY_ACCESS_STATS = false;
+  
+  /* Derived parameters */
+  public static final int DEFAULT_FIRSTN_BYTES = !DO_FIRSTN_OPT ? 0 : 1 << LOG_DEFAULT_FIRSTN_BYTES;
+  public static final boolean USE_ZERO_ARRAYLETS = DO_ZERO_ARRAY_COMPRESSION || DO_ARRAYLET_LAZY_ALLOC;
+  public static final boolean DO_ZERO_ARRAYLET_RETURN_SHORTCUT = false && USE_ZERO_ARRAYLETS; 
+  public static final boolean INLINE_BASELINE_REFERENCE_READ_BARRIER = INLINE_BASELINE_READ_BARRIERS && USE_REFERENCE_ARRAYLETS;
+  public static final boolean INLINE_BASELINE_INT_READ_BARRIER = INLINE_BASELINE_READ_BARRIERS && USE_PRIMITIVE_INT_ARRAYLETS;
+  public static final boolean INLINE_BASELINE_CHAR_READ_BARRIER = INLINE_BASELINE_READ_BARRIERS && (USE_PRIMITIVE_CHAR_ARRAYLETS || USE_PRIMITIVE_SHORT_ARRAYLETS);
+  public static final boolean INLINE_BASELINE_BOOL_READ_BARRIER = INLINE_BASELINE_READ_BARRIERS && (USE_PRIMITIVE_BYTE_ARRAYLETS || USE_PRIMITIVE_BOOLEAN_ARRAYLETS);
+  public static final boolean INLINE_BASELINE_INT_WRITE_BARRIER = USE_PRIMITIVE_INT_ARRAYLETS && false;  //jbs not currently working
+  public static final boolean USE_OBJECT_ARRAY_ACCESS_BARRIER = USE_REFERENCE_ARRAYLETS && true; 
+  public static final boolean USE_OBJECT_ARRAY_ACCESS_BARRIER_ON_EDGE_COUNTS = true && USE_OBJECT_ARRAY_ACCESS_BARRIER;                    
+
+  public static final int ARRAYLET_BYTES = 1 << LOG_ARRAYLET_BYTES;
+  
+  public static final int FIRSTN_REF_ELEMS     = DEFAULT_FIRSTN_BYTES >> LOG_BYTES_IN_ADDRESS;
+  public static final int FIRSTN_BOOLEAN_ELEMS = DEFAULT_FIRSTN_BYTES >> LOG_BYTES_IN_BOOLEAN;
+  public static final int FIRSTN_BYTE_ELEMS    = DEFAULT_FIRSTN_BYTES >> LOG_BYTES_IN_BYTE;
+  public static final int FIRSTN_CHAR_ELEMS    = DEFAULT_FIRSTN_BYTES >> LOG_BYTES_IN_CHAR;
+  public static final int FIRSTN_SHORT_ELEMS   = DEFAULT_FIRSTN_BYTES >> LOG_BYTES_IN_SHORT;
+  public static final int FIRSTN_INT_ELEMS     = DEFAULT_FIRSTN_BYTES >> LOG_BYTES_IN_INT;
+  public static final int FIRSTN_FLOAT_ELEMS   = DEFAULT_FIRSTN_BYTES >> LOG_BYTES_IN_FLOAT;
+  public static final int FIRSTN_DOUBLE_ELEMS  = DEFAULT_FIRSTN_BYTES >> LOG_BYTES_IN_DOUBLE;
+  public static final int FIRSTN_LONG_ELEMS    = DEFAULT_FIRSTN_BYTES >> LOG_BYTES_IN_LONG;
+
+  public static final int FIRSTN_REF_BYTES     = FIRSTN_REF_ELEMS << LOG_BYTES_IN_ADDRESS;
+  public static final int FIRSTN_BOOLEAN_BYTES = FIRSTN_BOOLEAN_ELEMS << LOG_BYTES_IN_BOOLEAN;
+  public static final int FIRSTN_BYTE_BYTES    = FIRSTN_BYTE_ELEMS << LOG_BYTES_IN_BYTE;
+  public static final int FIRSTN_CHAR_BYTES    = FIRSTN_CHAR_ELEMS << LOG_BYTES_IN_CHAR;
+  public static final int FIRSTN_SHORT_BYTES   = FIRSTN_SHORT_ELEMS << LOG_BYTES_IN_SHORT;
+  public static final int FIRSTN_INT_BYTES     = FIRSTN_INT_ELEMS << LOG_BYTES_IN_INT;
+  public static final int FIRSTN_FLOAT_BYTES   = FIRSTN_FLOAT_ELEMS << LOG_BYTES_IN_FLOAT;
+  public static final int FIRSTN_DOUBLE_BYTES  = FIRSTN_DOUBLE_ELEMS << LOG_BYTES_IN_DOUBLE;
+  public static final int FIRSTN_LONG_BYTES    = FIRSTN_LONG_ELEMS << LOG_BYTES_IN_LONG;
+
+  public static final int LOG_ELEMENTS_IN_REF_ARRAYLET     = LOG_ARRAYLET_BYTES - LOG_BYTES_IN_ADDRESS;
+  public static final int LOG_ELEMENTS_IN_BOOLEAN_ARRAYLET = LOG_ARRAYLET_BYTES - LOG_BYTES_IN_BOOLEAN;
+  public static final int LOG_ELEMENTS_IN_BYTE_ARRAYLET    = LOG_ARRAYLET_BYTES - LOG_BYTES_IN_BYTE;
+  public static final int LOG_ELEMENTS_IN_CHAR_ARRAYLET    = LOG_ARRAYLET_BYTES - LOG_BYTES_IN_CHAR;
+  public static final int LOG_ELEMENTS_IN_SHORT_ARRAYLET   = LOG_ARRAYLET_BYTES - LOG_BYTES_IN_SHORT;
+  public static final int LOG_ELEMENTS_IN_INT_ARRAYLET     = LOG_ARRAYLET_BYTES - LOG_BYTES_IN_INT;
+  public static final int LOG_ELEMENTS_IN_FLOAT_ARRAYLET   = LOG_ARRAYLET_BYTES - LOG_BYTES_IN_FLOAT;
+  public static final int LOG_ELEMENTS_IN_DOUBLE_ARRAYLET  = LOG_ARRAYLET_BYTES - LOG_BYTES_IN_DOUBLE;
+  public static final int LOG_ELEMENTS_IN_LONG_ARRAYLET    = LOG_ARRAYLET_BYTES - LOG_BYTES_IN_LONG;
+  
+  public static final int ELEMENTS_IN_REF_ARRAYLET     = 1 << LOG_ELEMENTS_IN_REF_ARRAYLET;
+  public static final int ELEMENTS_IN_BOOLEAN_ARRAYLET = 1 << LOG_ELEMENTS_IN_BOOLEAN_ARRAYLET;
+  public static final int ELEMENTS_IN_BYTE_ARRAYLET    = 1 << LOG_ELEMENTS_IN_BYTE_ARRAYLET;
+  public static final int ELEMENTS_IN_CHAR_ARRAYLET    = 1 << LOG_ELEMENTS_IN_CHAR_ARRAYLET;
+  public static final int ELEMENTS_IN_SHORT_ARRAYLET   = 1 << LOG_ELEMENTS_IN_SHORT_ARRAYLET;
+  public static final int ELEMENTS_IN_INT_ARRAYLET     = 1 << LOG_ELEMENTS_IN_INT_ARRAYLET;
+  public static final int ELEMENTS_IN_FLOAT_ARRAYLET   = 1 << LOG_ELEMENTS_IN_FLOAT_ARRAYLET;
+  public static final int ELEMENTS_IN_DOUBLE_ARRAYLET  = 1 << LOG_ELEMENTS_IN_DOUBLE_ARRAYLET;
+  public static final int ELEMENTS_IN_LONG_ARRAYLET    = 1 << LOG_ELEMENTS_IN_LONG_ARRAYLET;
+
+  public static final int REF_ARRAYLET_MASK     = ELEMENTS_IN_REF_ARRAYLET - 1;
+  public static final int BOOLEAN_ARRAYLET_MASK = ELEMENTS_IN_BOOLEAN_ARRAYLET - 1;
+  public static final int BYTE_ARRAYLET_MASK    = ELEMENTS_IN_BYTE_ARRAYLET - 1;
+  public static final int CHAR_ARRAYLET_MASK    = ELEMENTS_IN_CHAR_ARRAYLET - 1;
+  public static final int SHORT_ARRAYLET_MASK   = ELEMENTS_IN_SHORT_ARRAYLET - 1;
+  public static final int INT_ARRAYLET_MASK     = ELEMENTS_IN_INT_ARRAYLET - 1;
+  public static final int FLOAT_ARRAYLET_MASK   = ELEMENTS_IN_FLOAT_ARRAYLET - 1;
+  public static final int DOUBLE_ARRAYLET_MASK  = ELEMENTS_IN_DOUBLE_ARRAYLET - 1;
+  public static final int LONG_ARRAYLET_MASK    = ELEMENTS_IN_LONG_ARRAYLET - 1;
+
+  public static final int CONTIG_ARRAY_HEADER_BIT = MarkSweepSpace.LOCAL_GC_BITS_REQUIRED + 1;
+  public static final Word ARRAYLET_TAINT_WORD = Word.one();
+  public static final Word ARRAYLET_TAINT_MASK = ARRAYLET_TAINT_WORD.not();
+  //Kept track of in RVMArray and MemoryManager, printed in Statistics
+  
+  public static final boolean DO_COPY_ON_WRITE_BYTE_ARRAYS = DO_COPY_ON_WRITE_ALLTYPES_ARRAYS && true;
+  public static final boolean DO_COPY_ON_WRITE_SHORT_ARRAYS = DO_COPY_ON_WRITE_ALLTYPES_ARRAYS && true;
+  public static final boolean DO_COPY_ON_WRITE_INT_ARRAYS = DO_COPY_ON_WRITE_ALLTYPES_ARRAYS && true;
+  public static final boolean DO_COPY_ON_WRITE_CHAR_ARRAYS = DO_COPY_ON_WRITE_ALLTYPES_ARRAYS && true;
+  public static final boolean DO_COPY_ON_WRITE_REF_ARRAYS = DO_COPY_ON_WRITE_ALLTYPES_ARRAYS && true;
+  public static final boolean DO_COPY_ON_WRITE_FLOAT_ARRAYS = DO_COPY_ON_WRITE_ALLTYPES_ARRAYS && true;
+  public static final boolean DO_COPY_ON_WRITE_DOUBLE_ARRAYS = DO_COPY_ON_WRITE_ALLTYPES_ARRAYS && true;
+  public static final boolean DO_COPY_ON_WRITE_LONG_ARRAYS = DO_COPY_ON_WRITE_ALLTYPES_ARRAYS && true;
+  public static final boolean DO_COPY_ON_WRITE_BOOLEAN_ARRAYS = DO_COPY_ON_WRITE_ALLTYPES_ARRAYS && DO_COPY_ON_WRITE_BYTE_ARRAYS && true;
+  
+  public static final boolean DO_ANY_COPY_ON_WRITE_ARRAYS = DO_COPY_ON_WRITE_BYTE_ARRAYS || DO_COPY_ON_WRITE_SHORT_ARRAYS || 
+  DO_COPY_ON_WRITE_INT_ARRAYS || DO_COPY_ON_WRITE_CHAR_ARRAYS || DO_COPY_ON_WRITE_REF_ARRAYS || 
+  DO_COPY_ON_WRITE_FLOAT_ARRAYS || DO_COPY_ON_WRITE_DOUBLE_ARRAYS || DO_COPY_ON_WRITE_LONG_ARRAYS || DO_COPY_ON_WRITE_BOOLEAN_ARRAYS;
+  
+  public static final boolean DO_COLLECT_REF_COPY_ON_WRITE_STATS = DO_COLLECT_SPACE_SAVING_STATS && DO_COPY_ON_WRITE_REF_ARRAYS && true;
+  //public static final boolean DO_COLLECT_PRIM_COPY_ON_WRITE_STATS = DO_COLLECT_SPACE_SAVING_STATS && false;
+  public static final boolean DO_COLLECT_PRIMBYTE_COPY_ON_WRITE_STATS = DO_COLLECT_SPACE_SAVING_STATS && DO_COPY_ON_WRITE_BYTE_ARRAYS && true;
+  public static final boolean DO_COLLECT_PRIMBOOLEAN_COPY_ON_WRITE_STATS = DO_COLLECT_SPACE_SAVING_STATS && DO_COPY_ON_WRITE_BOOLEAN_ARRAYS && true;
+  public static final boolean DO_COLLECT_PRIMFLOAT_COPY_ON_WRITE_STATS = DO_COLLECT_SPACE_SAVING_STATS && DO_COPY_ON_WRITE_FLOAT_ARRAYS && true;
+  public static final boolean DO_COLLECT_PRIMLONG_COPY_ON_WRITE_STATS = DO_COLLECT_SPACE_SAVING_STATS && DO_COPY_ON_WRITE_LONG_ARRAYS && true;
+  public static final boolean DO_COLLECT_PRIMDOUBLE_COPY_ON_WRITE_STATS = DO_COLLECT_SPACE_SAVING_STATS && DO_COPY_ON_WRITE_DOUBLE_ARRAYS && true;
+  public static final boolean DO_COLLECT_PRIMCHAR_COPY_ON_WRITE_STATS = DO_COLLECT_SPACE_SAVING_STATS && DO_COPY_ON_WRITE_CHAR_ARRAYS && true;
+  public static final boolean DO_COLLECT_PRIMSHORT_COPY_ON_WRITE_STATS = DO_COLLECT_SPACE_SAVING_STATS && DO_COPY_ON_WRITE_SHORT_ARRAYS && true;
+  public static final boolean DO_COLLECT_PRIMINT_COPY_ON_WRITE_STATS = DO_COLLECT_SPACE_SAVING_STATS && DO_COPY_ON_WRITE_INT_ARRAYS && true;  
+  
+  public static int NUM_ZERO_ARRAYLET_ARRAYCOPY_OPT = 0;
+  public static int NUM_REF_ZERO_ARRAYLET_ARRAYCOPY_OPT = 0;
+  
+  public static int NUM_BYTE_ARRAYLETS_SHARED = 0;
+  public static int NUM_BYTE_ARRAYLETS_COPY_ON_WRITE = 0;
+  public static int NUM_CHAR_ARRAYLETS_SHARED = 0;
+  public static int NUM_CHAR_ARRAYLETS_COPY_ON_WRITE = 0;
+  public static int NUM_SHORT_ARRAYLETS_SHARED = 0;
+  public static int NUM_SHORT_ARRAYLETS_COPY_ON_WRITE = 0;
+  public static int NUM_INT_ARRAYLETS_SHARED = 0;
+  public static int NUM_INT_ARRAYLETS_COPY_ON_WRITE = 0;
+  public static int NUM_BYTE_ARRAYS_BYTES_COPIED = 0;
+  public static long NUM_CHAR_ARRAYS_BYTES_COPIED = 0;
+  public static int NUM_SHORT_ARRAYS_BYTES_COPIED = 0;
+  public static int NUM_INT_ARRAYS_BYTES_COPIED = 0;
+  public static int NUM_REF_ARRAYLETS_SHARED = 0;
+  public static int NUM_REF_ARRAYLETS_COPY_ON_WRITE = 0;
+  
+  public static int NUM_BOOLEAN_ARRAYLETS_SHARED = 0;
+  public static int NUM_BOOLEAN_ARRAYLETS_COPY_ON_WRITE = 0;
+  public static int NUM_BOOLEAN_ARRAYS_BYTES_COPIED = 0;
+  public static int NUM_FLOAT_ARRAYLETS_SHARED = 0;
+  public static int NUM_FLOAT_ARRAYLETS_COPY_ON_WRITE = 0;
+  public static int NUM_FLOAT_ARRAYS_BYTES_COPIED = 0;
+  public static int NUM_DOUBLE_ARRAYLETS_SHARED = 0;
+  public static int NUM_DOUBLE_ARRAYLETS_COPY_ON_WRITE = 0;
+  public static int NUM_DOUBLE_ARRAYS_BYTES_COPIED = 0;
+  public static int NUM_LONG_ARRAYLETS_SHARED = 0;
+  public static int NUM_LONG_ARRAYLETS_COPY_ON_WRITE = 0;
+  public static int NUM_LONG_ARRAYS_BYTES_COPIED = 0;
+  
+//jbs added	
+  public static long primWbFast = 0;
+  public static long primWbSlow = 0;
+  public static long primRbFast = 0;
+  public static long primRbSlow = 0;
+  public static long refWbFast = 0;
+  public static long refWbSlow = 0;
+  public static long refRbFast = 0;
+  public static long refRbSlow = 0;
+  
+  // Below here, unsure if we want to keep?
+  //Below 12 are all modified at allocation time in MemoryManager.allocateArray(), printed in Statistics
+  public static int NUM_ALLOC_ARRAYS = 0;
+  public static int NUM_ALLOC_ARRAYLETIZABLE = 0;
+  public static int NUM_ALLOC_ZRAYS = 0;
+  public static int NUM_ALLOC_REF_ARRAYS = 0;
+  public static int NUM_ALLOC_REF_ARRAYLETIZABLE = 0;
+  public static int NUM_ALLOC_REF_ZRAYS = 0;
+  
+  public static long NUM_ALLOC_BYTES_ARRAYS = 0;
+  public static long NUM_ALLOC_BYTES_ARRAYLETIZABLE = 0;
+  public static long NUM_ALLOC_BYTES_ZRAYS = 0;
+  public static long NUM_ALLOC_REF_BYTES_ARRAYS = 0;
+  public static long NUM_ALLOC_REF_BYTES_ARRAYLETIZABLE = 0;
+  public static long NUM_ALLOC_REF_BYTES_ZRAYS = 0;
+  public static long NUM_ALLOC_BYTES_SCALAR = 0;
+  
+  //These next 10 kept track of in SpecializedScanMethod, printed in ObjectModel.
+  public static int NUM_GC_SPINE_BYTES = 0;
+  public static int NUM_GC_ARRAYLET_BYTES = 0;
+  public static int NUM_GC_ARRAYLETIZED_BYTES = 0;
+  public static int NUM_GC_ZERO_ARRAYLET_BYTES = 0;
+  public static int ZERO_ARRAYLET_AT_GC = 0;
+  public static int NUM_GC_REF_SPINE_BYTES = 0;
+  public static int NUM_GC_REF_ARRAYLET_BYTES = 0;
+  public static int NUM_GC_REF_ARRAYLETIZED_BYTES = 0;
+  public static int NUM_GC_REF_ZERO_ARRAYLET_BYTES = 0;
+  public static int REF_ZERO_ARRAYLET_AT_GC = 0;
+  public static int NUM_PRIMARRCONTIG_BYTES_GC = 0;
+  public static int NUM_REFARRCONTIG_BYTES_GC = 0;
+  public static int CUM_GC_ZERO_ARRAYLET = 0;
+  public static int CUM_GC_REF_ZERO_ARRAYLET = 0;
+  public static int NUM_GC_TAINTED_ARRAYLET_PTRS = 0;
+
+  public static int NUM_GC_ARRAYLET_ZERO_BYTES = 0;
+  public static int NUM_GC_REF_ARRAYLET_ZERO_BYTES = 0;
+  
+  //SimpleCollector has NUM_GC_BYTES which is scalar bytes at GC time
+  
+  //next 2 updated in RVMArray arraycopy methods, printed in Statistics
+  public static long NUM_PRIM_BYTES_ARRAYCOPY = 0;
+  public static int NUM_REF_BYTES_ARRAYCOPY = 0;
+  public static int NUM_PRIM_BYTES_ARRAYCOPY_ARRAYLET = 0;
+  public static int NUM_REF_BYTES_ARRAYCOPY_ARRAYLET = 0;
+  
+  //next 2 are updated in MemoryManager, printed in Statistics
+  public static int ARRAYLET_BYTES_REQUESTED = 0;
+  public static int ARRAYLET_BYTES_ALLOCATED = 0;
+  //public static int ARRAY_SPINE_BYTES_ALLOCATED = 0;
+  //below are for boot image arraylet stats - currently unused
+  public static int ZERO_ARRAYLET_IN_BOOT = 0;
+  public static int TOTAL_ARRAYLET_IN_BOOT = 0;
 }
 
diff -r 743a2cc2ed20 -r 058fdc3780ba rvm/src/org/jikesrvm/mm/mminterface/SpecializedScanMethod.java
--- a/rvm/src/org/jikesrvm/mm/mminterface/SpecializedScanMethod.java	Tue Aug 04 11:04:15 2009 +1000
+++ b/rvm/src/org/jikesrvm/mm/mminterface/SpecializedScanMethod.java	Mon Nov 16 09:21:21 2009 +1100
@@ -12,10 +12,55 @@
  */
 package org.jikesrvm.mm.mminterface;
 
+import static org.jikesrvm.mm.mminterface.MemoryManagerConstants.FIRSTN_INT_BYTES;
+import static org.jikesrvm.mm.mminterface.MemoryManagerConstants.FIRSTN_SHORT_BYTES;
+import static org.jikesrvm.mm.mminterface.MemoryManagerConstants.FIRSTN_LONG_BYTES;
+import static org.jikesrvm.mm.mminterface.MemoryManagerConstants.FIRSTN_BYTE_BYTES;
+
+import static org.jikesrvm.mm.mminterface.MemoryManagerConstants.FIRSTN_REF_ELEMS;
+import static org.jikesrvm.mm.mminterface.MemoryManagerConstants.FIRSTN_REF_BYTES;
+import static org.jikesrvm.mm.mminterface.MemoryManagerConstants.LOG_ELEMENTS_IN_REF_ARRAYLET;
+import static org.jikesrvm.mm.mminterface.MemoryManagerConstants.ELEMENTS_IN_REF_ARRAYLET;
+
+import static org.jikesrvm.mm.mminterface.MemoryManagerConstants.USE_PRIMITIVE_BOOLEAN_ARRAYLETS;
+import static org.jikesrvm.mm.mminterface.MemoryManagerConstants.USE_PRIMITIVE_BYTE_ARRAYLETS;
+import static org.jikesrvm.mm.mminterface.MemoryManagerConstants.USE_PRIMITIVE_CHAR_ARRAYLETS;
+import static org.jikesrvm.mm.mminterface.MemoryManagerConstants.USE_PRIMITIVE_SHORT_ARRAYLETS;
+import static org.jikesrvm.mm.mminterface.MemoryManagerConstants.USE_PRIMITIVE_INT_ARRAYLETS;
+import static org.jikesrvm.mm.mminterface.MemoryManagerConstants.USE_PRIMITIVE_FLOAT_ARRAYLETS;
+import static org.jikesrvm.mm.mminterface.MemoryManagerConstants.USE_PRIMITIVE_LONG_ARRAYLETS;
+import static org.jikesrvm.mm.mminterface.MemoryManagerConstants.USE_PRIMITIVE_DOUBLE_ARRAYLETS;
+
+import static org.jikesrvm.mm.mminterface.MemoryManagerConstants.FIRSTN_BOOLEAN_BYTES;
+import static org.jikesrvm.mm.mminterface.MemoryManagerConstants.FIRSTN_BYTE_BYTES;
+import static org.jikesrvm.mm.mminterface.MemoryManagerConstants.FIRSTN_CHAR_BYTES;
+import static org.jikesrvm.mm.mminterface.MemoryManagerConstants.FIRSTN_SHORT_BYTES;
+import static org.jikesrvm.mm.mminterface.MemoryManagerConstants.FIRSTN_INT_BYTES;
+import static org.jikesrvm.mm.mminterface.MemoryManagerConstants.FIRSTN_FLOAT_BYTES;
+import static org.jikesrvm.mm.mminterface.MemoryManagerConstants.FIRSTN_LONG_BYTES;
+import static org.jikesrvm.mm.mminterface.MemoryManagerConstants.FIRSTN_DOUBLE_BYTES;
+
+import static org.jikesrvm.mm.mminterface.MemoryManagerConstants.LOG_ARRAYLET_BYTES;
+import static org.jikesrvm.mm.mminterface.MemoryManagerConstants.ARRAYLET_BYTES;
+
+import static org.jikesrvm.mm.mminterface.MemoryManagerConstants.DO_COLLECT_SPACE_SAVING_STATS;
+import static org.jikesrvm.mm.mminterface.MemoryManagerConstants.ZERO_ARRAYLET_AT_GC;
+import static org.jikesrvm.mm.mminterface.MemoryManagerConstants.NUM_GC_ARRAYLET_BYTES;
+import static org.jikesrvm.mm.mminterface.MemoryManagerConstants.NUM_GC_ZERO_ARRAYLET_BYTES;
+import static org.jikesrvm.mm.mminterface.MemoryManagerConstants.NUM_GC_SPINE_BYTES;
+import static org.jikesrvm.mm.mminterface.MemoryManagerConstants.NUM_PRIMARRCONTIG_BYTES_GC;
+import static org.jikesrvm.mm.mminterface.MemoryManagerConstants.REF_ZERO_ARRAYLET_AT_GC;
+import static org.jikesrvm.mm.mminterface.MemoryManagerConstants.NUM_GC_REF_ARRAYLET_BYTES;
+import static org.jikesrvm.mm.mminterface.MemoryManagerConstants.NUM_GC_REF_ZERO_ARRAYLET_BYTES;
+import static org.jikesrvm.mm.mminterface.MemoryManagerConstants.NUM_GC_REF_SPINE_BYTES;
+import static org.jikesrvm.mm.mminterface.MemoryManagerConstants.NUM_REFARRCONTIG_BYTES_GC;
+
+import org.jikesrvm.HeapLayoutConstants;
 import org.jikesrvm.VM;
 import org.jikesrvm.SizeConstants;
 import org.jikesrvm.ArchitectureSpecific.CodeArray;
 import org.jikesrvm.classloader.Atom;
+import org.jikesrvm.classloader.RVMArray;
 import org.jikesrvm.classloader.RVMClass;
 import org.jikesrvm.classloader.RVMMethod;
 import org.jikesrvm.classloader.SpecializedMethod;
@@ -25,14 +70,22 @@
 import org.jikesrvm.objectmodel.JavaHeaderConstants;
 import org.jikesrvm.objectmodel.ObjectModel;
 import org.jikesrvm.runtime.Magic;
+import org.jikesrvm.scheduler.Scheduler;
+import org.mmtk.plan.Plan;
 import org.mmtk.plan.TransitiveClosure;
+import org.mmtk.plan.TraceLocal;
+import org.mmtk.policy.Space;
+import org.mmtk.policy.arraylet.ArrayletSpace;
 import org.vmmagic.pragma.Inline;
 import org.vmmagic.pragma.Interruptible;
 import org.vmmagic.pragma.NoInline;
 import org.vmmagic.pragma.SpecializedMethodInvoke;
 import org.vmmagic.pragma.Uninterruptible;
 import org.vmmagic.unboxed.Address;
+import org.vmmagic.unboxed.Extent;
 import org.vmmagic.unboxed.ObjectReference;
+import org.vmmagic.unboxed.Offset;
+import org.vmmagic.unboxed.Word;
 
 /**
  * A method that scan objects and is specialized to a specific MMTk
@@ -70,8 +123,25 @@
   private static final int REFARRAY_PATTERN = 64;
   /** Fallback to a slower path that is not specialized */
   private static final int FALLBACK_PATTERN = 65;
+  
+  /** Arrayletized arrays with 1 byte elements */
+  private static final int BYTE_ARRAYLET_PATTERN = USE_PRIMITIVE_BYTE_ARRAYLETS ? FALLBACK_PATTERN + 1 : FALLBACK_PATTERN;
+  private static final int BOOLEAN_ARRAYLET_PATTERN = (USE_PRIMITIVE_BOOLEAN_ARRAYLETS && (!USE_PRIMITIVE_BYTE_ARRAYLETS || FIRSTN_BYTE_BYTES != FIRSTN_BOOLEAN_BYTES)) ? BYTE_ARRAYLET_PATTERN + 1 : BYTE_ARRAYLET_PATTERN;
+  
+  /** Arrayletized arrays with 2 byte elements */
+  private static final int CHAR_ARRAYLET_PATTERN = USE_PRIMITIVE_CHAR_ARRAYLETS ? BOOLEAN_ARRAYLET_PATTERN + 1 : BOOLEAN_ARRAYLET_PATTERN;
+  private static final int SHORT_ARRAYLET_PATTERN = (USE_PRIMITIVE_SHORT_ARRAYLETS && (!USE_PRIMITIVE_CHAR_ARRAYLETS || FIRSTN_CHAR_BYTES != FIRSTN_SHORT_BYTES)) ? CHAR_ARRAYLET_PATTERN + 1 : CHAR_ARRAYLET_PATTERN;
+  
+  /** Arrayletized arrays with 4 byte elements */
+  private static final int INT_ARRAYLET_PATTERN = USE_PRIMITIVE_INT_ARRAYLETS ? SHORT_ARRAYLET_PATTERN + 1 : SHORT_ARRAYLET_PATTERN;
+  private static final int FLOAT_ARRAYLET_PATTERN = (USE_PRIMITIVE_FLOAT_ARRAYLETS && (!USE_PRIMITIVE_INT_ARRAYLETS || FIRSTN_INT_BYTES != FIRSTN_FLOAT_BYTES)) ? INT_ARRAYLET_PATTERN + 1 : INT_ARRAYLET_PATTERN;
+  
+  /** Arrayletized arrays with 8 byte elements */
+  private static final int LONG_ARRAYLET_PATTERN = USE_PRIMITIVE_LONG_ARRAYLETS ? FLOAT_ARRAYLET_PATTERN + 1 : FLOAT_ARRAYLET_PATTERN;
+  private static final int DOUBLE_ARRAYLET_PATTERN = (USE_PRIMITIVE_DOUBLE_ARRAYLETS && (!USE_PRIMITIVE_LONG_ARRAYLETS || FIRSTN_LONG_BYTES != FIRSTN_DOUBLE_BYTES)) ? LONG_ARRAYLET_PATTERN + 1 : LONG_ARRAYLET_PATTERN;
+  
   /** The total number of patterns */
-  private static final int PATTERNS = 66;
+  private static final int PATTERNS = DOUBLE_ARRAYLET_PATTERN + 1;
   /** Maximum field offset we can deal with */
   private static final int MAX_SPECIALIZED_OFFSET = 6 << LOG_BYTES_IN_ADDRESS;
 
@@ -104,7 +174,20 @@
     if (type.isArrayType()) {
       if (type.asArray().getElementType().isReferenceType()) {
         return REFARRAY_PATTERN;
+      } else if (type.asArray().isArrayletizable()) {
+        if      (type == RVMArray.ByteArray)    return BYTE_ARRAYLET_PATTERN;
+        else if (type == RVMArray.BooleanArray) return BOOLEAN_ARRAYLET_PATTERN;
+        else if (type == RVMArray.CharArray)    return CHAR_ARRAYLET_PATTERN;
+        else if (type == RVMArray.ShortArray)   return SHORT_ARRAYLET_PATTERN;
+        else if (type == RVMArray.IntArray)     return INT_ARRAYLET_PATTERN;
+        else if (type == RVMArray.FloatArray)   return FLOAT_ARRAYLET_PATTERN;
+        else if (type == RVMArray.DoubleArray)  return DOUBLE_ARRAYLET_PATTERN;
+        else if (type == RVMArray.LongArray)    return LONG_ARRAYLET_PATTERN;
+        else {
+          VM.sysFail("Unknown primitive arraylet type " + type);
+        }
       }
+
       return NULL_PATTERN;
     }
 
@@ -194,16 +277,28 @@
   /** Fallback */
   public static void fallback(Object object, TransitiveClosure trace) {
     ObjectReference objectRef = ObjectReference.fromObject(object);
-    RVMType type = ObjectModel.getObjectType(objectRef.toObject());
+    RVMType type = ObjectModel.getObjectType(object);
     if (type.isClassType()) {
       RVMClass klass = type.asClass();
       int[] offsets = klass.getReferenceOffsets();
       for(int i=0; i < offsets.length; i++) {
         trace.processEdge(objectRef, objectRef.toAddress().plus(offsets[i]));
       }
-    } else if (type.isArrayType() && type.asArray().getElementType().isReferenceType()) {
-      for(int i=0; i < ObjectModel.getArrayLength(objectRef.toObject()); i++) {
-        trace.processEdge(objectRef, objectRef.toAddress().plus(i << LOG_BYTES_IN_ADDRESS));
+    } else {
+      if (VM.VerifyAssertions) VM._assert(type.isArrayType());
+      RVMArray arrayType = type.asArray();
+      if (arrayType.isArrayletizable()) {
+        if (arrayType.getElementType().isReferenceType()) { 
+          referenceArrayletSpine(object, trace);
+        } else {
+          int logElementSize = arrayType.getLogElementSize();
+          int firstNBytes = arrayType.getFirstNElements() << logElementSize;
+          primitiveArrayletSpine(firstNBytes, logElementSize, object, trace);
+        }
+      } else if (arrayType.getElementType().isReferenceType()) {
+        for(int i=0; i < ObjectModel.getArrayLength(objectRef.toObject()); i++) {
+          trace.processEdge(objectRef, objectRef.toAddress().plus(i << LOG_BYTES_IN_ADDRESS));
+        }
       }
     }
   }
@@ -219,10 +314,14 @@
 
   /** Reference Arrays */
   public static void referenceArray(Object object, TransitiveClosure trace) {
-    Address base = Magic.objectAsAddress(object);
-    int length = ObjectModel.getArrayLength(object);
-    for (int i=0; i < length; i++) {
-      trace.processEdge(ObjectReference.fromObject(object), base.plus(i << LOG_BYTES_IN_ADDRESS));
+    if (MemoryManagerConstants.USE_REFERENCE_ARRAYLETS) {
+      referenceArrayletSpine(object, trace);
+    } else {
+      Address base = Magic.objectAsAddress(object);
+      int length = ObjectModel.getArrayLength(object);
+      for (int i=0; i < length; i++) {
+        trace.processEdge(ObjectReference.fromObject(object), base.plus(i << LOG_BYTES_IN_ADDRESS));
+      }
     }
   }
 
@@ -254,6 +353,185 @@
   }
 
   /**
+   * Process a primitive arraylet spine.
+   */
+  @Inline
+  public static void primitiveArrayletSpine(int firstNBytes, int logElementSize, Object object, TransitiveClosure trace) {
+    Address zeroArrayletAddr = Magic.objectAsAddress(ObjectModel.zeroArraylet);
+    int length = ObjectModel.getArrayLength(object);
+    int bytes = length << logElementSize;
+    int arrayletCount = ((bytes - firstNBytes) >> LOG_ARRAYLET_BYTES);
+    int spinePointerOffset = firstNBytes;
+    
+    if (DO_COLLECT_SPACE_SAVING_STATS) {
+    	int remainingAndIndirectionBytes = (length << logElementSize) - firstNBytes - (arrayletCount * ARRAYLET_BYTES) + (BYTES_IN_ADDRESS * (arrayletCount+1));
+    	MemoryManagerConstants.NUM_GC_ARRAYLETIZED_BYTES += remainingAndIndirectionBytes;
+    }
+    boolean doICheckArraylet = false;
+    if (MemoryManagerConstants.DO_ANY_COPY_ON_WRITE_ARRAYS) {
+    if (logElementSize == LOG_BYTES_IN_BYTE) {
+    	doICheckArraylet = MemoryManagerConstants.DO_COPY_ON_WRITE_BYTE_ARRAYS || MemoryManagerConstants.DO_COPY_ON_WRITE_BOOLEAN_ARRAYS;
+    } else if (logElementSize == LOG_BYTES_IN_CHAR) {
+    	doICheckArraylet = MemoryManagerConstants.DO_COPY_ON_WRITE_CHAR_ARRAYS || MemoryManagerConstants.DO_COPY_ON_WRITE_SHORT_ARRAYS;
+    } else if (logElementSize == LOG_BYTES_IN_INT) {
+    	doICheckArraylet = MemoryManagerConstants.DO_COPY_ON_WRITE_INT_ARRAYS || MemoryManagerConstants.DO_COPY_ON_WRITE_FLOAT_ARRAYS;
+    } else if (logElementSize == LOG_BYTES_IN_SHORT) {
+    	doICheckArraylet = MemoryManagerConstants.DO_COPY_ON_WRITE_SHORT_ARRAYS;
+    } else if (logElementSize == LOG_BYTES_IN_LONG) {
+    	doICheckArraylet = MemoryManagerConstants.DO_COPY_ON_WRITE_LONG_ARRAYS || MemoryManagerConstants.DO_COPY_ON_WRITE_DOUBLE_ARRAYS;
+    }
+    }
+    for(int i=0; i < arrayletCount; i++) {
+      Address arraylet = Magic.getWordAtOffset(object, Offset.fromIntZeroExtend(spinePointerOffset)).toAddress();
+      if (doICheckArraylet) {
+    	  if (DO_COLLECT_SPACE_SAVING_STATS) {
+    		  boolean isTainted = arraylet.toWord().and(MemoryManagerConstants.ARRAYLET_TAINT_WORD).NE(Word.zero());
+    		  if (isTainted)  MemoryManagerConstants.NUM_GC_TAINTED_ARRAYLET_PTRS++;
+    	  }
+    	  arraylet = arraylet.toWord().and(MemoryManagerConstants.ARRAYLET_TAINT_MASK).toAddress();
+      }
+      if ((!MemoryManagerConstants.USE_ZERO_ARRAYLETS || arraylet.NE(zeroArrayletAddr))) {
+        if (!arraylet.isZero()) {
+          if (VM.VerifyAssertions) VM._assert(Space.isInSpace(Plan.ARRAYLET, arraylet));
+          if (MemoryManagerConstants.DO_ZERO_ARRAY_COMPRESSION && isArrayletZero(arraylet)) {
+            Magic.setWordAtOffset(object, Offset.fromIntZeroExtend(spinePointerOffset), zeroArrayletAddr.toWord());
+            if (DO_COLLECT_SPACE_SAVING_STATS) {
+            	ZERO_ARRAYLET_AT_GC += ARRAYLET_BYTES;
+            	MemoryManagerConstants.CUM_GC_ZERO_ARRAYLET += ARRAYLET_BYTES;
+            }
+          } else {
+        	  if (DO_COLLECT_SPACE_SAVING_STATS) {
+        		  NUM_GC_ARRAYLET_BYTES += ARRAYLET_BYTES;
+        		  MemoryManagerConstants.NUM_GC_ARRAYLETIZED_BYTES += ARRAYLET_BYTES;
+        		  Address currArrlet = arraylet;
+        		  for (int elem = 0; elem < MemoryManagerConstants.ELEMENTS_IN_BYTE_ARRAYLET; elem++) {
+        			  if (currArrlet.loadByte() == 0) MemoryManagerConstants.NUM_GC_ARRAYLET_ZERO_BYTES++;
+        			  currArrlet = currArrlet.plus(BYTES_IN_BYTE);
+        		  }
+        	  }
+        	  /*VM.sysWrite(" In SpecializedScan for primitive array, marking arraylet with logElementSize ");
+        	  VM.sysWrite(logElementSize);  VM.sysWrite(" and object is ");
+        	  VM.sysWriteln(Magic.objectAsAddress(object));*/
+            ArrayletSpace.markArraylet(arraylet);
+          }
+        }
+      }  else if (DO_COLLECT_SPACE_SAVING_STATS && MemoryManagerConstants.USE_ZERO_ARRAYLETS && arraylet.EQ(zeroArrayletAddr)) {
+    	  NUM_GC_ZERO_ARRAYLET_BYTES += ARRAYLET_BYTES;
+      }
+      spinePointerOffset += BYTES_IN_ADDRESS;
+    }
+    if (DO_COLLECT_SPACE_SAVING_STATS) {
+    	NUM_GC_SPINE_BYTES += ObjectModel.bytesUsed(object);
+    	NUM_PRIMARRCONTIG_BYTES_GC += ObjectModel.bytesRequiredWhenContiguousCopied(object, ObjectModel.getObjectType(object).asArray(), Magic.getArrayLength(object));
+    }
+  }
+
+  /**
+   * Check if all the values in this arraylet are zero.
+   *
+   * @param arraylet The arraylet to check
+   * @return true if all arraylets are zero.
+   */
+  @Inline
+  private static boolean isArrayletZero(Address arraylet) {
+    Address cursor = arraylet;
+    while (cursor.LT(arraylet.plus(ARRAYLET_BYTES))) {
+      if (!cursor.loadWord().isZero()) return false;
+      cursor = cursor.plus(BYTES_IN_WORD);
+    }
+    return true;
+  }
+
+  /**
+   * Process a reference arraylet spine.
+   */
+  @Inline
+  public static void referenceArrayletSpine(Object object, TransitiveClosure trace) {
+    Address zeroArrayletAddr = Magic.objectAsAddress(ObjectModel.zeroArraylet);
+    int remaining = ObjectModel.getArrayLength(object);
+    int arrayletCount = ((remaining - FIRSTN_REF_ELEMS) >> LOG_ELEMENTS_IN_REF_ARRAYLET);
+    int spinePointerOffset = FIRSTN_REF_BYTES;
+
+    ObjectReference ref = ObjectReference.fromObject(object); 
+    Address base = ref.toAddress();
+    //DebugUtil.dumpRef(ref);
+    
+    int contiguous = remaining < FIRSTN_REF_ELEMS ? remaining : FIRSTN_REF_ELEMS;
+    remaining -= contiguous;
+    for(int j=0; j < contiguous; j++) {
+      trace.processEdge(ref, base.plus(j << LOG_BYTES_IN_ADDRESS));
+    }
+
+    for(int i=0; i < arrayletCount; i++) {
+      if (VM.VerifyAssertions) VM._assert(remaining >= ELEMENTS_IN_REF_ARRAYLET);
+      Address arraylet = base.loadAddress(Offset.fromIntZeroExtend(spinePointerOffset));
+      if (MemoryManagerConstants.DO_COPY_ON_WRITE_REF_ARRAYS) {
+    	  if (DO_COLLECT_SPACE_SAVING_STATS) {
+    		  if (arraylet.toWord().and(MemoryManagerConstants.ARRAYLET_TAINT_WORD).NE(Word.zero()))  MemoryManagerConstants.NUM_GC_TAINTED_ARRAYLET_PTRS++;
+    	  }
+    	  arraylet = arraylet.toWord().and(MemoryManagerConstants.ARRAYLET_TAINT_MASK).toAddress();
+      }
+      //VM.sysWrite("  alet ");VM.sysWrite(arraylet);VM.sysWrite("\n");
+      remaining -= ELEMENTS_IN_REF_ARRAYLET;
+      if (!arraylet.isZero()) {
+        if (!MemoryManagerConstants.USE_ZERO_ARRAYLETS || arraylet.NE(zeroArrayletAddr)) {
+          if (VM.VerifyAssertions) VM._assert(Space.isInSpace(Plan.ARRAYLET, arraylet));
+          boolean allZero = true;
+          for(int j=0; j < ELEMENTS_IN_REF_ARRAYLET; j++) {
+            trace.processEdge(ref, arraylet.plus(j << LOG_BYTES_IN_ADDRESS));
+            if (MemoryManagerConstants.DO_ZERO_ARRAY_COMPRESSION) {
+              allZero = allZero && arraylet.plus(j << LOG_BYTES_IN_ADDRESS).loadWord().isZero();
+            }
+          }
+          if (MemoryManagerConstants.DO_ZERO_ARRAY_COMPRESSION && allZero) {
+            Magic.setWordAtOffset(object, Offset.fromIntZeroExtend(spinePointerOffset), zeroArrayletAddr.toWord());
+            if (DO_COLLECT_SPACE_SAVING_STATS) {
+            	REF_ZERO_ARRAYLET_AT_GC += ARRAYLET_BYTES;
+            	MemoryManagerConstants.CUM_GC_REF_ZERO_ARRAYLET += ARRAYLET_BYTES;
+            }
+          } else {
+        	  if (DO_COLLECT_SPACE_SAVING_STATS) {
+        		  NUM_GC_REF_ARRAYLET_BYTES += ARRAYLET_BYTES;
+        		  MemoryManagerConstants.NUM_GC_REF_ARRAYLETIZED_BYTES += (ARRAYLET_BYTES + BYTES_IN_ADDRESS); //arraylet + indirection pointer
+        		  Address currArrlet = arraylet;
+        		  for (int elem = 0; elem < MemoryManagerConstants.ELEMENTS_IN_BYTE_ARRAYLET; elem++) {
+        			  if (currArrlet.loadByte() == 0) MemoryManagerConstants.NUM_GC_REF_ARRAYLET_ZERO_BYTES++;
+        			  currArrlet = currArrlet.plus(BYTES_IN_BYTE);
+        		  }
+        	  }
+            ArrayletSpace.markArraylet(arraylet);
+          }
+        } else if (DO_COLLECT_SPACE_SAVING_STATS && MemoryManagerConstants.USE_ZERO_ARRAYLETS && arraylet.EQ(zeroArrayletAddr)) {
+        	NUM_GC_REF_ZERO_ARRAYLET_BYTES += ARRAYLET_BYTES;
+        }
+      }
+      spinePointerOffset += BYTES_IN_ADDRESS;
+    }
+    if (DO_COLLECT_SPACE_SAVING_STATS) {
+    	NUM_GC_REF_SPINE_BYTES += ObjectModel.bytesUsed(object);
+    	NUM_REFARRCONTIG_BYTES_GC += ObjectModel.bytesRequiredWhenContiguousCopied(object, ObjectModel.getObjectType(object).asArray(), Magic.getArrayLength(object));
+    	MemoryManagerConstants.NUM_GC_REF_ARRAYLETIZED_BYTES += (remaining << LOG_BYTES_IN_ADDRESS) + BYTES_IN_ADDRESS; //remaining + indirection pointer
+    }
+    if (VM.VerifyAssertions) VM._assert(remaining < ELEMENTS_IN_REF_ARRAYLET && remaining >= 0);
+    if (remaining > 0) {
+      Address arraylet = base.loadAddress(Offset.fromIntZeroExtend(spinePointerOffset));
+      if (!arraylet.isZero()) {
+        if (VM.VerifyAssertions && arraylet.NE(base.plus(spinePointerOffset+BYTES_IN_ADDRESS))) {
+          VM.sysWriteln(ObjectModel.getArrayLength(object));
+          VM.sysWriteln(base);
+          VM.sysWriteln(arraylet);
+          DebugUtil.dumpRef(ref);
+          DebugUtil.dumpRef(arraylet.toObjectReference());
+          VM._assert(false);
+        }
+        for(int j=0; j < remaining; j++) {
+          trace.processEdge(ref, arraylet.plus(j << LOG_BYTES_IN_ADDRESS));
+        }
+      }
+    }
+  }
+
+  /**
    * Find the template method name for a given pattern.
    *
    * @param pattern The pattern to look for
@@ -324,11 +602,26 @@
       case 61: return Names.scalarRNRRRR;
       case 62: return Names.scalarNRRRRR;
       case 63: return Names.scalarRRRRRR;
-      case NULL_PATTERN:     return Names.noReferences;
+      case NULL_PATTERN: return Names.noReferences;
       case REFARRAY_PATTERN: return Names.referenceArray;
-      case FALLBACK_PATTERN:
-      default:               return Names.scalar;
+      case FALLBACK_PATTERN: return Names.scalar;
     }
+    /**
+     * These methods are here because we try and share specialized methods when
+     * possible (firstn bytes and element size match). 
+     */
+    if      (pattern == BYTE_ARRAYLET_PATTERN)    return Names.arrayletSpineByte;
+    else if (pattern == BOOLEAN_ARRAYLET_PATTERN) return Names.arrayletSpineBoolean;
+    else if (pattern == CHAR_ARRAYLET_PATTERN)    return Names.arrayletSpineChar;
+    else if (pattern == SHORT_ARRAYLET_PATTERN)   return Names.arrayletSpineShort;
+    else if (pattern == INT_ARRAYLET_PATTERN)     return Names.arrayletSpineInt;
+    else if (pattern == FLOAT_ARRAYLET_PATTERN)   return Names.arrayletSpineFloat;
+    else if (pattern == LONG_ARRAYLET_PATTERN)    return Names.arrayletSpineLong;
+    else if (pattern == DOUBLE_ARRAYLET_PATTERN)  return Names.arrayletSpineDouble;
+    
+    /* should never fall through to here */
+    if (VM.VerifyAssertions) VM._assert(false);
+    return null;
   }
 
   /** The generic descriptor for the specialized methods */
@@ -403,6 +696,15 @@
     static final Atom scalarRNRRRR = Atom.findOrCreateAsciiAtom("scalarRNRRRR");
     static final Atom scalarNRRRRR = Atom.findOrCreateAsciiAtom("scalarNRRRRR");
     static final Atom scalarRRRRRR = Atom.findOrCreateAsciiAtom("scalarRRRRRR");
+    static final Atom arrayletSpineByte    = Atom.findOrCreateAsciiAtom("arrayletSpineByte");
+    static final Atom arrayletSpineBoolean = Atom.findOrCreateAsciiAtom("arrayletSpineBoolean");
+    static final Atom arrayletSpineChar    = Atom.findOrCreateAsciiAtom("arrayletSpineChar");
+    static final Atom arrayletSpineShort   = Atom.findOrCreateAsciiAtom("arrayletSpineShort");
+    static final Atom arrayletSpineInt     = Atom.findOrCreateAsciiAtom("arrayletSpineInt");
+    static final Atom arrayletSpineFloat  = Atom.findOrCreateAsciiAtom("arrayletSpineFloat");
+    static final Atom arrayletSpineDouble  = Atom.findOrCreateAsciiAtom("arrayletSpineDouble");
+    static final Atom arrayletSpineLong    = Atom.findOrCreateAsciiAtom("arrayletSpineLong");
+
   }
 
   // CHECKSTYLE:OFF
@@ -470,6 +772,15 @@
   public static void scalarRNRRRR(Object object, TransitiveClosure trace) { pattern(61, object, trace); }
   public static void scalarNRRRRR(Object object, TransitiveClosure trace) { pattern(62, object, trace); }
   public static void scalarRRRRRR(Object object, TransitiveClosure trace) { pattern(63, object, trace); }
+  
+  public static void arrayletSpineByte   (Object object, TransitiveClosure trace) { primitiveArrayletSpine(FIRSTN_BYTE_BYTES,    LOG_BYTES_IN_BYTE,    object, trace); }
+  public static void arrayletSpineBoolean(Object object, TransitiveClosure trace) { primitiveArrayletSpine(FIRSTN_BOOLEAN_BYTES, LOG_BYTES_IN_BOOLEAN, object, trace); }
+  public static void arrayletSpineChar   (Object object, TransitiveClosure trace) { primitiveArrayletSpine(FIRSTN_CHAR_BYTES,    LOG_BYTES_IN_CHAR,    object, trace); }
+  public static void arrayletSpineShort  (Object object, TransitiveClosure trace) { primitiveArrayletSpine(FIRSTN_SHORT_BYTES,   LOG_BYTES_IN_SHORT,   object, trace); }
+  public static void arrayletSpineInt    (Object object, TransitiveClosure trace) { primitiveArrayletSpine(FIRSTN_INT_BYTES,     LOG_BYTES_IN_INT,     object, trace); }
+  public static void arrayletSpineFloat  (Object object, TransitiveClosure trace) { primitiveArrayletSpine(FIRSTN_FLOAT_BYTES,   LOG_BYTES_IN_FLOAT,   object, trace); }
+  public static void arrayletSpineDouble (Object object, TransitiveClosure trace) { primitiveArrayletSpine(FIRSTN_DOUBLE_BYTES,  LOG_BYTES_IN_DOUBLE,  object, trace); }
+  public static void arrayletSpineLong   (Object object, TransitiveClosure trace) { primitiveArrayletSpine(FIRSTN_LONG_BYTES,    LOG_BYTES_IN_LONG,    object, trace); }
 
   // CHECKSTYLE:ON
 }
diff -r 743a2cc2ed20 -r 058fdc3780ba rvm/src/org/jikesrvm/objectmodel/JavaHeader.java
--- a/rvm/src/org/jikesrvm/objectmodel/JavaHeader.java	Tue Aug 04 11:04:15 2009 +1000
+++ b/rvm/src/org/jikesrvm/objectmodel/JavaHeader.java	Mon Nov 16 09:21:21 2009 +1100
@@ -13,6 +13,7 @@
 package org.jikesrvm.objectmodel;
 
 import org.jikesrvm.ArchitectureSpecific.Assembler;
+import org.jikesrvm.HeapLayoutConstants;
 import org.jikesrvm.VM;
 import org.jikesrvm.Configuration;
 import org.jikesrvm.SizeConstants;
@@ -25,6 +26,8 @@
 import org.jikesrvm.scheduler.Lock;
 import org.jikesrvm.scheduler.ThinLock;
 import org.jikesrvm.scheduler.RVMThread;
+import org.mmtk.plan.Plan;
+import org.mmtk.policy.Space;
 import org.vmmagic.pragma.Inline;
 import org.vmmagic.pragma.Interruptible;
 import org.vmmagic.pragma.NoInline;
@@ -137,15 +140,19 @@
    * What is the first word after the array?
    */
   public static Address getObjectEndAddress(Object obj, RVMArray type, int numElements) {
-    int size = type.getInstanceSize(numElements);
+    int size;
+    if (Magic.objectAsAddress(obj).LT(HeapLayoutConstants.BOOT_IMAGE_DATA_END)) {
+      size = type.getBootImageContiguousInstanceSize(numElements);
+    } else {
+      size = type.getInstanceSize(numElements);
+    }
     if (ADDRESS_BASED_HASHING && DYNAMIC_HASH_OFFSET) {
       Word hashState = Magic.getWordAtOffset(obj, STATUS_OFFSET).and(HASH_STATE_MASK);
       if (hashState.EQ(HASH_STATE_HASHED_AND_MOVED)) {
         size += HASHCODE_BYTES;
       }
     }
-    return Magic.objectAsAddress(obj).plus(Memory.alignUp(size, SizeConstants.BYTES_IN_INT) -
-                                              OBJECT_REF_OFFSET);
+    return Magic.objectAsAddress(obj).plus(Memory.alignUp(size, SizeConstants.BYTES_IN_INT) - OBJECT_REF_OFFSET);
   }
 
   /**
@@ -234,6 +241,8 @@
    * how many bytes are needed when the array object is copied by GC?
    */
   public static int bytesRequiredWhenCopied(Object fromObj, RVMArray type, int numElements) {
+    // NOTE: would need to check if fromObj is in boot image, but when we copy arrays from boot image, 
+    // they are copied into spines, so don't want to get instance size of contiguous boot image arrayletized array
     int size = type.getInstanceSize(numElements);
     if (ADDRESS_BASED_HASHING) {
       Word hashState = Magic.getWordAtOffset(fromObj, STATUS_OFFSET).and(HASH_STATE_MASK);
@@ -244,11 +253,29 @@
     return Memory.alignUp(size, SizeConstants.BYTES_IN_INT);
   }
 
+  public static int bytesRequiredWhenContiguousCopied(Object fromObj, RVMArray type, int numElements) {
+    //jbs added arraylet - NOTE: would need to check if fromObj is in boot image, but when we copy arrays from boot image, 
+    //they are copied into spines, so don't want to get instance size of contiguous boot image arrayletized array
+    int size = type.getContiguousInstanceSize(numElements);
+    if (ADDRESS_BASED_HASHING) {
+      Word hashState = Magic.getWordAtOffset(fromObj, STATUS_OFFSET).and(HASH_STATE_MASK);
+      if (hashState.NE(HASH_STATE_UNHASHED)) {
+        size += HASHCODE_BYTES;
+      }
+    }
+    return Memory.alignUp(size, SizeConstants.BYTES_IN_INT);
+  }
+
   /**
    * how many bytes are used by the array object?
    */
   public static int bytesUsed(Object obj, RVMArray type, int numElements) {
-    int size = type.getInstanceSize(numElements);
+    int size; 
+    if (Magic.objectAsAddress(obj).LT(HeapLayoutConstants.BOOT_IMAGE_DATA_END)) {
+      size = type.getBootImageContiguousInstanceSize(numElements);
+    } else {
+      size = type.getInstanceSize(numElements);
+    }
     if (MemoryManagerConstants.MOVES_OBJECTS) {
       if (ADDRESS_BASED_HASHING) {
         Word hashState = Magic.getWordAtOffset(obj, STATUS_OFFSET).and(HASH_STATE_MASK);
@@ -504,9 +531,18 @@
           if (DYNAMIC_HASH_OFFSET) {
             // Read the size of this object.
             RVMType t = Magic.getObjectType(o);
-            int offset =
-                t.isArrayType() ? t.asArray().getInstanceSize(Magic.getArrayLength(o)) -
-                                  OBJECT_REF_OFFSET : t.asClass().getInstanceSize() - OBJECT_REF_OFFSET;
+            int size = 0;
+            boolean arrayType = false;
+            if (t.isArrayType()) {
+              arrayType = true;
+              int numElements = Magic.getArrayLength(o);
+              if (Magic.objectAsAddress(o).LT(HeapLayoutConstants.BOOT_IMAGE_DATA_END)) {
+                size = t.asArray().getBootImageContiguousInstanceSize(numElements);
+              } else {
+                size = t.asArray().getInstanceSize(numElements);
+              }
+            }
+            int offset = arrayType ? size - OBJECT_REF_OFFSET : t.asClass().getInstanceSize() - OBJECT_REF_OFFSET;
             return Magic.getIntAtOffset(o, Offset.fromIntSignExtend(offset));
           } else {
             return (Magic.getIntAtOffset(o, HASHCODE_OFFSET) >>> 1);
@@ -897,7 +933,8 @@
       if (DYNAMIC_HASH_OFFSET) {
         // Read the size of this object.
         RVMType t = tib.getType();
-        bootImage.setFullWord(ptr.plus(t.asArray().getInstanceSize(numElements)), identityHashValue);
+        //jbs added arraylet - modified line below
+        bootImage.setFullWord(ptr.plus(/*t.asArray().getInstanceSize(numElements)*/t.asArray().getBootImageContiguousInstanceSize(numElements)), identityHashValue);
       } else {
         ref = ref.plus(HASHCODE_BYTES);
         bootImage.setFullWord(ref.plus(HASHCODE_OFFSET), (identityHashValue << 1) | ALIGNMENT_MASK);
diff -r 743a2cc2ed20 -r 058fdc3780ba rvm/src/org/jikesrvm/objectmodel/ObjectModel.java
--- a/rvm/src/org/jikesrvm/objectmodel/ObjectModel.java	Tue Aug 04 11:04:15 2009 +1000
+++ b/rvm/src/org/jikesrvm/objectmodel/ObjectModel.java	Mon Nov 16 09:21:21 2009 +1100
@@ -12,6 +12,8 @@
  */
 package org.jikesrvm.objectmodel;
 
+import static org.jikesrvm.mm.mminterface.MemoryManagerConstants.ELEMENTS_IN_REF_ARRAYLET;
+
 import org.jikesrvm.ArchitectureSpecific.Assembler;
 import org.jikesrvm.VM;
 import org.jikesrvm.SizeConstants;
@@ -19,6 +21,7 @@
 import org.jikesrvm.classloader.RVMClass;
 import org.jikesrvm.classloader.RVMType;
 import org.jikesrvm.mm.mminterface.MemoryManager;
+import org.jikesrvm.mm.mminterface.MemoryManagerConstants; //jbs added arraylet
 import org.jikesrvm.runtime.Magic;
 import org.jikesrvm.scheduler.Lock;
 import org.jikesrvm.scheduler.RVMThread;
@@ -30,6 +33,7 @@
 import org.vmmagic.unboxed.Address;
 import org.vmmagic.unboxed.Extent;
 import org.vmmagic.unboxed.ObjectReference;
+import org.vmmagic.unboxed.ObjectReferenceArray; //jbs added arraylet
 import org.vmmagic.unboxed.Offset;
 import org.vmmagic.unboxed.Word;
 
@@ -139,6 +143,8 @@
   /** Whether to pack bytes and shorts into 32bit fields*/
   private static final boolean PACKED = true;
 
+  public static final ObjectReferenceArray zeroArraylet;   
+
   /** Layout widget */
   private static final FieldLayout layout;
 
@@ -148,6 +154,7 @@
     } else {
       layout = new FieldLayoutUnpacked(true, false);
     }
+    zeroArraylet = ObjectReferenceArray.create(ELEMENTS_IN_REF_ARRAYLET);
   }
 
   /**
@@ -357,6 +364,10 @@
     return JavaHeader.bytesRequiredWhenCopied(fromObj, type, numElements);
   }
 
+  public static int bytesRequiredWhenContiguousCopied(Object fromObj, RVMArray type, int numElements) {
+	  return JavaHeader.bytesRequiredWhenContiguousCopied(fromObj, type, numElements);
+  }
+
   /**
    * Map from the object ref to the lowest address of the storage
    * associated with the object
@@ -809,7 +820,8 @@
   @Interruptible
   public static Address allocateArray(BootImageInterface bootImage, RVMArray array, int numElements, boolean needsIdentityHash, int identityHashValue) {
     TIB tib = array.getTypeInformationBlock();
-    int size = array.getInstanceSize(numElements);
+    //jbs added arraylet - change line below
+    int size = array.getBootImageContiguousInstanceSize(numElements); //array.getInstanceSize(numElements);
     if (needsIdentityHash) {
       if (JavaHeader.ADDRESS_BASED_HASHING) {
         size += JavaHeader.HASHCODE_BYTES;
@@ -826,6 +838,9 @@
     bootImage.setFullWord(ref.plus(getArrayLengthOffset()), numElements);
     MemoryManager.initializeHeader(bootImage, ref, tib, size, false);
     MiscHeader.initializeHeader(bootImage, ref, tib, size, false);
+    if (MemoryManagerConstants.BOOT_IMAGE_IS_ARRAYLETIZED && array.isArrayletizable()) {
+      //MemoryManager.initializeArrayletPointers(bootImage, ref, numElements, array.getLogElementSize());
+    }
     return ref;
   }
 
diff -r 743a2cc2ed20 -r 058fdc3780ba rvm/src/org/jikesrvm/objectmodel/TIB.java
--- a/rvm/src/org/jikesrvm/objectmodel/TIB.java	Tue Aug 04 11:04:15 2009 +1000
+++ b/rvm/src/org/jikesrvm/objectmodel/TIB.java	Mon Nov 16 09:21:21 2009 +1100
@@ -29,6 +29,7 @@
 import org.vmmagic.unboxed.Address;
 import org.vmmagic.unboxed.Offset;
 import org.vmmagic.unboxed.Word;
+import org.vmmagic.unboxed.WordArray;
 
 /**
  * This class represents an instance of a type information block, at runtime it
@@ -176,14 +177,14 @@
    * Get the superclass id set for this type.
    */
   @Inline
-  public short[] getSuperclassIds() {
-    return Magic.objectAsShortArray(get(TIB_SUPERCLASS_IDS_INDEX));
+  public WordArray getSuperclassIds() {
+    return Magic.objectAsWordArray(get(TIB_SUPERCLASS_IDS_INDEX));
   }
 
   /**
    * Set the superclass id set for this type.
    */
-  public void setSuperclassIds(short[] superclassIds) {
+  public void setSuperclassIds(WordArray superclassIds) {
     set(TIB_SUPERCLASS_IDS_INDEX, superclassIds);
   }
 
@@ -208,14 +209,14 @@
    * Get the does implement entry of the TIB
    */
   @Inline
-  public int[] getDoesImplement() {
-    return Magic.objectAsIntArray(get(TIB_DOES_IMPLEMENT_INDEX));
+  public WordArray getDoesImplement() {
+    return Magic.objectAsWordArray(get(TIB_DOES_IMPLEMENT_INDEX));
   }
 
   /**
    * Set the does implement entry of the TIB
    */
-  public void setDoesImplement(int[] doesImplement) {
+  public void setDoesImplement(WordArray doesImplement) {
     set(TIB_DOES_IMPLEMENT_INDEX, doesImplement);
   }
 
diff -r 743a2cc2ed20 -r 058fdc3780ba rvm/src/org/jikesrvm/osr/ObjectHolder.java
--- a/rvm/src/org/jikesrvm/osr/ObjectHolder.java	Tue Aug 04 11:04:15 2009 +1000
+++ b/rvm/src/org/jikesrvm/osr/ObjectHolder.java	Mon Nov 16 09:21:21 2009 +1100
@@ -93,7 +93,6 @@
     if (VM.TraceOnStackReplacement) {
       VM.sysWriteln("ObjectHolder cleanRefs");
     }
-    /* refs[h] = null; */
     if (MemoryManagerConstants.NEEDS_WRITE_BARRIER) {
       MemoryManager.arrayStoreWriteBarrier(refs, h, null);
     } else {
diff -r 743a2cc2ed20 -r 058fdc3780ba rvm/src/org/jikesrvm/osr/ia32/BaselineExecutionStateExtractor.java
--- a/rvm/src/org/jikesrvm/osr/ia32/BaselineExecutionStateExtractor.java	Tue Aug 04 11:04:15 2009 +1000
+++ b/rvm/src/org/jikesrvm/osr/ia32/BaselineExecutionStateExtractor.java	Mon Nov 16 09:21:21 2009 +1100
@@ -30,6 +30,7 @@
 import org.vmmagic.unboxed.Address;
 import org.vmmagic.unboxed.Offset;
 import org.vmmagic.unboxed.Word;
+import org.vmmagic.unboxed.WordArray;
 
 /**
  * OSR_BaselineExecStateExtractor retrieves the VM scope descriptor
@@ -78,7 +79,7 @@
       VM.sysWriteln("BASE execStateExtractor starting ...");
     }
 
-    byte[] stack = thread.getStack();
+    WordArray stack = thread.getStack();
 
     if (VM.VerifyAssertions) {
       int fooCmid = Magic.getIntAtOffset(stack, methFPoff.plus(STACKFRAME_METHOD_ID_OFFSET));
@@ -111,7 +112,7 @@
         VM.sysWriteln("instr_beg = ", Magic.objectAsAddress(fooCM.getEntryCodeArray()));
 
         for (int i = (osrFPoff.toInt()) - 10; i < (osrFPoff.toInt()) + 10; i++) {
-          VM.sysWriteln("  stack[" + i + "] = " + stack[i]);
+          VM.sysWriteln("  stack[" + i + "] = " + stack.getByte(i));
         }
 
         Offset ipIndex = ipOffset.toWord().rsha(LG_INSTRUCTION_WIDTH).toOffset();
@@ -188,7 +189,7 @@
   }
 
   /* go over local/stack array, and build VariableElement. */
-  private static void getVariableValue(byte[] stack, Offset offset, byte[] types,
+  private static void getVariableValue(WordArray stack, Offset offset, byte[] types,
                                        BaselineCompiledMethod compiledMethod, boolean kind, ExecutionState state) {
     int size = types.length;
     Offset vOffset = offset;
diff -r 743a2cc2ed20 -r 058fdc3780ba rvm/src/org/jikesrvm/osr/ia32/CodeInstaller.java
--- a/rvm/src/org/jikesrvm/osr/ia32/CodeInstaller.java	Tue Aug 04 11:04:15 2009 +1000
+++ b/rvm/src/org/jikesrvm/osr/ia32/CodeInstaller.java	Mon Nov 16 09:21:21 2009 +1100
@@ -28,6 +28,7 @@
 import org.jikesrvm.scheduler.RVMThread;
 import org.vmmagic.unboxed.Address;
 import org.vmmagic.unboxed.Offset;
+import org.vmmagic.unboxed.WordArray;
 
 /**
  * CodeInstaller generates a glue code which recovers registers and
@@ -39,7 +40,7 @@
 
   public static boolean install(ExecutionState state, CompiledMethod cm) {
     RVMThread thread = state.getThread();
-    byte[] stack = thread.getStack();
+    WordArray stack = thread.getStack();
 
     Offset tsfromFPOffset = state.getTSFPOffset();
     Offset fooFPOffset = state.getFPOffset();
diff -r 743a2cc2ed20 -r 058fdc3780ba rvm/src/org/jikesrvm/osr/ia32/OptExecutionStateExtractor.java
--- a/rvm/src/org/jikesrvm/osr/ia32/OptExecutionStateExtractor.java	Tue Aug 04 11:04:15 2009 +1000
+++ b/rvm/src/org/jikesrvm/osr/ia32/OptExecutionStateExtractor.java	Mon Nov 16 09:21:21 2009 +1100
@@ -62,7 +62,7 @@
     * from the register save area of '<tsfrom>' method.
     */
 
-    byte[] stack = thread.getStack();
+    WordArray stack = thread.getStack();
 
     // get registers for the caller ( real method )
     TempRegisters registers = new TempRegisters(thread.contextRegisters);
@@ -163,7 +163,7 @@
     *    |FPR states|
     *    |__________|  ___ FP
   */
-  private void restoreValuesFromOptSaveVolatile(byte[] stack, Offset osrFPoff, TempRegisters registers, int regmap,
+  private void restoreValuesFromOptSaveVolatile(WordArray stack, Offset osrFPoff, TempRegisters registers, int regmap,
                                                 CompiledMethod cm) {
 
     OptCompiledMethod tsfromCM = (OptCompiledMethod) cm;
@@ -219,7 +219,7 @@
     }
   }
 
-  private ExecutionState getExecStateSequence(RVMThread thread, byte[] stack, Offset ipOffset, Offset fpOffset,
+  private ExecutionState getExecStateSequence(RVMThread thread, WordArray stack, Offset ipOffset, Offset fpOffset,
                                                   int cmid, Offset tsFPOffset, TempRegisters registers,
                                                   EncodedOSRMap osrmap) {
 
@@ -369,7 +369,7 @@
   }
 
   /** auxillary functions to get value from different places. */
-  private static int getIntBitsFrom(int vtype, int value, byte[] stack, Offset fpOffset, TempRegisters registers) {
+  private static int getIntBitsFrom(int vtype, int value, WordArray stack, Offset fpOffset, TempRegisters registers) {
     // for INT_CONST type, the value is the value
     if (vtype == ICONST || vtype == ACONST) {
       return value;
@@ -393,7 +393,7 @@
     }
   }
 
-  private static long getLongBitsFrom(int vtypeHigh, int valueHigh, int vtypeLow, int valueLow, byte[] stack, Offset fpOffset,
+  private static long getLongBitsFrom(int vtypeHigh, int valueHigh, int vtypeLow, int valueLow, WordArray stack, Offset fpOffset,
                                       TempRegisters registers) {
 
     // for LCONST type, the value is the value
@@ -439,7 +439,7 @@
     return -1L;
   }
 
-  private static double getDoubleFrom(int vtype, int value, byte[] stack, Offset fpOffset,
+  private static double getDoubleFrom(int vtype, int value, WordArray stack, Offset fpOffset,
                                       TempRegisters registers) {
     if (vtype == PHYREG) {
       return registers.fprs[value - FIRST_DOUBLE];
@@ -456,7 +456,7 @@
     }
   }
 
-  private static Object getObjectFrom(int vtype, int value, byte[] stack, Offset fpOffset,
+  private static Object getObjectFrom(int vtype, int value, WordArray stack, Offset fpOffset,
                                       TempRegisters registers) {
     if (vtype == ICONST) { //kv:todo : to become ACONST
       // the only constant object for 64bit addressing is NULL
@@ -511,7 +511,7 @@
 
   /* walk on stack frame, print out methods
    */
-  private static void walkOnStack(byte[] stack, Offset fpOffset) {
+  private static void walkOnStack(WordArray stack, Offset fpOffset) {
     VM.disableGC();
 
     Address fp = Magic.objectAsAddress(stack).plus(fpOffset);
diff -r 743a2cc2ed20 -r 058fdc3780ba rvm/src/org/jikesrvm/osr/ia32/TempRegisters.java
--- a/rvm/src/org/jikesrvm/osr/ia32/TempRegisters.java	Tue Aug 04 11:04:15 2009 +1000
+++ b/rvm/src/org/jikesrvm/osr/ia32/TempRegisters.java	Mon Nov 16 09:21:21 2009 +1100
@@ -15,6 +15,7 @@
 import org.jikesrvm.VM;
 import org.jikesrvm.ia32.ArchConstants;
 import org.jikesrvm.ia32.Registers;
+import org.jikesrvm.runtime.Memory;
 import org.vmmagic.unboxed.Address;
 import org.vmmagic.unboxed.WordArray;
 
@@ -43,7 +44,7 @@
     for (int i = 0; i < NUM_GPRS; i++) {
       gprs.set(i, contextRegisters.gprs.get(i));
     }
-    System.arraycopy(contextRegisters.fprs, 0, fprs, 0, NUM_FPRS);
+    Memory.nativeMarshal(contextRegisters.fprs, fprs);
     ip = contextRegisters.ip;
   }
 
diff -r 743a2cc2ed20 -r 058fdc3780ba rvm/src/org/jikesrvm/osr/ppc/BaselineExecutionStateExtractor.java
--- a/rvm/src/org/jikesrvm/osr/ppc/BaselineExecutionStateExtractor.java	Tue Aug 04 11:04:15 2009 +1000
+++ b/rvm/src/org/jikesrvm/osr/ppc/BaselineExecutionStateExtractor.java	Mon Nov 16 09:21:21 2009 +1100
@@ -75,7 +75,7 @@
     }
 
     Registers contextRegisters = (Registers)thread.getContextRegisters();
-    byte[] stack = thread.getStack();
+    WordArray stack = thread.getStack();
 
     if (VM.VerifyAssertions) {
       int fooCmid = Magic.getIntAtOffset(stack, methFPoff.plus(STACKFRAME_METHOD_ID_OFFSET));
@@ -247,7 +247,7 @@
   }
 
   /** go over local/stack array, and build VariableElement. */
-  private static void getVariableValueFromLocations(byte[] stack, Offset methFPoff, byte[] types,
+  private static void getVariableValueFromLocations(WordArray stack, Offset methFPoff, byte[] types,
                                                     BaselineCompiledMethod compiledMethod, boolean kind,
                                                     TempRegisters registers, ExecutionState state) {
     int start = 0;
@@ -393,7 +393,7 @@
   }
 
   /* go over local/stack array, and build VariableElement. */
-  private static void getVariableValue(byte[] stack, Offset offset, byte[] types,
+  private static void getVariableValue(WordArray stack, Offset offset, byte[] types,
                                        BaselineCompiledMethod compiledMethod, boolean kind, ExecutionState state) {
     int size = types.length;
     Offset vOffset = offset;
diff -r 743a2cc2ed20 -r 058fdc3780ba rvm/src/org/jikesrvm/osr/ppc/CodeInstaller.java
--- a/rvm/src/org/jikesrvm/osr/ppc/CodeInstaller.java	Tue Aug 04 11:04:15 2009 +1000
+++ b/rvm/src/org/jikesrvm/osr/ppc/CodeInstaller.java	Mon Nov 16 09:21:21 2009 +1100
@@ -30,6 +30,7 @@
 import org.jikesrvm.scheduler.RVMThread;
 import org.vmmagic.unboxed.Address;
 import org.vmmagic.unboxed.Offset;
+import org.vmmagic.unboxed.WordArray;
 
 /**
  * CodeInstaller adjusts registers and return address to make a
@@ -43,7 +44,7 @@
   public static boolean install(ExecutionState state, CompiledMethod cm) {
 
     RVMThread thread = state.getThread();
-    byte[] stack = thread.getStack();
+    WordArray stack = thread.getStack();
 
     Offset fooFPOffset = state.getFPOffset();
 
diff -r 743a2cc2ed20 -r 058fdc3780ba rvm/src/org/jikesrvm/osr/ppc/OptExecutionStateExtractor.java
--- a/rvm/src/org/jikesrvm/osr/ppc/OptExecutionStateExtractor.java	Tue Aug 04 11:04:15 2009 +1000
+++ b/rvm/src/org/jikesrvm/osr/ppc/OptExecutionStateExtractor.java	Mon Nov 16 09:21:21 2009 +1100
@@ -61,7 +61,7 @@
     * the register save area of '<tsfrom>' method.
     */
 
-    byte[] stack = thread.getStack();
+    WordArray stack = thread.getStack();
 
     // get registers for the caller ( real method )
     TempRegisters registers = new TempRegisters((Registers)thread.getContextRegisters());
@@ -160,7 +160,7 @@
    *
    *   GPR 3 -- 14 15 16 17 -- 31, cr, xer, ctr, FPR 0 -- 15
    */
-  private void restoreValuesFromOptSaveVolatile(byte[] stack, Offset osrFPoff, TempRegisters registers, int regmap,
+  private void restoreValuesFromOptSaveVolatile(WordArray stack, Offset osrFPoff, TempRegisters registers, int regmap,
                                                 CompiledMethod cm) {
 
     OptCompiledMethod tsfromCM = (OptCompiledMethod) cm;
@@ -233,7 +233,7 @@
     registers.ctr = ctr;
   }
 
-  private ExecutionState getExecStateSequence(RVMThread thread, byte[] stack, Offset ipOffset, Offset fpOffset,
+  private ExecutionState getExecStateSequence(RVMThread thread, WordArray stack, Offset ipOffset, Offset fpOffset,
                                                   int cmid, Offset tsFPOffset, TempRegisters registers,
                                                   EncodedOSRMap osrmap) {
 
@@ -366,7 +366,7 @@
   }
 
   /** auxillary functions to get value from different places. */
-  private static int getIntBitsFrom(int vtype, int value, byte[] stack, Offset fpOffset, TempRegisters registers) {
+  private static int getIntBitsFrom(int vtype, int value, WordArray stack, Offset fpOffset, TempRegisters registers) {
     // for INT_CONST type, the value is the value
     if (vtype == ICONST || vtype == ACONST) {
       return value;
@@ -391,7 +391,7 @@
     }
   }
 
-  private static long getLongBitsFrom(int vtype, int valueHigh, int valueLow, byte[] stack, Offset fpOffset,
+  private static long getLongBitsFrom(int vtype, int valueHigh, int valueLow, WordArray stack, Offset fpOffset,
                                       TempRegisters registers) {
 
     // for LCONST type, the value is the value
@@ -432,7 +432,7 @@
     return -1L;
   }
 
-  private static double getDoubleFrom(int vtype, int value, byte[] stack, Offset fpOffset,
+  private static double getDoubleFrom(int vtype, int value, WordArray stack, Offset fpOffset,
                                       TempRegisters registers) {
     if (vtype == PHYREG) {
       return registers.fprs[value];
@@ -445,7 +445,7 @@
     }
   }
 
-  private static Object getObjectFrom(int vtype, int value, byte[] stack, Offset fpOffset,
+  private static Object getObjectFrom(int vtype, int value, WordArray stack, Offset fpOffset,
                                       TempRegisters registers) {
     if (vtype == ACONST) {
       // the only constant object is NULL, I believe.
@@ -463,7 +463,7 @@
   }
 
   @SuppressWarnings("unused")
-  private static void dumpStackContent(byte[] stack, Offset fpOffset) {
+  private static void dumpStackContent(WordArray stack, Offset fpOffset) {
     VM.disableGC();
     Address upper = Magic.objectAsAddress(stack).loadAddress(fpOffset);
     Offset upOffset = upper.diff(Magic.objectAsAddress(stack));
@@ -487,7 +487,7 @@
 
   /* walk on stack frame, print out methods
    */
-  private static void walkOnStack(byte[] stack, Offset fpOffset) {
+  private static void walkOnStack(WordArray stack, Offset fpOffset) {
     int cmid = STACKFRAME_SENTINEL_FP.toInt();
     do {
       cmid = Magic.getIntAtOffset(stack, fpOffset.plus(STACKFRAME_METHOD_ID_OFFSET));
diff -r 743a2cc2ed20 -r 058fdc3780ba rvm/src/org/jikesrvm/ppc/MachineReflection.java
--- a/rvm/src/org/jikesrvm/ppc/MachineReflection.java	Tue Aug 04 11:04:15 2009 +1000
+++ b/rvm/src/org/jikesrvm/ppc/MachineReflection.java	Mon Nov 16 09:21:21 2009 +1100
@@ -16,6 +16,7 @@
 import org.jikesrvm.Constants;
 import org.jikesrvm.classloader.RVMMethod;
 import org.jikesrvm.classloader.TypeReference;
+import org.jikesrvm.mm.mminterface.MemoryManager;
 import org.jikesrvm.runtime.Memory;
 import org.jikesrvm.runtime.Reflection;
 import org.vmmagic.unboxed.Word;
@@ -108,9 +109,9 @@
    * Collect parameters into arrays of registers/spills, as required to call specified method.
    */
   public static void packageParameters(RVMMethod method, Object thisArg, Object[] otherArgs, WordArray GPRs,
-                                       double[] FPRs, byte[] FPRmeta, WordArray Spills) {
+                                       WordArray FPRs, WordArray FPRmeta, WordArray Spills) {
     int GPR = GPRs.length();
-    int FPR = FPRs.length;
+    int FPR = MemoryManager.nativeLongBufferLength(FPRs);
     int Spill = Spills.length();
     int gp = FIRST_VOLATILE_GPR;
     int fp = FIRST_VOLATILE_FPR;
@@ -157,7 +158,7 @@
           Spills.set(--Spill, Word.fromIntZeroExtend(Float.floatToIntBits(f)));
         } else {
           fp++;
-          FPRs[--FPR] = f;
+          FPRs.setLong(--FPR, Double.doubleToLongBits(f));
         }
       } else if (t.isDoubleType()) {
         if (fp > LAST_VOLATILE_FPR) {
@@ -171,7 +172,7 @@
           }
         } else {
           fp++;
-          FPRs[--FPR] = Reflection.unwrapDouble(otherArgs[i]);
+          FPRs.setLong(--FPR, Double.doubleToLongBits(Reflection.unwrapDouble(otherArgs[i])));
         }
       } else if (t.isBooleanType()) {
         Word val = Word.fromIntZeroExtend(Reflection.unwrapBooleanAsInt(otherArgs[i]));
diff -r 743a2cc2ed20 -r 058fdc3780ba rvm/src/org/jikesrvm/ppc/Registers.java
--- a/rvm/src/org/jikesrvm/ppc/Registers.java	Tue Aug 04 11:04:15 2009 +1000
+++ b/rvm/src/org/jikesrvm/ppc/Registers.java	Mon Nov 16 09:21:21 2009 +1100
@@ -32,9 +32,9 @@
   @Untraced
   public final WordArray gprs; // word size general purpose registers (either 32 or 64 bit)
   @Untraced
-  public final double[] fprs; // 64-bit floating point registers
+  public final WordArray fprs; // 64-bit floating point registers
   public final WordArray gprsShadow;
-  public final double[] fprsShadow;
+  public final WordArray fprsShadow;
   public Address ip; // instruction address register
 
   // The following are used by exception delivery.
@@ -49,7 +49,7 @@
 
   public Registers() {
     gprs = gprsShadow = MemoryManager.newNonMovingWordArray(NUM_GPRS);
-    fprs = fprsShadow = MemoryManager.newNonMovingDoubleArray(NUM_FPRS);
+    fprs = fprsShadow = MemoryManager.createNonMovingNativeLongBuffer(NUM_FPRS);
     ip = invalidIP;
   }
 
diff -r 743a2cc2ed20 -r 058fdc3780ba rvm/src/org/jikesrvm/runtime/ArchEntrypoints.java
--- a/rvm/src/org/jikesrvm/runtime/ArchEntrypoints.java	Tue Aug 04 11:04:15 2009 +1000
+++ b/rvm/src/org/jikesrvm/runtime/ArchEntrypoints.java	Mon Nov 16 09:21:21 2009 +1100
@@ -38,7 +38,7 @@
                ArchCodeArrayName);
   RVMField registersIPField =
       EntrypointHelper.getField("Lorg/jikesrvm/" + arch + "/Registers;", "ip", "Lorg/vmmagic/unboxed/Address;");
-  RVMField registersFPRsField = EntrypointHelper.getField("Lorg/jikesrvm/" + arch + "/Registers;", "fprs", "[D");
+  RVMField registersFPRsField = EntrypointHelper.getField("Lorg/jikesrvm/" + arch + "/Registers;", "fprs", "Lorg/vmmagic/unboxed/WordArray;");
   RVMField registersGPRsField =
       EntrypointHelper.getField("Lorg/jikesrvm/" + arch + "/Registers;", "gprs", "Lorg/vmmagic/unboxed/WordArray;");
   RVMField registersInUseField = EntrypointHelper.getField("Lorg/jikesrvm/" + arch + "/Registers;", "inuse", "Z");
diff -r 743a2cc2ed20 -r 058fdc3780ba rvm/src/org/jikesrvm/runtime/DynamicLibrary.java
--- a/rvm/src/org/jikesrvm/runtime/DynamicLibrary.java	Tue Aug 04 11:04:15 2009 +1000
+++ b/rvm/src/org/jikesrvm/runtime/DynamicLibrary.java	Mon Nov 16 09:21:21 2009 +1100
@@ -15,6 +15,7 @@
 import java.util.Iterator;
 import org.jikesrvm.ArchitectureSpecific.StackframeLayoutConstants;
 import org.jikesrvm.VM;
+import org.jikesrvm.mm.mminterface.MemoryManager;
 import org.jikesrvm.scheduler.Scheduler;
 import org.jikesrvm.scheduler.RVMThread;
 import org.jikesrvm.scheduler.greenthreads.FileSystem;
@@ -84,7 +85,7 @@
       }
     }
 
-    libHandler = SysCall.sysCall.sysDlopen(asciiName);
+    libHandler = SysCall.sysCall.sysDlopen(MemoryManager.cloneToNativeBuffer(asciiName));
 
     if (libHandler.isZero()) {
       VM.sysWriteln("error loading library: " + libraryName);
@@ -190,7 +191,7 @@
     // (assume file name is ascii, for now).
     //
     byte[] asciiName = StringUtilities.stringToBytesNullTerminated(symbolName);
-    return SysCall.sysCall.sysDlsym(libHandler, asciiName);
+    return SysCall.sysCall.sysDlsym(libHandler, MemoryManager.cloneToNativeBuffer(asciiName));
   }
 
   /**
diff -r 743a2cc2ed20 -r 058fdc3780ba rvm/src/org/jikesrvm/runtime/Entrypoints.java
--- a/rvm/src/org/jikesrvm/runtime/Entrypoints.java	Tue Aug 04 11:04:15 2009 +1000
+++ b/rvm/src/org/jikesrvm/runtime/Entrypoints.java	Mon Nov 16 09:21:21 2009 +1100
@@ -19,6 +19,7 @@
 import org.jikesrvm.classloader.RVMField;
 import org.jikesrvm.classloader.RVMMethod;
 import org.jikesrvm.classloader.NormalMethod;
+import org.vmmagic.unboxed.WordArray;
 
 /**
  * Fields and methods of the virtual machine that are needed by
@@ -131,7 +132,7 @@
   public static final NormalMethod resolveMemberMethod =
       getMethod(org.jikesrvm.classloader.TableBasedDynamicLinker.class, "resolveMember", "(I)I");
   public static final RVMField memberOffsetsField =
-      getField(org.jikesrvm.classloader.TableBasedDynamicLinker.class, "memberOffsets", int[].class);
+      getField(org.jikesrvm.classloader.TableBasedDynamicLinker.class, "memberOffsets", WordArray.class);
 
   /** 1L */
   public static final RVMField longOneField = getField(org.jikesrvm.runtime.MathConstants.class, "longOne", long.class);
@@ -216,7 +217,7 @@
   public static final NormalMethod threadRunMethod = getMethod(org.jikesrvm.scheduler.RVMThread.class, "run", "()V");
   public static final NormalMethod threadStartoffMethod =
       getMethod(org.jikesrvm.scheduler.RVMThread.class, "startoff", "()V");
-  public static final RVMField threadStackField = getField(org.jikesrvm.scheduler.RVMThread.class, "stack", byte[].class);
+  public static final RVMField threadStackField = getField(org.jikesrvm.scheduler.RVMThread.class, "stack", WordArray.class);
   public static final RVMField stackLimitField =
       getField(org.jikesrvm.scheduler.RVMThread.class, "stackLimit", org.vmmagic.unboxed.Address.class);
 
@@ -255,6 +256,21 @@
   public static final RVMField synchronizedCounterField =
       getField(org.jikesrvm.mm.mmtk.SynchronizedCounter.class, "count", int.class);
 
+  //jbs added
+  public static final NormalMethod arrayStorePrimitiveShortWriteBarrierMethod = 
+	  getMethod(org.jikesrvm.mm.mminterface.MemoryManager.class, "arrayStorePrimitiveShortWriteBarrier", "(Ljava/lang/Object;IS)V");
+  public static final NormalMethod arrayStorePrimitiveCharWriteBarrierMethod = 
+	  getMethod(org.jikesrvm.mm.mminterface.MemoryManager.class, "arrayStorePrimitiveCharWriteBarrier", "(Ljava/lang/Object;IC)V");
+  public static final NormalMethod arrayStorePrimitiveByteWriteBarrierMethod = 
+	  getMethod(org.jikesrvm.mm.mminterface.MemoryManager.class, "arrayStorePrimitiveByteWriteBarrier", "(Ljava/lang/Object;IB)V");
+  public static final NormalMethod arrayStorePrimitiveFloatWriteBarrierMethod = 
+	  getMethod(org.jikesrvm.mm.mminterface.MemoryManager.class, "arrayStorePrimitiveFloatWriteBarrier", "(Ljava/lang/Object;IF)V");
+  public static final NormalMethod arrayStorePrimitiveIntWriteBarrierMethod = 
+	  getMethod(org.jikesrvm.mm.mminterface.MemoryManager.class, "arrayStorePrimitiveIntWriteBarrier", "(Ljava/lang/Object;II)V");
+  public static final NormalMethod arrayStorePrimitiveLongWriteBarrierMethod = 
+	  getMethod(org.jikesrvm.mm.mminterface.MemoryManager.class, "arrayStorePrimitiveLongWriteBarrier", "(Ljava/lang/Object;IJ)V");
+  public static final NormalMethod arrayStorePrimitiveDoubleWriteBarrierMethod = 
+	  getMethod(org.jikesrvm.mm.mminterface.MemoryManager.class, "arrayStorePrimitiveDoubleWriteBarrier", "(Ljava/lang/Object;ID)V");
   public static final NormalMethod arrayStoreWriteBarrierMethod =
       getMethod(org.jikesrvm.mm.mminterface.MemoryManager.class, "arrayStoreWriteBarrier", "(Ljava/lang/Object;ILjava/lang/Object;)V");
   public static final NormalMethod putfieldWriteBarrierMethod =
@@ -262,6 +278,22 @@
   public static final NormalMethod putstaticWriteBarrierMethod =
       getMethod(org.jikesrvm.mm.mminterface.MemoryManager.class, "putstaticWriteBarrier", "(Lorg/vmmagic/unboxed/Offset;Ljava/lang/Object;I)V");
 
+  public static final NormalMethod arrayLoadPrimitiveShortReadBarrierMethod =
+      getMethod(org.jikesrvm.mm.mminterface.MemoryManager.class, "arrayLoadPrimitiveShortReadBarrier", "(Ljava/lang/Object;I)S");
+  public static final NormalMethod arrayLoadPrimitiveCharReadBarrierMethod =
+      getMethod(org.jikesrvm.mm.mminterface.MemoryManager.class, "arrayLoadPrimitiveCharReadBarrier", "(Ljava/lang/Object;I)C");
+  public static final NormalMethod arrayLoadPrimitiveByteReadBarrierMethod =
+      getMethod(org.jikesrvm.mm.mminterface.MemoryManager.class, "arrayLoadPrimitiveByteReadBarrier", "(Ljava/lang/Object;I)B");
+  public static final NormalMethod arrayLoadPrimitiveFloatReadBarrierMethod =
+      getMethod(org.jikesrvm.mm.mminterface.MemoryManager.class, "arrayLoadPrimitiveFloatReadBarrier", "(Ljava/lang/Object;I)F");
+  public static final NormalMethod arrayLoadPrimitiveIntReadBarrierMethod =
+      getMethod(org.jikesrvm.mm.mminterface.MemoryManager.class, "arrayLoadPrimitiveIntReadBarrier", "(Ljava/lang/Object;I)I");
+  public static final NormalMethod arrayLoadPrimitiveLongReadBarrierMethod =
+      getMethod(org.jikesrvm.mm.mminterface.MemoryManager.class, "arrayLoadPrimitiveLongReadBarrier", "(Ljava/lang/Object;I)J");
+  public static final NormalMethod arrayLoadPrimitiveDoubleReadBarrierMethod =
+      getMethod(org.jikesrvm.mm.mminterface.MemoryManager.class, "arrayLoadPrimitiveDoubleReadBarrier", "(Ljava/lang/Object;I)D");
+  public static final NormalMethod hackArrayLoadReadBarrierMethod =
+      getMethod(org.jikesrvm.mm.mminterface.MemoryManager.class, "hackArrayLoadReadBarrier", "(Ljava/lang/Object;I)Ljava/lang/Object;");
   public static final NormalMethod arrayLoadReadBarrierMethod =
       getMethod(org.jikesrvm.mm.mminterface.MemoryManager.class, "arrayLoadReadBarrier", "(Ljava/lang/Object;I)Ljava/lang/Object;");
   public static final NormalMethod getfieldReadBarrierMethod =
@@ -339,7 +371,7 @@
       getField(org.jikesrvm.runtime.BootRecord.class, "sysDoubleRemainderIP", org.vmmagic.unboxed.Address.class);
 
   public static final RVMField edgeCountersField =
-      getField(org.jikesrvm.compilers.baseline.EdgeCounts.class, "data", int[][].class);
+      getField(org.jikesrvm.compilers.baseline.EdgeCounts.class, "data", WordArray[].class);
 
   public static final RVMField inetAddressAddressField = VM.BuildForGnuClasspath ?
       getField(java.net.InetAddress.class, "address", int.class) : null;
diff -r 743a2cc2ed20 -r 058fdc3780ba rvm/src/org/jikesrvm/runtime/Magic.java
--- a/rvm/src/org/jikesrvm/runtime/Magic.java	Tue Aug 04 11:04:15 2009 +1000
+++ b/rvm/src/org/jikesrvm/runtime/Magic.java	Mon Nov 16 09:21:21 2009 +1100
@@ -721,6 +721,12 @@
     return (int[]) object;
   }
 
+  public static WordArray objectAsWordArray(Object object) {
+    if (VM.runningVM && VM.VerifyAssertions) {
+      VM._assert(VM.NOT_REACHED);  // call site should have been hijacked by magic in compiler
+    }
+    return (WordArray) object;
+  }
   //---------------------------------------//
   //          Object Header Access.        //
   //---------------------------------------//
@@ -828,36 +834,36 @@
   }
 
   /** Call arbitrary method with argument list. */
-  public static void invokeMethodReturningVoid(CodeArray code, WordArray gprs, double[] fprs, byte[] fprmeta, WordArray spills) {
+  public static void invokeMethodReturningVoid(CodeArray code, WordArray gprs, WordArray fprs, WordArray fprmeta, WordArray spills) {
     if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED);  // call site should have been hijacked by magic in compiler
   }
 
   /** Call arbitrary method with argument list. */
-  public static int invokeMethodReturningInt(CodeArray code, WordArray gprs, double[] fprs, byte[] fprmeta, WordArray spills) {
+  public static int invokeMethodReturningInt(CodeArray code, WordArray gprs, WordArray fprs, WordArray fprmeta, WordArray spills) {
     if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED);  // call site should have been hijacked by magic in compiler
     return -1;
   }
 
   /** Call arbitrary method with argument list. */
-  public static long invokeMethodReturningLong(CodeArray code, WordArray gprs, double[] fprs, byte[] fprmeta, WordArray spills) {
+  public static long invokeMethodReturningLong(CodeArray code, WordArray gprs, WordArray fprs, WordArray fprmeta, WordArray spills) {
     if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED);  // call site should have been hijacked by magic in compiler
     return -1;
   }
 
   /** Call arbitrary method with argument list. */
-  public static float invokeMethodReturningFloat(CodeArray code, WordArray gprs, double[] fprs, byte[] fprmeta, WordArray spills) {
+  public static float invokeMethodReturningFloat(CodeArray code, WordArray gprs, WordArray fprs, WordArray fprmeta, WordArray spills) {
     if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED);  // call site should have been hijacked by magic in compiler
     return -1;
   }
 
   /** Call arbitrary method with argument list. */
-  public static double invokeMethodReturningDouble(CodeArray code, WordArray gprs, double[] fprs, byte[] fprmeta, WordArray spills) {
+  public static double invokeMethodReturningDouble(CodeArray code, WordArray gprs, WordArray fprs, WordArray fprmeta, WordArray spills) {
     if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED);  // call site should have been hijacked by magic in compiler
     return -1;
   }
 
   /** Call arbitrary method with argument list. */
-  public static Object invokeMethodReturningObject(CodeArray code, WordArray gprs, double[] fprs, byte[] fprmeta, WordArray spills) {
+  public static Object invokeMethodReturningObject(CodeArray code, WordArray gprs, WordArray fprs, WordArray fprmeta, WordArray spills) {
     if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED);  // call site should have been hijacked by magic in compiler
     return null;
   }
diff -r 743a2cc2ed20 -r 058fdc3780ba rvm/src/org/jikesrvm/runtime/MagicNames.java
--- a/rvm/src/org/jikesrvm/runtime/MagicNames.java	Tue Aug 04 11:04:15 2009 +1000
+++ b/rvm/src/org/jikesrvm/runtime/MagicNames.java	Mon Nov 16 09:21:21 2009 +1100
@@ -117,6 +117,7 @@
   public static final Atom addressAsByteArray = Atom.findOrCreateAsciiAtom("addressAsByteArray");
   public static final Atom objectAsShortArray = Atom.findOrCreateAsciiAtom("objectAsShortArray");
   public static final Atom objectAsIntArray = Atom.findOrCreateAsciiAtom("objectAsIntArray");
+  public static final Atom objectAsWordArray = Atom.findOrCreateAsciiAtom("objectAsWordArray");
   public static final Atom codeArrayAsObject = Atom.findOrCreateAsciiAtom("codeArrayAsObject");
   public static final Atom tibAsObject = Atom.findOrCreateAsciiAtom("tibAsObject");
 
@@ -192,4 +193,12 @@
   public static final Atom addressArrayLength = Atom.findOrCreateAsciiAtom("length");
   public static final Atom addressArrayGet = Atom.findOrCreateAsciiAtom("get");
   public static final Atom addressArraySet = Atom.findOrCreateAsciiAtom("set");
+  public static final Atom addressArrayGetByte = Atom.findOrCreateAsciiAtom("getByte");
+  public static final Atom addressArraySetByte = Atom.findOrCreateAsciiAtom("setByte");
+  public static final Atom addressArrayGetChar = Atom.findOrCreateAsciiAtom("getChar");
+  public static final Atom addressArraySetChar = Atom.findOrCreateAsciiAtom("setChar");
+  public static final Atom addressArrayGetInt = Atom.findOrCreateAsciiAtom("getInt");
+  public static final Atom addressArraySetInt = Atom.findOrCreateAsciiAtom("setInt");
+  public static final Atom addressArrayGetLong = Atom.findOrCreateAsciiAtom("getLong");
+  public static final Atom addressArraySetLong = Atom.findOrCreateAsciiAtom("setLong");
 }
diff -r 743a2cc2ed20 -r 058fdc3780ba rvm/src/org/jikesrvm/runtime/Memory.java
--- a/rvm/src/org/jikesrvm/runtime/Memory.java	Tue Aug 04 11:04:15 2009 +1000
+++ b/rvm/src/org/jikesrvm/runtime/Memory.java	Mon Nov 16 09:21:21 2009 +1100
@@ -17,14 +17,29 @@
 import static org.jikesrvm.SizeConstants.LOG_BYTES_IN_DOUBLE;
 import static org.jikesrvm.SizeConstants.LOG_BYTES_IN_INT;
 import static org.jikesrvm.SizeConstants.LOG_BYTES_IN_SHORT;
-
+import static org.jikesrvm.SizeConstants.LOG_BYTES_IN_CHAR;
+import static org.jikesrvm.SizeConstants.LOG_BYTES_IN_FLOAT;
+import static org.jikesrvm.SizeConstants.LOG_BYTES_IN_LONG;
+import static org.jikesrvm.mm.mminterface.MemoryManagerConstants.USE_PRIMITIVE_BOOLEAN_ARRAYLETS;
+import static org.jikesrvm.mm.mminterface.MemoryManagerConstants.USE_PRIMITIVE_BYTE_ARRAYLETS;
+import static org.jikesrvm.mm.mminterface.MemoryManagerConstants.USE_PRIMITIVE_CHAR_ARRAYLETS;
+import static org.jikesrvm.mm.mminterface.MemoryManagerConstants.USE_PRIMITIVE_SHORT_ARRAYLETS;
+import static org.jikesrvm.mm.mminterface.MemoryManagerConstants.USE_PRIMITIVE_INT_ARRAYLETS;
+import static org.jikesrvm.mm.mminterface.MemoryManagerConstants.USE_PRIMITIVE_FLOAT_ARRAYLETS;
+import static org.jikesrvm.mm.mminterface.MemoryManagerConstants.USE_PRIMITIVE_DOUBLE_ARRAYLETS;
+import static org.jikesrvm.mm.mminterface.MemoryManagerConstants.USE_PRIMITIVE_LONG_ARRAYLETS;
 import org.jikesrvm.VM;
+import org.jikesrvm.classloader.RVMArray;
+import org.jikesrvm.mm.mminterface.MemoryManagerConstants;
+import org.jikesrvm.mm.mminterface.MemoryManager; //jbs added
+import org.jikesrvm.scheduler.Scheduler;
 import org.vmmagic.pragma.Inline;
 import org.vmmagic.pragma.Uninterruptible;
 import org.vmmagic.unboxed.Address;
 import org.vmmagic.unboxed.Extent;
 import org.vmmagic.unboxed.Offset;
 import org.vmmagic.unboxed.Word;
+import org.vmmagic.unboxed.WordArray;
 
 /**
  * Low level memory management functions.
@@ -94,13 +109,28 @@
    * @param len     number of array elements to copy
    */
   public static void arraycopy8Bit(Object src, int srcPos, Object dst, int dstPos, int len) {
+    arraycopy8Bit(Magic.objectAsAddress(src), srcPos, Magic.objectAsAddress(dst), dstPos, len);
+  }
+
+  /**
+   * Low level copy of len elements from src[srcPos] to dst[dstPos].
+   *
+   * Assumptions: <code> src != dst || (scrPos >= dstPos + 4) </code>
+   *              and src and dst are 8Bit arrays.
+   * @param srcAddr the source address
+   * @param srcPos  index in the source array to begin copy
+   * @param dstAddr the destination address
+   * @param dstPos  index in the destination array to being copy
+   * @param len     number of array elements to copy
+   */
+  public static void arraycopy8Bit(Address srcAddr, int srcPos, Address dstAddr, int dstPos, int len) {
     if (USE_NATIVE && len > NATIVE_THRESHOLD) {
-      memcopy(Magic.objectAsAddress(dst).plus(dstPos), Magic.objectAsAddress(src).plus(srcPos), len);
+      memcopy(dstAddr.plus(dstPos), srcAddr.plus(srcPos), len);
     } else {
       if (len >= BYTES_IN_COPY && (srcPos & (BYTES_IN_COPY - 1)) == (dstPos & (BYTES_IN_COPY - 1))) {
         // relative alignment is the same
-        Address srcPtr = Magic.objectAsAddress(src).plus(srcPos);
-        Address dstPtr = Magic.objectAsAddress(dst).plus(dstPos);
+        Address srcPtr = srcAddr.plus(srcPos);
+        Address dstPtr = dstAddr.plus(dstPos);
         Address endPtr = srcPtr.plus(len);
         Address wordEndPtr = endPtr.toWord().and(Word.fromIntZeroExtend(BYTES_IN_COPY-1).not()).toAddress();
 
@@ -167,8 +197,8 @@
           }
         }
       } else {
-        Address srcPtr = Magic.objectAsAddress(src).plus(srcPos);
-        Address dstPtr = Magic.objectAsAddress(dst).plus(dstPos);
+        Address srcPtr = srcAddr.plus(srcPos);
+        Address dstPtr = dstAddr.plus(dstPos);
         Address endPtr = srcPtr.plus(len);
         while (srcPtr.LT(endPtr)) {
           dstPtr.store(srcPtr.loadByte());
@@ -191,17 +221,32 @@
    * @param len     number of array elements to copy
    */
   public static void arraycopy16Bit(Object src, int srcPos, Object dst, int dstPos, int len) {
+    arraycopy16Bit(Magic.objectAsAddress(src), srcPos, Magic.objectAsAddress(dst), dstPos, len);
+  }
+
+  /**
+   * Low level copy of len elements from src[srcPos] to dst[dstPos].
+   *
+   * Assumption src != dst || (srcPos >= dstPos + 2).
+   *
+   * @param srcAddr the source address
+   * @param srcPos  index in the source array to begin copy
+   * @param dstAddr the destination address
+   * @param dstPos  index in the destination array to being copy
+   * @param len     number of array elements to copy
+   */
+  public static void arraycopy16Bit(Address srcAddr, int srcPos, Address dstAddr, int dstPos, int len) {
     if (USE_NATIVE && len > (NATIVE_THRESHOLD >> LOG_BYTES_IN_SHORT)) {
-      memcopy(Magic.objectAsAddress(dst).plus(dstPos << LOG_BYTES_IN_SHORT),
-              Magic.objectAsAddress(src).plus(srcPos << LOG_BYTES_IN_SHORT),
+      memcopy(dstAddr.plus(dstPos << LOG_BYTES_IN_SHORT),
+              srcAddr.plus(srcPos << LOG_BYTES_IN_SHORT),
               len << LOG_BYTES_IN_SHORT);
     } else {
       if (len >= (BYTES_IN_COPY >>> LOG_BYTES_IN_SHORT) &&
           (srcPos & ((BYTES_IN_COPY - 1) >>> LOG_BYTES_IN_SHORT)) ==
           (dstPos & ((BYTES_IN_COPY - 1) >>> LOG_BYTES_IN_SHORT))) {
         // relative alignment is the same
-        Address srcPtr = Magic.objectAsAddress(src).plus(srcPos << LOG_BYTES_IN_SHORT);
-        Address dstPtr = Magic.objectAsAddress(dst).plus(dstPos << LOG_BYTES_IN_SHORT);
+        Address srcPtr = srcAddr.plus(srcPos << LOG_BYTES_IN_SHORT);
+        Address dstPtr = dstAddr.plus(dstPos << LOG_BYTES_IN_SHORT);
         Address endPtr = srcPtr.plus(len << LOG_BYTES_IN_SHORT);
         Address wordEndPtr = endPtr.toWord().and(Word.fromIntZeroExtend(BYTES_IN_COPY-1).not()).toAddress();
 
@@ -248,8 +293,8 @@
           }
         }
       } else {
-        Address srcPtr = Magic.objectAsAddress(src).plus(srcPos << LOG_BYTES_IN_SHORT);
-        Address dstPtr = Magic.objectAsAddress(dst).plus(dstPos << LOG_BYTES_IN_SHORT);
+        Address srcPtr = srcAddr.plus(srcPos << LOG_BYTES_IN_SHORT);
+        Address dstPtr = dstAddr.plus(dstPos << LOG_BYTES_IN_SHORT);
         Address endPtr = srcPtr.plus(len << LOG_BYTES_IN_SHORT);
         while (srcPtr.LT(endPtr)) {
           copy2Bytes(dstPtr, srcPtr);
@@ -266,14 +311,29 @@
    * Assumption: <code>src != dst || (srcPos >= dstPos)</code> and element size is 4 bytes.
    *
    * @param src     the source array
-   * @param srcIdx  index in the source array to begin copy
+   * @param srcPos  index in the source array to begin copy
    * @param dst     the destination array
-   * @param dstIdx  index in the destination array to being copy
+   * @param dstPos  index in the destination array to being copy
    * @param len     number of array elements to copy
    */
-  public static void arraycopy32Bit(Object src, int srcIdx, Object dst, int dstIdx, int len) {
-    Address srcPtr = Magic.objectAsAddress(src).plus(srcIdx << LOG_BYTES_IN_INT);
-    Address dstPtr = Magic.objectAsAddress(dst).plus(dstIdx << LOG_BYTES_IN_INT);
+  public static void arraycopy32Bit(Object src, int srcPos, Object dst, int dstPos, int len) {
+    arraycopy32Bit(Magic.objectAsAddress(src), srcPos, Magic.objectAsAddress(dst), dstPos, len);
+  }
+
+  /**
+   * Low level copy of <code>len</code> elements from <code>src[srcPos]</code> to <code>dst[dstPos]</code>.
+   *
+   * Assumption: <code>src != dst || (srcPos >= dstPos)</code> and element size is 4 bytes.
+   *
+   * @param srcAddr the source address
+   * @param srcPos  index in the source array to begin copy
+   * @param dstAddr the destination address
+   * @param dstPos  index in the destination array to being copy
+   * @param len     number of array elements to copy
+   */
+  public static void arraycopy32Bit(Address srcAddr, int srcPos, Address dstAddr, int dstPos, int len) {
+    Address srcPtr = srcAddr.plus(srcPos << LOG_BYTES_IN_INT);
+    Address dstPtr = dstAddr.plus(dstPos << LOG_BYTES_IN_INT);
     int copyBytes = len << LOG_BYTES_IN_INT;
     if (USE_NATIVE && len > (NATIVE_THRESHOLD >> LOG_BYTES_IN_INT)) {
       memcopy(dstPtr, srcPtr, copyBytes);
@@ -297,14 +357,29 @@
    * Assumption <code>src != dst || (srcPos >= dstPos)</code> and element size is 8 bytes.
    *
    * @param src     the source array
+   * @param srcPos  index in the source array to begin copy
+   * @param dst     the destination array
+   * @param dstPos  index in the destination array to being copy
+   * @param len     number of array elements to copy
+   */
+  public static void arraycopy64Bit(Object src, int srcPos, Object dst, int dstPos, int len) {
+    arraycopy64Bit(Magic.objectAsAddress(src), srcPos, Magic.objectAsAddress(dst), dstPos, len);
+  }
+
+  /**
+   * Low level copy of <code>len</code> elements from <code>src[srcPos]</code> to <code>dst[dstPos]</code>.
+   *
+   * Assumption <code>src != dst || (srcPos >= dstPos)</code> and element size is 8 bytes.
+   *
+   * @param srcAddr the source address
    * @param srcIdx  index in the source array to begin copy
-   * @param dst     the destination array
+   * @param dstAddr the destination address
    * @param dstIdx  index in the destination array to being copy
    * @param len     number of array elements to copy
    */
-  public static void arraycopy64Bit(Object src, int srcIdx, Object dst, int dstIdx, int len) {
-    Address srcPtr = Magic.objectAsAddress(src).plus(srcIdx << LOG_BYTES_IN_DOUBLE);
-    Address dstPtr = Magic.objectAsAddress(dst).plus(dstIdx << LOG_BYTES_IN_DOUBLE);
+  public static void arraycopy64Bit(Address srcAddr, int srcPos, Address dstAddr, int dstPos, int len) {
+    Address srcPtr = srcAddr.plus(srcPos << LOG_BYTES_IN_DOUBLE);
+    Address dstPtr = dstAddr.plus(dstPos << LOG_BYTES_IN_DOUBLE);
     int copyBytes = len << LOG_BYTES_IN_DOUBLE;
     if (USE_NATIVE && len > (NATIVE_THRESHOLD >> LOG_BYTES_IN_DOUBLE)) {
       memcopy(dstPtr, srcPtr, copyBytes);
@@ -321,6 +396,575 @@
   }
 
   /**
+   * Is this array in a native (contiguous) format?
+   */
+  public static boolean isNativeFormat(byte[] array) {
+    return !MemoryManagerConstants.USE_PRIMITIVE_BYTE_ARRAYLETS;
+  }
+  
+  /**
+   * Is this array in a native (contiguous) format?
+   */
+  public static boolean isNativeFormat(boolean[] array) {
+    return !MemoryManagerConstants.USE_PRIMITIVE_BOOLEAN_ARRAYLETS;
+  }
+  
+  /**
+   * Is this array in a native (contiguous) format?
+   */
+  public static boolean isNativeFormat(char[] array) {
+    return !MemoryManagerConstants.USE_PRIMITIVE_CHAR_ARRAYLETS;
+  }
+  
+  /**
+   * Is this array in a native (contiguous) format?
+   */
+  public static boolean isNativeFormat(short[] array) {
+    return !MemoryManagerConstants.USE_PRIMITIVE_SHORT_ARRAYLETS;
+  }
+  
+  /**
+   * Is this array in a native (contiguous) format?
+   */
+  public static boolean isNativeFormat(int[] array) {
+    return !MemoryManagerConstants.USE_PRIMITIVE_INT_ARRAYLETS;
+  }
+  
+  /**
+   * Is this array in a native (contiguous) format?
+   */
+  public static boolean isNativeFormat(float[] array) {
+    return !MemoryManagerConstants.USE_PRIMITIVE_FLOAT_ARRAYLETS;
+  }
+  
+  /**
+   * Is this array in a native (contiguous) format?
+   */
+  public static boolean isNativeFormat(long[] array) {
+    return !MemoryManagerConstants.USE_PRIMITIVE_LONG_ARRAYLETS;
+  }
+  
+  /**
+   * Is this array in a native (contiguous) format?
+   */
+  public static boolean isNativeFormat(double[] array) {
+    return !MemoryManagerConstants.USE_PRIMITIVE_DOUBLE_ARRAYLETS;
+  }
+  
+  /**
+   * Marshal between a native buffer and Java array.
+   */
+  public static void nativeMarshal(WordArray src, byte[] dst) {
+    nativeMarshal(Magic.objectAsAddress(src), 0, dst, 0, dst.length);
+  }
+  
+  /**
+   * Marshal between a native buffer and Java array.
+   */
+  public static void nativeMarshal(byte[] src, WordArray dst) {
+    nativeMarshal(src, 0, Magic.objectAsAddress(dst), 0, src.length);
+  }
+  
+  /**
+   * Marshal between a native buffer and Java array.
+   */
+  public static void nativeMarshal(WordArray src, boolean[] dst) {
+    nativeMarshal(Magic.objectAsAddress(src), 0, dst, 0, dst.length);
+  }
+  
+  /**
+   * Marshal between a native buffer and Java array.
+   */
+  public static void nativeMarshal(boolean[] src, WordArray dst) {
+    nativeMarshal(src, 0, Magic.objectAsAddress(dst), 0, src.length);
+  }
+  
+  /**
+   * Marshal between a native buffer and Java array.
+   */
+  public static void nativeMarshal(WordArray src, short[] dst) {
+    nativeMarshal(Magic.objectAsAddress(src), 0, dst, 0, dst.length);
+  }
+  
+  /**
+   * Marshal between a native buffer and Java array.
+   */
+  public static void nativeMarshal(short[] src, WordArray dst) {
+    nativeMarshal(src, 0, Magic.objectAsAddress(dst), 0, src.length);
+  }
+  
+  /**
+   * Marshal between a native buffer and Java array.
+   */
+  public static void nativeMarshal(WordArray src, char[] dst) {
+    nativeMarshal(Magic.objectAsAddress(src), 0, dst, 0, dst.length);
+  }
+  
+  /**
+   * Marshal between a native buffer and Java array.
+   */
+  public static void nativeMarshal(char[] src, WordArray dst) {
+    nativeMarshal(src, 0, Magic.objectAsAddress(dst), 0, src.length);
+  }
+
+  /**
+   * Marshal between a native buffer and Java array.
+   */
+  public static void nativeMarshal(WordArray src, int[] dst) {
+    nativeMarshal(Magic.objectAsAddress(src), 0, dst, 0, dst.length);
+  }
+  
+  /**
+   * Marshal between a native buffer and Java array.
+   */
+  public static void nativeMarshal(int[] src, WordArray dst) {
+    nativeMarshal(src, 0, Magic.objectAsAddress(dst), 0, src.length);
+  }
+
+  /**
+   * Marshal between a native buffer and Java array.
+   */
+  public static void nativeMarshal(WordArray src, float[] dst) {
+    nativeMarshal(Magic.objectAsAddress(src), 0, dst, 0, dst.length);
+  }
+  
+  /**
+   * Marshal between a native buffer and Java array.
+   */
+  public static void nativeMarshal(float[] src, WordArray dst) {
+    nativeMarshal(src, 0, Magic.objectAsAddress(dst), 0, src.length);
+  }
+  
+  /**
+   * Marshal between a native buffer and Java array.
+   */
+  public static void nativeMarshal(WordArray src, long[] dst) {
+    nativeMarshal(Magic.objectAsAddress(src), 0, dst, 0, dst.length);
+  }
+  
+  /**
+   * Marshal between a native buffer and Java array.
+   */
+  public static void nativeMarshal(long[] src, WordArray dst) {
+    nativeMarshal(src, 0, Magic.objectAsAddress(dst), 0, src.length);
+  }
+  
+  /**
+   * Marshal between a native buffer and Java array.
+   */
+  public static void nativeMarshal(WordArray src, double[] dst) {
+    nativeMarshal(Magic.objectAsAddress(src), 0, dst, 0, dst.length);
+  }
+  
+  /**
+   * Marshal between a native buffer and Java array.
+   */
+  public static void nativeMarshal(double[] src, WordArray dst) {
+    nativeMarshal(src, 0, Magic.objectAsAddress(dst), 0, src.length);
+  }
+  
+  /**
+   * Marshal between a native buffer and Java array.
+   */
+  public static void nativeMarshal(WordArray src, int srcPos, byte[] dst, int dstPos, int len) {
+    nativeMarshal(Magic.objectAsAddress(src), srcPos, dst, dstPos, len);
+  }
+  
+  /**
+   * Marshal between a native buffer and Java array.
+   */
+  public static void nativeMarshal(byte[] src, int srcPos, WordArray dst, int dstPos, int len) {
+    nativeMarshal(src, srcPos, Magic.objectAsAddress(dst), dstPos, len);
+  }
+  
+  
+  /**
+   * Marshal between a native buffer and Java array.
+   */
+  public static void nativeMarshal(WordArray src, int srcPos, boolean[] dst, int dstPos, int len) {
+    nativeMarshal(Magic.objectAsAddress(src), srcPos, dst, dstPos, len);
+  }
+  
+  /**
+   * Marshal between a native buffer and Java array.
+   */
+  public static void nativeMarshal(boolean[] src, int srcPos, WordArray dst, int dstPos, int len) {
+    nativeMarshal(src, srcPos, Magic.objectAsAddress(dst), dstPos, len);
+  }
+  
+  /**
+   * Marshal between a native buffer and Java array.
+   */
+  public static void nativeMarshal(WordArray src, int srcPos, short[] dst, int dstPos, int len) {
+    nativeMarshal(Magic.objectAsAddress(src), srcPos, dst, dstPos, len);
+  }
+  
+  /**
+   * Marshal between a native buffer and Java array.
+   */
+  public static void nativeMarshal(short[] src, int srcPos, WordArray dst, int dstPos, int len) {
+    nativeMarshal(src, srcPos, Magic.objectAsAddress(dst), dstPos, len);
+  }
+  
+  /**
+   * Marshal between a native buffer and Java array.
+   */
+  public static void nativeMarshal(WordArray src, int srcPos, char[] dst, int dstPos, int len) {
+    nativeMarshal(Magic.objectAsAddress(src), srcPos, dst, dstPos, len);
+  }
+  
+  /**
+   * Marshal between a native buffer and Java array.
+   */
+  public static void nativeMarshal(char[] src, int srcPos, WordArray dst, int dstPos, int len) {
+    nativeMarshal(src, srcPos, Magic.objectAsAddress(dst), dstPos, len);
+  }
+  
+  /**
+   * Marshal between a native buffer and Java array.
+   */
+  public static void nativeMarshal(WordArray src, int srcPos, int[] dst, int dstPos, int len) {
+    nativeMarshal(Magic.objectAsAddress(src), srcPos, dst, dstPos, len);
+  }
+  
+  /**
+   * Marshal between a native buffer and Java array.
+   */
+  public static void nativeMarshal(int[] src, int srcPos, WordArray dst, int dstPos, int len) {
+    nativeMarshal(src, srcPos, Magic.objectAsAddress(dst), dstPos, len);
+  }
+  
+  /**
+   * Marshal between a native buffer and Java array.
+   */
+  public static void nativeMarshal(WordArray src, int srcPos, float[] dst, int dstPos, int len) {
+    nativeMarshal(Magic.objectAsAddress(src), srcPos, dst, dstPos, len);
+  }
+  
+  /**
+   * Marshal between a native buffer and Java array.
+   */
+  public static void nativeMarshal(float[] src, int srcPos, WordArray dst, int dstPos, int len) {
+    nativeMarshal(src, srcPos, Magic.objectAsAddress(dst), dstPos, len);
+  }
+  
+  /**
+   * Marshal between a native buffer and Java array.
+   */
+  public static void nativeMarshal(WordArray src, int srcPos, long[] dst, int dstPos, int len) {
+    nativeMarshal(Magic.objectAsAddress(src), srcPos, dst, dstPos, len);
+  }
+  
+  /**
+   * Marshal between a native buffer and Java array.
+   */
+  public static void nativeMarshal(long[] src, int srcPos, WordArray dst, int dstPos, int len) {
+    nativeMarshal(src, srcPos, Magic.objectAsAddress(dst), dstPos, len);
+  }
+  
+  /**
+   * Marshal between a native buffer and Java array.
+   */
+  public static void nativeMarshal(WordArray src, int srcPos, double[] dst, int dstPos, int len) {
+    nativeMarshal(Magic.objectAsAddress(src), srcPos, dst, dstPos, len);
+  }
+  
+  /**
+   * Marshal between a native buffer and Java array.
+   */
+  public static void nativeMarshal(double[] src, int srcPos, WordArray dst, int dstPos, int len) {
+    nativeMarshal(src, srcPos, Magic.objectAsAddress(dst), dstPos, len);
+  }
+  
+  /**
+   * Marshal between a native buffer and Java array.
+   */
+  public static void nativeMarshal(Address src, byte[] dst) {
+    nativeMarshal(src, 0, dst, 0, dst.length);
+  }
+  
+  /**
+   * Marshal between a native buffer and Java array.
+   */
+  public static void nativeMarshal(byte[] src, Address dst) {
+    nativeMarshal(src, 0, dst, 0, src.length);
+  }
+
+  /**
+   * Marshal between a native buffer and Java array.
+   */
+  public static void nativeMarshal(Address src, boolean[] dst) {
+    nativeMarshal(src, 0, dst, 0, dst.length);
+  }
+  
+  /**
+   * Marshal between a native buffer and Java array.
+   */
+  public static void nativeMarshal(boolean[] src, Address dst) {
+    nativeMarshal(src, 0, dst, 0, src.length);
+  }
+
+  /**
+   * Marshal between a native buffer and Java array.
+   */
+  public static void nativeMarshal(Address src, short[] dst) {
+    nativeMarshal(src, 0, dst, 0, dst.length);
+  }
+  
+  /**
+   * Marshal between a native buffer and Java array.
+   */
+  public static void nativeMarshal(short[] src, Address dst) {
+    nativeMarshal(src, 0, dst, 0, src.length);
+  }
+  
+  /**
+   * Marshal between a native buffer and Java array.
+   */
+  public static void nativeMarshal(Address src, char[] dst) {
+    nativeMarshal(src, 0, dst, 0, dst.length);
+  }
+  
+  /**
+   * Marshal between a native buffer and Java array.
+   */
+  public static void nativeMarshal(char[] src, Address dst) {
+    nativeMarshal(src, 0, dst, 0, src.length);
+  }
+
+  /**
+   * Marshal between a native buffer and Java array.
+   */
+  public static void nativeMarshal(Address src, int[] dst) {
+    nativeMarshal(src, 0, dst, 0, dst.length);
+  }
+  
+  /**
+   * Marshal between a native buffer and Java array.
+   */
+  public static void nativeMarshal(int[] src, Address dst) {
+    nativeMarshal(src, 0, dst, 0, src.length);
+  }
+
+  /**
+   * Marshal between a native buffer and Java array.
+   */
+  public static void nativeMarshal(Address src, float[] dst) {
+    nativeMarshal(src, 0, dst, 0, dst.length);
+  }
+  
+  /**
+   * Marshal between a native buffer and Java array.
+   */
+  public static void nativeMarshal(float[] src, Address dst) {
+    nativeMarshal(src, 0, dst, 0, src.length);
+  }
+  
+  /**
+   * Marshal between a native buffer and Java array.
+   */
+  public static void nativeMarshal(Address src, long[] dst) {
+    nativeMarshal(src, 0, dst, 0, dst.length);
+  }
+  
+  /**
+   * Marshal between a native buffer and Java array.
+   */
+  public static void nativeMarshal(long[] src, Address dst) {
+    nativeMarshal(src, 0, dst, 0, src.length);
+  }
+  
+  /**
+   * Marshal between a native buffer and Java array.
+   */
+  public static void nativeMarshal(Address src, double[] dst) {
+    nativeMarshal(src, 0, dst, 0, dst.length);
+  }
+  
+  /**
+   * Marshal between a native buffer and Java array.
+   */
+  public static void nativeMarshal(double[] src, Address dst) {
+    nativeMarshal(src, 0, dst, 0, src.length);
+  }
+  
+  /**
+   * Marshal between a native buffer and Java array.
+   */
+  public static void nativeMarshal(Address src, int srcPos, byte[] dst, int dstPos, int len) {
+    if (USE_PRIMITIVE_BYTE_ARRAYLETS) {
+      for (int idx = 0; idx < len; idx++)
+        dst[dstPos + idx] = src.loadByte(Offset.fromIntZeroExtend(srcPos + idx));
+    } else
+      arraycopy8Bit(src, srcPos, Magic.objectAsAddress(dst), dstPos, len);
+  }
+  
+  /**
+   * Marshal between a native buffer and Java array.
+   */
+  public static void nativeMarshal(byte[] src, int srcPos, Address dst, int dstPos, int len) {
+    if (USE_PRIMITIVE_BYTE_ARRAYLETS) {
+      for (int idx = 0; idx < len; idx++)
+        dst.store(src[srcPos + idx], Offset.fromIntZeroExtend(dstPos + idx));
+    } else
+      arraycopy8Bit(Magic.objectAsAddress(src), srcPos, dst, dstPos, len);
+  }
+  
+  /**
+   * Marshal between a native buffer and Java array.
+   */
+  public static void nativeMarshal(Address src, int srcPos, boolean[] dst, int dstPos, int len) {
+    if (USE_PRIMITIVE_BOOLEAN_ARRAYLETS) {
+      for (int idx = 0; idx < len; idx++)
+        dst[dstPos + idx] = src.loadByte(Offset.fromIntZeroExtend(srcPos + idx)) == 1;
+    } else
+      arraycopy8Bit(src, srcPos, Magic.objectAsAddress(dst), dstPos, len);
+  }
+  
+  /**
+   * Marshal between a native buffer and Java array.
+   */
+  public static void nativeMarshal(boolean[] src, int srcPos, Address dst, int dstPos, int len) {
+    if (USE_PRIMITIVE_BOOLEAN_ARRAYLETS) {
+      for (int idx = 0; idx < len; idx++)
+        dst.store((byte) (src[srcPos + idx] ? 1 : 0), Offset.fromIntZeroExtend(dstPos + idx));
+    } else
+      arraycopy8Bit(Magic.objectAsAddress(src), srcPos, dst, dstPos, len);
+  }
+  
+  /**
+   * Marshal between a native buffer and Java array.
+   */
+  public static void nativeMarshal(Address src, int srcPos, short[] dst, int dstPos, int len) {
+    if (USE_PRIMITIVE_SHORT_ARRAYLETS) {
+      for (int idx = 0; idx < len; idx++)
+        dst[dstPos + idx] = src.loadShort(Offset.fromIntZeroExtend((srcPos + idx)<<LOG_BYTES_IN_SHORT));
+    } else
+      arraycopy16Bit(src, srcPos, Magic.objectAsAddress(dst), dstPos, len);
+  }
+  
+  /**
+   * Marshal between a native buffer and Java array.
+   */
+  public static void nativeMarshal(short[] src, int srcPos, Address dst, int dstPos, int len) {
+    if (USE_PRIMITIVE_SHORT_ARRAYLETS) {
+      for (int idx = 0; idx < len; idx++)
+        dst.store(src[srcPos + idx], Offset.fromIntZeroExtend((dstPos + idx)<<LOG_BYTES_IN_SHORT));
+    } else
+      arraycopy16Bit(Magic.objectAsAddress(src), srcPos, dst, dstPos, len);
+  }
+  
+  /**
+   * Marshal between a native buffer and Java array.
+   */
+  public static void nativeMarshal(Address src, int srcPos, char[] dst, int dstPos, int len) {
+    if (USE_PRIMITIVE_CHAR_ARRAYLETS) {
+      for (int idx = 0; idx < len; idx++)
+        dst[dstPos + idx] = src.loadChar(Offset.fromIntZeroExtend((srcPos + idx)<<LOG_BYTES_IN_CHAR));
+    } else
+      arraycopy16Bit(src, srcPos, Magic.objectAsAddress(dst), dstPos, len);
+  }
+  
+  /**
+   * Marshal between a native buffer and Java array.
+   */
+  public static void nativeMarshal(char[] src, int srcPos, Address dst, int dstPos, int len) {
+    if (USE_PRIMITIVE_CHAR_ARRAYLETS) {
+      for (int idx = 0; idx < len; idx++)
+        dst.store(src[srcPos + idx], Offset.fromIntZeroExtend((dstPos + idx)<<LOG_BYTES_IN_CHAR));
+    } else
+      arraycopy16Bit(Magic.objectAsAddress(src), srcPos, dst, dstPos, len);
+  }
+  
+  /**
+   * Marshal between a native buffer and Java array.
+   */
+  public static void nativeMarshal(Address src, int srcPos, int[] dst, int dstPos, int len) {
+    if (USE_PRIMITIVE_INT_ARRAYLETS) {
+      for (int idx = 0; idx < len; idx++)
+        dst[dstPos + idx] = src.loadInt(Offset.fromIntZeroExtend((srcPos + idx)<<LOG_BYTES_IN_INT));
+    } else
+      arraycopy32Bit(src, srcPos, Magic.objectAsAddress(dst), dstPos, len);
+  }
+  
+  /**
+   * Marshal between a native buffer and Java array.
+   */
+  public static void nativeMarshal(int[] src, int srcPos, Address dst, int dstPos, int len) {
+    if (USE_PRIMITIVE_INT_ARRAYLETS) {
+      for (int idx = 0; idx < len; idx++)
+        dst.store(src[srcPos + idx], Offset.fromIntZeroExtend((dstPos + idx)<<LOG_BYTES_IN_INT));
+    } else
+      arraycopy32Bit(Magic.objectAsAddress(src), srcPos, dst, dstPos, len);
+  }
+  
+  /**
+   * Marshal between a native buffer and Java array.
+   */
+  public static void nativeMarshal(Address src, int srcPos, float[] dst, int dstPos, int len) {
+    if (USE_PRIMITIVE_FLOAT_ARRAYLETS) {
+      for (int idx = 0; idx < len; idx++)
+        dst[dstPos + idx] = src.loadFloat(Offset.fromIntZeroExtend((srcPos + idx)<<LOG_BYTES_IN_FLOAT));
+    } else
+      arraycopy32Bit(src, srcPos, Magic.objectAsAddress(dst), dstPos, len);
+  }
+  
+  /**
+   * Marshal between a native buffer and Java array.
+   */
+  public static void nativeMarshal(float[] src, int srcPos, Address dst, int dstPos, int len) {
+    if (USE_PRIMITIVE_FLOAT_ARRAYLETS) {
+      for (int idx = 0; idx < len; idx++)
+        dst.store(src[srcPos + idx], Offset.fromIntZeroExtend((dstPos + idx)<<LOG_BYTES_IN_FLOAT));
+    } else
+      arraycopy32Bit(Magic.objectAsAddress(src), srcPos, dst, dstPos, len);
+  }
+  
+  /**
+   * Marshal between a native buffer and Java array.
+   */
+  public static void nativeMarshal(Address src, int srcPos, long[] dst, int dstPos, int len) {
+    if (USE_PRIMITIVE_LONG_ARRAYLETS) {
+      for (int idx = 0; idx < len; idx++)
+        dst[dstPos + idx] = src.loadLong(Offset.fromIntZeroExtend((srcPos + idx)<<LOG_BYTES_IN_LONG));
+    } else
+      arraycopy64Bit(src, srcPos, Magic.objectAsAddress(dst), dstPos, len);
+  }
+  
+  /**
+   * Marshal between a native buffer and Java array.
+   */
+  public static void nativeMarshal(long[] src, int srcPos, Address dst, int dstPos, int len) {
+    if (USE_PRIMITIVE_LONG_ARRAYLETS) {
+      for (int idx = 0; idx < len; idx++)
+        dst.store(src[srcPos + idx], Offset.fromIntZeroExtend((dstPos + idx)<<LOG_BYTES_IN_LONG));
+    } else
+      arraycopy64Bit(Magic.objectAsAddress(src), srcPos, dst, dstPos, len);
+  }
+  
+  /**
+   * Marshal between a native buffer and Java array.
+   */
+  public static void nativeMarshal(Address src, int srcPos, double[] dst, int dstPos, int len) {
+    if (USE_PRIMITIVE_DOUBLE_ARRAYLETS) {
+      for (int idx = 0; idx < len; idx++)
+        dst[dstPos + idx] = src.loadDouble(Offset.fromIntZeroExtend((srcPos + idx)<<LOG_BYTES_IN_DOUBLE));
+    } else
+      arraycopy64Bit(src, srcPos, Magic.objectAsAddress(dst), dstPos, len);
+  }
+  
+  /**
+   * Marshal between a native buffer and Java array.
+   */
+  public static void nativeMarshal(double[] src, int srcPos, Address dst, int dstPos, int len) {
+    if (USE_PRIMITIVE_DOUBLE_ARRAYLETS) {
+      for (int idx = 0; idx < len; idx++)
+        dst.store(src[srcPos + idx], Offset.fromIntZeroExtend((dstPos + idx)<<LOG_BYTES_IN_DOUBLE));
+    } else
+      arraycopy64Bit(Magic.objectAsAddress(src), srcPos, dst, dstPos, len);
+  }
+  
+  /**
    * Copy numbytes from src to dst.
    * Assumption either the ranges are non overlapping, or src >= dst + 4.
    * Also, src and dst are 4 byte aligned and numBytes is a multiple of 4.
diff -r 743a2cc2ed20 -r 058fdc3780ba rvm/src/org/jikesrvm/runtime/Reflection.java
--- a/rvm/src/org/jikesrvm/runtime/Reflection.java	Tue Aug 04 11:04:15 2009 +1000
+++ b/rvm/src/org/jikesrvm/runtime/Reflection.java	Mon Nov 16 09:21:21 2009 +1100
@@ -20,6 +20,7 @@
 import org.jikesrvm.classloader.RVMMethod;
 import org.jikesrvm.classloader.TypeReference;
 import org.jikesrvm.compilers.common.CompiledMethod;
+import org.jikesrvm.mm.mminterface.MemoryManager;
 import org.jikesrvm.scheduler.Processor;
 import org.vmmagic.pragma.Inline;
 import org.vmmagic.pragma.NoInline;
@@ -92,8 +93,8 @@
   }
 
   private static final WordArray emptyWordArray = WordArray.create(0);
-  private static final double[] emptyDoubleArray = new double[0];
-  private static final byte[] emptyByteArray = new byte[0];
+  private static final WordArray emptyDoubleArray = MemoryManager.createNativeLongBuffer(0);
+  private static final WordArray emptyByteArray = MemoryManager.createNativeByteBuffer(0);
 
   private static Object outOfLineInvoke(RVMMethod method, Object thisArg, Object[] otherArgs, boolean isNonvirtual) {
 
@@ -117,10 +118,10 @@
     int gprs = triple & REFLECTION_GPRS_MASK;
     WordArray GPRs = (gprs > 0) ? WordArray.create(gprs) : emptyWordArray;
     int fprs = (triple >> REFLECTION_GPRS_BITS) & 0x1F;
-    double[] FPRs = (fprs > 0) ? new double[fprs] : emptyDoubleArray;
-    byte[] FPRmeta;
+    WordArray FPRs = (fprs > 0) ? MemoryManager.createNativeLongBuffer(fprs) : emptyDoubleArray;
+    WordArray FPRmeta;
     if (BuildForSSE2Full) {
-      FPRmeta = (fprs > 0) ? new byte[fprs] : emptyByteArray;
+      FPRmeta = (fprs > 0) ? MemoryManager.createNativeByteBuffer(fprs) : emptyByteArray;
     } else {
       FPRmeta = null;
     }
diff -r 743a2cc2ed20 -r 058fdc3780ba rvm/src/org/jikesrvm/runtime/RuntimeEntrypoints.java
--- a/rvm/src/org/jikesrvm/runtime/RuntimeEntrypoints.java	Tue Aug 04 11:04:15 2009 +1000
+++ b/rvm/src/org/jikesrvm/runtime/RuntimeEntrypoints.java	Mon Nov 16 09:21:21 2009 +1100
@@ -622,7 +622,7 @@
     Registers exceptionRegisters = myThread.getExceptionRegisters();
 
     if ((trapCode == TRAP_STACK_OVERFLOW || trapCode == TRAP_JNI_STACK) &&
-        myThread.getStack().length < (STACK_SIZE_MAX >> LOG_BYTES_IN_ADDRESS) &&
+        myThread.getStackLength() < (STACK_SIZE_MAX >> LOG_BYTES_IN_ADDRESS) &&
         !myThread.hasNativeStackFrame()) {
       // expand stack by the size appropriate for normal or native frame
       // and resume execution at successor to trap instruction
diff -r 743a2cc2ed20 -r 058fdc3780ba rvm/src/org/jikesrvm/runtime/Statics.java
--- a/rvm/src/org/jikesrvm/runtime/Statics.java	Tue Aug 04 11:04:15 2009 +1000
+++ b/rvm/src/org/jikesrvm/runtime/Statics.java	Mon Nov 16 09:21:21 2009 +1100
@@ -187,7 +187,13 @@
     final int bottom = getLowestInUseSlot();
     final int top = middleOfTable;
     for (int i=top; i >= bottom; i--) {
-      if ((slots[i] == literal) && !numericFieldVector.get(i) && (i != numericSlotHole)) {
+      int elem;
+      if (VM.runningVM){
+        elem = Magic.getIntAtOffset(slots, Offset.fromIntZeroExtend(i << LOG_BYTES_IN_INT));
+      } else {
+        elem = slots[i];
+      }
+      if ((elem == literal) && !numericFieldVector.get(i) && (i != numericSlotHole)) {
         return slotAsOffset(i).toInt();
       }
     }
@@ -446,7 +452,7 @@
   }
 
   /**
-   * Fetch jtoc object (for JNI environment and GC).
+   * Fetch jtoc object (for boot image writing).
    */
   @Uninterruptible
   public static int[] getSlotsAsIntArray() {
diff -r 743a2cc2ed20 -r 058fdc3780ba rvm/src/org/jikesrvm/runtime/SysCall.java
--- a/rvm/src/org/jikesrvm/runtime/SysCall.java	Tue Aug 04 11:04:15 2009 +1000
+++ b/rvm/src/org/jikesrvm/runtime/SysCall.java	Mon Nov 16 09:21:21 2009 +1100
@@ -19,6 +19,7 @@
 import org.vmmagic.unboxed.Address;
 import org.vmmagic.unboxed.Extent;
 import org.vmmagic.unboxed.Offset;
+import org.vmmagic.unboxed.WordArray;
 
 /**
  * Support for lowlevel (ie non-JNI) invocation of C functions with
@@ -76,11 +77,11 @@
   public abstract void sysExit(int value);
 
   @SysCallTemplate
-  public abstract int sysArg(int argno, byte[] buf, int buflen);
+  public abstract int sysArg(int argno, WordArray buf, int buflen);
 
   // misc. info on the process -- used in startup/shutdown
   @SysCallTemplate
-  public abstract int sysGetenv(byte[] varName, byte[] buf, int limit);
+  public abstract int sysGetenv(WordArray varName, WordArray buf, int limit);
 
   // memory
   @SysCallTemplate
@@ -118,7 +119,7 @@
 
   // files
   @SysCallTemplate
-  public abstract int sysStat(byte[] name, int kind);
+  public abstract int sysStat(WordArray name, int kind);
 
   @SysCallTemplate
   public abstract int sysReadByte(int fd);
@@ -142,7 +143,7 @@
   public abstract int sysSetFdCloseOnExec(int fd);
 
   @SysCallTemplate
-  public abstract int sysAccess(byte[] name, int kind);
+  public abstract int sysAccess(WordArray name, int kind);
 
   // mmap - memory mapping
   @SysCallTemplate
@@ -249,7 +250,7 @@
    * @return the floating-point value produced by the call to strtof() on buf.
    */
   @SysCallTemplate
-  public abstract float sysPrimitiveParseFloat(byte[] buf);
+  public abstract float sysPrimitiveParseFloat(WordArray buf);
 
   /**
    * Used to parse command line arguments that are
@@ -263,13 +264,13 @@
    * @return the int value produced by the call to strtol() on buf.
    */
   @SysCallTemplate
-  public abstract int sysPrimitiveParseInt(byte[] buf);
+  public abstract int sysPrimitiveParseInt(WordArray buf);
 
   /** Parse memory sizes passed as command-line arguments.
    */
   @SysCallTemplate
-  public abstract long sysParseMemorySize(byte[] sizeName, byte[] sizeFlag, byte[] defaultFactor, int roundTo,
-                                          byte[] argToken, byte[] subArg);
+  public abstract long sysParseMemorySize(WordArray sizeName, WordArray sizeFlag, WordArray defaultFactor, int roundTo,
+      WordArray argToken, WordArray subArg);
 
   // time
   @SysCallTemplate
@@ -283,10 +284,10 @@
 
   // shared libraries
   @SysCallTemplate
-  public abstract Address sysDlopen(byte[] libname);
+  public abstract Address sysDlopen(WordArray libname);
 
   @SysCallTemplate
-  public abstract Address sysDlsym(Address libHandler, byte[] symbolName);
+  public abstract Address sysDlsym(Address libHandler, WordArray symbolName);
 
   // network
   @SysCallTemplate
@@ -332,11 +333,11 @@
   public abstract int sysNetSocketShutdown(int fd, int how);
 
   @SysCallTemplate
-  public abstract int sysNetSelect(int[] allFds, int rc, int wc, int ec);
+  public abstract int sysNetSelect(WordArray allFds, int rc, int wc, int ec);
 
   // process management
   @SysCallTemplate
-  public abstract void sysWaitPids(Address pidArray, Address exitStatusArray, int numPids);
+  public abstract void sysWaitPids(WordArray pidArray, WordArray exitStatusArray, int numPids);
 
   // system startup pthread sync. primitives
   @SysCallTemplate
diff -r 743a2cc2ed20 -r 058fdc3780ba rvm/src/org/jikesrvm/scheduler/Processor.java
--- a/rvm/src/org/jikesrvm/scheduler/Processor.java	Tue Aug 04 11:04:15 2009 +1000
+++ b/rvm/src/org/jikesrvm/scheduler/Processor.java	Mon Nov 16 09:21:21 2009 +1100
@@ -231,32 +231,6 @@
   public boolean isInitialized;
 
   /**
-   * number of processor locks currently held (for assertion checking)
-   */
-  private int lockCount;
-
-  private final String[] lockReasons = VM.VerifyAssertions ? new String[100] : null;
-
-  public void registerLock(String reason) {
-    Magic.setObjectAtOffset(lockReasons, Offset.fromIntSignExtend(lockCount<<VM.LOG_BITS_IN_ADDRESS), reason);
-    lockCount ++;
-  }
-  public void registerUnlock() {
-    lockCount --;
-    VM._assert(lockCount >= 0);
-  }
-  protected void checkLockCount(int i) {
-    if (lockCount != i) {
-      VM.sysWrite("Error lock count not ", i);
-      VM.sysWriteln(" but ", lockCount);
-      for (int j=0; j < lockCount; j++) {
-        VM.sysWrite("Processor lock ", j);
-        VM.sysWriteln(" acquired for ", lockReasons[j]);
-      }
-      Scheduler.dumpStack();
-    }
-  }
-  /**
    * Status of the processor.
    * Always one of IN_JAVA, IN_NATIVE or BLOCKED_IN_NATIVE.
    */
diff -r 743a2cc2ed20 -r 058fdc3780ba rvm/src/org/jikesrvm/scheduler/ProcessorLock.java
--- a/rvm/src/org/jikesrvm/scheduler/ProcessorLock.java	Tue Aug 04 11:04:15 2009 +1000
+++ b/rvm/src/org/jikesrvm/scheduler/ProcessorLock.java	Mon Nov 16 09:21:21 2009 +1100
@@ -110,9 +110,6 @@
   public void lock(String reason) {
     if (Scheduler.getNumberOfProcessors() == 1) return;
     Processor i = Processor.getCurrentProcessor();
-    if (VM.VerifyAssertions) {
-      i.registerLock(reason);
-    }
     Processor p;
     int attempts = 0;
     Offset latestContenderOffset = Entrypoints.latestContenderField.getOffset();
@@ -175,7 +172,6 @@
     Offset latestContenderOffset = Entrypoints.latestContenderField.getOffset();
     Processor i = Processor.getCurrentProcessor();
     if (!MCS_Locking) {
-      if (VM.VerifyAssertions) i.registerUnlock();
       Magic.setObjectAtOffset(this, latestContenderOffset, null);  // latestContender = null;
       return;
     }
@@ -209,7 +205,6 @@
         Magic.setObjectAtOffset(this, latestContenderOffset, p); // other contenders can get at the lock
       }
     }
-    if (VM.VerifyAssertions) i.registerUnlock();
   }
 
   /**
diff -r 743a2cc2ed20 -r 058fdc3780ba rvm/src/org/jikesrvm/scheduler/RVMThread.java
--- a/rvm/src/org/jikesrvm/scheduler/RVMThread.java	Tue Aug 04 11:04:15 2009 +1000
+++ b/rvm/src/org/jikesrvm/scheduler/RVMThread.java	Mon Nov 16 09:21:21 2009 +1100
@@ -49,6 +49,7 @@
 import org.vmmagic.pragma.Untraced;
 import org.vmmagic.unboxed.Address;
 import org.vmmagic.unboxed.Offset;
+import org.vmmagic.unboxed.WordArray;
 
 /**
  * A generic java thread's execution context.
@@ -247,7 +248,7 @@
    * Execution stack for this thread.
    */
   @Entrypoint
-  private byte[] stack;
+  private WordArray stack;
 
   /** The {@link Address} of the guard area for {@link #stack}. */
   @Entrypoint
@@ -418,7 +419,7 @@
   /**
    * @param stack stack in which to execute the thread
    */
-  protected RVMThread(byte[] stack, Thread thread, String name, boolean daemon, boolean system, int priority) {
+  protected RVMThread(WordArray stack, Thread thread, String name, boolean daemon, boolean system, int priority) {
     this.stack = stack;
     this.name = name;
     this.daemon = daemon;
@@ -466,7 +467,7 @@
 
       // initialize thread registers
       Address ip = Magic.objectAsAddress(instructions);
-      Address sp = Magic.objectAsAddress(stack).plus(stack.length);
+      Address sp = Magic.objectAsAddress(stack).plus(MemoryManager.nativeByteBufferLength(stack));
 
       // Initialize the a thread stack as if "startoff" method had been called
       // by an empty baseline-compiled "sentinel" frame with one local variable.
@@ -1233,14 +1234,14 @@
     if (MemoryManager.gcInProgress()) {
       VM.sysFail("system error: resizing stack while GC is in progress");
     }
-    byte[] newStack = MemoryManager.newStack(newSize, false);
+    WordArray newStack = MemoryManager.newStack(newSize, false);
     Processor.getCurrentProcessor().disableThreadSwitching("disabled for stack resizing");
     transferExecutionToNewStack(newStack, exceptionRegisters);
     Processor.getCurrentProcessor().enableThreadSwitching();
     if (traceAdjustments) {
       RVMThread t = Scheduler.getCurrentThread();
       VM.sysWrite("Thread: resized stack ", t.getIndex());
-      VM.sysWrite(" to ", t.stack.length / 1024);
+      VM.sysWrite(" to ", MemoryManager.nativeByteBufferLength(t.stack) / 1024);
       VM.sysWrite("k\n");
     }
   }
@@ -1248,12 +1249,12 @@
   @NoInline
   @BaselineNoRegisters
   //this method does not do a normal return and hence does not execute epilogue --> non-volatiles not restored!
-  private static void transferExecutionToNewStack(byte[] newStack, Registers exceptionRegisters) {
+  private static void transferExecutionToNewStack(WordArray newStack, Registers exceptionRegisters) {
     // prevent opt compiler from inlining a method that contains a magic
     // (returnToNewStack) that it does not implement.
 
     RVMThread myThread = Scheduler.getCurrentThread();
-    byte[] myStack = myThread.stack;
+    WordArray myStack = myThread.stack;
 
     // initialize new stack with live portion of stack we're
     // currently running on
@@ -1270,8 +1271,8 @@
     //       +-------------------+---------------+
     //        ^newStack           ^newFP          ^newTop
     //
-    Address myTop = Magic.objectAsAddress(myStack).plus(myStack.length);
-    Address newTop = Magic.objectAsAddress(newStack).plus(newStack.length);
+    Address myTop = Magic.objectAsAddress(myStack).plus(MemoryManager.nativeByteBufferLength(myStack));
+    Address newTop = Magic.objectAsAddress(newStack).plus(MemoryManager.nativeByteBufferLength(newStack));
 
     Address myFP = Magic.getFramePointer();
     Offset myDepth = myTop.diff(myFP);
@@ -1379,7 +1380,7 @@
    * @param fp    pointer to its innermost frame
    * @param delta displacement to be applied to all its interior references
    */
-  private static void adjustStack(byte[] stack, Address fp, Offset delta) {
+  private static void adjustStack(WordArray stack, Address fp, Offset delta) {
     if (traceAdjustments) VM.sysWrite("Thread: adjustStack\n");
 
     while (Magic.getCallerFramePointer(fp).NE(STACKFRAME_SENTINEL_FP)) {
@@ -1414,12 +1415,12 @@
    *        ^newStack           ^newFP          ^newTop
    *  </pre>
    */
-  private static Offset copyStack(byte[] newStack) {
+  private static Offset copyStack(WordArray newStack) {
     RVMThread myThread = Scheduler.getCurrentThread();
-    byte[] myStack = myThread.stack;
+    WordArray myStack = myThread.stack;
 
-    Address myTop = Magic.objectAsAddress(myStack).plus(myStack.length);
-    Address newTop = Magic.objectAsAddress(newStack).plus(newStack.length);
+    Address myTop = Magic.objectAsAddress(myStack).plus(MemoryManager.nativeByteBufferLength(myStack));
+    Address newTop = Magic.objectAsAddress(newStack).plus(MemoryManager.nativeByteBufferLength(newStack));
     Address myFP = Magic.getFramePointer();
     Offset myDepth = myTop.diff(myFP);
     Address newFP = newTop.minus(myDepth);
@@ -1777,13 +1778,13 @@
    * @return the length of the stack
    */
   public final int getStackLength() {
-    return stack.length;
+    return MemoryManager.nativeByteBufferLength(stack);
   }
 
   /**
    * @return the stack
    */
-  public final byte[] getStack() {
+  public final WordArray getStack() {
     return stack;
   }
 
diff -r 743a2cc2ed20 -r 058fdc3780ba rvm/src/org/jikesrvm/scheduler/Scheduler.java
--- a/rvm/src/org/jikesrvm/scheduler/Scheduler.java	Tue Aug 04 11:04:15 2009 +1000
+++ b/rvm/src/org/jikesrvm/scheduler/Scheduler.java	Mon Nov 16 09:21:21 2009 +1100
@@ -39,6 +39,7 @@
 import org.vmmagic.pragma.Unpreemptible;
 import org.vmmagic.unboxed.Address;
 import org.vmmagic.unboxed.Offset;
+import org.vmmagic.unboxed.WordArray;
 
 /**
  * Global variables used to implement virtual machine thread scheduler.
@@ -52,7 +53,7 @@
 
   @NonMoving
   public static class ThreadModel extends org.jikesrvm.scheduler.greenthreads.GreenThread {
-    public ThreadModel(byte[] stack, String s) {
+    public ThreadModel(WordArray stack, String s) {
       super(stack, s);
     }
     public ThreadModel(String s) {
@@ -218,11 +219,11 @@
      *  barrier. Generational collectors may not care about a null
      *  store, but a reference counting collector sure does.
      */
-    if (MemoryManagerConstants.NEEDS_WRITE_BARRIER)
-      MemoryManager.arrayStoreWriteBarrier(Scheduler.threads,
-          threadSlot, null);
-    Magic.setObjectAtOffset(Scheduler.threads,
-        Offset.fromIntZeroExtend(threadSlot << SizeConstants.LOG_BYTES_IN_ADDRESS), null);
+    if (MemoryManagerConstants.NEEDS_WRITE_BARRIER || MemoryManagerConstants.USE_REFERENCE_ARRAYLETS || MemoryManagerConstants.USE_OBJECT_ARRAY_ACCESS_BARRIER) {
+      MemoryManager.arrayStoreWriteBarrier(Scheduler.threads, threadSlot, null);
+    } else {
+      Magic.setObjectAtOffset(Scheduler.threads, Offset.fromIntZeroExtend(threadSlot << SizeConstants.LOG_BYTES_IN_ADDRESS), null);
+    }
     if (threadSlot < Scheduler.threadAllocationIndex)
       Scheduler.threadAllocationIndex = threadSlot;
     threadCreationMutex.unlock();
diff -r 743a2cc2ed20 -r 058fdc3780ba rvm/src/org/jikesrvm/scheduler/greenthreads/FileSystem.java
--- a/rvm/src/org/jikesrvm/scheduler/greenthreads/FileSystem.java	Tue Aug 04 11:04:15 2009 +1000
+++ b/rvm/src/org/jikesrvm/scheduler/greenthreads/FileSystem.java	Mon Nov 16 09:21:21 2009 +1100
@@ -20,12 +20,14 @@
 import java.io.PrintStream;
 import org.jikesrvm.VM;
 import org.jikesrvm.Callbacks;
+import org.jikesrvm.mm.mminterface.MemoryManager;
 import org.jikesrvm.runtime.Magic;
 import static org.jikesrvm.runtime.SysCall.sysCall;
 import org.jikesrvm.runtime.Time;
 import org.jikesrvm.runtime.TimeoutException;
 import org.jikesrvm.util.StringUtilities;
 import org.vmmagic.pragma.Inline;
+import org.vmmagic.unboxed.WordArray;
 
 /**
  * Interface to filesystem of underlying operating system.
@@ -104,7 +106,7 @@
     // convert file name from unicode to filesystem character set
     // (assume file name is ascii, for now)
     byte[] asciiName = StringUtilities.stringToBytesNullTerminated(fileName);
-    int rc = sysCall.sysStat(asciiName, kind);
+    int rc = sysCall.sysStat(MemoryManager.cloneToNativeBuffer(asciiName), kind);
     if (VM.TraceFileSystem) VM.sysWrite("FileSystem.stat: name=" + fileName + " kind=" + kind + " rc=" + rc + "\n");
     return rc;
   }
@@ -120,7 +122,7 @@
     // (assume file name is ascii, for now)
     byte[] asciiName = StringUtilities.stringToBytesNullTerminated(fileName);
 
-    int rc = sysCall.sysAccess(asciiName, kind);
+    int rc = sysCall.sysAccess(MemoryManager.cloneToNativeBuffer(asciiName), kind);
 
     if (VM.TraceFileSystem) {
       VM.sysWrite("FileSystem.access: name=" + fileName + " kind=" + kind + " rc=" + rc + "\n");
@@ -254,7 +256,7 @@
    * Will block indefinitely until data can be read.
    * @see #readBytes(int,byte[],int,int,double)
    */
-  public static int readBytes(int fd, byte[] buf, int off, int cnt) {
+  public static int readBytes(int fd, WordArray buf, int off, int cnt) {
     try {
       return readBytes(fd, buf, off, cnt, ThreadEventConstants.WAIT_INFINITE);
     } catch (TimeoutException e) {
@@ -275,7 +277,7 @@
    * @return number of bytes read (-2: error)
    * @throws TimeoutException if the read times out
    */
-  public static int readBytes(int fd, byte[] buf, int off, int cnt, double totalWaitTime) throws TimeoutException {
+  public static int readBytes(int fd, WordArray buf, int off, int cnt, double totalWaitTime) throws TimeoutException {
 
     if (off < 0) {
       throw new IndexOutOfBoundsException();
@@ -285,8 +287,8 @@
     // note: this behavior is the way the JDK does it (as of version 1.1.3)
     // whereas the language spec says to throw IndexOutOfBounds exception...
     //
-    if (off + cnt > buf.length) {
-      cnt = buf.length - off;
+    if (off + cnt > MemoryManager.nativeByteBufferLength(buf)) {
+      cnt = MemoryManager.nativeByteBufferLength(buf) - off;
     }
 
     // The canonical read loop.  Try the read repeatedly until either
@@ -372,7 +374,7 @@
    * @param cnt number of bytes to write
    * @return number of bytes written (-2: error)
    */
-  public static int writeBytes(int fd, byte[] buf, int off, int cnt) {
+  public static int writeBytes(int fd, WordArray buf, int off, int cnt) {
     if (cnt == 0) return 0;
 
     if (off < 0) {
@@ -383,8 +385,8 @@
     // note: this behavior is the way the JDK does it (as of version 1.1.3)
     // whereas the language spec says to throw IndexOutOfBounds exception...
     //
-    if (off + cnt > buf.length) {
-      cnt = buf.length - off;
+    if (off + cnt > MemoryManager.nativeByteBufferLength(buf)) {
+      cnt = MemoryManager.nativeByteBufferLength(buf) - off;
     }
 
     // The canonical write loop.  Try the write repeatedly until
diff -r 743a2cc2ed20 -r 058fdc3780ba rvm/src/org/jikesrvm/scheduler/greenthreads/GreenProcessor.java
--- a/rvm/src/org/jikesrvm/scheduler/greenthreads/GreenProcessor.java	Tue Aug 04 11:04:15 2009 +1000
+++ b/rvm/src/org/jikesrvm/scheduler/greenthreads/GreenProcessor.java	Mon Nov 16 09:21:21 2009 +1100
@@ -62,13 +62,10 @@
   int threadSwitchPending;
 
   /**
-   * The reason given for disabling thread switching
-   */
-  private final String[] threadSwitchDisabledReason = VM.VerifyAssertions ? new String[10] : null;
-  /**
    * threads to be added to ready queue
    */
   public final GlobalGreenThreadQueue transferQueue;
+
   /** guard for transferQueue */
   public final ProcessorLock transferMutex;
 
@@ -239,12 +236,6 @@
   @Override
   public void disableThreadSwitching(String reason) {
     --threadSwitchingEnabledCount;
-    if (VM.VerifyAssertions && (-threadSwitchingEnabledCount < threadSwitchDisabledReason.length)) {
-      Magic.setObjectAtOffset(threadSwitchDisabledReason,
-          Offset.fromIntZeroExtend(-threadSwitchingEnabledCount << Constants.BYTES_IN_ADDRESS),
-          reason);
-      // threadSwitchDisabledReason[-threadSwitchingEnabledCount] = reason;
-    }
   }
 
   /**
@@ -286,8 +277,6 @@
   @Unpreemptible("Becoming another thread interrupts the current thread, avoid preemption in the process")
   public void dispatch(boolean timerTick) {
     // no processor locks should be held across a thread switch
-    if (VM.VerifyAssertions) checkLockCount(0);
-
     if (flushRequested) processMutatorFlushRequest();
 
     GreenThread newThread = getRunnableThread();
@@ -620,11 +609,6 @@
     if (!threadSwitchingEnabled()) {
       VM.sysWrite("No threadswitching on proc ", id);
       VM.sysWrite(" with addr ", Magic.objectAsAddress(GreenProcessor.getCurrentProcessor()));
-      if (VM.VerifyAssertions) {
-        for (int i=0; i <= -threadSwitchingEnabledCount; i++) {
-          VM.sysWrite(" because: ", threadSwitchDisabledReason[i]);
-        }
-      }
       VM.sysWriteln();
       VM._assert(false);
     }
diff -r 743a2cc2ed20 -r 058fdc3780ba rvm/src/org/jikesrvm/scheduler/greenthreads/GreenScheduler.java
--- a/rvm/src/org/jikesrvm/scheduler/greenthreads/GreenScheduler.java	Tue Aug 04 11:04:15 2009 +1000
+++ b/rvm/src/org/jikesrvm/scheduler/greenthreads/GreenScheduler.java	Mon Nov 16 09:21:21 2009 +1100
@@ -38,6 +38,7 @@
 import org.vmmagic.pragma.Uninterruptible;
 import org.vmmagic.pragma.UninterruptibleNoWarn;
 import org.vmmagic.pragma.Unpreemptible;
+import org.vmmagic.unboxed.WordArray;
 
 /**
  * Global variables used to implement virtual machine thread scheduler.
@@ -688,7 +689,7 @@
   @Interruptible
   protected RVMThread setupBootThreadInternal() {
     int initProc = PRIMORDIAL_PROCESSOR_ID;
-    byte[] stack = new byte[ArchitectureSpecific.ArchConstants.STACK_SIZE_BOOT];
+    WordArray stack = MemoryManager.createNativeByteBuffer(ArchitectureSpecific.ArchConstants.STACK_SIZE_BOOT);
     GreenThread startupThread = new Scheduler.ThreadModel(stack, "Jikes_RVM_Boot_Thread");
     startupThread.feedlet = TraceEngine.engine.makeFeedlet("Jikes RVM boot thread", "Thread used to execute the initial boot sequence of Jikes RVM");
     numDaemons++;
diff -r 743a2cc2ed20 -r 058fdc3780ba rvm/src/org/jikesrvm/scheduler/greenthreads/GreenThread.java
--- a/rvm/src/org/jikesrvm/scheduler/greenthreads/GreenThread.java	Tue Aug 04 11:04:15 2009 +1000
+++ b/rvm/src/org/jikesrvm/scheduler/greenthreads/GreenThread.java	Mon Nov 16 09:21:21 2009 +1100
@@ -36,6 +36,7 @@
 import org.vmmagic.pragma.Unpreemptible;
 import org.vmmagic.unboxed.Address;
 import org.vmmagic.unboxed.Offset;
+import org.vmmagic.unboxed.WordArray;
 
 /**
  * A green thread's Java execution context
@@ -109,7 +110,7 @@
    * {@link org.jikesrvm.mm.mminterface.CollectorThread} and the
    * boot image writer for the boot thread.
    */
-  public GreenThread(byte[] stack, String name) {
+  public GreenThread(WordArray stack, String name) {
     this(stack,
         null, // java.lang.Thread
         name,
@@ -130,7 +131,7 @@
   /**
    * Create a thread.
    */
-  protected GreenThread(byte[] stack, Thread thread, String name, boolean daemon, boolean system, int priority) {
+  protected GreenThread(WordArray stack, Thread thread, String name, boolean daemon, boolean system, int priority) {
     super(stack, thread, name, daemon, system, priority);
     // for load balancing
     chosenProcessorId = (VM.runningVM ? Processor.getCurrentProcessorId() : 0);
diff -r 743a2cc2ed20 -r 058fdc3780ba rvm/src/org/jikesrvm/scheduler/greenthreads/JikesRVMSocketImpl.java
--- a/rvm/src/org/jikesrvm/scheduler/greenthreads/JikesRVMSocketImpl.java	Tue Aug 04 11:04:15 2009 +1000
+++ b/rvm/src/org/jikesrvm/scheduler/greenthreads/JikesRVMSocketImpl.java	Mon Nov 16 09:21:21 2009 +1100
@@ -35,8 +35,13 @@
 import org.jikesrvm.SizeConstants;
 import org.jikesrvm.UnimplementedError;
 import static org.jikesrvm.runtime.SysCall.sysCall;
+
+import org.jikesrvm.classloader.RVMArray;
+import org.jikesrvm.mm.mminterface.MemoryManager;
+import org.jikesrvm.runtime.Memory;
 import org.jikesrvm.runtime.Time;
 import org.jikesrvm.runtime.TimeoutException;
+import org.vmmagic.unboxed.WordArray;
 
 /**
  * Sockets using Jikes RVM non-blocking I/O support
@@ -601,7 +606,9 @@
 
     int rc;
     try {
-      rc = FileSystem.readBytes(native_fd, buffer, offset, count, totalWaitTime);
+      WordArray tmp = MemoryManager.createNativeByteBuffer(count);
+      rc = FileSystem.readBytes(native_fd, tmp, 0, count, totalWaitTime);
+      Memory.nativeMarshal(tmp, 0, buffer, offset, count);
     } catch (TimeoutException e) {
       throw new SocketTimeoutException("socket receive timed out");
     }
@@ -611,7 +618,8 @@
 
   synchronized int write(byte[] buffer, int offset, int count) throws IOException {
     if (count == 0) return 0;
-    return FileSystem.writeBytes(native_fd, buffer, offset, count);
+    WordArray tmp = MemoryManager.cloneToNativeBuffer(buffer);
+    return FileSystem.writeBytes(native_fd, tmp, offset, count);
   }
 
   protected void finalize() throws Throwable {
diff -r 743a2cc2ed20 -r 058fdc3780ba rvm/src/org/jikesrvm/scheduler/greenthreads/ThreadIOQueue.java
--- a/rvm/src/org/jikesrvm/scheduler/greenthreads/ThreadIOQueue.java	Tue Aug 04 11:04:15 2009 +1000
+++ b/rvm/src/org/jikesrvm/scheduler/greenthreads/ThreadIOQueue.java	Mon Nov 16 09:21:21 2009 +1100
@@ -14,10 +14,15 @@
 
 import org.jikesrvm.VM;
 import static org.jikesrvm.runtime.SysCall.sysCall;
+
+import org.jikesrvm.classloader.RVMArray;
+import org.jikesrvm.mm.mminterface.MemoryManager;
+import org.jikesrvm.runtime.Memory;
 import org.jikesrvm.scheduler.ProcessorLock;
 import org.vmmagic.pragma.Interruptible;
 import org.vmmagic.pragma.Uninterruptible;
 import org.vmmagic.pragma.Unpreemptible;
+import org.vmmagic.unboxed.WordArray;
 
 /**
  * A list of threads waiting for i/o data to become available.
@@ -71,7 +76,7 @@
    * Array containing read, write, and exception file descriptor sets.
    * Used by sysNetSelect().
    */
-  private int[] allFds = new int[3 * FD_SETSIZE];
+  private WordArray allFds = MemoryManager.createNativeIntBuffer(3 * FD_SETSIZE);
 
   /** Offset of read file descriptors in allFds. */
   public static final int READ_OFFSET = 0 * FD_SETSIZE;
@@ -100,10 +105,10 @@
    * @param src the source file descriptor array
    * @return number of descriptors added
    */
-  private static int addFileDescriptors(int[] dest, int offset, int[] src) {
+  private static int addFileDescriptors(WordArray dest, int offset, int[] src) {
     //TODO: Remove manual System.arraycopy
     for (int aSrc : src) {
-      dest[offset++] = aSrc;
+      dest.setInt(offset++, aSrc);
     }
     return src.length;
   }
@@ -133,7 +138,7 @@
    * @return the number of file descriptors which became ready
    *     or invalid
    */
-  private int updateStatus(int[] waitDataFds, int waitDataOffset, int[] selectFds, int setOffset) {
+  private int updateStatus(int[] waitDataFds, int waitDataOffset, WordArray selectFds, int setOffset) {
 
     if (waitDataFds == null) {
       return 0;
@@ -143,7 +148,7 @@
     int selectIndex = setOffset + waitDataOffset;
     for (int i = 0; i < waitDataFds.length; ++i) {
       //boolean ready = selectFds[selectIndex++] == FD_READY;
-      int fd = selectFds[selectIndex++];
+      int fd = selectFds.getInt(selectIndex++);
       switch (fd) {
         case FD_READY:
           waitDataFds[i] |= FD_READY_BIT;
diff -r 743a2cc2ed20 -r 058fdc3780ba rvm/src/org/jikesrvm/scheduler/greenthreads/ThreadProcessWaitQueue.java
--- a/rvm/src/org/jikesrvm/scheduler/greenthreads/ThreadProcessWaitQueue.java	Tue Aug 04 11:04:15 2009 +1000
+++ b/rvm/src/org/jikesrvm/scheduler/greenthreads/ThreadProcessWaitQueue.java	Mon Nov 16 09:21:21 2009 +1100
@@ -12,13 +12,17 @@
  */
 package org.jikesrvm.scheduler.greenthreads;
 
+import static org.jikesrvm.SizeConstants.LOG_BYTES_IN_INT;
 import org.jikesrvm.VM;
+import org.jikesrvm.mm.mminterface.MemoryManager;
 import org.jikesrvm.runtime.Magic;
 import static org.jikesrvm.runtime.SysCall.sysCall;
 import org.jikesrvm.scheduler.ProcessorLock;
 import org.vmmagic.pragma.Interruptible;
 import org.vmmagic.pragma.Uninterruptible;
 import org.vmmagic.pragma.Unpreemptible;
+import org.vmmagic.unboxed.Offset;
+import org.vmmagic.unboxed.WordArray;
 
 /**
  * A wait queue for threads that are waiting for a process
@@ -98,12 +102,12 @@
    * Array specifying pids to query to see if the
    * processes they represent have exited.
    */
-  private final int[] pidArray;
+  private final WordArray pidArray;
 
   /**
    * Array for returning exit status of pids which have exited.
    */
-  private final int[] exitStatusArray;
+  private final WordArray exitStatusArray;
 
   /**
    * Number of interrupted threads.
@@ -119,8 +123,8 @@
    * Constructor.
    */
   public ThreadProcessWaitQueue() {
-    pidArray = new int[MAX_NUM_PIDS];
-    exitStatusArray = new int[MAX_NUM_PIDS];
+    pidArray = MemoryManager.createNativeIntBuffer(MAX_NUM_PIDS);
+    exitStatusArray = MemoryManager.createNativeIntBuffer(MAX_NUM_PIDS);
   }
 
   /**
@@ -155,7 +159,7 @@
           if (VM.VerifyAssertions) VM._assert(waitData == thread.waitData);
 
           // Add pid to array of pids to query
-          pidArray[numPids] = waitData.pid;
+          Magic.setIntAtOffset(pidArray, Offset.fromIntZeroExtend(numPids<<LOG_BYTES_IN_INT), waitData.pid);
         }
 
       } // !thread.beingDispatched
@@ -173,7 +177,7 @@
     waitPidLock.lock("mutex while reading pids");
 
     // Call sysWaitPids() to see which (if any) have finished
-    sysCall.sysWaitPids(Magic.objectAsAddress(pidArray), Magic.objectAsAddress(exitStatusArray), numPids);
+    sysCall.sysWaitPids(pidArray, exitStatusArray, numPids);
 
     waitPidLock.unlock();
 
@@ -182,14 +186,14 @@
     // Mark threads whose processes have finished
     thread = head;
     while (thread != null) {
-      if (pidArray[numPids] == PROCESS_FINISHED) {
+      if (Magic.getIntAtOffset(pidArray, Offset.fromIntZeroExtend(numPids<<LOG_BYTES_IN_INT)) == PROCESS_FINISHED) {
         // Safe downcast from ThreadEventWaitData to ThreadProcessWaitData
         thread.waitData.accept(myDowncaster);
         ThreadProcessWaitData waitData = myDowncaster.waitData;
         if (VM.VerifyAssertions) VM._assert(waitData == thread.waitData);
 
         waitData.finished = true;
-        waitData.exitStatus = exitStatusArray[numPids];
+        waitData.exitStatus = Magic.getIntAtOffset(exitStatusArray, Offset.fromIntZeroExtend(numPids<<LOG_BYTES_IN_INT));
       }
 
       ++numPids;
diff -r 743a2cc2ed20 -r 058fdc3780ba rvm/src/org/jikesrvm/scheduler/greenthreads/VMProcess.java
--- a/rvm/src/org/jikesrvm/scheduler/greenthreads/VMProcess.java	Tue Aug 04 11:04:15 2009 +1000
+++ b/rvm/src/org/jikesrvm/scheduler/greenthreads/VMProcess.java	Mon Nov 16 09:21:21 2009 +1100
@@ -16,7 +16,11 @@
 import java.io.InputStream;
 import java.io.OutputStream;
 import org.jikesrvm.VM;
+import org.jikesrvm.classloader.RVMArray;
+import org.jikesrvm.mm.mminterface.MemoryManager;
+import org.jikesrvm.runtime.Memory;
 import org.vmmagic.pragma.Uninterruptible;
+import org.vmmagic.unboxed.WordArray;
 
 /**
  * Jikes RVM implementation of <code>java.lang.Process</code>.
@@ -268,11 +272,17 @@
       }
 
       public int read(byte[] buffer) throws IOException {
-        return FileSystem.readBytes(fd, buffer, 0, buffer.length);
+        WordArray tmp = MemoryManager.createNativeByteBuffer(buffer.length);
+        int rtn = FileSystem.readBytes(fd, tmp, 0, buffer.length);
+        Memory.nativeMarshal(tmp, buffer);
+        return rtn;
       }
 
       public int read(byte[] buf, int off, int len) throws IOException {
-        return FileSystem.readBytes(fd, buf, off, len);
+        WordArray tmp = MemoryManager.createNativeByteBuffer(len);
+        int rtn = FileSystem.readBytes(fd, tmp, 0, len);
+        Memory.nativeMarshal(tmp, 0, buf, off, len);
+        return rtn;
       }
     };
   }
@@ -284,11 +294,11 @@
       }
 
       public void write(byte[] b) throws IOException {
-        FileSystem.writeBytes(fd, b, 0, b.length);
+        FileSystem.writeBytes(fd, MemoryManager.cloneToNativeBuffer(b), 0, b.length);
       }
 
       public void write(byte[] b, int off, int len) throws IOException {
-        FileSystem.writeBytes(fd, b, off, len);
+        FileSystem.writeBytes(fd, MemoryManager.cloneToNativeBuffer(b), off, len);
       }
 
       public void flush() throws IOException {
diff -r 743a2cc2ed20 -r 058fdc3780ba rvm/src/org/jikesrvm/scheduler/nativethreads/NativeThread.java
--- a/rvm/src/org/jikesrvm/scheduler/nativethreads/NativeThread.java	Tue Aug 04 11:04:15 2009 +1000
+++ b/rvm/src/org/jikesrvm/scheduler/nativethreads/NativeThread.java	Mon Nov 16 09:21:21 2009 +1100
@@ -18,6 +18,7 @@
 import org.jikesrvm.scheduler.Lock;
 import org.jikesrvm.scheduler.RVMThread;
 import org.vmmagic.pragma.NonMoving;
+import org.vmmagic.unboxed.WordArray;
 
 @NonMoving
 public class NativeThread extends RVMThread {
@@ -39,7 +40,7 @@
    * {@link org.jikesrvm.mm.mminterface.CollectorThread} and the
    * boot image writer for the boot thread.
    */
-  public NativeThread(byte[] stack, String name) {
+  public NativeThread(WordArray stack, String name) {
     this(stack,
         null, // java.lang.Thread
         name,
@@ -60,7 +61,7 @@
   /**
    * Create a thread.
    */
-  protected NativeThread(byte[] stack, Thread thread, String name, boolean daemon, boolean system, int priority) {
+  protected NativeThread(WordArray stack, Thread thread, String name, boolean daemon, boolean system, int priority) {
     super(stack, thread, name, daemon, system, priority);
   }
 
diff -r 743a2cc2ed20 -r 058fdc3780ba testing/tests/arraylets/build.xml
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/testing/tests/arraylets/build.xml	Mon Nov 16 09:21:21 2009 +1100
@@ -0,0 +1,75 @@
+<!--
+ ~  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ ~
+ ~  This file is licensed to You under the Common Public License (CPL);
+ ~  You may not use this file except in compliance with the License. You
+ ~  may obtain a copy of the License at
+ ~
+ ~      http://www.opensource.org/licenses/cpl1.0.php
+ ~
+ ~  See the COPYRIGHT.txt file distributed with this work for information
+ ~  regarding copyright ownership.
+ -->
+<project name="arraylets" default="test" basedir=".">
+
+  <condition property="test.time.limit" value="1000" else="400">
+    <equals arg1="${test.mode}" arg2="gcstress"/>
+  </condition>
+
+  <property name="test.max.heapsize" value="150"/>
+
+  <import file="../../../build/tests.xml"/>
+
+  <property name="main.java" location="${basedir}/src"/>
+
+  <property name="build.classes" location="${build.tests.dir}/classes"/>
+
+  <property name="test.class.path" value="${build.classes}"/>
+
+  <!-- **************************************************************************** -->
+  <!-- *                                                                          * -->
+  <!-- *                            Compile the tests                             * -->
+  <!-- *                                                                          * -->
+  <!-- **************************************************************************** -->
+
+  <target name="compile" depends="init">
+    <mkdir dir="${build.classes}"/>
+    <javac srcdir="${main.java}" destdir="${build.classes}" debug="true">
+      <!-- need extra classpath for vmmagic -->
+      <classpath>
+        <pathelement path="${test.rvm.dir}/jksvm.jar"/>
+      </classpath>
+    </javac>
+  </target>
+
+  <!-- **************************************************************************** -->
+  <!-- *                                                                          * -->
+  <!-- *                            Run the tests                                 * -->
+  <!-- *                                                                          * -->
+  <!-- **************************************************************************** -->
+
+  <macrodef name="runArrayletTest">
+    <attribute name="tag"/>
+    <attribute name="type"/>
+    <sequential>
+      <runCompareTest tag="@{tag}" class="test.org.jikesrvm.arraylets.TestArraylets" args="@{type}" expectedSuffix=".@{type}" />
+    </sequential>
+  </macrodef>
+
+  <target name="test" depends="compile">
+    <startResults/>
+
+    <runArrayletTest tag="ByteArrays" type="b"/>
+    <runArrayletTest tag="BooleanArrays" type="z"/>
+    <runArrayletTest tag="CharArrays" type="c"/>
+    <runArrayletTest tag="ShortArrays"  type="s"/>
+    <runArrayletTest tag="IntArrays" type="i"/>
+    <runArrayletTest tag="FloatArrays" type="f"/>
+    <runArrayletTest tag="LongArrays" type="j"/>
+    <runArrayletTest tag="DoubleArrays" type="d"/>
+    <runArrayletTest tag="RefArrays" type="a"/>
+
+    <finishResults/>
+  </target>
+
+</project>
diff -r 743a2cc2ed20 -r 058fdc3780ba testing/tests/arraylets/src/test/org/jikesrvm/arraylets/TestArraylets.a.expected
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/testing/tests/arraylets/src/test/org/jikesrvm/arraylets/TestArraylets.a.expected	Mon Nov 16 09:21:21 2009 +1100
@@ -0,0 +1,1 @@
+Testing Object[]... Done.
diff -r 743a2cc2ed20 -r 058fdc3780ba testing/tests/arraylets/src/test/org/jikesrvm/arraylets/TestArraylets.b.expected
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/testing/tests/arraylets/src/test/org/jikesrvm/arraylets/TestArraylets.b.expected	Mon Nov 16 09:21:21 2009 +1100
@@ -0,0 +1,1 @@
+Testing byte[]... Done.
diff -r 743a2cc2ed20 -r 058fdc3780ba testing/tests/arraylets/src/test/org/jikesrvm/arraylets/TestArraylets.c.expected
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/testing/tests/arraylets/src/test/org/jikesrvm/arraylets/TestArraylets.c.expected	Mon Nov 16 09:21:21 2009 +1100
@@ -0,0 +1,1 @@
+Testing char[]... Done.
diff -r 743a2cc2ed20 -r 058fdc3780ba testing/tests/arraylets/src/test/org/jikesrvm/arraylets/TestArraylets.d.expected
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/testing/tests/arraylets/src/test/org/jikesrvm/arraylets/TestArraylets.d.expected	Mon Nov 16 09:21:21 2009 +1100
@@ -0,0 +1,1 @@
+Testing double[]... Done.
diff -r 743a2cc2ed20 -r 058fdc3780ba testing/tests/arraylets/src/test/org/jikesrvm/arraylets/TestArraylets.f.expected
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/testing/tests/arraylets/src/test/org/jikesrvm/arraylets/TestArraylets.f.expected	Mon Nov 16 09:21:21 2009 +1100
@@ -0,0 +1,1 @@
+Testing float[]... Done.
diff -r 743a2cc2ed20 -r 058fdc3780ba testing/tests/arraylets/src/test/org/jikesrvm/arraylets/TestArraylets.i.expected
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/testing/tests/arraylets/src/test/org/jikesrvm/arraylets/TestArraylets.i.expected	Mon Nov 16 09:21:21 2009 +1100
@@ -0,0 +1,1 @@
+Testing int[]... Done.
diff -r 743a2cc2ed20 -r 058fdc3780ba testing/tests/arraylets/src/test/org/jikesrvm/arraylets/TestArraylets.j.expected
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/testing/tests/arraylets/src/test/org/jikesrvm/arraylets/TestArraylets.j.expected	Mon Nov 16 09:21:21 2009 +1100
@@ -0,0 +1,1 @@
+Testing long[]... Done.
diff -r 743a2cc2ed20 -r 058fdc3780ba testing/tests/arraylets/src/test/org/jikesrvm/arraylets/TestArraylets.java
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/testing/tests/arraylets/src/test/org/jikesrvm/arraylets/TestArraylets.java	Mon Nov 16 09:21:21 2009 +1100
@@ -0,0 +1,306 @@
+/*
+ *  This file is part of the Jikes RVM project (http://jikesrvm.org).
+ *
+ *  This file is licensed to You under the Common Public License (CPL);
+ *  You may not use this file except in compliance with the License. You
+ *  may obtain a copy of the License at
+ *
+ *      http://www.opensource.org/licenses/cpl1.0.php
+ *
+ *  See the COPYRIGHT.txt file distributed with this work for information
+ *  regarding copyright ownership.
+ */
+package test.org.jikesrvm.arraylets;
+
+import java.util.Random;
+
+/**
+ * Class to test arraylet barriers.
+ */
+public class TestArraylets {
+
+  private static int SMALL_ARRAY_SIZE = 16;
+  private static int LARGE_ARRAY_SIZE = 1 << 11;
+  private static int SEED = 2346222;
+
+  public static void main(String[] args) {
+    String types;
+    if (args.length == 0) {
+      types = "bzscifjda";
+    } else {
+      types = args[0];
+    }
+    
+    for(char t: types.toUpperCase().toCharArray()) {
+      switch(t) {
+        case 'B':
+          System.out.print("Testing byte[]...");
+          testBytes(SMALL_ARRAY_SIZE, false);
+          testBytes(LARGE_ARRAY_SIZE, false);
+          testBytes(LARGE_ARRAY_SIZE, true);
+          break;
+        case 'Z':
+          System.out.print("Testing boolean[]...");
+          testBooleans(SMALL_ARRAY_SIZE, false);
+          testBooleans(LARGE_ARRAY_SIZE, false);
+          testBooleans(LARGE_ARRAY_SIZE, true);
+          break;
+        case 'S':
+          System.out.print("Testing short[]...");
+          testShorts(SMALL_ARRAY_SIZE, false);
+          testShorts(LARGE_ARRAY_SIZE, false);
+          testShorts(LARGE_ARRAY_SIZE, true);
+          break;
+        case 'C':
+          System.out.print("Testing char[]...");
+          testChars(SMALL_ARRAY_SIZE, false);
+          testChars(LARGE_ARRAY_SIZE, false);
+          testChars(LARGE_ARRAY_SIZE, true);
+          break;
+        case 'I':
+          System.out.print("Testing int[]...");
+          testInts(SMALL_ARRAY_SIZE, false);
+          testInts(LARGE_ARRAY_SIZE, false);
+          testInts(LARGE_ARRAY_SIZE, true);
+          break;
+        case 'F':
+          System.out.print("Testing float[]...");
+          testFloats(SMALL_ARRAY_SIZE, false);
+          testFloats(LARGE_ARRAY_SIZE, false);
+          testFloats(LARGE_ARRAY_SIZE, true);
+          break;
+        case 'J':
+          System.out.print("Testing long[]...");
+          testLongs(SMALL_ARRAY_SIZE, false);
+          testLongs(LARGE_ARRAY_SIZE, false);
+          testLongs(LARGE_ARRAY_SIZE, true);
+          break;
+        case 'D':
+          System.out.print("Testing double[]...");
+          testDoubles(SMALL_ARRAY_SIZE, false);
+          testDoubles(LARGE_ARRAY_SIZE, false);
+          testDoubles(LARGE_ARRAY_SIZE, true);
+          break;
+        case 'A':
+          System.out.print("Testing Object[]...");
+           testRefs(SMALL_ARRAY_SIZE, false);
+          testRefs(LARGE_ARRAY_SIZE, false);
+          testRefs(LARGE_ARRAY_SIZE, true);
+          break;
+      }
+      System.out.println(" Done.");
+    }
+  }
+
+  private static void testBytes(int size, boolean gc) {
+    byte[] array = new byte[size];
+    Random r = new Random(SEED);
+    
+    for(int i=0; i < array.length;i++) {
+      byte val = (byte)(r.nextInt() % 128);
+      beEvil();
+      array[i] = val;
+    }
+
+    if (gc) System.gc();
+    r = new Random(SEED);
+
+    for(int i=0; i < array.length;i++) { 
+      byte expected = (byte)(r.nextInt() % 128);
+      if (array[i] != expected) System.err.println("MISMATCH: Size " + size + " Iteration " + i + " read value " + array[i] + " expected " + expected);
+    }
+  }
+
+  private static void testBooleans(int size, boolean gc) {
+    boolean[] array = new boolean[size];
+    Random r = new Random(SEED);
+    
+    for(int i=0; i < array.length;i++) {
+      boolean val = r.nextFloat() > 0.5f;
+      beEvil();
+      array[i] = val;
+    }
+
+    if (gc) System.gc();
+    r = new Random(SEED);
+
+    for(int i=0; i < array.length;i++) { 
+      boolean expected = r.nextFloat() > 0.5f;
+      if (array[i] != expected) System.err.println("MISMATCH: Size " + size + " Iteration " + i + " read value " + array[i] + " expected " + expected);
+    }
+  }
+
+  private static void testChars(int size, boolean gc) {
+    char[] array = new char[size];
+    Random r = new Random(SEED);
+    
+    for(int i=0; i < array.length;i++) {
+      char val = (char)(r.nextInt(65536));
+      beEvil();
+      array[i] = val;
+    }
+
+    if (gc) System.gc();
+    r = new Random(SEED);
+
+    for(int i=0; i < array.length;i++) { 
+      char expected = (char)(r.nextInt(65536));
+      if (array[i] != expected) System.err.println("MISMATCH: Size " + size + " Iteration " + i + " read value " + array[i] + " expected " + expected);
+    }
+  }
+
+  private static void testShorts(int size, boolean gc) {
+    short[] array = new short[size];
+    Random r = new Random(SEED);
+    
+    for(int i=0; i < array.length;i++) {
+      short val = (short)(r.nextInt() % 32768);
+      beEvil();
+      array[i] = val;
+    }
+
+    if (gc) System.gc();
+    r = new Random(SEED);
+
+    for(int i=0; i < array.length;i++) { 
+      short expected = (short)(r.nextInt() % 32768);
+      if (array[i] != expected) System.err.println("MISMATCH: Size " + size + " Iteration " + i + " read value " + array[i] + " expected " + expected);
+    }
+  }
+
+  private static void testInts(int size, boolean gc) {
+    int[] array = new int[size];
+    Random r = new Random(SEED);
+    
+    for(int i=0; i < array.length;i++) {
+      int val = r.nextInt();
+      beEvil();
+      array[i] = val;
+    }
+
+    if (gc) System.gc();
+    r = new Random(SEED);
+
+    for(int i=0; i < array.length;i++) { 
+      int expected = r.nextInt();
+      if (array[i] != expected) System.err.println("MISMATCH: Size " + size + " Iteration " + i + " read value " + array[i] + " expected " + expected);
+    }
+  }
+
+  private static void testFloats(int size, boolean gc) {
+    float[] array = new float[size];
+    Random r = new Random(SEED);
+    
+    for(int i=0; i < array.length;i++) {
+      float val = r.nextFloat();
+      beEvil();
+      array[i] = val;
+    }
+
+    if (gc) System.gc();
+    r = new Random(SEED);
+
+    for(int i=0; i < array.length;i++) { 
+      float expected = r.nextFloat();
+      if (array[i] != expected) System.err.println("MISMATCH: Size " + size + " Iteration " + i + " read value " + array[i] + " expected " + expected);
+    }
+  }
+
+  private static void testDoubles(int size, boolean gc) {
+    double[] array = new double[size];
+    Random r = new Random(SEED);
+    
+    for(int i=0; i < array.length;i++) {
+      double val = r.nextDouble();
+      beEvil();
+      array[i] = val;
+    }
+
+    if (gc) System.gc();
+    r = new Random(SEED);
+
+    for(int i=0; i < array.length;i++) { 
+      double expected = r.nextDouble();
+      if (array[i] != expected) System.err.println("MISMATCH: Size " + size + " Iteration " + i + " read value " + array[i] + " expected " + expected);
+    }
+  }
+
+  private static void testLongs(int size, boolean gc) {
+    long[] array = new long[size];
+    Random r = new Random(SEED);
+    
+    for(int i=0; i < array.length;i++) {
+      long val = r.nextLong();
+      beEvil();
+      array[i] = val;
+    }
+
+    if (gc) System.gc();
+    r = new Random(SEED);
+
+    for(int i=0; i < array.length;i++) { 
+      long expected = r.nextLong();
+      if (array[i] != expected) System.err.println("MISMATCH: Size " + size + " Iteration " + i + " read value " + array[i] + " expected " + expected);
+    }
+  }
+
+  private static Object evilObject;
+
+  private static void beEvil() {
+    evilObject = new Float(100.0f);
+  }
+
+  private static String nameRef(Object x, Object c0, Object c1, Object c2, Object c3, Object c4, Object c5, Object c6, Object c7) {
+    if (x == null) return "null";
+    if (x == c0) return "c0";
+    if (x == c1) return "c1";
+    if (x == c2) return "c2";
+    if (x == c3) return "c3";
+    if (x == c4) return "c4";
+    if (x == c5) return "c5";
+    if (x == c6) return "c6";
+    if (x == c7) return "c7";
+    return "unknown";
+  }
+
+  private static Object pickRef(int x, Object c0, Object c1, Object c2, Object c3, Object c4, Object c5, Object c6, Object c7) {
+    switch(x) {
+      case 0: return c0;
+      case 1: return c1;
+      case 2: return c2;
+      case 3: return c3;
+      case 4: return c4;
+      case 5: return c5;
+      case 6: return c6;
+      case 7: return c7;
+      default: return null;
+    }
+  }
+
+  private static void testRefs(int size, boolean gc) {
+    Object[] array = new Object[size];
+    Random r = new Random(SEED);
+    Object c0 = new Object();
+    Object c1 = new Object();
+    Object c2 = new Object();
+    Object c3 = new Object();
+    Object c4 = new Object();
+    Object c5 = new Object();
+    Object c6 = new Object();
+    Object c7 = new Object();
+    
+    for(int i=0; i < array.length;i++) {
+      Object val = pickRef(r.nextInt(16), c0, c1, c2, c3, c4, c5, c6, c7);
+      beEvil();
+      array[i] = val;
+    }
+
+    if (gc) System.gc();
+    r = new Random(SEED);
+
+    for(int i=0; i < array.length;i++) { 
+      Object expected = pickRef(r.nextInt(16), c0, c1, c2, c3, c4, c5, c6, c7);
+      if (array[i] != expected) System.err.println("MISMATCH: Size " + size + " Iteration " + i + " read value " + nameRef(array[i], c0, c1, c2, c3, c4, c5, c6, c7) + " expected " + nameRef(expected, c0, c1, c2, c3, c4, c5, c6, c7));
+    }
+  }
+}
diff -r 743a2cc2ed20 -r 058fdc3780ba testing/tests/arraylets/src/test/org/jikesrvm/arraylets/TestArraylets.s.expected
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/testing/tests/arraylets/src/test/org/jikesrvm/arraylets/TestArraylets.s.expected	Mon Nov 16 09:21:21 2009 +1100
@@ -0,0 +1,1 @@
+Testing short[]... Done.
diff -r 743a2cc2ed20 -r 058fdc3780ba testing/tests/arraylets/src/test/org/jikesrvm/arraylets/TestArraylets.z.expected
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/testing/tests/arraylets/src/test/org/jikesrvm/arraylets/TestArraylets.z.expected	Mon Nov 16 09:21:21 2009 +1100
@@ -0,0 +1,1 @@
+Testing boolean[]... Done.
diff -r 743a2cc2ed20 -r 058fdc3780ba tools/bootImageRunner/RunBootImage.C
--- a/tools/bootImageRunner/RunBootImage.C	Tue Aug 04 11:04:15 2009 +1000
+++ b/tools/bootImageRunner/RunBootImage.C	Mon Nov 16 09:21:21 2009 +1100
@@ -403,7 +403,7 @@
 int
 main(int argc, const char **argv)
 {
-    Me            = strrchr(*argv, '/') + 1;
+    Me            = strrchr((char*)*argv, '/') + 1;
     ++argv, --argc;
     initialHeapSize = heap_default_initial_size;
     maximumHeapSize = heap_default_maximum_size;
diff -r 743a2cc2ed20 -r 058fdc3780ba tools/bootImageWriter/src/org/jikesrvm/tools/bootImageWriter/BootImage.java
--- a/tools/bootImageWriter/src/org/jikesrvm/tools/bootImageWriter/BootImage.java	Tue Aug 04 11:04:15 2009 +1000
+++ b/tools/bootImageWriter/src/org/jikesrvm/tools/bootImageWriter/BootImage.java	Mon Nov 16 09:21:21 2009 +1100
@@ -245,7 +245,7 @@
    */
   public Address allocateArray(RVMArray array, int numElements, boolean needsIdentityHash, int identityHashValue) {
     numObjects++;
-    BootImageWriter.logAllocation(array, array.getInstanceSize(numElements));
+    BootImageWriter.logAllocation(array, array.getBootImageContiguousInstanceSize(numElements)); //array.getInstanceSize(numElements));
     return ObjectModel.allocateArray(this, array, numElements, needsIdentityHash, identityHashValue);
   }
 
diff -r 743a2cc2ed20 -r 058fdc3780ba tools/bootImageWriter/src/org/jikesrvm/tools/bootImageWriter/BootImageWriter.java
--- a/tools/bootImageWriter/src/org/jikesrvm/tools/bootImageWriter/BootImageWriter.java	Tue Aug 04 11:04:15 2009 +1000
+++ b/tools/bootImageWriter/src/org/jikesrvm/tools/bootImageWriter/BootImageWriter.java	Mon Nov 16 09:21:21 2009 +1100
@@ -12,6 +12,8 @@
  */
 package org.jikesrvm.tools.bootImageWriter;
 
+import org.jikesrvm.mm.mminterface.MemoryManagerConstants;
+
 import java.io.BufferedOutputStream;
 import java.io.File;
 import java.io.FileOutputStream;
@@ -60,6 +62,8 @@
 import org.jikesrvm.compilers.common.CompiledMethods;
 import org.jikesrvm.jni.FunctionTable;
 import org.jikesrvm.jni.JNIEnvironment;
+import org.jikesrvm.mm.mminterface.MemoryManager;
+import org.jikesrvm.mm.mminterface.MemoryManagerConstants;
 import org.jikesrvm.objectmodel.MiscHeader;
 import org.jikesrvm.objectmodel.ObjectModel;
 import org.jikesrvm.objectmodel.RuntimeTable;
@@ -75,6 +79,7 @@
 import org.vmmagic.unboxed.ObjectReference;
 import org.vmmagic.unboxed.Offset;
 import org.vmmagic.unboxed.Word;
+import org.vmmagic.unboxed.WordArray;
 
 /**
  * Construct an RVM virtual machine bootimage.
@@ -936,7 +941,7 @@
     Address bootRecordImageAddress = Address.zero();
     try {
       // copy just the boot record
-      bootRecordImageAddress = copyToBootImage(bootRecord, true, Address.max(), null, false);
+      bootRecordImageAddress = copyToBootImage(bootRecord, true, Address.max(), null, false, false);
       if (bootRecordImageAddress.EQ(OBJECT_NOT_PRESENT)) {
         fail("can't copy boot record");
       }
@@ -951,7 +956,7 @@
     // Pointer to middle of JTOC
     Address jtocImageAddress = Address.zero();
     try {
-      jtocImageAddress = copyToBootImage(Statics.getSlotsAsIntArray(), false, Address.max(), null, false);
+      jtocImageAddress = copyToBootImage(Statics.getSlotsAsIntArray(), false, Address.max(), null, false, true);
       if (jtocImageAddress.EQ(OBJECT_NOT_PRESENT)) {
         fail("can't copy jtoc");
       }
@@ -1001,7 +1006,7 @@
       for (int i=0; i < BootImageMap.objectIdToEntry.size(); i++) {
         BootImageMap.Entry mapEntry = BootImageMap.objectIdToEntry.get(i);
         if (mapEntry.imageAddress.EQ(OBJECT_NOT_ALLOCATED)) {
-          mapEntry.imageAddress = copyToBootImage(mapEntry.jdkObject, false, Address.max(), null, false);
+          mapEntry.imageAddress = copyToBootImage(mapEntry.jdkObject, false, Address.max(), null, false, false);
           fixupLinkAddresses(mapEntry);
         }
       }
@@ -1019,11 +1024,11 @@
     //
     if (verbose >= 1) say("updating boot record");
 
-    byte[] startupStack = startupThread.getStack();
+    WordArray startupStack = startupThread.getStack();
     CodeArray startupCode  = Entrypoints.bootMethod.getCurrentEntryCodeArray();
 
     bootRecord.tiRegister  = startupThread.getLockingId();
-    bootRecord.spRegister  = BootImageMap.getImageAddress(startupStack, true).plus(startupStack.length);
+    bootRecord.spRegister  = BootImageMap.getImageAddress(startupStack, true).plus(MemoryManager.nativeByteBufferLength(startupStack));
     bootRecord.ipRegister  = BootImageMap.getImageAddress(startupCode.getBacking(), true);
 
     bootRecord.greenProcessorsOffset = Entrypoints.greenProcessorsField.getOffset();
@@ -1039,7 +1044,7 @@
     //
     if (verbose >= 1) say("re-copying boot record (and its TIB)");
     try {
-      Address newBootRecordImageAddress = copyToBootImage(bootRecord, false, bootRecordImageAddress, null, false);
+      Address newBootRecordImageAddress = copyToBootImage(bootRecord, false, bootRecordImageAddress, null, false, false);
       if (!newBootRecordImageAddress.EQ(bootRecordImageAddress)) {
         VM.sysWriteln("bootRecordImageOffset = ", bootRecordImageAddress);
         VM.sysWriteln("newBootRecordImageOffset = ", newBootRecordImageAddress);
@@ -1380,11 +1385,11 @@
                                     ObjectModel.getAlignment(rvmBRType),
                                     ObjectModel.getOffsetForAlignment(rvmBRType, false));
       // allocate storeage for JTOC
-      Address jtocAddress = bootImage.allocateDataStorage(intArrayType.getInstanceSize(0),
+      Address jtocAddress = bootImage.allocateDataStorage(intArrayType.getContiguousInstanceSize(0), //getInstanceSize(0),
                                                           ObjectModel.getAlignment(intArrayType),
                                                           ObjectModel.getOffsetForAlignment(intArrayType, false));
       bootImage.resetAllocator();
-      bootRecord.tocRegister = jtocAddress.plus(intArrayType.getInstanceSize(Statics.middleOfTable));
+      bootRecord.tocRegister = jtocAddress.plus(intArrayType.getContiguousInstanceSize(Statics.middleOfTable));//getInstanceSize(Statics.middleOfTable));
 
       // set up some stuff we need for compiling
       OutOfLineMachineCode.init();
@@ -1528,19 +1533,19 @@
       // Create stack, thread, and processor context in which rvm will begin
       // execution.
       startupThread = Scheduler.setupBootThread();
-      byte[] stack = startupThread.getStack();
+      WordArray stack = startupThread.getStack();
       // sanity check for bootstrap loader
-      int idx = stack.length - 1;
+      int idx = MemoryManager.nativeByteBufferLength(stack) - 1;
       if (VM.LittleEndian) {
-        stack[idx--] = (byte)0xde;
-        stack[idx--] = (byte)0xad;
-        stack[idx--] = (byte)0xba;
-        stack[idx--] = (byte)0xbe;
+        stack.setByte(idx--, (byte)0xde);
+        stack.setByte(idx--, (byte)0xad);
+        stack.setByte(idx--, (byte)0xba);
+        stack.setByte(idx--, (byte)0xbe);
       } else {
-        stack[idx--] = (byte)0xbe;
-        stack[idx--] = (byte)0xba;
-        stack[idx--] = (byte)0xad;
-        stack[idx--] = (byte)0xde;
+        stack.setByte(idx--, (byte)0xbe);
+        stack.setByte(idx--, (byte)0xba);
+        stack.setByte(idx--, (byte)0xad);
+        stack.setByte(idx--, (byte)0xde);
       }
 
       //
@@ -1795,7 +1800,7 @@
           root = false;
         } else {
           // Recurse placing work on the stack
-          mapEntry.imageAddress = copyToBootImage(referencedObject, false, Address.max(), parentObject, false);
+          mapEntry.imageAddress = copyToBootImage(referencedObject, false, Address.max(), parentObject, false, false);
           imageAddress = mapEntry.imageAddress;
         }
         if (imageAddress.EQ(OBJECT_NOT_PRESENT)) {
@@ -1823,7 +1828,7 @@
       BootImageMap.Entry mapEntry = pendingEntries.remove();
       mapEntry.clearPendingEntry();
       if (mapEntry.imageAddress.EQ(OBJECT_NOT_ALLOCATED)) {
-        mapEntry.imageAddress = copyToBootImage(mapEntry.jdkObject, false, Address.max(), null, false);
+        mapEntry.imageAddress = copyToBootImage(mapEntry.jdkObject, false, Address.max(), null, false, false);
       }
       fixupLinkAddresses(mapEntry);
     }
@@ -1868,7 +1873,7 @@
    *            it's not part of bootimage)
    */
   private static Address copyToBootImage(Object jdkObject, boolean allocOnly,
-      Address overwriteAddress, Object parentObject, boolean untraced) throws IllegalAccessException
+      Address overwriteAddress, Object parentObject, boolean untraced, boolean doNotArrayletize) throws IllegalAccessException
   {
     try {
       // Return object if it is already copied and not being overwritten
@@ -1898,12 +1903,12 @@
         Address arrayImageAddress = (overwriteAddress.isMax()) ? bootImage.allocateArray(rvmArrayType, arrayCount, needsIdentityHash, identityHashValue) : overwriteAddress;
         mapEntry.imageAddress = arrayImageAddress;
         mapEntry.imageAddress = copyArrayToBootImage(arrayCount, arrayImageAddress, jdkObject, jdkType,
-            rvmArrayType, allocOnly, overwriteAddress, parentObject, untraced);
+            rvmArrayType, allocOnly, overwriteAddress, parentObject, untraced, doNotArrayletize);
         // copy object's type information block into image, if it's not there
         // already
         if (!allocOnly) {
           if (verbose >= 2) traceContext.push("", jdkObject.getClass().getName(), "tib");
-          Address tibImageAddress = copyToBootImage(rvmType.getTypeInformationBlock(), allocOnly, Address.max(), jdkObject, false);
+          Address tibImageAddress = copyToBootImage(rvmType.getTypeInformationBlock(), allocOnly, Address.max(), jdkObject, false, false);
           if (verbose >= 2) traceContext.pop();
           if (tibImageAddress.EQ(OBJECT_NOT_ALLOCATED)) {
             fail("can't copy tib for " + jdkObject);
@@ -1914,7 +1919,7 @@
         Object backing = ((RuntimeTable<?>)jdkObject).getBacking();
 
         /* Copy the backing array, and then replace its TIB */
-        mapEntry.imageAddress = copyToBootImage(backing, allocOnly, overwriteAddress, jdkObject, rvmType.getTypeRef().isRuntimeTable());
+        mapEntry.imageAddress = copyToBootImage(backing, allocOnly, overwriteAddress, jdkObject, rvmType.getTypeRef().isRuntimeTable(), true);
 
         if (!allocOnly) {
           copyTIBToBootImage(rvmType, jdkObject, mapEntry.imageAddress);
@@ -1971,7 +1976,7 @@
       depth--;
       traceContext.push("", jdkObject.getClass().getName(), "tib");
     }
-    Address tibImageAddress = copyToBootImage(rvmType.getTypeInformationBlock(), false, Address.max(), jdkObject, false);
+    Address tibImageAddress = copyToBootImage(rvmType.getTypeInformationBlock(), false, Address.max(), jdkObject, false, false);
     if (verbose >= 2) {
       traceContext.pop();
       depth++;
@@ -2131,7 +2136,7 @@
    * @throws IllegalAccessException
    */
   private static Address copyArrayToBootImage(int arrayCount, Address arrayImageAddress, Object jdkObject, Class<?> jdkType, RVMArray rvmArrayType,
-      boolean allocOnly, Address overwriteAddress, Object parentObject, boolean  untraced)
+      boolean allocOnly, Address overwriteAddress, Object parentObject, boolean  untraced, boolean doNotArrayletize)
   throws IllegalAccessException {
     if (verbose >= 2) {
       if (depth == depthCutoff)
@@ -2140,7 +2145,7 @@
         String tab = SPACES.substring(0,depth+1);
         if (depth == 0 && jtocCount >= 0)
           tab = tab + "jtoc #" + String.valueOf(jtocCount) + ": ";
-        int arraySize = rvmArrayType.getInstanceSize(arrayCount);
+        int arraySize = rvmArrayType.getBootImageContiguousInstanceSize(arrayCount); //.getInstanceSize(arrayCount);
         say(tab, "Copying array  ", jdkType.getName(),
             "   length=", String.valueOf(arrayCount),
             (arraySize >= LARGE_ARRAY_SIZE) ? " large object!!!" : "");
@@ -2149,70 +2154,88 @@
 
     RVMType rvmElementType = rvmArrayType.getElementType();
 
-    // copy array elements from host jdk address space into image
-    // recurse on values that are references
-    if (rvmElementType.isPrimitiveType()) {
-      // array element is logical or numeric type
-      if (rvmElementType.equals(RVMType.BooleanType)) {
-        boolean[] values = (boolean[]) jdkObject;
-        for (int i = 0; i < arrayCount; ++i)
-          bootImage.setByte(arrayImageAddress.plus(i), values[i] ? 1 : 0);
-      } else if (rvmElementType.equals(RVMType.ByteType)) {
-        byte[] values = (byte[]) jdkObject;
-        for (int i = 0; i < arrayCount; ++i)
-          bootImage.setByte(arrayImageAddress.plus(i), values[i]);
-      } else if (rvmElementType.equals(RVMType.CharType)) {
-        char[] values = (char[]) jdkObject;
-        for (int i = 0; i < arrayCount; ++i)
-          bootImage.setHalfWord(arrayImageAddress.plus(i << LOG_BYTES_IN_CHAR), values[i]);
-      } else if (rvmElementType.equals(RVMType.ShortType)) {
-        short[] values = (short[]) jdkObject;
-        for (int i = 0; i < arrayCount; ++i)
-          bootImage.setHalfWord(arrayImageAddress.plus(i << LOG_BYTES_IN_SHORT), values[i]);
-      } else if (rvmElementType.equals(RVMType.IntType)) {
-        int[] values = (int[]) jdkObject;
-        for (int i = 0; i < arrayCount; ++i)
-          bootImage.setFullWord(arrayImageAddress.plus(i << LOG_BYTES_IN_INT), values[i]);
-      } else if (rvmElementType.equals(RVMType.LongType)) {
-        long[] values = (long[]) jdkObject;
-        for (int i = 0; i < arrayCount; ++i)
-          bootImage.setDoubleWord(arrayImageAddress.plus(i << LOG_BYTES_IN_LONG), values[i]);
-      } else if (rvmElementType.equals(RVMType.FloatType)) {
-        float[] values = (float[]) jdkObject;
-        for (int i = 0; i < arrayCount; ++i)
-          bootImage.setFullWord(arrayImageAddress.plus(i << LOG_BYTES_IN_FLOAT),
-              Float.floatToIntBits(values[i]));
-      } else if (rvmElementType.equals(RVMType.DoubleType)) {
-        double[] values = (double[]) jdkObject;
-        for (int i = 0; i < arrayCount; ++i)
-          bootImage.setDoubleWord(arrayImageAddress.plus(i << LOG_BYTES_IN_DOUBLE),
-              Double.doubleToLongBits(values[i]));
-      } else {
-        fail("unexpected primitive array type: " + rvmArrayType);
+    // only used for object reference arrays
+    Class<?> jdkClass = jdkObject.getClass();
+    boolean isTIB = parentObject instanceof TIB;
+
+    // array element is logical or numeric type
+    boolean arrayletize = (MemoryManagerConstants.BOOT_IMAGE_IS_ARRAYLETIZED && 
+                           rvmArrayType.isArrayletizable() && 
+                           !doNotArrayletize);
+
+    int logElementSize = rvmArrayType.getLogElementSize();
+
+    // only used for arraylets
+    int firstN = 0;
+    int arrayletCount = 0;
+
+    if (arrayletize) {
+      firstN = rvmArrayType.getFirstNElements();
+      int logArrayletElements = rvmArrayType.getLogArrayletElements();
+      int arrayletizedElements = arrayCount - firstN;
+      if (arrayletizedElements > 0) {
+        //System.err.println("arraylet " + arrayImageAddress + " " + arrayletizedElements);
+        arrayletCount = 1 + (arrayletizedElements >> logArrayletElements);
+        // install arraylet pointers
+        int spinePointerOffset = (firstN << logElementSize);
+        int arrayletOffset = spinePointerOffset + (arrayletCount << LOG_BYTES_IN_ADDRESS);
+        for(int j = 0; j < arrayletCount; j++) {
+          //System.err.println(spinePointerOffset + "-->" + arrayletOffset);
+          bootImage.setAddressWord(arrayImageAddress.plus(spinePointerOffset), arrayImageAddress.plus(arrayletOffset).toWord(), false, false);
+          spinePointerOffset += BYTES_IN_ADDRESS;
+          arrayletOffset += MemoryManagerConstants.ARRAYLET_BYTES;
+        }
       }
-    } else {
-      // array element is reference type
-      boolean isTIB = parentObject instanceof TIB;
-      Object[] values = (Object []) jdkObject;
-      Class<?> jdkClass = jdkObject.getClass();
-      if (!allocOnly) {
-        for (int i = 0; i<arrayCount; ++i) {
-          if (values[i] != null) {
-            if (verbose >= 2) traceContext.push(values[i].getClass().getName(), jdkClass.getName(), i);
-            if (isTIB && values[i] instanceof Word) {
-              bootImage.setAddressWord(arrayImageAddress.plus(i << LOG_BYTES_IN_ADDRESS), (Word)values[i], false, false);
-            } else if (isTIB && values[i] == LazyCompilationTrampoline.instructions) {
+    }
+
+    if (!allocOnly) {
+      int elementOffset = 0;
+      for (int i = 0; i < arrayCount; i++) {
+        if (arrayletize && i == firstN) {
+          // skip over the arraylet pointers.
+          elementOffset += arrayletCount << LOG_BYTES_IN_ADDRESS;
+        }
+        
+        if (rvmElementType.isPrimitiveType()) {
+          if (rvmElementType.equals(RVMType.BooleanType)) {
+            bootImage.setByte(arrayImageAddress.plus(elementOffset), ((boolean[])jdkObject)[i] ? 1 : 0);
+          } else if (rvmElementType.equals(RVMType.ByteType)) {
+            bootImage.setByte(arrayImageAddress.plus(elementOffset), ((byte[])jdkObject)[i]);
+          } else if (rvmElementType.equals(RVMType.CharType)) {
+            bootImage.setHalfWord(arrayImageAddress.plus(elementOffset), ((char[])jdkObject)[i]);
+          } else if (rvmElementType.equals(RVMType.ShortType)) {
+            bootImage.setHalfWord(arrayImageAddress.plus(elementOffset), ((short[])jdkObject)[i]);
+          } else if (rvmElementType.equals(RVMType.IntType)) {
+            bootImage.setFullWord(arrayImageAddress.plus(elementOffset), ((int[])jdkObject)[i]);
+          } else if (rvmElementType.equals(RVMType.LongType)) {
+            bootImage.setDoubleWord(arrayImageAddress.plus(elementOffset), ((long[])jdkObject)[i]);
+          } else if (rvmElementType.equals(RVMType.FloatType)) {
+            bootImage.setFullWord(arrayImageAddress.plus(elementOffset), Float.floatToIntBits(((float[])jdkObject)[i]));
+          } else if (rvmElementType.equals(RVMType.DoubleType)) {
+            bootImage.setDoubleWord(arrayImageAddress.plus(elementOffset), Double.doubleToLongBits(((double[])jdkObject)[i]));
+          } else {
+            fail("unexpected primitive array type: " + rvmArrayType);
+          }
+        } else {
+          Object value = ((Object[])jdkObject)[i]; 
+          if (value != null) {
+            if (verbose >= 2) traceContext.push(value.getClass().getName(), jdkClass.getName(), i);
+            if (isTIB && value instanceof Word) {
+              bootImage.setAddressWord(arrayImageAddress.plus(elementOffset), (Word)value, false, false);
+            } else if (isTIB && value == LazyCompilationTrampoline.instructions) {
               Address codeAddress = arrayImageAddress.plus(((TIB)parentObject).lazyMethodInvokerTrampolineIndex() << LOG_BYTES_IN_ADDRESS);
-              bootImage.setAddressWord(arrayImageAddress.plus(i << LOG_BYTES_IN_ADDRESS), codeAddress.toWord(), false, false);
+              bootImage.setAddressWord(arrayImageAddress.plus(elementOffset), codeAddress.toWord(), false, false);
             } else {
-              copyReferenceFieldToBootImage(arrayImageAddress.plus(i << LOG_BYTES_IN_ADDRESS), values[i],
+              copyReferenceFieldToBootImage(arrayImageAddress.plus(elementOffset), value,
                   jdkObject, !untraced, !untraced, null, null);
             }
             if (verbose >= 2) traceContext.pop();
           } else {
-            bootImage.setNullAddressWord(arrayImageAddress.plus(i << LOG_BYTES_IN_ADDRESS), !untraced, !untraced, true);
+            bootImage.setNullAddressWord(arrayImageAddress.plus(elementOffset), !untraced, !untraced, true);
           }
         }
+       
+        elementOffset += 1 << logElementSize;
       }
     }
     return arrayImageAddress;
@@ -2579,7 +2602,7 @@
           if (verbose >= 2) traceContext.traceObjectNotInBootImage();
           bootImage.setNullAddressWord(rvmFieldAddress, true, true, false);
         } else if (imageAddress.EQ(OBJECT_NOT_ALLOCATED)) {
-          imageAddress = copyToBootImage(value, false, Address.max(), jdkObject, false);
+          imageAddress = copyToBootImage(value, false, Address.max(), jdkObject, false, false);
           if (verbose >= 3) traceContext.traceObjectFoundThroughKnown();
           bootImage.setAddressWord(rvmFieldAddress, imageAddress.toWord(), true, !fieldIsFinal);
         } else {
@@ -2626,7 +2649,7 @@
           if (verbose >= 2) traceContext.traceObjectNotInBootImage();
           throw new Error("Failed to populate " + fieldName + " in Locale");
         } else if (imageAddress.EQ(OBJECT_NOT_ALLOCATED)) {
-          imageAddress = copyToBootImage(value, false, Address.max(), jdkObject, false);
+          imageAddress = copyToBootImage(value, false, Address.max(), jdkObject, false, false);
           if (verbose >= 3) traceContext.traceObjectFoundThroughKnown();
           bootImage.setAddressWord(rvmFieldAddress, imageAddress.toWord(), true, false);
         } else {
@@ -2647,7 +2670,7 @@
           if (verbose >= 2) traceContext.traceObjectNotInBootImage();
           throw new Error("Failed to populate referenceQueue in WeakHashMap");
         } else if (imageAddress.EQ(OBJECT_NOT_ALLOCATED)) {
-          imageAddress = copyToBootImage(value, false, Address.max(), jdkObject, false);
+          imageAddress = copyToBootImage(value, false, Address.max(), jdkObject, false, false);
           if (verbose >= 3) traceContext.traceObjectFoundThroughKnown();
           bootImage.setAddressWord(rvmFieldAddress, imageAddress.toWord(), true, false);
         } else {
@@ -2699,7 +2722,7 @@
             if (verbose >= 2) traceContext.traceObjectNotInBootImage();
             bootImage.setNullAddressWord(rvmFieldAddress, true, false, false);
           } else if (imageAddress.EQ(OBJECT_NOT_ALLOCATED)) {
-            imageAddress = copyToBootImage(constructor, false, Address.max(), jdkObject, false);
+            imageAddress = copyToBootImage(constructor, false, Address.max(), jdkObject, false, false);
             if (verbose >= 3) traceContext.traceObjectFoundThroughKnown();
             bootImage.setAddressWord(rvmFieldAddress, imageAddress.toWord(), true, false);
           } else {
@@ -2771,7 +2794,7 @@
             if (verbose >= 2) traceContext.traceObjectNotInBootImage();
             bootImage.setNullAddressWord(rvmFieldAddress, true, false, false);
           } else if (imageAddress.EQ(OBJECT_NOT_ALLOCATED)) {
-            imageAddress = copyToBootImage(vmcons, false, Address.max(), jdkObject, false);
+            imageAddress = copyToBootImage(vmcons, false, Address.max(), jdkObject, false, false);
             if (verbose >= 3) traceContext.traceObjectFoundThroughKnown();
             bootImage.setAddressWord(rvmFieldAddress, imageAddress.toWord(), true, false);
           } else {
@@ -2823,7 +2846,7 @@
             if (verbose >= 2) traceContext.traceObjectNotInBootImage();
             bootImage.setNullAddressWord(rvmFieldAddress, true, false);
           } else if (imageAddress.EQ(OBJECT_NOT_ALLOCATED)) {
-            imageAddress = copyToBootImage(bits, false, Address.max(), jdkObject, false);
+            imageAddress = copyToBootImage(bits, false, Address.max(), jdkObject, false, false);
             if (verbose >= 3) traceContext.traceObjectFoundThroughKnown();
             bootImage.setAddressWord(rvmFieldAddress, imageAddress.toWord(), false, false);
           } else {
@@ -3423,7 +3446,7 @@
       if (!obj.getClass().isArray()) {
         fail("This should be an array " + obj.getClass() + " " + type);
       }
-      return type.asArray().getInstanceSize(Array.getLength(obj));
+      return type.asArray().getBootImageContiguousInstanceSize(Array.getLength(obj)); //.getInstanceSize(Array.getLength(obj));
     } else {
       return type.asClass().getInstanceSize();
     }
diff -r 743a2cc2ed20 -r 058fdc3780ba tools/bootImageWriter/vmmagic/src/org/vmmagic/unboxed/WordArray.java
--- a/tools/bootImageWriter/vmmagic/src/org/vmmagic/unboxed/WordArray.java	Tue Aug 04 11:04:15 2009 +1000
+++ b/tools/bootImageWriter/vmmagic/src/org/vmmagic/unboxed/WordArray.java	Mon Nov 16 09:21:21 2009 +1100
@@ -13,15 +13,18 @@
 package org.vmmagic.unboxed;
 
 import org.vmmagic.pragma.*;
+import org.vmmagic.unboxed.Word;
+import org.jikesrvm.SizeConstants;
 import org.jikesrvm.VM;
 import org.jikesrvm.objectmodel.RuntimeTable;
+import org.jikesrvm.runtime.Memory;
 
 /**
  * The VM front end is not capable of correct handling an array of Address, Word, ....
  * In the boot image writer we provide special types to handle these situations.
  */
 @Uninterruptible
-public final class WordArray implements RuntimeTable<Word> {
+public final class WordArray implements SizeConstants, RuntimeTable<Word> {
 
   private final Word[] data;
 
@@ -71,10 +74,94 @@
 
   @Inline
   public int length() {
-    if (VM.runningVM || VM.writingImage) VM._assert(false);  // should be hijacked
+    if (VM.runningVM) VM._assert(false);  // should be hijacked
     return data.length;
   }
 
+  public byte getByte(int index) {
+    if (VM.runningVM) VM._assert(false);  // should be hijacked
+    return (byte)endianMagic(index, 0, 0, false);
+  }
+
+  public void setByte(int index, byte v) {
+    if (VM.runningVM || VM.writingImage) VM._assert(false);  // should be hijacked
+    endianMagic(index, 0, v, true);
+  }
+
+  public char getChar(int index) {
+    if (VM.runningVM) VM._assert(false);  // should be hijacked
+    return (char)endianMagic(index, LOG_BYTES_IN_CHAR, 0, false);
+  }
+
+  public void setChar(int index, char v) {
+    if (VM.runningVM || VM.writingImage) VM._assert(false);  // should be hijacked
+    endianMagic(index, LOG_BYTES_IN_CHAR, v, true);
+  }
+
+  public int getInt(int index) {
+    if (VM.runningVM) VM._assert(false);  // should be hijacked
+    return endianMagic(index, LOG_BYTES_IN_INT, 0, false);
+  }
+
+  public void setInt(int index, int v) {
+    if (VM.runningVM || VM.writingImage) VM._assert(false);  // should be hijacked
+    endianMagic(index, LOG_BYTES_IN_INT, v, true);
+  }
+
+  public long getLong(int index) {
+    if (VM.runningVM) VM._assert(false);  // should be hijacked
+    if (BYTES_IN_LONG == BYTES_IN_WORD) {
+      return get(index).toLong();
+    } else if (BYTES_IN_LONG == 2 * BYTES_IN_WORD) {
+      if (VM.LittleEndian) {
+        return get(index).toInt() | (((long)get(index+1).toInt()) << 32);  
+      } else {
+        return get(index+1).toInt() | (((long)get(index).toInt()) << 32);
+      }
+    } else {
+      VM._assert(VM.NOT_REACHED);
+    }
+    return 0;
+  }
+
+  public void setLong(int index, long v) {
+    if (VM.runningVM || VM.writingImage) VM._assert(false);  // should be hijacked
+    if (BYTES_IN_LONG == BYTES_IN_WORD) {
+      set(index, Word.fromLong(v));
+    } else if (BYTES_IN_LONG == 2 * BYTES_IN_WORD) {
+      if (VM.LittleEndian) {
+        set(index,   Word.fromIntZeroExtend((int)(v & 0xFFFFFFFF)));
+        set(index+1, Word.fromIntZeroExtend((int)(v >>> 32)));
+      } else {
+        set(index,   Word.fromIntZeroExtend((int)(v >>> 32)));
+        set(index+1, Word.fromIntZeroExtend((int)(v & 0xFFFFFFFF)));
+      }
+    } else {
+      VM._assert(VM.NOT_REACHED);
+    }
+  }
+
+  /**
+   * This is a terrible method used to play games with endianness during boot.
+   */
+  private int endianMagic(int index, int logSize, int value, boolean store) {
+    int wordIndex = ((index << logSize) >> LOG_BYTES_IN_WORD);
+    int bitIndex = ((index << logSize) & (BYTES_IN_WORD - 1)) << LOG_BITS_IN_BYTE;
+    int bitsInElem = ((1 << logSize) * BITS_IN_BYTE);
+    if (!VM.LittleEndian) {
+      bitIndex = (BITS_IN_WORD - bitsInElem - bitIndex);
+    }
+    int mask = -1 >>> (BITS_IN_WORD - bitsInElem);
+    if (store) {
+      Word base = data[wordIndex];
+      data[wordIndex] = base.and(Word.fromIntZeroExtend(mask).lsh(bitIndex).not()).or(Word.fromIntZeroExtend(value & mask).lsh(bitIndex));
+      return 0;
+    } else {
+      Word base = data[wordIndex];
+      return base.rshl(bitIndex).toInt() & mask;
+    }
+  }
+  
   @Inline
   public Word[] getBacking() {
     if (!VM.writingImage)
