From 1c7b1fcf0ff29d83d13d38d0451a54474ccf5964 Mon Sep 17 00:00:00 2001 From: Alex Light Date: Fri, 5 Oct 2018 23:42:12 +0000 Subject: 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 --- runtime/interpreter/interpreter_switch_impl.cc | 118 +++++++++++++++++++------ 1 file changed, 91 insertions(+), 27 deletions(-) (limited to 'runtime/interpreter/interpreter_switch_impl.cc') diff --git a/runtime/interpreter/interpreter_switch_impl.cc b/runtime/interpreter/interpreter_switch_impl.cc index 04935cfe42..cb64ff402a 100644 --- a/runtime/interpreter/interpreter_switch_impl.cc +++ b/runtime/interpreter/interpreter_switch_impl.cc @@ -24,16 +24,39 @@ #include "interpreter_common.h" #include "jit/jit.h" #include "jvalue-inl.h" +#include "nth_caller_visitor.h" #include "safe_math.h" #include "shadow_frame-inl.h" +#include "thread.h" namespace art { namespace interpreter { +#define CHECK_FORCE_RETURN() \ + do { \ + if (UNLIKELY(shadow_frame.GetForcePopFrame())) { \ + DCHECK(PrevFrameWillRetry(self, shadow_frame)) \ + << "Pop frame forced without previous frame ready to retry instruction!"; \ + DCHECK(Runtime::Current()->AreNonStandardExitsEnabled()); \ + if (UNLIKELY(NeedsMethodExitEvent(instrumentation))) { \ + SendMethodExitEvents(self, \ + instrumentation, \ + shadow_frame, \ + shadow_frame.GetThisObject(accessor.InsSize()), \ + shadow_frame.GetMethod(), \ + inst->GetDexPc(insns), \ + JValue()); \ + } \ + ctx->result = JValue(); /* Handled in caller. */ \ + return; \ + } \ + } while (false) + #define HANDLE_PENDING_EXCEPTION_WITH_INSTRUMENTATION(instr) \ do { \ DCHECK(self->IsExceptionPending()); \ self->AllowThreadSuspension(); \ + CHECK_FORCE_RETURN(); \ if (!MoveToExceptionHandler(self, shadow_frame, instr)) { \ /* Structured locking is to be enforced for abnormal termination, too. */ \ DoMonitorCheckOnExit(self, &shadow_frame); \ @@ -44,6 +67,7 @@ namespace interpreter { ctx->result = JValue(); /* Handled in caller. */ \ return; \ } else { \ + CHECK_FORCE_RETURN(); \ int32_t displacement = \ static_cast(shadow_frame.GetDexPC()) - static_cast(dex_pc); \ inst = inst->RelativeAt(displacement); \ @@ -52,8 +76,39 @@ namespace interpreter { #define HANDLE_PENDING_EXCEPTION() HANDLE_PENDING_EXCEPTION_WITH_INSTRUMENTATION(instrumentation) +#define POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE_IMPL(_is_exception_pending, _next_function) \ + do { \ + if (UNLIKELY(shadow_frame.GetForceRetryInstruction())) { \ + /* Don't need to do anything except clear the flag and exception. We leave the */ \ + /* instruction the same so it will be re-executed on the next go-around. */ \ + DCHECK(inst->IsInvoke()); \ + shadow_frame.SetForceRetryInstruction(false); \ + if (UNLIKELY(_is_exception_pending)) { \ + DCHECK(self->IsExceptionPending()); \ + if (kIsDebugBuild) { \ + LOG(WARNING) << "Suppressing exception for instruction-retry: " \ + << self->GetException()->Dump(); \ + } \ + self->ClearException(); \ + } \ + } else if (UNLIKELY(_is_exception_pending)) { \ + /* Should have succeeded. */ \ + DCHECK(!shadow_frame.GetForceRetryInstruction()); \ + HANDLE_PENDING_EXCEPTION(); \ + } else { \ + inst = inst->_next_function(); \ + } \ + } while (false) + +#define POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE_POLYMORPHIC(_is_exception_pending) \ + POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE_IMPL(_is_exception_pending, Next_4xx) +#define POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(_is_exception_pending) \ + POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE_IMPL(_is_exception_pending, Next_3xx) + #define POSSIBLY_HANDLE_PENDING_EXCEPTION(_is_exception_pending, _next_function) \ do { \ + /* Should only be on invoke instructions. */ \ + DCHECK(!shadow_frame.GetForceRetryInstruction()); \ if (UNLIKELY(_is_exception_pending)) { \ HANDLE_PENDING_EXCEPTION(); \ } else { \ @@ -67,17 +122,22 @@ namespace interpreter { } // Code to run before each dex instruction. -#define PREAMBLE_SAVE(save_ref) \ +#define PREAMBLE_SAVE(save_ref) \ { \ - if (UNLIKELY(instrumentation->HasDexPcListeners()) && \ - UNLIKELY(!DoDexPcMoveEvent(self, \ - accessor, \ - shadow_frame, \ - dex_pc, \ - instrumentation, \ - save_ref))) { \ - HANDLE_PENDING_EXCEPTION(); \ - break; \ + /* We need to put this before & after the instrumentation to avoid having to put in a */ \ + /* post-script macro. */ \ + CHECK_FORCE_RETURN(); \ + if (UNLIKELY(instrumentation->HasDexPcListeners())) { \ + if (UNLIKELY(!DoDexPcMoveEvent(self, \ + accessor, \ + shadow_frame, \ + dex_pc, \ + instrumentation, \ + save_ref))) { \ + HANDLE_PENDING_EXCEPTION(); \ + break; \ + } \ + CHECK_FORCE_RETURN(); \ } \ } \ do {} while (false) @@ -181,7 +241,8 @@ NO_INLINE static bool SendMethodExitEvents(Thread* self, const JValue& result) REQUIRES_SHARED(Locks::mutator_lock_) { bool had_event = false; - if (UNLIKELY(instrumentation->HasMethodExitListeners())) { + // We don't send method-exit if it's a pop-frame. We still send frame_popped though. + if (UNLIKELY(instrumentation->HasMethodExitListeners() && !frame.GetForcePopFrame())) { had_event = true; instrumentation->MethodExitEvent(self, thiz.Ptr(), method, dex_pc, result); } @@ -221,6 +282,9 @@ ATTRIBUTE_NO_SANITIZE_ADDRESS void ExecuteSwitchImplCpp(SwitchImplContext* ctx) uint16_t inst_data; jit::Jit* jit = Runtime::Current()->GetJit(); + DCHECK(!shadow_frame.GetForceRetryInstruction()) + << "Entered interpreter from invoke without retry instruction being handled!"; + do { dex_pc = inst->GetDexPc(insns); shadow_frame.SetDexPC(dex_pc); @@ -1607,84 +1671,84 @@ ATTRIBUTE_NO_SANITIZE_ADDRESS void ExecuteSwitchImplCpp(SwitchImplContext* ctx) PREAMBLE(); bool success = DoInvoke( self, shadow_frame, inst, inst_data, &result_register); - POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_3xx); + POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success); break; } case Instruction::INVOKE_VIRTUAL_RANGE: { PREAMBLE(); bool success = DoInvoke( self, shadow_frame, inst, inst_data, &result_register); - POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_3xx); + POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success); break; } case Instruction::INVOKE_SUPER: { PREAMBLE(); bool success = DoInvoke( self, shadow_frame, inst, inst_data, &result_register); - POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_3xx); + POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success); break; } case Instruction::INVOKE_SUPER_RANGE: { PREAMBLE(); bool success = DoInvoke( self, shadow_frame, inst, inst_data, &result_register); - POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_3xx); + POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success); break; } case Instruction::INVOKE_DIRECT: { PREAMBLE(); bool success = DoInvoke( self, shadow_frame, inst, inst_data, &result_register); - POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_3xx); + POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success); break; } case Instruction::INVOKE_DIRECT_RANGE: { PREAMBLE(); bool success = DoInvoke( self, shadow_frame, inst, inst_data, &result_register); - POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_3xx); + POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success); break; } case Instruction::INVOKE_INTERFACE: { PREAMBLE(); bool success = DoInvoke( self, shadow_frame, inst, inst_data, &result_register); - POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_3xx); + POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success); break; } case Instruction::INVOKE_INTERFACE_RANGE: { PREAMBLE(); bool success = DoInvoke( self, shadow_frame, inst, inst_data, &result_register); - POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_3xx); + POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success); break; } case Instruction::INVOKE_STATIC: { PREAMBLE(); bool success = DoInvoke( self, shadow_frame, inst, inst_data, &result_register); - POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_3xx); + POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success); break; } case Instruction::INVOKE_STATIC_RANGE: { PREAMBLE(); bool success = DoInvoke( self, shadow_frame, inst, inst_data, &result_register); - POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_3xx); + POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success); break; } case Instruction::INVOKE_VIRTUAL_QUICK: { PREAMBLE(); bool success = DoInvokeVirtualQuick( self, shadow_frame, inst, inst_data, &result_register); - POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_3xx); + POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success); break; } case Instruction::INVOKE_VIRTUAL_RANGE_QUICK: { PREAMBLE(); bool success = DoInvokeVirtualQuick( self, shadow_frame, inst, inst_data, &result_register); - POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_3xx); + POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success); break; } case Instruction::INVOKE_POLYMORPHIC: { @@ -1692,7 +1756,7 @@ ATTRIBUTE_NO_SANITIZE_ADDRESS void ExecuteSwitchImplCpp(SwitchImplContext* ctx) DCHECK(Runtime::Current()->IsMethodHandlesEnabled()); bool success = DoInvokePolymorphic( self, shadow_frame, inst, inst_data, &result_register); - POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_4xx); + POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE_POLYMORPHIC(!success); break; } case Instruction::INVOKE_POLYMORPHIC_RANGE: { @@ -1700,7 +1764,7 @@ ATTRIBUTE_NO_SANITIZE_ADDRESS void ExecuteSwitchImplCpp(SwitchImplContext* ctx) DCHECK(Runtime::Current()->IsMethodHandlesEnabled()); bool success = DoInvokePolymorphic( self, shadow_frame, inst, inst_data, &result_register); - POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_4xx); + POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE_POLYMORPHIC(!success); break; } case Instruction::INVOKE_CUSTOM: { @@ -1708,7 +1772,7 @@ ATTRIBUTE_NO_SANITIZE_ADDRESS void ExecuteSwitchImplCpp(SwitchImplContext* ctx) DCHECK(Runtime::Current()->IsMethodHandlesEnabled()); bool success = DoInvokeCustom( self, shadow_frame, inst, inst_data, &result_register); - POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_3xx); + POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success); break; } case Instruction::INVOKE_CUSTOM_RANGE: { @@ -1716,7 +1780,7 @@ ATTRIBUTE_NO_SANITIZE_ADDRESS void ExecuteSwitchImplCpp(SwitchImplContext* ctx) DCHECK(Runtime::Current()->IsMethodHandlesEnabled()); bool success = DoInvokeCustom( self, shadow_frame, inst, inst_data, &result_register); - POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_3xx); + POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success); break; } case Instruction::NEG_INT: -- cgit v1.2.3-59-g8ed1b