OSDN Git Service

Add a bit-map encoding of Object-reference field offsets to ClassObject.
authorBarry Hayes <bhayes@google.com>
Wed, 8 Jul 2009 17:01:56 +0000 (10:01 -0700)
committerBarry Hayes <bhayes@google.com>
Wed, 26 Aug 2009 16:39:46 +0000 (09:39 -0700)
Class.c populates a new field with a bit for each of the first 32 instance
fields, to show if it is a reference or not, and an escape value if there is a
reference field beyond 32.

The GC uses the encoded bitmap -- if available -- to extract Object refererences
from DataObjects.

vm/oo/Class.c
vm/oo/Object.h

index a5d42eb..e00fae7 100644 (file)
@@ -181,6 +181,8 @@ static void loadSFieldFromDex(ClassObject* clazz,
     const DexField* pDexSField, StaticField* sfield);
 static void loadIFieldFromDex(ClassObject* clazz,
     const DexField* pDexIField, InstField* field);
+static bool precacheReferenceOffsets(ClassObject* clazz);
+static void computeRefOffsets(ClassObject* clazz);
 static void freeMethodInnards(Method* meth);
 static bool createVtable(ClassObject* clazz);
 static bool createIftable(ClassObject* clazz);
@@ -2157,7 +2159,7 @@ static void loadIFieldFromDex(ClassObject* clazz,
 /*
  * Cache java.lang.ref.Reference fields and methods.
  */
-static bool precacheReferenceOffsets(ClassObject *clazz)
+static bool precacheReferenceOffsets(ClassObjectclazz)
 {
     Method *meth;
     int i;
@@ -2256,6 +2258,51 @@ static bool precacheReferenceOffsets(ClassObject *clazz)
 
 
 /*
+ * Set the bitmap of reference offsets, refOffsets, from the ifields
+ * list.
+ */
+static void computeRefOffsets(ClassObject* clazz)
+{
+    if (clazz->super != NULL) {
+        clazz->refOffsets = clazz->super->refOffsets;
+    } else {
+        clazz->refOffsets = 0;
+    }
+    /*
+     * If our superclass overflowed, we don't stand a chance.
+     */
+    if (clazz->refOffsets != CLASS_WALK_SUPER) {
+        InstField *f;
+        int i;
+
+        /* All of the fields that contain object references
+         * are guaranteed to be at the beginning of the ifields list.
+         */
+        f = clazz->ifields;
+        const int ifieldRefCount = clazz->ifieldRefCount;
+        for (i = 0; i < ifieldRefCount; i++) {
+          /*
+           * Note that, per the comment on struct InstField,
+           * f->byteOffset is the offset from the beginning of
+           * obj, not the offset into obj->instanceData.
+           */
+          assert(f->byteOffset >= CLASS_SMALLEST_OFFSET);
+          assert((f->byteOffset & (CLASS_OFFSET_ALIGNMENT - 1)) == 0);
+          if (CLASS_CAN_ENCODE_OFFSET(f->byteOffset)) {
+              u4 newBit = CLASS_BIT_FROM_OFFSET(f->byteOffset);
+              assert(newBit != 0);
+              clazz->refOffsets |= newBit;
+          } else {
+              clazz->refOffsets = CLASS_WALK_SUPER;
+              break;
+          }
+          f++;
+        }
+    }
+}
+
+
+/*
  * Link (prepare and resolve).  Verification is deferred until later.
  *
  * This converts symbolic references into pointers.  It's independent of
@@ -2623,6 +2670,13 @@ bail_during_resolve:
     }
 
     /*
+     * Compact the offsets the GC has to examine into a bitmap, if
+     * possible.  (This has to happen after Reference.referent is
+     * massaged in precacheReferenceOffsets.)
+     */
+    computeRefOffsets(clazz);
+
+    /*
      * Done!
      */
     if (IS_CLASS_FLAG_SET(clazz, CLASS_ISPREVERIFIED))
@@ -4249,44 +4303,6 @@ noverify:
         dvmCallMethod(self, method, NULL, &unused);
     }
 
-    /* Set the bitmap of reference offsets. Except for class Object,
-     * start with the superclass offsets.
-     */
-    if (clazz->super != NULL) {
-        clazz->refOffsets = clazz->super->refOffsets;
-    } else {
-        clazz->refOffsets = 0;
-    }
-    /*
-     * If our superclass overflowed, we don't stand a chance.
-     */
-    if (clazz->refOffsets != CLASS_WALK_SUPER) {
-        InstField *f;
-        int i;
-
-        /* All of the fields that contain object references
-         * are guaranteed to be at the beginning of the ifields list.
-         */
-        f = clazz->ifields;
-        for (i = 0; i < clazz->ifieldRefCount; i++) {
-            /*
-             * Note that, per the comment on struct InstField,
-             * f->byteOffset is the offset from the beginning of
-             * obj, not the offset into obj->instanceData.
-             */
-            assert(f->byteOffset >= CLASS_SMALLEST_OFFSET);
-            assert((f->byteOffset & (CLASS_OFFSET_ALIGNMENT - 1)) == 0);
-            u4 newBit = CLASS_BIT_FROM_OFFSET(f->byteOffset);
-            if (newBit != 0) {
-                clazz->refOffsets |= newBit;
-            } else {
-                clazz->refOffsets = CLASS_WALK_SUPER;
-                break;
-            }
-            f++;
-        }
-    }
-
     if (dvmCheckException(self)) {
         /*
          * We've had an exception thrown during static initialization.  We
index 8c2f251..82194c3 100644 (file)
@@ -148,12 +148,23 @@ typedef enum PrimitiveType {
 #define CLASS_OFFSET_ALIGNMENT 4
 #define CLASS_HIGH_BIT ((unsigned int)1 << (CLASS_BITS_PER_WORD - 1))
 /*
- * Return a single bit, or zero if the encoding can't encode the offset.
+ * Given an offset, return the bit number which would encode that offset.
+ * Local use only.
+ */
+#define _CLASS_BIT_NUMBER_FROM_OFFSET(byteOffset) \
+    (((unsigned int)(byteOffset) - CLASS_SMALLEST_OFFSET) / \
+     CLASS_OFFSET_ALIGNMENT)
+/*
+ * Is the given offset too large to be encoded?
+ */
+#define CLASS_CAN_ENCODE_OFFSET(byteOffset) \
+    (_CLASS_BIT_NUMBER_FROM_OFFSET(byteOffset) < CLASS_BITS_PER_WORD)
+/*
+ * Return a single bit, encoding the offset.
+ * Undefined if the offset is too large, as defined above.
  */
 #define CLASS_BIT_FROM_OFFSET(byteOffset) \
-    (CLASS_HIGH_BIT >> \
-      (((unsigned int)(byteOffset) - CLASS_SMALLEST_OFFSET) / \
-       CLASS_OFFSET_ALIGNMENT))
+    (CLASS_HIGH_BIT >> _CLASS_BIT_NUMBER_FROM_OFFSET(byteOffset))
 /*
  * Return an offset, given a bit number as returned from CLZ.
  */