diff options
-rw-r--r-- | runtime/native/sun_misc_Unsafe.cc | 31 | ||||
-rw-r--r-- | runtime/thread.cc | 142 | ||||
-rw-r--r-- | runtime/thread.h | 7 | ||||
-rw-r--r-- | runtime/well_known_classes.cc | 2 | ||||
-rw-r--r-- | runtime/well_known_classes.h | 1 | ||||
-rw-r--r-- | test/004-ThreadStress/src-art/Main.java | 36 | ||||
-rw-r--r-- | test/913-heaps/expected.txt | 52 |
7 files changed, 34 insertions, 237 deletions
diff --git a/runtime/native/sun_misc_Unsafe.cc b/runtime/native/sun_misc_Unsafe.cc index a739c2d16e..e021b77dae 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 @@ static void Unsafe_fullFence(JNIEnv*, jobject) { 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 @@ static JNINativeMethod gMethods[] = { 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 4291709fb0..b5d214def4 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" @@ -286,115 +285,6 @@ void Thread::AssertHasDeoptimizationContext() { << "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); @@ -599,22 +489,6 @@ void* Thread::CreateCallback(void* arg) { 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; @@ -2259,9 +2133,6 @@ Thread::Thread(bool daemon) 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, @@ -2578,15 +2449,12 @@ bool Thread::IsInterrupted() { } 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 b304cef74d..941867ce2d 100644 --- a/runtime/thread.h +++ b/runtime/thread.h @@ -581,11 +581,6 @@ class Thread { 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_); @@ -1548,8 +1543,6 @@ class Thread { // 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 94faa626f6..206418fbc6 100644 --- a/runtime/well_known_classes.cc +++ b/runtime/well_known_classes.cc @@ -128,7 +128,6 @@ jfieldID WellKnownClasses::java_lang_Thread_lock; 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 @@ void WellKnownClasses::Init(JNIEnv* env) { 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 8c85228dfc..ce5ab1df84 100644 --- a/runtime/well_known_classes.h +++ b/runtime/well_known_classes.h @@ -137,7 +137,6 @@ struct WellKnownClasses { 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 b8bfafb2d3..3a89f4f166 100644 --- a/test/004-ThreadStress/src-art/Main.java +++ b/test/004-ThreadStress/src-art/Main.java @@ -26,7 +26,6 @@ import java.util.List; 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 @@ public class Main implements Runnable { } } - 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 @@ public class Main implements Runnable { 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 @@ public class Main implements Runnable { 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 1bd56d1a53..065b854a6a 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 --(thread)--> 3000@0 [size=124, length=-1] --- 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 @@ root@root --(thread)--> 3000@0 [size=124, length=-1] 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 --(thread)--> 3000@0 [size=124, length=-1] --- 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 @@ root@root --(thread)--> 1@1000 [size=16, length=-1] --- --- ---- 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 --(thread)--> 3000@0 [size=124, length=-1] --- 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 @@ root@root --(thread)--> 3000@0 [size=124, length=-1] 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 @@ root@root --(thread)--> 3000@0 [size=124, length=-1] 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] |