diff options
author | 2018-10-05 23:42:12 +0000 | |
---|---|---|
committer | 2018-10-08 13:18:35 -0700 | |
commit | 1c7b1fcf0ff29d83d13d38d0451a54474ccf5964 (patch) | |
tree | b978817acd252f10bd4648d3582ac9459fc9a0f4 /openjdkjvmti/ti_stack.cc | |
parent | 59b950f53152c169464ba8c63d44102eeba1e594 (diff) |
Revert^2 "JVMTI PopFrame support"
This reverts commit f67d0cbf2743b29aa6e1be7ae2f71762b8762785.
Redefine-stress causes classes to be loaded at slightly different
places due to the deep verification needed to redefine a class. This
would cause the parts of tests 1953 and 1954 to fail due to classes
loading at unexpected times. We changed the test to skip these
test-cases when they cannot be correctly executed.
Reason for revert: Fixed issue causing tests to fail under
redefine-stress
Test: ./test.py --host
Test: ./art/tools/run-libjdwp-tests.sh --mode=host
Test: ./test/testrunner/testrunner.py --host --redefine-stress
Bug: 73255278
Bug: 111357976
Change-Id: I46fb4aed878bcc9398f2b73ad5040d7c97aec3ef
Diffstat (limited to 'openjdkjvmti/ti_stack.cc')
-rw-r--r-- | openjdkjvmti/ti_stack.cc | 100 |
1 files changed, 90 insertions, 10 deletions
diff --git a/openjdkjvmti/ti_stack.cc b/openjdkjvmti/ti_stack.cc index 220ad22be5..3ba5d3a316 100644 --- a/openjdkjvmti/ti_stack.cc +++ b/openjdkjvmti/ti_stack.cc @@ -112,6 +112,23 @@ struct GetStackTraceVisitor : public art::StackVisitor { size_t stop; }; +art::ShadowFrame* FindFrameAtDepthVisitor::GetOrCreateShadowFrame(bool* created_frame) { + art::ShadowFrame* cur = GetCurrentShadowFrame(); + if (cur == nullptr) { + *created_frame = true; + art::ArtMethod* method = GetMethod(); + const uint16_t num_regs = method->DexInstructionData().RegistersSize(); + cur = GetThread()->FindOrCreateDebuggerShadowFrame(GetFrameId(), + num_regs, + method, + GetDexPc()); + DCHECK(cur != nullptr); + } else { + *created_frame = false; + } + return cur; +} + template <typename FrameFn> GetStackTraceVisitor<FrameFn> MakeStackTraceVisitor(art::Thread* thread_in, size_t start, @@ -1065,16 +1082,7 @@ jvmtiError StackUtil::NotifyFramePop(jvmtiEnv* env, jthread thread, jint depth) // From here we are sure to succeed. bool needs_instrument = false; // Get/create a shadow frame - art::ShadowFrame* shadow_frame = visitor.GetCurrentShadowFrame(); - if (shadow_frame == nullptr) { - needs_instrument = true; - const size_t frame_id = visitor.GetFrameId(); - const uint16_t num_regs = method->DexInstructionData().RegistersSize(); - shadow_frame = target->FindOrCreateDebuggerShadowFrame(frame_id, - num_regs, - method, - visitor.GetDexPc()); - } + art::ShadowFrame* shadow_frame = visitor.GetOrCreateShadowFrame(&needs_instrument); { art::WriterMutexLock lk(self, tienv->event_info_mutex_); // Mark shadow frame as needs_notify_pop_ @@ -1089,4 +1097,76 @@ jvmtiError StackUtil::NotifyFramePop(jvmtiEnv* env, jthread thread, jint depth) } while (true); } +jvmtiError StackUtil::PopFrame(jvmtiEnv* env ATTRIBUTE_UNUSED, jthread thread) { + art::Thread* self = art::Thread::Current(); + art::Thread* target; + do { + ThreadUtil::SuspendCheck(self); + art::MutexLock ucsl_mu(self, *art::Locks::user_code_suspension_lock_); + // Make sure we won't be suspended in the middle of holding the thread_suspend_count_lock_ by a + // user-code suspension. We retry and do another SuspendCheck to clear this. + if (ThreadUtil::WouldSuspendForUserCodeLocked(self)) { + continue; + } + // From now on we know we cannot get suspended by user-code. + // NB This does a SuspendCheck (during thread state change) so we need to make sure we don't + // have the 'suspend_lock' locked here. + art::ScopedObjectAccess soa(self); + art::MutexLock tll_mu(self, *art::Locks::thread_list_lock_); + jvmtiError err = ERR(INTERNAL); + if (!ThreadUtil::GetAliveNativeThread(thread, soa, &target, &err)) { + return err; + } + { + art::MutexLock tscl_mu(self, *art::Locks::thread_suspend_count_lock_); + if (target == self || target->GetUserCodeSuspendCount() == 0) { + // We cannot be the current thread for this function. + return ERR(THREAD_NOT_SUSPENDED); + } + } + // We hold the user_code_suspension_lock_ so the target thread is staying suspended until we are + // done. + std::unique_ptr<art::Context> context(art::Context::Create()); + FindFrameAtDepthVisitor final_frame(target, context.get(), 0); + FindFrameAtDepthVisitor penultimate_frame(target, context.get(), 1); + final_frame.WalkStack(); + penultimate_frame.WalkStack(); + + if (!final_frame.FoundFrame() || !penultimate_frame.FoundFrame()) { + // Cannot do it if there is only one frame! + return ERR(NO_MORE_FRAMES); + } + + art::ArtMethod* called_method = final_frame.GetMethod(); + art::ArtMethod* calling_method = penultimate_frame.GetMethod(); + if (calling_method->IsNative() || called_method->IsNative()) { + return ERR(OPAQUE_FRAME); + } + // From here we are sure to succeed. + + // Get/create a shadow frame + bool created_final_frame = false; + bool created_penultimate_frame = false; + art::ShadowFrame* called_shadow_frame = + final_frame.GetOrCreateShadowFrame(&created_final_frame); + art::ShadowFrame* calling_shadow_frame = + penultimate_frame.GetOrCreateShadowFrame(&created_penultimate_frame); + + bool needs_instrument = created_penultimate_frame || created_final_frame; + + CHECK_NE(called_shadow_frame, calling_shadow_frame) + << "Frames at different depths not different!"; + + // Tell the shadow-frame to return immediately and skip all exit events. + called_shadow_frame->SetForcePopFrame(true); + calling_shadow_frame->SetForceRetryInstruction(true); + + // Make sure can we will go to the interpreter and use the shadow frames. + if (needs_instrument) { + art::Runtime::Current()->GetInstrumentation()->InstrumentThreadStack(target); + } + return OK; + } while (true); +} + } // namespace openjdkjvmti |