diff options
author | 2017-03-28 12:59:38 -0700 | |
---|---|---|
committer | 2017-03-28 13:40:41 -0700 | |
commit | f169e27100acbec024f699de9ef842a27c0b2036 (patch) | |
tree | 2d82abce1f923863f023cb8ee12409ad82809dad | |
parent | ae60e48f1077a2221549c733623c25f79733caf0 (diff) |
Fix lock order for jvmti kTaggingLockLevel
Add test for duplicate env free order.
Bug: 36648696
Test: ./test.py --host
Change-Id: I76fc8187b29f5e66cc29674320e887dbc508fe19
-rw-r--r-- | runtime/base/mutex.h | 3 | ||||
-rw-r--r-- | runtime/openjdkjvmti/jvmti_weak_table.h | 6 | ||||
-rw-r--r-- | test/905-object-free/expected.txt | 1 | ||||
-rw-r--r-- | test/905-object-free/src/Main.java | 26 | ||||
-rw-r--r-- | test/905-object-free/tracking_free.cc | 57 |
5 files changed, 71 insertions, 22 deletions
diff --git a/runtime/base/mutex.h b/runtime/base/mutex.h index 038aeb33e7..2414b5f937 100644 --- a/runtime/base/mutex.h +++ b/runtime/base/mutex.h @@ -62,10 +62,11 @@ enum LockLevel { kJdwpAdbStateLock, kJdwpSocketLock, kRegionSpaceRegionLock, + kMarkSweepMarkStackLock, kRosAllocGlobalLock, kRosAllocBracketLock, kRosAllocBulkFreeLock, - kMarkSweepMarkStackLock, + kTaggingLockLevel, kTransactionLogLock, kJniFunctionTableLock, kJniWeakGlobalsLock, diff --git a/runtime/openjdkjvmti/jvmti_weak_table.h b/runtime/openjdkjvmti/jvmti_weak_table.h index ae3612208c..eeea75aa9d 100644 --- a/runtime/openjdkjvmti/jvmti_weak_table.h +++ b/runtime/openjdkjvmti/jvmti_weak_table.h @@ -53,7 +53,7 @@ template <typename T> class JvmtiWeakTable : public art::gc::SystemWeakHolder { public: JvmtiWeakTable() - : art::gc::SystemWeakHolder(kTaggingLockLevel), + : art::gc::SystemWeakHolder(art::kTaggingLockLevel), update_since_last_sweep_(false) { } @@ -200,10 +200,6 @@ class JvmtiWeakTable : public art::gc::SystemWeakHolder { } }; - // The tag table is used when visiting roots. So it needs to have a low lock level. - static constexpr art::LockLevel kTaggingLockLevel = - static_cast<art::LockLevel>(art::LockLevel::kAbortLock + 1); - std::unordered_map<art::GcRoot<art::mirror::Object>, T, HashGcRoot, diff --git a/test/905-object-free/expected.txt b/test/905-object-free/expected.txt index 436ca115b1..6594ad8243 100644 --- a/test/905-object-free/expected.txt +++ b/test/905-object-free/expected.txt @@ -10,3 +10,4 @@ --- [] --- +Free counts 1000000 1000000 diff --git a/test/905-object-free/src/Main.java b/test/905-object-free/src/Main.java index e41e378c19..67811c26d5 100644 --- a/test/905-object-free/src/Main.java +++ b/test/905-object-free/src/Main.java @@ -33,6 +33,9 @@ public class Main { enableFreeTracking(false); run(l); + + enableFreeTracking(true); + stress(); } private static void run(ArrayList<Object> l) { @@ -62,6 +65,25 @@ public class Main { System.out.println("---"); } + private static void stress() { + getCollectedTags(0); + getCollectedTags(1); + for (int i = 0; i <= 1000000; ++i) { + Object obj = new Object(); + setTag(obj, i); + obj = null; // Clear vreg. + } + Runtime.getRuntime().gc(); + long[] freedTags1 = getCollectedTags(0); + long[] freedTags2 = getCollectedTags(1); + System.out.println("Free counts " + freedTags1.length + " " + freedTags2.length); + for (int i = 0; i < freedTags1.length; ++i) { + if (freedTags1[i] != freedTags2[i]) { + System.out.println("Mismatched tags " + freedTags1[i] + " " + freedTags2[i]); + } + } + } + private static void allocate(ArrayList<Object> l, long tag) { Object obj = new Object(); l.add(obj); @@ -69,7 +91,7 @@ public class Main { } private static void getAndPrintTags() { - long[] freedTags = getCollectedTags(); + long[] freedTags = getCollectedTags(0); Arrays.sort(freedTags); System.out.println(Arrays.toString(freedTags)); } @@ -77,5 +99,5 @@ public class Main { private static native void setupObjectFreeCallback(); private static native void enableFreeTracking(boolean enable); private static native void setTag(Object o, long tag); - private static native long[] getCollectedTags(); + private static native long[] getCollectedTags(int index); } diff --git a/test/905-object-free/tracking_free.cc b/test/905-object-free/tracking_free.cc index 5eed4729af..3baac88968 100644 --- a/test/905-object-free/tracking_free.cc +++ b/test/905-object-free/tracking_free.cc @@ -31,27 +31,44 @@ namespace art { namespace Test905ObjectFree { -static std::vector<jlong> collected_tags; +static std::vector<jlong> collected_tags1; +static std::vector<jlong> collected_tags2; -static void JNICALL ObjectFree(jvmtiEnv* ti_env ATTRIBUTE_UNUSED, jlong tag) { - collected_tags.push_back(tag); +jvmtiEnv* jvmti_env2; + +static void JNICALL ObjectFree1(jvmtiEnv* ti_env, jlong tag) { + CHECK_EQ(ti_env, jvmti_env); + collected_tags1.push_back(tag); } -extern "C" JNIEXPORT void JNICALL Java_Main_setupObjectFreeCallback( - JNIEnv* env ATTRIBUTE_UNUSED, jclass klass ATTRIBUTE_UNUSED) { +static void JNICALL ObjectFree2(jvmtiEnv* ti_env, jlong tag) { + CHECK_EQ(ti_env, jvmti_env2); + collected_tags2.push_back(tag); +} + +static void setupObjectFreeCallback(jvmtiEnv* env, jvmtiEventObjectFree callback) { jvmtiEventCallbacks callbacks; memset(&callbacks, 0, sizeof(jvmtiEventCallbacks)); - callbacks.ObjectFree = ObjectFree; - - jvmtiError ret = jvmti_env->SetEventCallbacks(&callbacks, sizeof(callbacks)); + callbacks.ObjectFree = callback; + jvmtiError ret = env->SetEventCallbacks(&callbacks, sizeof(callbacks)); if (ret != JVMTI_ERROR_NONE) { char* err; - jvmti_env->GetErrorName(ret, &err); + env->GetErrorName(ret, &err); printf("Error setting callbacks: %s\n", err); - jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(err)); + env->Deallocate(reinterpret_cast<unsigned char*>(err)); } } +extern "C" JNIEXPORT void JNICALL Java_Main_setupObjectFreeCallback( + JNIEnv* env, jclass klass ATTRIBUTE_UNUSED) { + setupObjectFreeCallback(jvmti_env, ObjectFree1); + JavaVM* jvm = nullptr; + env->GetJavaVM(&jvm); + CHECK_EQ(jvm->GetEnv(reinterpret_cast<void**>(&jvmti_env2), JVMTI_VERSION_1_2), 0); + SetAllCapabilities(jvmti_env2); + setupObjectFreeCallback(jvmti_env2, ObjectFree2); +} + extern "C" JNIEXPORT void JNICALL Java_Main_enableFreeTracking(JNIEnv* env ATTRIBUTE_UNUSED, jclass klass ATTRIBUTE_UNUSED, jboolean enable) { @@ -65,17 +82,29 @@ extern "C" JNIEXPORT void JNICALL Java_Main_enableFreeTracking(JNIEnv* env ATTRI printf("Error enabling/disabling object-free callbacks: %s\n", err); jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(err)); } + ret = jvmti_env2->SetEventNotificationMode( + enable ? JVMTI_ENABLE : JVMTI_DISABLE, + JVMTI_EVENT_OBJECT_FREE, + nullptr); + if (ret != JVMTI_ERROR_NONE) { + char* err; + jvmti_env2->GetErrorName(ret, &err); + printf("Error enabling/disabling object-free callbacks: %s\n", err); + jvmti_env2->Deallocate(reinterpret_cast<unsigned char*>(err)); + } } extern "C" JNIEXPORT jlongArray JNICALL Java_Main_getCollectedTags(JNIEnv* env, - jclass klass ATTRIBUTE_UNUSED) { - jlongArray ret = env->NewLongArray(collected_tags.size()); + jclass klass ATTRIBUTE_UNUSED, + jint index) { + std::vector<jlong>& tags = (index == 0) ? collected_tags1 : collected_tags2; + jlongArray ret = env->NewLongArray(tags.size()); if (ret == nullptr) { return ret; } - env->SetLongArrayRegion(ret, 0, collected_tags.size(), collected_tags.data()); - collected_tags.clear(); + env->SetLongArrayRegion(ret, 0, tags.size(), tags.data()); + tags.clear(); return ret; } |