diff options
author | Carl Shapiro <cshapiro@google.com> | 2011-02-01 11:32:44 -0800 |
---|---|---|
committer | Carl Shapiro <cshapiro@google.com> | 2011-02-01 11:32:44 -0800 |
commit | 01605d2b668e8e1701cfdfa302dde847b9171fc9 (patch) | |
tree | 0e4191085609463310771764c2e877c9499b5080 | |
parent | 83d17b3741cfa07176f8559b6585fe9a61a27091 (diff) | |
download | android_dalvik-01605d2b668e8e1701cfdfa302dde847b9171fc9.tar.gz android_dalvik-01605d2b668e8e1701cfdfa302dde847b9171fc9.tar.bz2 android_dalvik-01605d2b668e8e1701cfdfa302dde847b9171fc9.zip |
Remove the unused monitor tracking and deadlock prediction code.
This feature has been in the code base for several releases but has never
been enabled.
Change-Id: Ia770b03ebc90a3dc7851c0cd8ef301f9762f50db
-rw-r--r-- | docs/embedded-vm-control.html | 35 | ||||
-rw-r--r-- | vm/Dvm.mk | 8 | ||||
-rw-r--r-- | vm/Globals.h | 7 | ||||
-rw-r--r-- | vm/Init.c | 24 | ||||
-rw-r--r-- | vm/Sync.c | 718 | ||||
-rw-r--r-- | vm/Thread.c | 153 | ||||
-rw-r--r-- | vm/Thread.h | 40 | ||||
-rw-r--r-- | vm/compiler/codegen/arm/Codegen.h | 3 | ||||
-rw-r--r-- | vm/compiler/codegen/arm/CodegenDriver.c | 11 | ||||
-rw-r--r-- | vm/mterp/armv5te/OP_MONITOR_ENTER.S | 8 | ||||
-rw-r--r-- | vm/mterp/c/OP_MONITOR_ENTER.c | 6 | ||||
-rw-r--r-- | vm/mterp/out/InterpAsm-armv5te-vfp.S | 8 | ||||
-rw-r--r-- | vm/mterp/out/InterpAsm-armv5te.S | 8 | ||||
-rw-r--r-- | vm/mterp/out/InterpAsm-armv7-a-neon.S | 8 | ||||
-rw-r--r-- | vm/mterp/out/InterpAsm-armv7-a.S | 8 | ||||
-rw-r--r-- | vm/mterp/out/InterpAsm-x86-atom.S | 11 | ||||
-rw-r--r-- | vm/mterp/out/InterpAsm-x86.S | 9 | ||||
-rw-r--r-- | vm/mterp/out/InterpC-allstubs.c | 6 | ||||
-rw-r--r-- | vm/mterp/out/InterpC-portdbg.c | 6 | ||||
-rw-r--r-- | vm/mterp/out/InterpC-portstd.c | 6 | ||||
-rw-r--r-- | vm/mterp/x86-atom/OP_MONITOR_ENTER.S | 11 | ||||
-rw-r--r-- | vm/mterp/x86/OP_MONITOR_ENTER.S | 9 |
22 files changed, 15 insertions, 1088 deletions
diff --git a/docs/embedded-vm-control.html b/docs/embedded-vm-control.html index 11751e075..a0bdd292b 100644 --- a/docs/embedded-vm-control.html +++ b/docs/embedded-vm-control.html @@ -13,7 +13,6 @@ <li><a href="#assertions">Assertions</a> <li><a href="#verifier">Bytecode Verification and Optimization</a> <li><a href="#execmode">Execution Mode</a> - <li><a href="#dp">Deadlock Prediction</a> <li><a href="#stackdump">Stack Dumps</a> <li><a href="#dexcheck">DEX File Checksums</a> <li><a href="#general">General Flags</a> @@ -207,40 +206,6 @@ suspect that JIT compilation is causing your application to behave incorrectly. -<h2><a name="dp">Deadlock Prediction</a></h2> - -<p>If the VM is built with <code>WITH_DEADLOCK_PREDICTION</code>, the deadlock -predictor can be enabled with the <code>-Xdeadlockpredict</code> argument. -(The output from <code>dalvikvm -help</code> will tell you if the VM was -built appropriately -- look for <code>deadlock_prediction</code> on the -<code>Configured with:</code> line.) -This feature tells the VM to keep track of the order in which object -monitor locks are acquired. If the program attempts to acquire a set -of locks in a different order from what was seen earlier, the VM logs -a warning and optionally throws an exception. - -<p>Valid values for the command-line argument are -<code>off</code> to disable it (default), <code>warn</code> to log the -problem but continue executing, <code>err</code> to cause a -<code>dalvik.system.PotentialDeadlockError</code> to be thrown from the -<code>monitor-enter</code> instruction, and <code>abort</code> to have -the entire VM abort. - -<p>You will usually want to use: -<pre>adb shell setprop dalvik.vm.extra-opts -Xdeadlockpredict:err</pre> -unless you are keeping an eye on the logs as they scroll by. - -<p>Please note that this feature is deadlock prediction, not deadlock -detection -- in the current implementation, the computations are performed -after the lock is acquired (this simplifies the code, reducing the -overhead added to every mutex operation). You can spot a deadlock in a -hung process by sending a <code>kill -3</code> and examining the stack -trace written to the log. - -<p>This only takes monitors into account. Native mutexes and other resources -can also be the cause of deadlocks, but will not be detected by this. - - <h2><a name="stackdump">Stack Dumps</a></h2> <p>Like other desktop VMs, when the Dalvik VM receives a SIGQUIT @@ -33,14 +33,6 @@ LOCAL_CFLAGS += -DARCH_VARIANT=\"$(dvm_arch_variant)\" # Optional features. These may impact the size or performance of the VM. # -ifeq ($(WITH_DEADLOCK_PREDICTION),true) - LOCAL_CFLAGS += -DWITH_DEADLOCK_PREDICTION - WITH_MONITOR_TRACKING := true -endif -ifeq ($(WITH_MONITOR_TRACKING),true) - LOCAL_CFLAGS += -DWITH_MONITOR_TRACKING -endif - # Make a debugging version when building the simulator (if not told # otherwise) and when explicitly asked. dvm_make_debug_vm := false diff --git a/vm/Globals.h b/vm/Globals.h index 2a43b0525..f96cbf232 100644 --- a/vm/Globals.h +++ b/vm/Globals.h @@ -608,13 +608,6 @@ struct DvmGlobals { int allocRecordHead; /* most-recently-added entry */ int allocRecordCount; /* #of valid entries */ -#ifdef WITH_DEADLOCK_PREDICTION - /* global lock on history tree accesses */ - pthread_mutex_t deadlockHistoryLock; - - enum { kDPOff=0, kDPWarn, kDPErr, kDPAbort } deadlockPredictMode; -#endif - /* * When normal control flow needs to be interrupted because * of an attached debugger, profiler, thread stop request, etc., @@ -142,12 +142,6 @@ static void usage(const char* progName) " debugger" " profiler" " hprof" -#ifdef WITH_MONITOR_TRACKING - " monitor_tracking" -#endif -#ifdef WITH_DEADLOCK_PREDICTION - " deadlock_prediction" -#endif #ifdef WITH_TRACKREF_CHECKS " trackref_checks" #endif @@ -965,24 +959,6 @@ static int processOptions(int argc, const char* const argv[], } #endif - } else if (strncmp(argv[i], "-Xdeadlockpredict:", 18) == 0) { -#ifdef WITH_DEADLOCK_PREDICTION - if (strcmp(argv[i] + 18, "off") == 0) - gDvm.deadlockPredictMode = kDPOff; - else if (strcmp(argv[i] + 18, "warn") == 0) - gDvm.deadlockPredictMode = kDPWarn; - else if (strcmp(argv[i] + 18, "err") == 0) - gDvm.deadlockPredictMode = kDPErr; - else if (strcmp(argv[i] + 18, "abort") == 0) - gDvm.deadlockPredictMode = kDPAbort; - else { - dvmFprintf(stderr, "Bad value for -Xdeadlockpredict"); - return -1; - } - if (gDvm.deadlockPredictMode != kDPOff) - LOGD("Deadlock prediction enabled (%s)\n", argv[i]+18); -#endif - } else if (strncmp(argv[i], "-Xstacktracefile:", 17) == 0) { gDvm.stackTraceFile = strdup(argv[i]+17); @@ -42,31 +42,6 @@ #define LOG_THIN LOGV -#ifdef WITH_DEADLOCK_PREDICTION /* fwd */ -static const char* kStartBanner = - "<-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#"; -static const char* kEndBanner = - "#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#->"; - -/* - * Unsorted, expanding list of objects. - * - * This is very similar to PointerSet (which came into existence after this), - * but these are unsorted, uniqueness is not enforced by the "add" function, - * and the base object isn't allocated on the heap. - */ -typedef struct ExpandingObjectList { - u2 alloc; - u2 count; - Object** list; -} ExpandingObjectList; - -/* fwd */ -static void updateDeadlockPrediction(Thread* self, Object* obj); -static void removeCollectedObject(Object* obj); -static void expandObjClear(ExpandingObjectList* pList); -#endif - /* * Every Object has a monitor associated with it, but not every Object is * actually locked. Even the ones that are locked do not need a @@ -130,29 +105,6 @@ struct Monitor { */ char* ownerFileName; u4 ownerLineNumber; - -#ifdef WITH_DEADLOCK_PREDICTION - /* - * Objects that have been locked immediately after this one in the - * past. We use an expanding flat array, allocated on first use, to - * minimize allocations. Deletions from the list, expected to be - * infrequent, are crunched down. - */ - ExpandingObjectList historyChildren; - - /* - * We also track parents. This isn't strictly necessary, but it makes - * the cleanup at GC time significantly faster. - */ - ExpandingObjectList historyParents; - - /* used during cycle detection */ - bool historyMark; - - /* stack trace, established the first time we locked the object */ - int historyStackDepth; - int* historyRawStackTrace; -#endif }; @@ -195,12 +147,6 @@ void dvmFreeMonitorList(void) mon = gDvm.monitorList; while (mon != NULL) { nextMon = mon->next; - -#ifdef WITH_DEADLOCK_PREDICTION - expandObjClear(&mon->historyChildren); - expandObjClear(&mon->historyParents); - free(mon->historyRawStackTrace); -#endif free(mon); mon = nextMon; } @@ -302,11 +248,6 @@ static void freeObjectMonitor(Object* obj) assert(LW_SHAPE(obj->lock) == LW_SHAPE_FAT); -#ifdef WITH_DEADLOCK_PREDICTION - if (gDvm.deadlockPredictMode != kDPOff) - removeCollectedObject(obj); -#endif - mon = LW_MONITOR(obj->lock); obj->lock = DVM_LOCK_INITIAL_THIN_VALUE; @@ -320,11 +261,6 @@ static void freeObjectMonitor(Object* obj) assert(pthread_mutex_trylock(&mon->lock) == 0); assert(pthread_mutex_unlock(&mon->lock) == 0); dvmDestroyMutex(&mon->lock); -#ifdef WITH_DEADLOCK_PREDICTION - expandObjClear(&mon->historyChildren); - expandObjClear(&mon->historyParents); - free(mon->historyRawStackTrace); -#endif free(mon); } @@ -339,9 +275,6 @@ void dvmSweepMonitorList(Monitor** mon, int (*isUnmarkedObject)(void*)) assert(mon != NULL); assert(isUnmarkedObject != NULL); -#ifdef WITH_DEADLOCK_PREDICTION - dvmDumpMonitorInfo("before monitor sweep"); -#endif prev = &handle; prev->next = curr = *mon; while (curr != NULL) { @@ -355,9 +288,6 @@ void dvmSweepMonitorList(Monitor** mon, int (*isUnmarkedObject)(void*)) } } *mon = handle.next; -#ifdef WITH_DEADLOCK_PREDICTION - dvmDumpMonitorInfo("after monitor sweep"); -#endif } static char *logWriteInt(char *dst, int value) @@ -1107,56 +1037,6 @@ retry: assert(LW_MONITOR(obj->lock) != NULL); lockMonitor(self, LW_MONITOR(obj->lock)); } -#ifdef WITH_DEADLOCK_PREDICTION - /* - * See if we were allowed to grab the lock at this time. We do it - * *after* acquiring the lock, rather than before, so that we can - * freely update the Monitor struct. This seems counter-intuitive, - * but our goal is deadlock *prediction* not deadlock *prevention*. - * (If we actually deadlock, the situation is easy to diagnose from - * a thread dump, so there's no point making a special effort to do - * the checks before the lock is held.) - * - * This needs to happen before we add the object to the thread's - * monitor list, so we can tell the difference between first-lock and - * re-lock. - * - * It's also important that we do this while in THREAD_RUNNING, so - * that we don't interfere with cleanup operations in the GC. - */ - if (gDvm.deadlockPredictMode != kDPOff) { - if (self->status != THREAD_RUNNING) { - LOGE("Bad thread status (%d) in DP\n", self->status); - dvmDumpThread(self, false); - dvmAbort(); - } - assert(!dvmCheckException(self)); - updateDeadlockPrediction(self, obj); - if (dvmCheckException(self)) { - /* - * If we're throwing an exception here, we need to free the - * lock. We add the object to the thread's monitor list so the - * "unlock" code can remove it. - */ - dvmAddToMonitorList(self, obj, false); - dvmUnlockObject(self, obj); - LOGV("--- unlocked, pending is '%s'\n", - dvmGetException(self)->clazz->descriptor); - } - } - - /* - * Add the locked object, and the current stack trace, to the list - * held by the Thread object. If deadlock prediction isn't on, - * don't capture the stack trace. - */ - dvmAddToMonitorList(self, obj, gDvm.deadlockPredictMode != kDPOff); -#elif defined(WITH_MONITOR_TRACKING) - /* - * Add the locked object to the list held by the Thread object. - */ - dvmAddToMonitorList(self, obj, false); -#endif } /* @@ -1222,14 +1102,6 @@ bool dvmUnlockObject(Thread* self, Object *obj) return false; } } - -#ifdef WITH_MONITOR_TRACKING - /* - * Remove the object from the Thread's list. - */ - dvmRemoveFromMonitorList(self, obj); -#endif - return true; } @@ -1546,593 +1418,3 @@ retry: return 0; /* Quiet the compiler. */ } #endif /* WITH_COPYING_GC */ - -#ifdef WITH_DEADLOCK_PREDICTION -/* - * =========================================================================== - * Deadlock prediction - * =========================================================================== - */ -/* -The idea is to predict the possibility of deadlock by recording the order -in which monitors are acquired. If we see an attempt to acquire a lock -out of order, we can identify the locks and offending code. - -To make this work, we need to keep track of the locks held by each thread, -and create history trees for each lock. When a thread tries to acquire -a new lock, we walk through the "history children" of the lock, looking -for a match with locks the thread already holds. If we find a match, -it means the thread has made a request that could result in a deadlock. - -To support recursive locks, we always allow re-locking a currently-held -lock, and maintain a recursion depth count. - -An ASCII-art example, where letters represent Objects: - - A - /|\ - / | \ - B | D - \ | - \| - C - -The above is the tree we'd have after handling Object synchronization -sequences "ABC", "AC", "AD". A has three children, {B, C, D}. C is also -a child of B. (The lines represent pointers between parent and child. -Every node can have multiple parents and multiple children.) - -If we hold AC, and want to lock B, we recursively search through B's -children to see if A or C appears. It does, so we reject the attempt. -(A straightforward way to implement it: add a link from C to B, then -determine whether the graph starting at B contains a cycle.) - -If we hold AC and want to lock D, we would succeed, creating a new link -from C to D. - -The lock history and a stack trace is attached to the Object's Monitor -struct, which means we need to fatten every Object we lock (thin locking -is effectively disabled). If we don't need the stack trace we can -avoid fattening the leaf nodes, only fattening objects that need to hold -history trees. - -Updates to Monitor structs are only allowed for the thread that holds -the Monitor, so we actually do most of our deadlock prediction work after -the lock has been acquired. - -When an object with a monitor is GCed, we need to remove it from the -history trees. There are two basic approaches: - (1) For through the entire set of known monitors, search all child - lists for the object in question. This is rather slow, resulting - in GC passes that take upwards of 10 seconds to complete. - (2) Maintain "parent" pointers in each node. Remove the entries as - required. This requires additional storage and maintenance for - every operation, but is significantly faster at GC time. -For each GCed object, we merge all of the object's children into each of -the object's parents. -*/ - -#if !defined(WITH_MONITOR_TRACKING) -# error "WITH_DEADLOCK_PREDICTION requires WITH_MONITOR_TRACKING" -#endif - -/* - * Clear out the contents of an ExpandingObjectList, freeing any - * dynamic allocations. - */ -static void expandObjClear(ExpandingObjectList* pList) -{ - if (pList->list != NULL) { - free(pList->list); - pList->list = NULL; - } - pList->alloc = pList->count = 0; -} - -/* - * Get the number of objects currently stored in the list. - */ -static inline int expandBufGetCount(const ExpandingObjectList* pList) -{ - return pList->count; -} - -/* - * Get the Nth entry from the list. - */ -static inline Object* expandBufGetEntry(const ExpandingObjectList* pList, - int i) -{ - return pList->list[i]; -} - -/* - * Add a new entry to the list. - * - * We don't check for or try to enforce uniqueness. It's expected that - * the higher-level code does this for us. - */ -static void expandObjAddEntry(ExpandingObjectList* pList, Object* obj) -{ - if (pList->count == pList->alloc) { - /* time to expand */ - Object** newList; - - if (pList->alloc == 0) - pList->alloc = 4; - else - pList->alloc *= 2; - LOGVV("expanding %p to %d\n", pList, pList->alloc); - newList = realloc(pList->list, pList->alloc * sizeof(Object*)); - if (newList == NULL) { - LOGE("Failed expanding DP object list (alloc=%d)\n", pList->alloc); - dvmAbort(); - } - pList->list = newList; - } - - pList->list[pList->count++] = obj; -} - -/* - * Returns "true" if the element was successfully removed. - */ -static bool expandObjRemoveEntry(ExpandingObjectList* pList, Object* obj) -{ - int i; - - for (i = pList->count-1; i >= 0; i--) { - if (pList->list[i] == obj) - break; - } - if (i < 0) - return false; - - if (i != pList->count-1) { - /* - * The order of elements is not important, so we just copy the - * last entry into the new slot. - */ - //memmove(&pList->list[i], &pList->list[i+1], - // (pList->count-1 - i) * sizeof(pList->list[0])); - pList->list[i] = pList->list[pList->count-1]; - } - - pList->count--; - pList->list[pList->count] = (Object*) 0xdecadead; - return true; -} - -/* - * Returns "true" if "obj" appears in the list. - */ -static bool expandObjHas(const ExpandingObjectList* pList, Object* obj) -{ - int i; - - for (i = 0; i < pList->count; i++) { - if (pList->list[i] == obj) - return true; - } - return false; -} - -/* - * Print the list contents to stdout. For debugging. - */ -static void expandObjDump(const ExpandingObjectList* pList) -{ - int i; - for (i = 0; i < pList->count; i++) - printf(" %p", pList->list[i]); -} - -/* - * Check for duplicate entries. Returns the index of the first instance - * of the duplicated value, or -1 if no duplicates were found. - */ -static int expandObjCheckForDuplicates(const ExpandingObjectList* pList) -{ - int i, j; - for (i = 0; i < pList->count-1; i++) { - for (j = i + 1; j < pList->count; j++) { - if (pList->list[i] == pList->list[j]) { - return i; - } - } - } - - return -1; -} - - -/* - * Determine whether "child" appears in the list of objects associated - * with the Monitor in "parent". If "parent" is a thin lock, we return - * false immediately. - */ -static bool objectInChildList(const Object* parent, Object* child) -{ - u4 lock = parent->lock; - if (!IS_LOCK_FAT(&lock)) { - //LOGI("on thin\n"); - return false; - } - - return expandObjHas(&LW_MONITOR(lock)->historyChildren, child); -} - -/* - * Print the child list. - */ -static void dumpKids(Object* parent) -{ - Monitor* mon = LW_MONITOR(parent->lock); - - printf("Children of %p:", parent); - expandObjDump(&mon->historyChildren); - printf("\n"); -} - -/* - * Add "child" to the list of children in "parent", and add "parent" to - * the list of parents in "child". - */ -static void linkParentToChild(Object* parent, Object* child) -{ - //assert(LW_MONITOR(parent->lock)->owner == dvmThreadSelf()); // !owned for merge - assert(IS_LOCK_FAT(&parent->lock)); - assert(IS_LOCK_FAT(&child->lock)); - assert(parent != child); - Monitor* mon; - - mon = LW_MONITOR(parent->lock); - assert(!expandObjHas(&mon->historyChildren, child)); - expandObjAddEntry(&mon->historyChildren, child); - - mon = LW_MONITOR(child->lock); - assert(!expandObjHas(&mon->historyParents, parent)); - expandObjAddEntry(&mon->historyParents, parent); -} - - -/* - * Remove "child" from the list of children in "parent". - */ -static void unlinkParentFromChild(Object* parent, Object* child) -{ - //assert(LW_MONITOR(parent->lock)->owner == dvmThreadSelf()); // !owned for GC - assert(IS_LOCK_FAT(&parent->lock)); - assert(IS_LOCK_FAT(&child->lock)); - assert(parent != child); - Monitor* mon; - - mon = LW_MONITOR(parent->lock); - if (!expandObjRemoveEntry(&mon->historyChildren, child)) { - LOGW("WARNING: child %p not found in parent %p\n", child, parent); - } - assert(!expandObjHas(&mon->historyChildren, child)); - assert(expandObjCheckForDuplicates(&mon->historyChildren) < 0); - - mon = LW_MONITOR(child->lock); - if (!expandObjRemoveEntry(&mon->historyParents, parent)) { - LOGW("WARNING: parent %p not found in child %p\n", parent, child); - } - assert(!expandObjHas(&mon->historyParents, parent)); - assert(expandObjCheckForDuplicates(&mon->historyParents) < 0); -} - - -/* - * Log the monitors held by the current thread. This is done as part of - * flagging an error. - */ -static void logHeldMonitors(Thread* self) -{ - char* name = NULL; - - name = dvmGetThreadName(self); - LOGW("Monitors currently held by thread (threadid=%d '%s')\n", - self->threadId, name); - LOGW("(most-recently-acquired on top):\n"); - free(name); - - LockedObjectData* lod = self->pLockedObjects; - while (lod != NULL) { - LOGW("--- object %p[%d] (%s)\n", - lod->obj, lod->recursionCount, lod->obj->clazz->descriptor); - dvmLogRawStackTrace(lod->rawStackTrace, lod->stackDepth); - - lod = lod->next; - } -} - -/* - * Recursively traverse the object hierarchy starting at "obj". We mark - * ourselves on entry and clear the mark on exit. If we ever encounter - * a marked object, we have a cycle. - * - * Returns "true" if all is well, "false" if we found a cycle. - */ -static bool traverseTree(Thread* self, const Object* obj) -{ - assert(IS_LOCK_FAT(&obj->lock)); - Monitor* mon = LW_MONITOR(obj->lock); - - /* - * Have we been here before? - */ - if (mon->historyMark) { - int* rawStackTrace; - int stackDepth; - - LOGW("%s\n", kStartBanner); - LOGW("Illegal lock attempt:\n"); - LOGW("--- object %p (%s)\n", obj, obj->clazz->descriptor); - - rawStackTrace = dvmFillInStackTraceRaw(self, &stackDepth); - dvmLogRawStackTrace(rawStackTrace, stackDepth); - free(rawStackTrace); - - LOGW(" "); - logHeldMonitors(self); - - LOGW(" "); - LOGW("Earlier, the following lock order (from last to first) was\n"); - LOGW("established -- stack trace is from first successful lock):\n"); - return false; - } - mon->historyMark = true; - - /* - * Examine the children. We do NOT hold these locks, so they might - * very well transition from thin to fat or change ownership while - * we work. - * - * NOTE: we rely on the fact that they cannot revert from fat to thin - * while we work. This is currently a safe assumption. - * - * We can safely ignore thin-locked children, because by definition - * they have no history and are leaf nodes. In the current - * implementation we always fatten the locks to provide a place to - * hang the stack trace. - */ - ExpandingObjectList* pList = &mon->historyChildren; - int i; - for (i = expandBufGetCount(pList)-1; i >= 0; i--) { - const Object* child = expandBufGetEntry(pList, i); - u4 lock = child->lock; - if (!IS_LOCK_FAT(&lock)) - continue; - if (!traverseTree(self, child)) { - LOGW("--- object %p (%s)\n", obj, obj->clazz->descriptor); - dvmLogRawStackTrace(mon->historyRawStackTrace, - mon->historyStackDepth); - mon->historyMark = false; - return false; - } - } - - mon->historyMark = false; - - return true; -} - -/* - * Update the deadlock prediction tree, based on the current thread - * acquiring "acqObj". This must be called before the object is added to - * the thread's list of held monitors. - * - * If the thread already holds the lock (recursion), or this is a known - * lock configuration, we return without doing anything. Otherwise, we add - * a link from the most-recently-acquired lock in this thread to "acqObj" - * after ensuring that the parent lock is "fat". - * - * This MUST NOT be called while a GC is in progress in another thread, - * because we assume exclusive access to history trees in owned monitors. - */ -static void updateDeadlockPrediction(Thread* self, Object* acqObj) -{ - LockedObjectData* lod; - LockedObjectData* mrl; - - /* - * Quick check for recursive access. - */ - lod = dvmFindInMonitorList(self, acqObj); - if (lod != NULL) { - LOGV("+++ DP: recursive %p\n", acqObj); - return; - } - - /* - * Make the newly-acquired object's monitor "fat". In some ways this - * isn't strictly necessary, but we need the GC to tell us when - * "interesting" objects go away, and right now the only way to make - * an object look interesting is to give it a monitor. - * - * This also gives us a place to hang a stack trace. - * - * Our thread holds the lock, so we're allowed to rewrite the lock - * without worrying that something will change out from under us. - */ - if (!IS_LOCK_FAT(&acqObj->lock)) { - LOGVV("fattening lockee %p (recur=%d)\n", - acqObj, LW_LOCK_COUNT(acqObj->lock.thin)); - inflateMonitor(self, acqObj); - } - - /* if we don't have a stack trace for this monitor, establish one */ - if (LW_MONITOR(acqObj->lock)->historyRawStackTrace == NULL) { - Monitor* mon = LW_MONITOR(acqObj->lock); - mon->historyRawStackTrace = dvmFillInStackTraceRaw(self, - &mon->historyStackDepth); - } - - /* - * We need to examine and perhaps modify the most-recently-locked - * monitor. We own that, so there's no risk of another thread - * stepping on us. - * - * Retrieve the most-recently-locked entry from our thread. - */ - mrl = self->pLockedObjects; - if (mrl == NULL) - return; /* no other locks held */ - - /* - * Do a quick check to see if "acqObj" is a direct descendant. We can do - * this without holding the global lock because of our assertion that - * a GC is not running in parallel -- nobody except the GC can - * modify a history list in a Monitor they don't own, and we own "mrl". - * (There might be concurrent *reads*, but no concurrent *writes.) - * - * If we find it, this is a known good configuration, and we're done. - */ - if (objectInChildList(mrl->obj, acqObj)) - return; - - /* - * "mrl" is going to need to have a history tree. If it's currently - * a thin lock, we make it fat now. The thin lock might have a - * nonzero recursive lock count, which we need to carry over. - * - * Our thread holds the lock, so we're allowed to rewrite the lock - * without worrying that something will change out from under us. - */ - if (!IS_LOCK_FAT(&mrl->obj->lock)) { - LOGVV("fattening parent %p f/b/o child %p (recur=%d)\n", - mrl->obj, acqObj, LW_LOCK_COUNT(mrl->obj->lock)); - inflateMonitor(self, mrl->obj); - } - - /* - * We haven't seen this configuration before. We need to scan down - * acqObj's tree to see if any of the monitors in self->pLockedObjects - * appear. We grab a global lock before traversing or updating the - * history list. - * - * If we find a match for any of our held locks, we know that the lock - * has previously been acquired *after* acqObj, and we throw an error. - * - * The easiest way to do this is to create a link from "mrl" to "acqObj" - * and do a recursive traversal, marking nodes as we cross them. If - * we cross one a second time, we have a cycle and can throw an error. - * (We do the flag-clearing traversal before adding the new link, so - * that we're guaranteed to terminate.) - * - * If "acqObj" is a thin lock, it has no history, and we can create a - * link to it without additional checks. [ We now guarantee that it's - * always fat. ] - */ - bool failed = false; - dvmLockMutex(&gDvm.deadlockHistoryLock); - linkParentToChild(mrl->obj, acqObj); - if (!traverseTree(self, acqObj)) { - LOGW("%s\n", kEndBanner); - failed = true; - - /* remove the entry so we're still okay when in "warning" mode */ - unlinkParentFromChild(mrl->obj, acqObj); - } - dvmUnlockMutex(&gDvm.deadlockHistoryLock); - - if (failed) { - switch (gDvm.deadlockPredictMode) { - case kDPErr: - dvmThrowException("Ldalvik/system/PotentialDeadlockError;", NULL); - break; - case kDPAbort: - LOGE("Aborting due to potential deadlock\n"); - dvmAbort(); - break; - default: - /* warn only */ - break; - } - } -} - -/* - * We're removing "child" from existence. We want to pull all of - * child's children into "parent", filtering out duplicates. This is - * called during the GC. - * - * This does not modify "child", which might have multiple parents. - */ -static void mergeChildren(Object* parent, const Object* child) -{ - Monitor* mon; - int i; - - assert(IS_LOCK_FAT(&child->lock)); - mon = LW_MONITOR(child->lock); - ExpandingObjectList* pList = &mon->historyChildren; - - for (i = expandBufGetCount(pList)-1; i >= 0; i--) { - Object* grandChild = expandBufGetEntry(pList, i); - - if (!objectInChildList(parent, grandChild)) { - LOGVV("+++ migrating %p link to %p\n", grandChild, parent); - linkParentToChild(parent, grandChild); - } else { - LOGVV("+++ parent %p already links to %p\n", parent, grandChild); - } - } -} - -/* - * An object with a fat lock is being collected during a GC pass. We - * want to remove it from any lock history trees that it is a part of. - * - * This may require updating the history trees in several monitors. The - * monitor semantics guarantee that no other thread will be accessing - * the history trees at the same time. - */ -static void removeCollectedObject(Object* obj) -{ - Monitor* mon; - - LOGVV("+++ collecting %p\n", obj); - - /* - * For every parent of this object: - * - merge all of our children into the parent's child list (creates - * a two-way link between parent and child) - * - remove ourselves from the parent's child list - */ - ExpandingObjectList* pList; - int i; - - assert(IS_LOCK_FAT(&obj->lock)); - mon = LW_MONITOR(obj->lock); - pList = &mon->historyParents; - for (i = expandBufGetCount(pList)-1; i >= 0; i--) { - Object* parent = expandBufGetEntry(pList, i); - Monitor* parentMon = LW_MONITOR(parent->lock); - - if (!expandObjRemoveEntry(&parentMon->historyChildren, obj)) { - LOGW("WARNING: child %p not found in parent %p\n", obj, parent); - } - assert(!expandObjHas(&parentMon->historyChildren, obj)); - - mergeChildren(parent, obj); - } - - /* - * For every child of this object: - * - remove ourselves from the child's parent list - */ - pList = &mon->historyChildren; - for (i = expandBufGetCount(pList)-1; i >= 0; i--) { - Object* child = expandBufGetEntry(pList, i); - Monitor* childMon = LW_MONITOR(child->lock); - - if (!expandObjRemoveEntry(&childMon->historyParents, obj)) { - LOGW("WARNING: parent %p not found in child %p\n", obj, child); - } - assert(!expandObjHas(&childMon->historyParents, obj)); - } -} - -#endif /*WITH_DEADLOCK_PREDICTION*/ diff --git a/vm/Thread.c b/vm/Thread.c index 36c34f41a..6745dae36 100644 --- a/vm/Thread.c +++ b/vm/Thread.c @@ -284,9 +284,6 @@ bool dvmThreadStartup(void) dvmInitMutex(&gDvm._threadSuspendLock); dvmInitMutex(&gDvm.threadSuspendCountLock); pthread_cond_init(&gDvm.threadSuspendCountCond, NULL); -#ifdef WITH_DEADLOCK_PREDICTION - dvmInitMutex(&gDvm.deadlockHistoryLock); -#endif /* * Dedicated monitor for Thread.sleep(). @@ -3622,29 +3619,6 @@ void dvmDumpThreadEx(const DebugOutputTarget* target, Thread* thread, schedstatBuf, procStatData.utime, procStatData.stime, procStatData.processor); -#ifdef WITH_MONITOR_TRACKING - if (!isRunning) { - LockedObjectData* lod = thread->pLockedObjects; - if (lod != NULL) - dvmPrintDebugMessage(target, " | monitors held:\n"); - else - dvmPrintDebugMessage(target, " | monitors held: <none>\n"); - while (lod != NULL) { - Object* obj = lod->obj; - if (obj->clazz == gDvm.classJavaLangClass) { - ClassObject* clazz = (ClassObject*) obj; - dvmPrintDebugMessage(target, " > %p[%d] (%s object for class %s)\n", - obj, lod->recursionCount, obj->clazz->descriptor, - clazz->descriptor); - } else { - dvmPrintDebugMessage(target, " > %p[%d] (%s)\n", - obj, lod->recursionCount, obj->clazz->descriptor); - } - lod = lod->next; - } - } -#endif - if (isRunning) dvmDumpRunningThreadStack(target, thread); else @@ -3786,130 +3760,3 @@ void dvmNukeThread(Thread* thread) signal(SIGSEGV, SIG_IGN); LOGD("Continuing\n"); } - -#ifdef WITH_MONITOR_TRACKING -/* - * Count up the #of locked objects in the current thread. - */ -static int getThreadObjectCount(const Thread* self) -{ - LockedObjectData* lod; - int count = 0; - - lod = self->pLockedObjects; - while (lod != NULL) { - count++; - lod = lod->next; - } - return count; -} - -/* - * Add the object to the thread's locked object list if it doesn't already - * exist. The most recently added object is the most likely to be released - * next, so we insert at the head of the list. - * - * If it already exists, we increase the recursive lock count. - * - * The object's lock may be thin or fat. - */ -void dvmAddToMonitorList(Thread* self, Object* obj, bool withTrace) -{ - LockedObjectData* newLod; - LockedObjectData* lod; - int* trace; - int depth; - - lod = self->pLockedObjects; - while (lod != NULL) { - if (lod->obj == obj) { - lod->recursionCount++; - LOGV("+++ +recursive lock %p -> %d\n", obj, lod->recursionCount); - return; - } - lod = lod->next; - } - - newLod = (LockedObjectData*) calloc(1, sizeof(LockedObjectData)); - if (newLod == NULL) { - LOGE("malloc failed on %d bytes\n", sizeof(LockedObjectData)); - return; - } - newLod->obj = obj; - newLod->recursionCount = 0; - - if (withTrace) { - trace = dvmFillInStackTraceRaw(self, &depth); - newLod->rawStackTrace = trace; - newLod->stackDepth = depth; - } - - newLod->next = self->pLockedObjects; - self->pLockedObjects = newLod; - - LOGV("+++ threadid=%d: added %p, now %d\n", - self->threadId, newLod, getThreadObjectCount(self)); -} - -/* - * Remove the object from the thread's locked object list. If the entry - * has a nonzero recursion count, we just decrement the count instead. - */ -void dvmRemoveFromMonitorList(Thread* self, Object* obj) -{ - LockedObjectData* lod; - LockedObjectData* prevLod; - - lod = self->pLockedObjects; - prevLod = NULL; - while (lod != NULL) { - if (lod->obj == obj) { - if (lod->recursionCount > 0) { - lod->recursionCount--; - LOGV("+++ -recursive lock %p -> %d\n", - obj, lod->recursionCount); - return; - } else { - break; - } - } - prevLod = lod; - lod = lod->next; - } - - if (lod == NULL) { - LOGW("BUG: object %p not found in thread's lock list\n", obj); - return; - } - if (prevLod == NULL) { - /* first item in list */ - assert(self->pLockedObjects == lod); - self->pLockedObjects = lod->next; - } else { - /* middle/end of list */ - prevLod->next = lod->next; - } - - LOGV("+++ threadid=%d: removed %p, now %d\n", - self->threadId, lod, getThreadObjectCount(self)); - free(lod->rawStackTrace); - free(lod); -} - -/* - * If the specified object is already in the thread's locked object list, - * return the LockedObjectData struct. Otherwise return NULL. - */ -LockedObjectData* dvmFindInMonitorList(const Thread* self, const Object* obj) -{ - LockedObjectData* lod; - - lod = self->pLockedObjects; - while (lod != NULL) { - if (lod->obj == obj) - return lod; - lod = lod->next; - } - return NULL; -} -#endif /*WITH_MONITOR_TRACKING*/ diff --git a/vm/Thread.h b/vm/Thread.h index 5fdb86955..bcd85a918 100644 --- a/vm/Thread.h +++ b/vm/Thread.h @@ -32,10 +32,6 @@ int pthread_mutexattr_settype(pthread_mutexattr_t *attr, int type); enum { PTHREAD_MUTEX_ERRORCHECK = PTHREAD_MUTEX_ERRORCHECK_NP }; #endif -#ifdef WITH_MONITOR_TRACKING -struct LockedObjectData; -#endif - /* * Current status; these map to JDWP constants, so don't rearrange them. * (If you do alter this, update the strings in dvmDumpThread and the @@ -214,11 +210,6 @@ typedef struct Thread { /* JDWP invoke-during-breakpoint support */ DebugInvokeReq invokeReq; -#ifdef WITH_MONITOR_TRACKING - /* objects locked by this thread; most recent is at head of list */ - struct LockedObjectData* pLockedObjects; -#endif - /* base time for per-thread CPU timing (used by method profiling) */ bool cpuClockBaseSet; u8 cpuClockBase; @@ -527,35 +518,4 @@ void dvmDumpAllThreadsEx(const DebugOutputTarget* target, bool grabLock); */ void dvmNukeThread(Thread* thread); -#ifdef WITH_MONITOR_TRACKING -/* - * Track locks held by the current thread, along with the stack trace at - * the point the lock was acquired. - * - * At any given time the number of locks held across the VM should be - * fairly small, so there's no reason not to generate and store the entire - * stack trace. - */ -typedef struct LockedObjectData { - /* the locked object */ - struct Object* obj; - - /* number of times it has been locked recursively (zero-based ref count) */ - int recursionCount; - - /* stack trace at point of initial acquire */ - u4 stackDepth; - int* rawStackTrace; - - struct LockedObjectData* next; -} LockedObjectData; - -/* - * Add/remove/find objects from the thread's monitor list. - */ -void dvmAddToMonitorList(Thread* self, Object* obj, bool withTrace); -void dvmRemoveFromMonitorList(Thread* self, Object* obj); -LockedObjectData* dvmFindInMonitorList(const Thread* self, const Object* obj); -#endif - #endif /*_DALVIK_THREAD*/ diff --git a/vm/compiler/codegen/arm/Codegen.h b/vm/compiler/codegen/arm/Codegen.h index 8522e623f..330619b29 100644 --- a/vm/compiler/codegen/arm/Codegen.h +++ b/vm/compiler/codegen/arm/Codegen.h @@ -45,8 +45,7 @@ static bool genArithOpDoublePortable(CompilationUnit *cUnit, MIR *mir, static bool genConversionPortable(CompilationUnit *cUnit, MIR *mir); -#if defined(WITH_DEADLOCK_PREDICTION) || defined(WITH_MONITOR_TRACKING) || \ - defined(__ARM_ARCH_5__) +#if defined(__ARM_ARCH_5__) static void genMonitorPortable(CompilationUnit *cUnit, MIR *mir); #endif diff --git a/vm/compiler/codegen/arm/CodegenDriver.c b/vm/compiler/codegen/arm/CodegenDriver.c index 8e1b09c60..fb7e30e81 100644 --- a/vm/compiler/codegen/arm/CodegenDriver.c +++ b/vm/compiler/codegen/arm/CodegenDriver.c @@ -1275,8 +1275,7 @@ static void genInterpSingleStep(CompilationUnit *cUnit, MIR *mir) opReg(cUnit, kOpBlx, r2); } -#if defined(WITH_DEADLOCK_PREDICTION) || defined(WITH_MONITOR_TRACKING) || \ - defined(_ARMV5TE) || defined(_ARMV5TE_VFP) +#if defined(_ARMV5TE) || defined(_ARMV5TE_VFP) /* * To prevent a thread in a monitor wait from blocking the Jit from * resetting the code cache, heavyweight monitor lock will not @@ -1301,11 +1300,7 @@ static void genMonitorPortable(CompilationUnit *cUnit, MIR *mir) /* Get dPC of next insn */ loadConstant(cUnit, r4PC, (int)(cUnit->method->insns + mir->offset + dexGetWidthFromOpcode(OP_MONITOR_ENTER))); -#if defined(WITH_DEADLOCK_PREDICTION) - genDispatchToHandler(cUnit, TEMPLATE_MONITOR_ENTER_DEBUG); -#else genDispatchToHandler(cUnit, TEMPLATE_MONITOR_ENTER); -#endif } else { LOAD_FUNC_ADDR(cUnit, r2, (int)dvmUnlockObject); /* Do the call */ @@ -1810,11 +1805,7 @@ static bool handleFmt11x(CompilationUnit *cUnit, MIR *mir) } case OP_MONITOR_EXIT: case OP_MONITOR_ENTER: -#if defined(WITH_DEADLOCK_PREDICTION) || defined(WITH_MONITOR_TRACKING) - genMonitorPortable(cUnit, mir); -#else genMonitor(cUnit, mir); -#endif break; case OP_THROW: { genInterpSingleStep(cUnit, mir); diff --git a/vm/mterp/armv5te/OP_MONITOR_ENTER.S b/vm/mterp/armv5te/OP_MONITOR_ENTER.S index 36faabcdb..b3f74b07c 100644 --- a/vm/mterp/armv5te/OP_MONITOR_ENTER.S +++ b/vm/mterp/armv5te/OP_MONITOR_ENTER.S @@ -8,15 +8,9 @@ GET_VREG(r1, r2) @ r1<- vAA (object) ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self cmp r1, #0 @ null object? - EXPORT_PC() @ need for precise GC, MONITOR_TRACKING + EXPORT_PC() @ need for precise GC beq common_errNullObject @ null object, throw an exception FETCH_ADVANCE_INST(1) @ advance rPC, load rINST bl dvmLockObject @ call(self, obj) -#ifdef WITH_DEADLOCK_PREDICTION /* implies WITH_MONITOR_TRACKING */ - ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self - ldr r1, [r0, #offThread_exception] @ check for exception - cmp r1, #0 - bne common_exceptionThrown @ exception raised, bail out -#endif GET_INST_OPCODE(ip) @ extract opcode from rINST GOTO_OPCODE(ip) @ jump to next instruction diff --git a/vm/mterp/c/OP_MONITOR_ENTER.c b/vm/mterp/c/OP_MONITOR_ENTER.c index c9d89994a..de3348361 100644 --- a/vm/mterp/c/OP_MONITOR_ENTER.c +++ b/vm/mterp/c/OP_MONITOR_ENTER.c @@ -9,12 +9,8 @@ HANDLE_OPCODE(OP_MONITOR_ENTER /*vAA*/) if (!checkForNullExportPC(obj, fp, pc)) GOTO_exceptionThrown(); ILOGV("+ locking %p %s\n", obj, obj->clazz->descriptor); - EXPORT_PC(); /* need for precise GC, also WITH_MONITOR_TRACKING */ + EXPORT_PC(); /* need for precise GC */ dvmLockObject(self, obj); -#ifdef WITH_DEADLOCK_PREDICTION - if (dvmCheckException(self)) - GOTO_exceptionThrown(); -#endif } FINISH(1); OP_END diff --git a/vm/mterp/out/InterpAsm-armv5te-vfp.S b/vm/mterp/out/InterpAsm-armv5te-vfp.S index 6cb562060..60fb6c382 100644 --- a/vm/mterp/out/InterpAsm-armv5te-vfp.S +++ b/vm/mterp/out/InterpAsm-armv5te-vfp.S @@ -849,16 +849,10 @@ dalvik_inst: GET_VREG(r1, r2) @ r1<- vAA (object) ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self cmp r1, #0 @ null object? - EXPORT_PC() @ need for precise GC, MONITOR_TRACKING + EXPORT_PC() @ need for precise GC beq common_errNullObject @ null object, throw an exception FETCH_ADVANCE_INST(1) @ advance rPC, load rINST bl dvmLockObject @ call(self, obj) -#ifdef WITH_DEADLOCK_PREDICTION /* implies WITH_MONITOR_TRACKING */ - ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self - ldr r1, [r0, #offThread_exception] @ check for exception - cmp r1, #0 - bne common_exceptionThrown @ exception raised, bail out -#endif GET_INST_OPCODE(ip) @ extract opcode from rINST GOTO_OPCODE(ip) @ jump to next instruction diff --git a/vm/mterp/out/InterpAsm-armv5te.S b/vm/mterp/out/InterpAsm-armv5te.S index bf719ad20..c869286c9 100644 --- a/vm/mterp/out/InterpAsm-armv5te.S +++ b/vm/mterp/out/InterpAsm-armv5te.S @@ -849,16 +849,10 @@ dalvik_inst: GET_VREG(r1, r2) @ r1<- vAA (object) ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self cmp r1, #0 @ null object? - EXPORT_PC() @ need for precise GC, MONITOR_TRACKING + EXPORT_PC() @ need for precise GC beq common_errNullObject @ null object, throw an exception FETCH_ADVANCE_INST(1) @ advance rPC, load rINST bl dvmLockObject @ call(self, obj) -#ifdef WITH_DEADLOCK_PREDICTION /* implies WITH_MONITOR_TRACKING */ - ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self - ldr r1, [r0, #offThread_exception] @ check for exception - cmp r1, #0 - bne common_exceptionThrown @ exception raised, bail out -#endif GET_INST_OPCODE(ip) @ extract opcode from rINST GOTO_OPCODE(ip) @ jump to next instruction diff --git a/vm/mterp/out/InterpAsm-armv7-a-neon.S b/vm/mterp/out/InterpAsm-armv7-a-neon.S index 0cacb5d5f..4784fbcc6 100644 --- a/vm/mterp/out/InterpAsm-armv7-a-neon.S +++ b/vm/mterp/out/InterpAsm-armv7-a-neon.S @@ -860,16 +860,10 @@ dalvik_inst: GET_VREG(r1, r2) @ r1<- vAA (object) ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self cmp r1, #0 @ null object? - EXPORT_PC() @ need for precise GC, MONITOR_TRACKING + EXPORT_PC() @ need for precise GC beq common_errNullObject @ null object, throw an exception FETCH_ADVANCE_INST(1) @ advance rPC, load rINST bl dvmLockObject @ call(self, obj) -#ifdef WITH_DEADLOCK_PREDICTION /* implies WITH_MONITOR_TRACKING */ - ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self - ldr r1, [r0, #offThread_exception] @ check for exception - cmp r1, #0 - bne common_exceptionThrown @ exception raised, bail out -#endif GET_INST_OPCODE(ip) @ extract opcode from rINST GOTO_OPCODE(ip) @ jump to next instruction diff --git a/vm/mterp/out/InterpAsm-armv7-a.S b/vm/mterp/out/InterpAsm-armv7-a.S index 2ab215e4f..8d5786c81 100644 --- a/vm/mterp/out/InterpAsm-armv7-a.S +++ b/vm/mterp/out/InterpAsm-armv7-a.S @@ -860,16 +860,10 @@ dalvik_inst: GET_VREG(r1, r2) @ r1<- vAA (object) ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self cmp r1, #0 @ null object? - EXPORT_PC() @ need for precise GC, MONITOR_TRACKING + EXPORT_PC() @ need for precise GC beq common_errNullObject @ null object, throw an exception FETCH_ADVANCE_INST(1) @ advance rPC, load rINST bl dvmLockObject @ call(self, obj) -#ifdef WITH_DEADLOCK_PREDICTION /* implies WITH_MONITOR_TRACKING */ - ldr r0, [rGLUE, #offGlue_self] @ r0<- glue->self - ldr r1, [r0, #offThread_exception] @ check for exception - cmp r1, #0 - bne common_exceptionThrown @ exception raised, bail out -#endif GET_INST_OPCODE(ip) @ extract opcode from rINST GOTO_OPCODE(ip) @ jump to next instruction diff --git a/vm/mterp/out/InterpAsm-x86-atom.S b/vm/mterp/out/InterpAsm-x86-atom.S index 8a3e43bfa..2ba7e5a73 100644 --- a/vm/mterp/out/InterpAsm-x86-atom.S +++ b/vm/mterp/out/InterpAsm-x86-atom.S @@ -1845,9 +1845,7 @@ dalvik_inst: GET_VREG rINST # rINST<- vAA cmp $0, rINST # check for null object movl offGlue_self(%eax), %eax # %eax<- glue->self -#ifdef WITH_MONITOR_TRACKING - EXPORT_PC # export PC so we can grab stack trace -#endif + EXPORT_PC # need for precise GC je common_errNullObject # handle null object # jmp .LOP_MONITOR_ENTER_finish #%break @@ -1860,13 +1858,6 @@ dalvik_inst: # return: void FFETCH_ADV 1, %edx # %edx<- next instruction hi; fetch, advance lea 8(%esp), %esp -#ifdef WITH_DEADLOCK_PREDICTION - movl rGLUE, %eax # %eax<- pMterpGlue - movl offGlue_self(%eax), %eax # %eax<- glue->self - movl offThread_exception(%eax), %eax # %eax<- glue->self->exception - cmp $0, %eax # check for exception - jne common_exceptionThrown # handle exception -#endif FGETOP_JMP 1, %edx # jump to next instruction; getop, jmp /* ------------------------------ */ diff --git a/vm/mterp/out/InterpAsm-x86.S b/vm/mterp/out/InterpAsm-x86.S index 7e6279845..e42a8cde3 100644 --- a/vm/mterp/out/InterpAsm-x86.S +++ b/vm/mterp/out/InterpAsm-x86.S @@ -1059,7 +1059,7 @@ dvmAsmInstructionStart = .L_OP_NOP movl offGlue_self(%ecx),%ecx # ecx<- glue->self FETCH_INST_WORD 1 testl %eax,%eax # null object? - EXPORT_PC # need for precise GC, MONITOR_TRACKING + EXPORT_PC # need for precise GC jne .LOP_MONITOR_ENTER_continue jmp common_errNullObject @@ -9261,13 +9261,6 @@ dvmAsmSisterStart: movl %ecx,OUT_ARG0(%esp) movl %eax,OUT_ARG1(%esp) call dvmLockObject # dvmLockObject(self,object) -#ifdef WITH_DEADLOCK_PREDICTION - movl rGLUE,%ecx - movl offGlueSelf(%ecx),%ecx # ecx<- glue->self - movl offThread_exception(%ecx),%eax - testl %eax,%eax - jne common_exceptionThrown -#endif ADVANCE_PC 1 GOTO_NEXT diff --git a/vm/mterp/out/InterpC-allstubs.c b/vm/mterp/out/InterpC-allstubs.c index 861a1509a..e1acf618a 100644 --- a/vm/mterp/out/InterpC-allstubs.c +++ b/vm/mterp/out/InterpC-allstubs.c @@ -1653,12 +1653,8 @@ HANDLE_OPCODE(OP_MONITOR_ENTER /*vAA*/) if (!checkForNullExportPC(obj, fp, pc)) GOTO_exceptionThrown(); ILOGV("+ locking %p %s\n", obj, obj->clazz->descriptor); - EXPORT_PC(); /* need for precise GC, also WITH_MONITOR_TRACKING */ + EXPORT_PC(); /* need for precise GC */ dvmLockObject(self, obj); -#ifdef WITH_DEADLOCK_PREDICTION - if (dvmCheckException(self)) - GOTO_exceptionThrown(); -#endif } FINISH(1); OP_END diff --git a/vm/mterp/out/InterpC-portdbg.c b/vm/mterp/out/InterpC-portdbg.c index 00caa6ecd..94f927c04 100644 --- a/vm/mterp/out/InterpC-portdbg.c +++ b/vm/mterp/out/InterpC-portdbg.c @@ -2015,12 +2015,8 @@ HANDLE_OPCODE(OP_MONITOR_ENTER /*vAA*/) if (!checkForNullExportPC(obj, fp, pc)) GOTO_exceptionThrown(); ILOGV("+ locking %p %s\n", obj, obj->clazz->descriptor); - EXPORT_PC(); /* need for precise GC, also WITH_MONITOR_TRACKING */ + EXPORT_PC(); /* need for precise GC */ dvmLockObject(self, obj); -#ifdef WITH_DEADLOCK_PREDICTION - if (dvmCheckException(self)) - GOTO_exceptionThrown(); -#endif } FINISH(1); OP_END diff --git a/vm/mterp/out/InterpC-portstd.c b/vm/mterp/out/InterpC-portstd.c index 46b712feb..dbcf913e8 100644 --- a/vm/mterp/out/InterpC-portstd.c +++ b/vm/mterp/out/InterpC-portstd.c @@ -1765,12 +1765,8 @@ HANDLE_OPCODE(OP_MONITOR_ENTER /*vAA*/) if (!checkForNullExportPC(obj, fp, pc)) GOTO_exceptionThrown(); ILOGV("+ locking %p %s\n", obj, obj->clazz->descriptor); - EXPORT_PC(); /* need for precise GC, also WITH_MONITOR_TRACKING */ + EXPORT_PC(); /* need for precise GC */ dvmLockObject(self, obj); -#ifdef WITH_DEADLOCK_PREDICTION - if (dvmCheckException(self)) - GOTO_exceptionThrown(); -#endif } FINISH(1); OP_END diff --git a/vm/mterp/x86-atom/OP_MONITOR_ENTER.S b/vm/mterp/x86-atom/OP_MONITOR_ENTER.S index d3fada35c..39d0e7b16 100644 --- a/vm/mterp/x86-atom/OP_MONITOR_ENTER.S +++ b/vm/mterp/x86-atom/OP_MONITOR_ENTER.S @@ -33,9 +33,7 @@ GET_VREG rINST # rINST<- vAA cmp $$0, rINST # check for null object movl offGlue_self(%eax), %eax # %eax<- glue->self -#ifdef WITH_MONITOR_TRACKING - EXPORT_PC # export PC so we can grab stack trace -#endif + EXPORT_PC # need for precise GC je common_errNullObject # handle null object # jmp .L${opcode}_finish #%break @@ -48,11 +46,4 @@ # return: void FFETCH_ADV 1, %edx # %edx<- next instruction hi; fetch, advance lea 8(%esp), %esp -#ifdef WITH_DEADLOCK_PREDICTION - movl rGLUE, %eax # %eax<- pMterpGlue - movl offGlue_self(%eax), %eax # %eax<- glue->self - movl offThread_exception(%eax), %eax # %eax<- glue->self->exception - cmp $$0, %eax # check for exception - jne common_exceptionThrown # handle exception -#endif FGETOP_JMP 1, %edx # jump to next instruction; getop, jmp diff --git a/vm/mterp/x86/OP_MONITOR_ENTER.S b/vm/mterp/x86/OP_MONITOR_ENTER.S index 848f0fd30..a26726662 100644 --- a/vm/mterp/x86/OP_MONITOR_ENTER.S +++ b/vm/mterp/x86/OP_MONITOR_ENTER.S @@ -9,7 +9,7 @@ movl offGlue_self(%ecx),%ecx # ecx<- glue->self FETCH_INST_WORD 1 testl %eax,%eax # null object? - EXPORT_PC # need for precise GC, MONITOR_TRACKING + EXPORT_PC # need for precise GC jne .L${opcode}_continue jmp common_errNullObject %break @@ -18,12 +18,5 @@ movl %ecx,OUT_ARG0(%esp) movl %eax,OUT_ARG1(%esp) call dvmLockObject # dvmLockObject(self,object) -#ifdef WITH_DEADLOCK_PREDICTION - movl rGLUE,%ecx - movl offGlueSelf(%ecx),%ecx # ecx<- glue->self - movl offThread_exception(%ecx),%eax - testl %eax,%eax - jne common_exceptionThrown -#endif ADVANCE_PC 1 GOTO_NEXT |