Add JNI app bug workarounds.
Specifically, this hands out direct pointers for all local references,
and lets you use a JNIEnv* on the wrong thread. This is off by default,
but enabled for apps that don't have ICS as their targetSdkVersion.
Bug: 4772166
Change-Id: I20c403a8e63481a35d579d2bd3b121c80ec08f89
diff --git a/vm/IndirectRefTable.cpp b/vm/IndirectRefTable.cpp
index fcf59af..6a50dab 100644
--- a/vm/IndirectRefTable.cpp
+++ b/vm/IndirectRefTable.cpp
@@ -194,6 +194,19 @@
return true;
}
+static int linearScan(IndirectRef iref, int bottomIndex, int topIndex, Object** table) {
+ for (int i = bottomIndex; i < topIndex; ++i) {
+ if (table[i] == reinterpret_cast<Object*>(iref)) {
+ return i;
+ }
+ }
+ return -1;
+}
+
+bool IndirectRefTable::contains(IndirectRef iref) const {
+ return linearScan(iref, 0, segmentState.parts.topIndex, table) != -1;
+}
+
/*
* Remove "obj" from "pRef". We extract the table offset bits from "iref"
* and zap the corresponding entry, leaving a hole if it's not at the top.
@@ -219,6 +232,17 @@
assert(segmentState.parts.numHoles >= prevState.parts.numHoles);
int idx = extractIndex(iref);
+ bool fakeDirectReferenceHack = false;
+
+ if (indirectRefKind(iref) == kIndirectKindInvalid && gDvmJni.workAroundAppJniBugs) {
+ idx = linearScan(iref, bottomIndex, topIndex, table);
+ fakeDirectReferenceHack = true;
+ if (idx == -1) {
+ LOGW("trying to work around app JNI bugs, but didn't find %p in table!", iref);
+ return false;
+ }
+ }
+
if (idx < bottomIndex) {
/* wrong segment */
LOGV("Attempt to remove index outside index area (%d vs %d-%d)",
@@ -237,10 +261,9 @@
* Top-most entry. Scan up and consume holes. No need to NULL
* out the entry, since the test vs. topIndex will catch it.
*/
- if (!checkEntry("remove", iref, idx)) {
+ if (fakeDirectReferenceHack == false && !checkEntry("remove", iref, idx)) {
return false;
}
- updateSlotRemove(idx);
#ifndef NDEBUG
table[idx] = (Object*)0xd3d3d3d3;
@@ -274,10 +297,9 @@
LOGV("--- WEIRD: removing null entry %d", idx);
return false;
}
- if (!checkEntry("remove", iref, idx)) {
+ if (fakeDirectReferenceHack == false && !checkEntry("remove", iref, idx)) {
return false;
}
- updateSlotRemove(idx);
table[idx] = NULL;
segmentState.parts.numHoles++;