Revert "Implement LockSupport.park with a futex"
This reverts commit 5e1a75c1d12ea47bdc0f73d378b5fa25326829f4.
Reason for revert: This CL unfortunately breaks:
sdk_gphone_x86-sdk_addon_mac
sdk_mac
Following error:
art/runtime/thread.cc:370:4: warning: "LockSupport.park/unpark implemented as noops without FUTEX support." [-W#warnings]
#warning "LockSupport.park/unpark implemented as noops without FUTEX support."
^
art/runtime/thread.cc:295:24: error: unused parameter 'is_absolute' [-Werror,-Wunused-parameter]
void Thread::Park(bool is_absolute, int64_t time) {
^
art/runtime/thread.cc:295:45: error: unused parameter 'time' [-Werror,-Wunused-parameter]
void Thread::Park(bool is_absolute, int64_t time) {
^
1 warning and 2 errors generated.
Change-Id: Iae41cce7cd5fc38f605173519931491a019f7c80
diff --git a/runtime/native/sun_misc_Unsafe.cc b/runtime/native/sun_misc_Unsafe.cc
index 10a499c..4644480 100644
--- a/runtime/native/sun_misc_Unsafe.cc
+++ b/runtime/native/sun_misc_Unsafe.cc
@@ -31,10 +31,8 @@
#include "mirror/array.h"
#include "mirror/class-inl.h"
#include "mirror/object-inl.h"
-#include "art_field-inl.h"
#include "native_util.h"
#include "scoped_fast_native_object_access-inl.h"
-#include "well_known_classes.h"
namespace art {
@@ -506,33 +504,6 @@
std::atomic_thread_fence(std::memory_order_seq_cst);
}
-static void Unsafe_park(JNIEnv* env, jobject, jboolean isAbsolute, jlong time) {
- ScopedObjectAccess soa(env);
- Thread::Current()->Park(isAbsolute, time);
-}
-
-static void Unsafe_unpark(JNIEnv* env, jobject, jobject jthread) {
- art::ScopedFastNativeObjectAccess soa(env);
- if (jthread == nullptr || !env->IsInstanceOf(jthread, WellKnownClasses::java_lang_Thread)) {
- ThrowIllegalArgumentException("Argument to unpark() was not a Thread");
- return;
- }
- art::MutexLock mu(soa.Self(), *art::Locks::thread_list_lock_);
- art::Thread* thread = art::Thread::FromManagedThread(soa, jthread);
- if (thread != nullptr) {
- thread->Unpark();
- } else {
- // If thread is null, that means that either the thread is not started yet,
- // or the thread has already terminated. Setting the field to true will be
- // respected when the thread does start, and is harmless if the thread has
- // already terminated.
- ArtField* unparked =
- jni::DecodeArtField(WellKnownClasses::java_lang_Thread_unparkedBeforeStart);
- // JNI must use non transactional mode.
- unparked->SetBoolean<false>(soa.Decode<mirror::Object>(jthread), JNI_TRUE);
- }
-}
-
static JNINativeMethod gMethods[] = {
FAST_NATIVE_METHOD(Unsafe, compareAndSwapInt, "(Ljava/lang/Object;JII)Z"),
FAST_NATIVE_METHOD(Unsafe, compareAndSwapLong, "(Ljava/lang/Object;JJJ)Z"),
@@ -575,8 +546,6 @@
FAST_NATIVE_METHOD(Unsafe, putShort, "(Ljava/lang/Object;JS)V"),
FAST_NATIVE_METHOD(Unsafe, putFloat, "(Ljava/lang/Object;JF)V"),
FAST_NATIVE_METHOD(Unsafe, putDouble, "(Ljava/lang/Object;JD)V"),
- FAST_NATIVE_METHOD(Unsafe, unpark, "(Ljava/lang/Object;)V"),
- NATIVE_METHOD(Unsafe, park, "(ZJ)V"),
// Each of the getFoo variants are overloaded with a call that operates
// directively on a native pointer.
diff --git a/runtime/thread.cc b/runtime/thread.cc
index 4dae07e..51775c6 100644
--- a/runtime/thread.cc
+++ b/runtime/thread.cc
@@ -44,7 +44,6 @@
#include "arch/context.h"
#include "art_field-inl.h"
#include "art_method-inl.h"
-#include "base/atomic.h"
#include "base/bit_utils.h"
#include "base/casts.h"
#include "base/file_utils.h"
@@ -283,115 +282,6 @@
<< "No deoptimization context for thread " << *this;
}
-enum {
- kPermitAvailable = 0, // Incrementing consumes the permit
- kNoPermit = 1, // Incrementing marks as waiter waiting
- kNoPermitWaiterWaiting = 2
-};
-
-void Thread::Park(bool is_absolute, int64_t time) {
- DCHECK(this == Thread::Current());
-#if ART_USE_FUTEXES
- // Consume the permit, or mark as waiting. This cannot cause park_state to go
- // outside of its valid range (0, 1, 2), because in all cases where 2 is
- // assigned it is set back to 1 before returning, and this method cannot run
- // concurrently with itself since it operates on the current thread.
- int old_state = tls32_.park_state_.fetch_add(1, std::memory_order_relaxed);
- if (old_state == kNoPermit) {
- // no permit was available. block thread until later.
- // TODO: Call to signal jvmti here
- int result = 0;
- if (!is_absolute && time == 0) {
- // Thread.getState() is documented to return waiting for untimed parks.
- ScopedThreadSuspension sts(this, ThreadState::kWaiting);
- DCHECK_EQ(NumberOfHeldMutexes(), 0u);
- result = futex(tls32_.park_state_.Address(),
- FUTEX_WAIT_PRIVATE,
- /* sleep if val = */ kNoPermitWaiterWaiting,
- /* timeout */ nullptr,
- nullptr,
- 0);
- } else if (time > 0) {
- // Only actually suspend and futex_wait if we're going to wait for some
- // positive amount of time - the kernel will reject negative times with
- // EINVAL, and a zero time will just noop.
-
- // Thread.getState() is documented to return timed wait for timed parks.
- ScopedThreadSuspension sts(this, ThreadState::kTimedWaiting);
- DCHECK_EQ(NumberOfHeldMutexes(), 0u);
- timespec timespec;
- if (is_absolute) {
- // Time is millis when scheduled for an absolute time
- timespec.tv_nsec = (time % 1000) * 1000000;
- timespec.tv_sec = time / 1000;
- // This odd looking pattern is recommended by futex documentation to
- // wait until an absolute deadline, with otherwise identical behavior to
- // FUTEX_WAIT_PRIVATE. This also allows parkUntil() to return at the
- // correct time when the system clock changes.
- result = futex(tls32_.park_state_.Address(),
- FUTEX_WAIT_BITSET_PRIVATE | FUTEX_CLOCK_REALTIME,
- /* sleep if val = */ kNoPermitWaiterWaiting,
- ×pec,
- nullptr,
- FUTEX_BITSET_MATCH_ANY);
- } else {
- // Time is nanos when scheduled for a relative time
- timespec.tv_sec = time / 1000000000;
- timespec.tv_nsec = time % 1000000000;
- result = futex(tls32_.park_state_.Address(),
- FUTEX_WAIT_PRIVATE,
- /* sleep if val = */ kNoPermitWaiterWaiting,
- ×pec,
- nullptr,
- 0);
- }
- }
- if (result == -1) {
- switch (errno) {
- case EAGAIN:
- case ETIMEDOUT:
- case EINTR: break; // park() is allowed to spuriously return
- default: PLOG(FATAL) << "Failed to park";
- }
- }
- // Mark as no longer waiting, and consume permit if there is one.
- tls32_.park_state_.store(kNoPermit, std::memory_order_relaxed);
- // TODO: Call to signal jvmti here
- } else {
- // the fetch_add has consumed the permit. immediately return.
- DCHECK_EQ(old_state, kPermitAvailable);
- }
-#else
- #pragma clang diagnostic push
- #pragma clang diagnostic warning "-W#warnings"
- #warning "LockSupport.park/unpark implemented as noops without FUTEX support."
- #pragma clang diagnostic pop
- UNIMPLEMENTED(WARNING);
- sched_yield();
-#endif
-}
-
-void Thread::Unpark() {
-#if ART_USE_FUTEXES
- // Set permit available; will be consumed either by fetch_add (when the thread
- // tries to park) or store (when the parked thread is woken up)
- if (tls32_.park_state_.exchange(kPermitAvailable, std::memory_order_relaxed)
- == kNoPermitWaiterWaiting) {
- int result = futex(tls32_.park_state_.Address(),
- FUTEX_WAKE_PRIVATE,
- /* number of waiters = */ 1,
- nullptr,
- nullptr,
- 0);
- if (result == -1) {
- PLOG(FATAL) << "Failed to unpark";
- }
- }
-#else
- UNIMPLEMENTED(WARNING);
-#endif
-}
-
void Thread::PushStackedShadowFrame(ShadowFrame* sf, StackedShadowFrameType type) {
StackedShadowFrameRecord* record = new StackedShadowFrameRecord(
sf, type, tlsPtr_.stacked_shadow_frame_record);
@@ -596,22 +486,6 @@
runtime->GetRuntimeCallbacks()->ThreadStart(self);
- // Unpark ourselves if the java peer was unparked before it started (see
- // b/28845097#comment49 for more information)
-
- ArtField* unparkedField = jni::DecodeArtField(
- WellKnownClasses::java_lang_Thread_unparkedBeforeStart);
- bool should_unpark = false;
- {
- // Hold the lock here, so that if another thread calls unpark before the thread starts
- // we don't observe the unparkedBeforeStart field before the unparker writes to it,
- // which could cause a lost unpark.
- art::MutexLock mu(soa.Self(), *art::Locks::thread_list_lock_);
- should_unpark = unparkedField->GetBoolean(self->tlsPtr_.opeer) == JNI_TRUE;
- }
- if (should_unpark) {
- self->Unpark();
- }
// Invoke the 'run' method of our java.lang.Thread.
ObjPtr<mirror::Object> receiver = self->tlsPtr_.opeer;
jmethodID mid = WellKnownClasses::java_lang_Thread_run;
@@ -2256,9 +2130,6 @@
tls32_.state_and_flags.as_struct.flags = 0;
tls32_.state_and_flags.as_struct.state = kNative;
tls32_.interrupted.store(false, std::memory_order_relaxed);
- // Initialize with no permit; if the java Thread was unparked before being
- // started, it will unpark itself before calling into java code.
- tls32_.park_state_.store(kNoPermit, std::memory_order_relaxed);
memset(&tlsPtr_.held_mutexes[0], 0, sizeof(tlsPtr_.held_mutexes));
std::fill(tlsPtr_.rosalloc_runs,
tlsPtr_.rosalloc_runs + kNumRosAllocThreadLocalSizeBracketsInThread,
@@ -2570,15 +2441,12 @@
}
void Thread::Interrupt(Thread* self) {
- {
- MutexLock mu(self, *wait_mutex_);
- if (tls32_.interrupted.load(std::memory_order_seq_cst)) {
- return;
- }
- tls32_.interrupted.store(true, std::memory_order_seq_cst);
- NotifyLocked(self);
+ MutexLock mu(self, *wait_mutex_);
+ if (tls32_.interrupted.load(std::memory_order_seq_cst)) {
+ return;
}
- Unpark();
+ tls32_.interrupted.store(true, std::memory_order_seq_cst);
+ NotifyLocked(self);
}
void Thread::Notify() {
diff --git a/runtime/thread.h b/runtime/thread.h
index 9a0ea6f..47a3af2 100644
--- a/runtime/thread.h
+++ b/runtime/thread.h
@@ -580,11 +580,6 @@
return poison_object_cookie_;
}
- // Parking for 0ns of relative time means an untimed park, negative (though
- // should be handled in java code) returns immediately
- void Park(bool is_absolute, int64_t time) REQUIRES_SHARED(Locks::mutator_lock_);
- void Unpark();
-
private:
void NotifyLocked(Thread* self) REQUIRES(wait_mutex_);
@@ -1561,8 +1556,6 @@
// Thread "interrupted" status; stays raised until queried or thrown.
Atomic<bool32_t> interrupted;
- AtomicInteger park_state_;
-
// True if the thread is allowed to access a weak ref (Reference::GetReferent() and system
// weaks) and to potentially mark an object alive/gray. This is used for concurrent reference
// processing of the CC collector only. This is thread local so that we can enable/disable weak
diff --git a/runtime/well_known_classes.cc b/runtime/well_known_classes.cc
index 94faa62..206418f 100644
--- a/runtime/well_known_classes.cc
+++ b/runtime/well_known_classes.cc
@@ -128,7 +128,6 @@
jfieldID WellKnownClasses::java_lang_Thread_name;
jfieldID WellKnownClasses::java_lang_Thread_priority;
jfieldID WellKnownClasses::java_lang_Thread_nativePeer;
-jfieldID WellKnownClasses::java_lang_Thread_unparkedBeforeStart;
jfieldID WellKnownClasses::java_lang_ThreadGroup_groups;
jfieldID WellKnownClasses::java_lang_ThreadGroup_ngroups;
jfieldID WellKnownClasses::java_lang_ThreadGroup_mainThreadGroup;
@@ -377,7 +376,6 @@
java_lang_Thread_name = CacheField(env, java_lang_Thread, false, "name", "Ljava/lang/String;");
java_lang_Thread_priority = CacheField(env, java_lang_Thread, false, "priority", "I");
java_lang_Thread_nativePeer = CacheField(env, java_lang_Thread, false, "nativePeer", "J");
- java_lang_Thread_unparkedBeforeStart = CacheField(env, java_lang_Thread, false, "unparkedBeforeStart", "Z");
java_lang_ThreadGroup_groups = CacheField(env, java_lang_ThreadGroup, false, "groups", "[Ljava/lang/ThreadGroup;");
java_lang_ThreadGroup_ngroups = CacheField(env, java_lang_ThreadGroup, false, "ngroups", "I");
java_lang_ThreadGroup_mainThreadGroup = CacheField(env, java_lang_ThreadGroup, true, "mainThreadGroup", "Ljava/lang/ThreadGroup;");
diff --git a/runtime/well_known_classes.h b/runtime/well_known_classes.h
index 8c85228..ce5ab1d 100644
--- a/runtime/well_known_classes.h
+++ b/runtime/well_known_classes.h
@@ -137,7 +137,6 @@
static jfieldID java_lang_Thread_name;
static jfieldID java_lang_Thread_priority;
static jfieldID java_lang_Thread_nativePeer;
- static jfieldID java_lang_Thread_unparkedBeforeStart;
static jfieldID java_lang_ThreadGroup_groups;
static jfieldID java_lang_ThreadGroup_ngroups;
static jfieldID java_lang_ThreadGroup_mainThreadGroup;
diff --git a/test/004-ThreadStress/src-art/Main.java b/test/004-ThreadStress/src-art/Main.java
index b8bfafb..3a89f4f 100644
--- a/test/004-ThreadStress/src-art/Main.java
+++ b/test/004-ThreadStress/src-art/Main.java
@@ -26,7 +26,6 @@
import java.util.Map;
import java.util.Set;
import java.util.concurrent.Semaphore;
-import java.util.concurrent.locks.LockSupport;
// Run on host with:
// javac ThreadTest.java && java ThreadStress && rm *.class
@@ -252,31 +251,6 @@
}
}
- private final static class TimedPark extends Operation {
- private final static int SLEEP_TIME = 100;
-
- public TimedPark() {}
-
- @Override
- public boolean perform() {
- LockSupport.parkNanos(this, 100*1000000);
- return true;
- }
- }
-
- private final static class UnparkAllThreads extends Operation {
- public UnparkAllThreads() {}
-
- @Override
- public boolean perform() {
- Set<Thread> threads = Thread.getAllStackTraces().keySet();
- for (Thread candidate : threads) {
- LockSupport.unpark(candidate);
- }
- return true;
- }
- }
-
private final static class SyncAndWork extends Operation {
private final Object lock;
@@ -346,9 +320,7 @@
frequencyMap.put(new NonMovingAlloc(), 0.025); // 5/200
frequencyMap.put(new StackTrace(), 0.1); // 20/200
frequencyMap.put(new Exit(), 0.225); // 45/200
- frequencyMap.put(new Sleep(), 0.125); // 15/200
- frequencyMap.put(new TimedPark(), 0.025); // 5/200
- frequencyMap.put(new UnparkAllThreads(), 0.025); // 5/200
+ frequencyMap.put(new Sleep(), 0.125); // 25/200
frequencyMap.put(new TimedWait(lock), 0.05); // 10/200
frequencyMap.put(new Wait(lock), 0.075); // 15/200
frequencyMap.put(new QueuedWait(semaphore), 0.05); // 10/200
@@ -369,11 +341,9 @@
private final static Map<Operation, Double> createLockFrequencyMap(Object lock) {
Map<Operation, Double> frequencyMap = new HashMap<Operation, Double>();
frequencyMap.put(new Sleep(), 0.2); // 40/200
- frequencyMap.put(new TimedWait(lock), 0.1); // 20/200
- frequencyMap.put(new Wait(lock), 0.1); // 20/200
+ frequencyMap.put(new TimedWait(lock), 0.2); // 40/200
+ frequencyMap.put(new Wait(lock), 0.2); // 40/200
frequencyMap.put(new SyncAndWork(lock), 0.4); // 80/200
- frequencyMap.put(new TimedPark(), 0.1); // 20/200
- frequencyMap.put(new UnparkAllThreads(), 0.1); // 20/200
return frequencyMap;
}
diff --git a/test/913-heaps/expected.txt b/test/913-heaps/expected.txt
index 1bd56d1..065b854 100644
--- a/test/913-heaps/expected.txt
+++ b/test/913-heaps/expected.txt
@@ -1,9 +1,9 @@
---
true true
-root@root --(jni-local[id=1,tag=3000,depth=0,method=followReferences])--> 3000@0 [size=124, length=-1]
+root@root --(jni-local[id=1,tag=3000,depth=0,method=followReferences])--> 3000@0 [size=132, length=-1]
root@root --(stack-local[id=1,tag=3000,depth=2,method=doFollowReferencesTestNonRoot,vreg=8,location= 31])--> 1@1000 [size=16, length=-1]
-root@root --(stack-local[id=1,tag=3000,depth=5,method=run,vreg=2,location= 0])--> 3000@0 [size=124, length=-1]
-root@root --(thread)--> 3000@0 [size=124, length=-1]
+root@root --(stack-local[id=1,tag=3000,depth=5,method=run,vreg=2,location= 0])--> 3000@0 [size=132, length=-1]
+root@root --(thread)--> 3000@0 [size=132, length=-1]
1001@0 --(superclass)--> 1000@0 [size=123456780000, length=-1]
1002@0 --(interface)--> 2001@0 [size=123456780004, length=-1]
1002@0 --(superclass)--> 1001@0 [size=123456780001, length=-1]
@@ -44,14 +44,14 @@
---
root@root --(jni-global)--> 1@1000 [size=16, length=-1]
root@root --(jni-local[id=1,tag=3000,depth=0,method=followReferences])--> 1@1000 [size=16, length=-1]
-root@root --(jni-local[id=1,tag=3000,depth=0,method=followReferences])--> 3000@0 [size=124, length=-1]
+root@root --(jni-local[id=1,tag=3000,depth=0,method=followReferences])--> 3000@0 [size=132, length=-1]
root@root --(stack-local[id=1,tag=3000,depth=1,method=doFollowReferencesTestImpl,vreg=10,location= 8])--> 1@1000 [size=16, length=-1]
root@root --(stack-local[id=1,tag=3000,depth=1,method=doFollowReferencesTestImpl,vreg=5,location= 8])--> 1@1000 [size=16, length=-1]
root@root --(stack-local[id=1,tag=3000,depth=2,method=doFollowReferencesTestRoot,vreg=13,location= 20])--> 1@1000 [size=16, length=-1]
root@root --(stack-local[id=1,tag=3000,depth=2,method=doFollowReferencesTestRoot,vreg=4,location= 20])--> 1@1000 [size=16, length=-1]
-root@root --(stack-local[id=1,tag=3000,depth=5,method=run,vreg=2,location= 0])--> 3000@0 [size=124, length=-1]
+root@root --(stack-local[id=1,tag=3000,depth=5,method=run,vreg=2,location= 0])--> 3000@0 [size=132, length=-1]
root@root --(thread)--> 1@1000 [size=16, length=-1]
-root@root --(thread)--> 3000@0 [size=124, length=-1]
+root@root --(thread)--> 3000@0 [size=132, length=-1]
1001@0 --(superclass)--> 1000@0 [size=123456780005, length=-1]
1002@0 --(interface)--> 2001@0 [size=123456780009, length=-1]
1002@0 --(superclass)--> 1001@0 [size=123456780006, length=-1]
@@ -90,18 +90,18 @@
5@1002 --(field@9)--> 6@1000 [size=16, length=-1]
6@1000 --(class)--> 1000@0 [size=123456780005, length=-1]
---
-root@root --(thread)--> 3000@0 [size=124, length=-1]
+root@root --(thread)--> 3000@0 [size=132, length=-1]
---
3@1001 --(class)--> 1001@0 [size=123456780011, length=-1]
---
-root@root --(thread)--> 3000@0 [size=124, length=-1]
+root@root --(thread)--> 3000@0 [size=132, length=-1]
---
3@1001 --(class)--> 1001@0 [size=123456780016, length=-1]
---
-root@root --(jni-local[id=1,tag=3000,depth=0,method=followReferences])--> 3000@0 [size=124, length=-1]
+root@root --(jni-local[id=1,tag=3000,depth=0,method=followReferences])--> 3000@0 [size=132, length=-1]
root@root --(stack-local[id=1,tag=3000,depth=2,method=doFollowReferencesTestNonRoot,vreg=8,location= 31])--> 1@1000 [size=16, length=-1]
-root@root --(stack-local[id=1,tag=3000,depth=5,method=run,vreg=2,location= 0])--> 3000@0 [size=124, length=-1]
-root@root --(thread)--> 3000@0 [size=124, length=-1]
+root@root --(stack-local[id=1,tag=3000,depth=5,method=run,vreg=2,location= 0])--> 3000@0 [size=132, length=-1]
+root@root --(thread)--> 3000@0 [size=132, length=-1]
---
1001@0 --(superclass)--> 1000@0 [size=123456780020, length=-1]
3@1001 --(class)--> 1001@0 [size=123456780021, length=-1]
@@ -110,14 +110,14 @@
---
root@root --(jni-global)--> 1@1000 [size=16, length=-1]
root@root --(jni-local[id=1,tag=3000,depth=0,method=followReferences])--> 1@1000 [size=16, length=-1]
-root@root --(jni-local[id=1,tag=3000,depth=0,method=followReferences])--> 3000@0 [size=124, length=-1]
+root@root --(jni-local[id=1,tag=3000,depth=0,method=followReferences])--> 3000@0 [size=132, length=-1]
root@root --(stack-local[id=1,tag=3000,depth=1,method=doFollowReferencesTestImpl,vreg=10,location= 8])--> 1@1000 [size=16, length=-1]
root@root --(stack-local[id=1,tag=3000,depth=1,method=doFollowReferencesTestImpl,vreg=5,location= 8])--> 1@1000 [size=16, length=-1]
root@root --(stack-local[id=1,tag=3000,depth=2,method=doFollowReferencesTestRoot,vreg=13,location= 20])--> 1@1000 [size=16, length=-1]
root@root --(stack-local[id=1,tag=3000,depth=2,method=doFollowReferencesTestRoot,vreg=4,location= 20])--> 1@1000 [size=16, length=-1]
-root@root --(stack-local[id=1,tag=3000,depth=5,method=run,vreg=2,location= 0])--> 3000@0 [size=124, length=-1]
+root@root --(stack-local[id=1,tag=3000,depth=5,method=run,vreg=2,location= 0])--> 3000@0 [size=132, length=-1]
root@root --(thread)--> 1@1000 [size=16, length=-1]
-root@root --(thread)--> 3000@0 [size=124, length=-1]
+root@root --(thread)--> 3000@0 [size=132, length=-1]
---
1001@0 --(superclass)--> 1000@0 [size=123456780025, length=-1]
3@1001 --(class)--> 1001@0 [size=123456780026, length=-1]
@@ -198,10 +198,10 @@
---
---
---- untagged objects
-root@root --(jni-local[id=1,tag=3000,depth=0,method=followReferences])--> 3000@0 [size=124, length=-1]
+root@root --(jni-local[id=1,tag=3000,depth=0,method=followReferences])--> 3000@0 [size=132, length=-1]
root@root --(stack-local[id=1,tag=3000,depth=2,method=doFollowReferencesTestNonRoot,vreg=8,location= 31])--> 1@1000 [size=16, length=-1]
-root@root --(stack-local[id=1,tag=3000,depth=5,method=run,vreg=2,location= 0])--> 3000@0 [size=124, length=-1]
-root@root --(thread)--> 3000@0 [size=124, length=-1]
+root@root --(stack-local[id=1,tag=3000,depth=5,method=run,vreg=2,location= 0])--> 3000@0 [size=132, length=-1]
+root@root --(thread)--> 3000@0 [size=132, length=-1]
1001@0 --(superclass)--> 1000@0 [size=123456780050, length=-1]
1002@0 --(interface)--> 2001@0 [size=123456780054, length=-1]
1002@0 --(superclass)--> 1001@0 [size=123456780051, length=-1]
@@ -242,14 +242,14 @@
---
root@root --(jni-global)--> 1@1000 [size=16, length=-1]
root@root --(jni-local[id=1,tag=3000,depth=0,method=followReferences])--> 1@1000 [size=16, length=-1]
-root@root --(jni-local[id=1,tag=3000,depth=0,method=followReferences])--> 3000@0 [size=124, length=-1]
+root@root --(jni-local[id=1,tag=3000,depth=0,method=followReferences])--> 3000@0 [size=132, length=-1]
root@root --(stack-local[id=1,tag=3000,depth=1,method=doFollowReferencesTestImpl,vreg=10,location= 8])--> 1@1000 [size=16, length=-1]
root@root --(stack-local[id=1,tag=3000,depth=1,method=doFollowReferencesTestImpl,vreg=5,location= 8])--> 1@1000 [size=16, length=-1]
root@root --(stack-local[id=1,tag=3000,depth=2,method=doFollowReferencesTestRoot,vreg=13,location= 20])--> 1@1000 [size=16, length=-1]
root@root --(stack-local[id=1,tag=3000,depth=2,method=doFollowReferencesTestRoot,vreg=4,location= 20])--> 1@1000 [size=16, length=-1]
-root@root --(stack-local[id=1,tag=3000,depth=5,method=run,vreg=2,location= 0])--> 3000@0 [size=124, length=-1]
+root@root --(stack-local[id=1,tag=3000,depth=5,method=run,vreg=2,location= 0])--> 3000@0 [size=132, length=-1]
root@root --(thread)--> 1@1000 [size=16, length=-1]
-root@root --(thread)--> 3000@0 [size=124, length=-1]
+root@root --(thread)--> 3000@0 [size=132, length=-1]
1001@0 --(superclass)--> 1000@0 [size=123456780055, length=-1]
1002@0 --(interface)--> 2001@0 [size=123456780059, length=-1]
1002@0 --(superclass)--> 1001@0 [size=123456780056, length=-1]
@@ -289,9 +289,9 @@
6@1000 --(class)--> 1000@0 [size=123456780055, length=-1]
---
---- tagged classes
-root@root --(jni-local[id=1,tag=3000,depth=0,method=followReferences])--> 3000@0 [size=124, length=-1]
-root@root --(stack-local[id=1,tag=3000,depth=5,method=run,vreg=2,location= 0])--> 3000@0 [size=124, length=-1]
-root@root --(thread)--> 3000@0 [size=124, length=-1]
+root@root --(jni-local[id=1,tag=3000,depth=0,method=followReferences])--> 3000@0 [size=132, length=-1]
+root@root --(stack-local[id=1,tag=3000,depth=5,method=run,vreg=2,location= 0])--> 3000@0 [size=132, length=-1]
+root@root --(thread)--> 3000@0 [size=132, length=-1]
1001@0 --(superclass)--> 1000@0 [size=123456780060, length=-1]
1002@0 --(interface)--> 2001@0 [size=123456780064, length=-1]
1002@0 --(superclass)--> 1001@0 [size=123456780061, length=-1]
@@ -316,9 +316,9 @@
5@1002 --(field@8)--> 500@0 [size=20, length=2]
6@1000 --(class)--> 1000@0 [size=123456780060, length=-1]
---
-root@root --(jni-local[id=1,tag=3000,depth=0,method=followReferences])--> 3000@0 [size=124, length=-1]
-root@root --(stack-local[id=1,tag=3000,depth=5,method=run,vreg=2,location= 0])--> 3000@0 [size=124, length=-1]
-root@root --(thread)--> 3000@0 [size=124, length=-1]
+root@root --(jni-local[id=1,tag=3000,depth=0,method=followReferences])--> 3000@0 [size=132, length=-1]
+root@root --(stack-local[id=1,tag=3000,depth=5,method=run,vreg=2,location= 0])--> 3000@0 [size=132, length=-1]
+root@root --(thread)--> 3000@0 [size=132, length=-1]
1001@0 --(superclass)--> 1000@0 [size=123456780065, length=-1]
1002@0 --(interface)--> 2001@0 [size=123456780069, length=-1]
1002@0 --(superclass)--> 1001@0 [size=123456780066, length=-1]