summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCarl Shapiro <cshapiro@google.com>2011-02-01 11:32:44 -0800
committerCarl Shapiro <cshapiro@google.com>2011-02-01 11:32:44 -0800
commit01605d2b668e8e1701cfdfa302dde847b9171fc9 (patch)
tree0e4191085609463310771764c2e877c9499b5080
parent83d17b3741cfa07176f8559b6585fe9a61a27091 (diff)
downloadandroid_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.html35
-rw-r--r--vm/Dvm.mk8
-rw-r--r--vm/Globals.h7
-rw-r--r--vm/Init.c24
-rw-r--r--vm/Sync.c718
-rw-r--r--vm/Thread.c153
-rw-r--r--vm/Thread.h40
-rw-r--r--vm/compiler/codegen/arm/Codegen.h3
-rw-r--r--vm/compiler/codegen/arm/CodegenDriver.c11
-rw-r--r--vm/mterp/armv5te/OP_MONITOR_ENTER.S8
-rw-r--r--vm/mterp/c/OP_MONITOR_ENTER.c6
-rw-r--r--vm/mterp/out/InterpAsm-armv5te-vfp.S8
-rw-r--r--vm/mterp/out/InterpAsm-armv5te.S8
-rw-r--r--vm/mterp/out/InterpAsm-armv7-a-neon.S8
-rw-r--r--vm/mterp/out/InterpAsm-armv7-a.S8
-rw-r--r--vm/mterp/out/InterpAsm-x86-atom.S11
-rw-r--r--vm/mterp/out/InterpAsm-x86.S9
-rw-r--r--vm/mterp/out/InterpC-allstubs.c6
-rw-r--r--vm/mterp/out/InterpC-portdbg.c6
-rw-r--r--vm/mterp/out/InterpC-portstd.c6
-rw-r--r--vm/mterp/x86-atom/OP_MONITOR_ENTER.S11
-rw-r--r--vm/mterp/x86/OP_MONITOR_ENTER.S9
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
diff --git a/vm/Dvm.mk b/vm/Dvm.mk
index 9e3f33fae..91d6b416f 100644
--- a/vm/Dvm.mk
+++ b/vm/Dvm.mk
@@ -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.,
diff --git a/vm/Init.c b/vm/Init.c
index c2c0d5eda..2b590bc52 100644
--- a/vm/Init.c
+++ b/vm/Init.c
@@ -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);
diff --git a/vm/Sync.c b/vm/Sync.c
index ff58aad8d..a33a71e7c 100644
--- a/vm/Sync.c
+++ b/vm/Sync.c
@@ -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