OSDN Git Service

am 34bfe020: Fix a couple copyright headers that aren\'t in the prescribed format.
authorDan Bornstein <danfuzz@android.com>
Tue, 10 Aug 2010 02:57:01 +0000 (19:57 -0700)
committerAndroid Git Automerger <android-git-automerger@android.com>
Tue, 10 Aug 2010 02:57:01 +0000 (19:57 -0700)
Merge commit '34bfe020eccbe4034322c5952012612b0540acb3'

* commit '34bfe020eccbe4034322c5952012612b0540acb3':
  Fix a couple copyright headers that aren't in the prescribed format.

vm/Globals.h
vm/Init.c
vm/Intern.c
vm/Intern.h
vm/UtfString.c
vm/UtfString.h
vm/alloc/CardTable.c
vm/alloc/CardTable.h
vm/alloc/Heap.c
vm/alloc/HeapWorker.c
vm/compiler/codegen/arm/CodegenDriver.c

index 5341d26..90e9e88 100644 (file)
@@ -119,7 +119,6 @@ struct DvmGlobals {
      * GC option flags.
      */
     bool        preciseGc;
-    bool        overwriteFree;
     bool        preVerify;
     bool        postVerify;
     bool        generateRegisterMaps;
index 06ceabc..6c8ec9e 100644 (file)
--- a/vm/Init.c
+++ b/vm/Init.c
@@ -115,7 +115,6 @@ static void dvmUsage(const char* progName)
     dvmFprintf(stderr, "  -Xdeadlockpredict:{off,warn,err,abort}\n");
     dvmFprintf(stderr, "  -Xstacktracefile:<filename>\n");
     dvmFprintf(stderr, "  -Xgc:[no]precise\n");
-    dvmFprintf(stderr, "  -Xgc:[no]overwritefree\n");
     dvmFprintf(stderr, "  -Xgc:[no]preverify\n");
     dvmFprintf(stderr, "  -Xgc:[no]postverify\n");
     dvmFprintf(stderr, "  -Xgc:[no]concurrent\n");
@@ -975,10 +974,6 @@ static int dvmProcessOptions(int argc, const char* const argv[],
                 gDvm.preciseGc = true;
             else if (strcmp(argv[i] + 5, "noprecise") == 0)
                 gDvm.preciseGc = false;
-            else if (strcmp(argv[i] + 5, "overwritefree") == 0)
-                gDvm.overwriteFree = true;
-            else if (strcmp(argv[i] + 5, "nooverwritefree") == 0)
-                gDvm.overwriteFree = false;
             else if (strcmp(argv[i] + 5, "preverify") == 0)
                 gDvm.preVerify = true;
             else if (strcmp(argv[i] + 5, "nopreverify") == 0)
index 15bf8ab..bb8fb18 100644 (file)
@@ -98,6 +98,27 @@ StringObject* dvmLookupImmortalInternedString(StringObject* strObj)
     return lookupInternedString(strObj, true);
 }
 
+/*
+ * Returns true if the object is a weak interned string.  Any string
+ * interned by the user is weak.
+ */
+bool dvmIsWeakInternedString(const StringObject* strObj)
+{
+    StringObject* found;
+    u4 hash;
+
+    assert(strObj != NULL);
+    if (gDvm.internedStrings == NULL) {
+        return false;
+    }
+    dvmLockMutex(&gDvm.internLock);
+    hash = dvmComputeStringHash(strObj);
+    found = dvmHashTableLookup(gDvm.internedStrings, hash, (void*)strObj,
+                               dvmHashcmpStrings, false);
+    dvmUnlockMutex(&gDvm.internLock);
+    return found == strObj;
+}
+
 static int markStringObject(void* strObj, void* arg)
 {
     UNUSED_PARAMETER(arg);
index 6b713fb..a378fa5 100644 (file)
@@ -21,8 +21,8 @@
 
 bool dvmStringInternStartup(void);
 void dvmStringInternShutdown(void);
-
 StringObject* dvmLookupInternedString(StringObject* strObj);
 StringObject* dvmLookupImmortalInternedString(StringObject* strObj);
+bool dvmIsWeakInternedString(const StringObject* strObj);
 
 #endif /*_DALVIK_INTERN*/
index 0b81c6d..f560dac 100644 (file)
@@ -243,7 +243,7 @@ static inline u4 dvmComputeUtf16Hash(const u2* utf16Str, int len)
 
     return hash;
 }
-u4 dvmComputeStringHash(StringObject* strObj) {
+u4 dvmComputeStringHash(const StringObject* strObj) {
     ArrayObject* chars = (ArrayObject*) dvmGetFieldObject((Object*) strObj,
                                 STRING_FIELDOFF_VALUE);
     int offset, len;
index 9308d77..b291f5a 100644 (file)
@@ -53,7 +53,7 @@ u4 dvmComputeUtf8Hash(const char* str);
 /*
  * Hash function for string objects.
  */
-u4 dvmComputeStringHash(StringObject* strObj);
+u4 dvmComputeStringHash(const StringObject* strObj);
 
 /*
  * Create a java/lang/String from a C string.
index bd8de9a..787bd06 100644 (file)
  * limitations under the License.
  */
 
-/*
- * Needed for PROT_* definitions.
- */
-#include <sys/mman.h>
+#include <sys/mman.h>  /* for PROT_* */
 
 #include "Dalvik.h"
 #include "alloc/HeapSource.h"
@@ -140,3 +137,143 @@ void dvmMarkCard(const void *addr)
     u1 *cardAddr = dvmCardFromAddr(addr);
     *cardAddr = GC_CARD_DIRTY;
 }
+
+/*
+ * Handles the complexity of object arrays for isObjectDirty.  Array
+ * objects are exactly marked so all spanned cards are examined.
+ */
+static bool isObjectArrayDirty(const Object *obj)
+{
+    u1 *ptr, *limit;
+    size_t size;
+
+    assert(obj != NULL);
+    assert(dvmIsValidObject(obj));
+    assert(IS_CLASS_FLAG_SET(obj->clazz, CLASS_ISOBJECTARRAY));
+    size = dvmArrayObjectSize((const ArrayObject *)obj);
+    ptr = dvmCardFromAddr(obj);
+    limit = dvmCardFromAddr((u1 *)obj + size - 1) + 1;
+    assert(ptr != limit);
+    for (; ptr != limit; ++ptr) {
+        if (*ptr == GC_CARD_DIRTY) {
+            return true;
+        }
+    }
+    return false;
+}
+
+/*
+ * Returns true if the object is on a dirty card.
+ */
+static bool isObjectDirty(const Object *obj)
+{
+    assert(obj != NULL);
+    assert(dvmIsValidObject(obj));
+    if (IS_CLASS_FLAG_SET(obj->clazz, CLASS_ISOBJECTARRAY)) {
+        return isObjectArrayDirty(obj);
+   } else {
+        u1 *card = dvmCardFromAddr(obj);
+        return *card == GC_CARD_DIRTY;
+    }
+}
+
+/*
+ * Context structure for verifying the card table.
+ */
+typedef struct {
+    HeapBitmap *markBits;
+    size_t whiteRefs;
+} WhiteReferenceCounter;
+
+/*
+ * Visitor that counts white referents.
+ */
+static void countWhiteReferenceVisitor(void *addr, void *arg)
+{
+    WhiteReferenceCounter *ctx;
+    Object *obj;
+
+    assert(addr != NULL);
+    assert(arg != NULL);
+    obj = *(Object **)addr;
+    assert(dvmIsValidObject(obj));
+    ctx = arg;
+    if (obj == NULL || dvmHeapBitmapIsObjectBitSet(ctx->markBits, obj)) {
+        return;
+    }
+    ctx->whiteRefs += 1;
+}
+
+/*
+ * Returns true if the given object is a reference object and the
+ * just the referent is unmarked.
+ */
+static bool isReferentUnmarked(const Object *obj,
+                               const WhiteReferenceCounter* ctx)
+{
+    assert(obj != NULL);
+    assert(obj->clazz != NULL);
+    assert(ctx != NULL);
+    if (ctx->whiteRefs != 1) {
+        return false;
+    } else if (IS_CLASS_FLAG_SET(obj->clazz, CLASS_ISREFERENCE)) {
+        size_t offset = gDvm.offJavaLangRefReference_referent;
+        const Object *referent = dvmGetFieldObject(obj, offset);
+        return !dvmHeapBitmapIsObjectBitSet(ctx->markBits, referent);
+    } else {
+        return false;
+    }
+}
+
+/*
+ * Returns true if the given object is a string and has been interned
+ * by the user.
+ */
+static bool isWeakInternedString(const Object *obj)
+{
+    assert(obj != NULL);
+    if (obj->clazz == gDvm.classJavaLangString) {
+        return dvmIsWeakInternedString((StringObject *)obj);
+    } else {
+        return false;
+    }
+}
+
+/*
+ * Callback applied to marked objects.  If the object is found to be
+ * gray a message is written to the log.  By virtue of where the card
+ * table verification occurs weak references have yet to be blackened
+ * and so their containing objects are permitted to be gray.
+ */
+static void verifyCardTableCallback(size_t numPtrs, void **ptrs,
+                                    const void *finger, void *arg)
+{
+    size_t i;
+
+    for (i = 0; i < numPtrs; ++i) {
+        Object *obj = ptrs[i];
+        WhiteReferenceCounter ctx = { arg, 0 };
+        dvmVisitObject(countWhiteReferenceVisitor, obj, &ctx);
+        if (ctx.whiteRefs == 0) {
+            continue;
+        } else if (isObjectDirty(obj)) {
+            continue;
+        } else if (isReferentUnmarked(obj, &ctx)) {
+            continue;
+        } else if (isWeakInternedString(obj)) {
+            continue;
+        }
+        LOGE("Verify failed, object %p is gray", obj);
+        dvmDumpObject(obj);
+        dvmAbort();
+    }
+}
+
+/*
+ * Verifies that gray objects are on a dirty card.
+ */
+void dvmVerifyCardTable(void)
+{
+    HeapBitmap *markBits = gDvm.gcHeap->markContext.bitmap;
+    dvmHeapBitmapWalk(markBits, verifyCardTableCallback, markBits);
+}
index 7a86bd0..1a6db11 100644 (file)
 #ifndef _DALVIK_ALLOC_CARDTABLE
 #define _DALVIK_ALLOC_CARDTABLE
 
-/*
- * TODO: Better documentation of these values pending integration of
- * concurrent collections and the card table.
- */
 #define GC_CARD_SHIFT 7
 #define GC_CARD_SIZE (1 << GC_CARD_SHIFT)
 #define GC_CARD_CLEAN 0
@@ -65,12 +61,8 @@ void *dvmAddrFromCard(const u1 *card);
 void dvmMarkCard(const void *addr);
 
 /*
- * dvmAbort if any clean object in the Zygote heap contains a
- * reference to the application heap, or if the immune limit is not as
- * expected.
+ * Verifies that all gray objects are on a dirty card.
  */
 void dvmVerifyCardTable(void);
 
-/* TODO: Clearing, querying, and iterating over the card table. */
-
 #endif /*_DALVIK_ALLOC_CARDTABLE*/
index 1d8cfde..8f5189b 100644 (file)
@@ -571,10 +571,7 @@ size_t dvmObjectSizeInHeap(const Object *obj)
     return dvmHeapSourceChunkSize(obj);
 }
 
-/*
- * Scan every live object in the heap, holding the locks.
- */
-static void verifyHeap(void)
+static void verifyRootsAndHeap(void)
 {
     dvmVerifyRoots();
     dvmVerifyBitmap(dvmHeapSourceGetLiveBits());
@@ -675,8 +672,8 @@ void dvmCollectGarbageInternal(bool clearSoftRefs, GcReason reason)
     dvmLockMutex(&gDvm.heapWorkerListLock);
 
     if (gDvm.preVerify) {
-        LOGV_HEAP("Verifying heap before GC");
-        verifyHeap();
+        LOGV_HEAP("Verifying roots and heap before GC");
+        verifyRootsAndHeap();
     }
 
 #ifdef WITH_PROFILER
@@ -777,6 +774,13 @@ void dvmCollectGarbageInternal(bool clearSoftRefs, GcReason reason)
          */
         dvmHeapReMarkRootSet();
         /*
+         * With the exception of reference objects and weak interned
+         * strings, all gray objects should now be on dirty cards.
+         */
+        if (gDvm.verifyCardTable) {
+            dvmVerifyCardTable();
+        }
+        /*
          * Recursively mark gray objects pointed to by the roots or by
          * heap objects dirtied during the concurrent mark.
          */
@@ -862,8 +866,8 @@ void dvmCollectGarbageInternal(bool clearSoftRefs, GcReason reason)
     LOGV_HEAP("GC finished");
 
     if (gDvm.postVerify) {
-        LOGV_HEAP("Verifying heap after GC");
-        verifyHeap();
+        LOGV_HEAP("Verifying roots and heap after GC");
+        verifyRootsAndHeap();
     }
 
     gcHeap->gcRunning = false;
index f1d4169..42b8942 100644 (file)
@@ -365,14 +365,23 @@ static void* heapWorkerThreadStart(void* arg)
             {
                 size_t madvisedSizes[HEAP_SOURCE_MAX_HEAP_COUNT];
 
-                /* The heap must be locked before the HeapWorker;
-                 * unroll and re-order the locks.  dvmLockHeap()
-                 * will put us in VMWAIT if necessary.  Once it
-                 * returns, there shouldn't be any contention on
-                 * heapWorkerLock.
+                /*
+                 * Acquire the gcHeapLock.  The requires releasing the
+                 * heapWorkerLock before the gcHeapLock is acquired.
+                 * It is possible that the gcHeapLock may be acquired
+                 * during a concurrent GC in which case heapWorkerLock
+                 * is held by the GC and we are unable to make forward
+                 * progress.  We avoid deadlock by releasing the
+                 * gcHeapLock and then waiting to be signaled when the
+                 * GC completes.  There is no guarantee that the next
+                 * time we are run will coincide with GC inactivity so
+                 * the check and wait must be performed within a loop.
                  */
                 dvmUnlockMutex(&gDvm.heapWorkerLock);
                 dvmLockHeap();
+                while (gDvm.gcHeap->gcRunning) {
+                    dvmWaitForConcurrentGcToComplete();
+                }
                 dvmLockMutex(&gDvm.heapWorkerLock);
 
                 memset(madvisedSizes, 0, sizeof(madvisedSizes));
@@ -404,11 +413,23 @@ static void* heapWorkerThreadStart(void* arg)
             dvmWaitCond(&gDvm.heapWorkerCond, &gDvm.heapWorkerLock);
         }
 
-        /* dvmChangeStatus() may block;  don't hold heapWorkerLock.
+        /*
+         * Return to the running state before doing heap work.  This
+         * will block if the GC has initiated a suspend.  We release
+         * the heapWorkerLock beforehand for the GC to make progress
+         * and wait to be signaled after the GC completes.  There is
+         * no guarantee that the next time we are run will coincide
+         * with GC inactivity so the check and wait must be performed
+         * within a loop.
          */
         dvmUnlockMutex(&gDvm.heapWorkerLock);
         dvmChangeStatus(NULL, THREAD_RUNNING);
+        dvmLockHeap();
+        while (gDvm.gcHeap->gcRunning) {
+            dvmWaitForConcurrentGcToComplete();
+        }
         dvmLockMutex(&gDvm.heapWorkerLock);
+        dvmUnlockHeap();
         LOGV("HeapWorker is awake\n");
 
         /* Process any events in the queue.
index 37425ad..a1e5449 100644 (file)
@@ -41,6 +41,8 @@ static void markCard(CompilationUnit *cUnit, int valReg, int tgtAddrReg)
     ArmLIR *target = newLIR0(cUnit, kArmPseudoTargetLabel);
     target->defMask = ENCODE_ALL;
     branchOver->generic.target = (LIR *)target;
+    dvmCompilerFreeTemp(cUnit, regCardBase);
+    dvmCompilerFreeTemp(cUnit, regCardNo);
 }
 
 static bool genConversionCall(CompilationUnit *cUnit, MIR *mir, void *funct,
@@ -574,6 +576,9 @@ static void genArrayObjectPut(CompilationUnit *cUnit, MIR *mir,
                      scale, kWord);
     HEAP_ACCESS_SHADOW(false);
 
+    dvmCompilerFreeTemp(cUnit, regPtr);
+    dvmCompilerFreeTemp(cUnit, regIndex);
+
     /* NOTE: marking card here based on object head */
     markCard(cUnit, r0, r1);
 }
@@ -1549,6 +1554,7 @@ static bool handleFmt21c_Fmt31c(CompilationUnit *cUnit, MIR *mir)
                 /* NOTE: marking card based on field address */
                 markCard(cUnit, rlSrc.lowReg, tReg);
             }
+            dvmCompilerFreeTemp(cUnit, tReg);
 
             break;
         }