summaryrefslogtreecommitdiff
path: root/runtime/interpreter/interpreter_switch_impl-inl.h
diff options
context:
space:
mode:
author Vladimir Marko <vmarko@google.com> 2024-05-21 09:08:32 +0000
committer VladimĂ­r Marko <vmarko@google.com> 2024-05-22 13:07:23 +0000
commita11d8246f846148c83bbcbbe39511c460cc0319a (patch)
treec68e33f67340e7872086993c1124cfc87d875be3 /runtime/interpreter/interpreter_switch_impl-inl.h
parentd3f3b2b2790f773c6281730802f52f894d800384 (diff)
Refactor instrumentation handling in interpreter.
The transactional interpreter does not need to check for instrumentation events. Also change `PerformNonStandartReturn()` which is used only for unusual code paths (only for instrumentation and aborted transactions) from `ALWAYS_INLINE` to non-inline and remove some dead code from it. Test: m test-art-host-gtest Test: testrunner.py --host --optimizing --interp-ac Change-Id: I2b00c82eac480dd3291f2c7cd68430e606804eaf
Diffstat (limited to 'runtime/interpreter/interpreter_switch_impl-inl.h')
-rw-r--r--runtime/interpreter/interpreter_switch_impl-inl.h113
1 files changed, 45 insertions, 68 deletions
diff --git a/runtime/interpreter/interpreter_switch_impl-inl.h b/runtime/interpreter/interpreter_switch_impl-inl.h
index 35708b00c6..222f3775bc 100644
--- a/runtime/interpreter/interpreter_switch_impl-inl.h
+++ b/runtime/interpreter/interpreter_switch_impl-inl.h
@@ -49,6 +49,11 @@ namespace interpreter {
class ActiveTransactionChecker; // For transactional interpreter.
class InactiveTransactionChecker; // For non-transactional interpreter.
+// We declare the helpers classes for instrumentation handling here but they shall be defined
+// only when compiling the transactional and non-transactional interpreter.
+class ActiveInstrumentationHandler; // For non-transactional interpreter.
+class InactiveInstrumentationHandler; // For transactional interpreter.
+
// Handles iget-XXX and sget-XXX instructions.
// Returns true on success, otherwise throws an exception and returns false.
template<FindFieldType find_type,
@@ -57,9 +62,13 @@ template<FindFieldType find_type,
ALWAYS_INLINE bool DoFieldGet(Thread* self,
ShadowFrame& shadow_frame,
const Instruction* inst,
- uint16_t inst_data) REQUIRES_SHARED(Locks::mutator_lock_) {
+ uint16_t inst_data,
+ const instrumentation::Instrumentation* instrumentation)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ using InstrumentationHandler = typename std::conditional_t<
+ transaction_active, InactiveInstrumentationHandler, ActiveInstrumentationHandler>;
+ bool should_report = InstrumentationHandler::HasFieldReadListeners(instrumentation);
const bool is_static = (find_type == StaticObjectRead) || (find_type == StaticPrimitiveRead);
- bool should_report = Runtime::Current()->GetInstrumentation()->HasFieldReadListeners();
ArtField* field = nullptr;
MemberOffset offset(0u);
bool is_volatile;
@@ -150,9 +159,12 @@ template<FindFieldType find_type, Primitive::Type field_type, bool transaction_a
ALWAYS_INLINE bool DoFieldPut(Thread* self,
const ShadowFrame& shadow_frame,
const Instruction* inst,
- uint16_t inst_data)
+ uint16_t inst_data,
+ const instrumentation::Instrumentation* instrumentation)
REQUIRES_SHARED(Locks::mutator_lock_) {
- bool should_report = Runtime::Current()->GetInstrumentation()->HasFieldWriteListeners();
+ using InstrumentationHandler = typename std::conditional_t<
+ transaction_active, InactiveInstrumentationHandler, ActiveInstrumentationHandler>;
+ bool should_report = InstrumentationHandler::HasFieldWriteListeners(instrumentation);
bool is_static = (find_type == StaticObjectWrite) || (find_type == StaticPrimitiveWrite);
uint32_t vregA = is_static ? inst->VRegA_21c(inst_data) : inst->VRegA_22c(inst_data);
bool resolve_field_type = (shadow_frame.GetVRegReference(vregA) != nullptr);
@@ -254,6 +266,8 @@ ALWAYS_INLINE bool DoFieldPut(Thread* self,
template<bool transaction_active, Instruction::Format kFormat>
class InstructionHandler {
public:
+ using InstrumentationHandler = typename std::conditional_t<
+ transaction_active, InactiveInstrumentationHandler, ActiveInstrumentationHandler>;
using TransactionChecker = typename std::conditional_t<
transaction_active, ActiveTransactionChecker, InactiveTransactionChecker>;
@@ -268,8 +282,7 @@ class InstructionHandler {
DCHECK(abort_exception != nullptr);
DCHECK(abort_exception->GetClass()->DescriptorEquals(kTransactionAbortErrorDescriptor));
Self()->ClearException();
- PerformNonStandardReturn(
- Self(), shadow_frame_, ctx_->result, Instrumentation(), Accessor().InsSize());
+ PerformNonStandardReturn(Self(), shadow_frame_, ctx_->result, Instrumentation());
Self()->SetException(abort_exception.Get());
ExitInterpreterLoop();
return false;
@@ -278,10 +291,9 @@ class InstructionHandler {
}
HANDLER_ATTRIBUTES bool CheckForceReturn() {
- if (shadow_frame_.GetForcePopFrame()) {
+ if (InstrumentationHandler::GetForcePopFrame(shadow_frame_)) {
DCHECK(Runtime::Current()->AreNonStandardExitsEnabled());
- PerformNonStandardReturn(
- Self(), shadow_frame_, ctx_->result, Instrumentation(), Accessor().InsSize());
+ PerformNonStandardReturn(Self(), shadow_frame_, ctx_->result, Instrumentation());
ExitInterpreterLoop();
return false;
}
@@ -348,16 +360,16 @@ class InstructionHandler {
if (!CheckForceReturn()) {
return false;
}
- if (UNLIKELY(shadow_frame_.GetNotifyDexPcMoveEvents())) {
+ if (UNLIKELY(InstrumentationHandler::NeedsDexPcEvents(shadow_frame_))) {
uint8_t opcode = inst_->Opcode(inst_data_);
bool is_move_result_object = (opcode == Instruction::MOVE_RESULT_OBJECT);
JValue* save_ref = is_move_result_object ? &ctx_->result_register : nullptr;
- if (UNLIKELY(!DoDexPcMoveEvent(Self(),
- Accessor(),
- shadow_frame_,
- DexPC(),
- Instrumentation(),
- save_ref))) {
+ if (UNLIKELY(!InstrumentationHandler::DoDexPcMoveEvent(Self(),
+ Accessor(),
+ shadow_frame_,
+ DexPC(),
+ Instrumentation(),
+ save_ref))) {
DCHECK(Self()->IsExceptionPending());
// Do not raise exception event if it is caused by other instrumentation event.
shadow_frame_.SetSkipNextExceptionEvent(true);
@@ -370,53 +382,17 @@ class InstructionHandler {
return true;
}
- // Unlike most other events the DexPcMovedEvent can be sent when there is a pending exception (if
- // the next instruction is MOVE_EXCEPTION). This means it needs to be handled carefully to be able
- // to detect exceptions thrown by the DexPcMovedEvent itself. These exceptions could be thrown by
- // jvmti-agents while handling breakpoint or single step events. We had to move this into its own
- // function because it was making ExecuteSwitchImpl have too large a stack.
- NO_INLINE static bool DoDexPcMoveEvent(Thread* self,
- const CodeItemDataAccessor& accessor,
- const ShadowFrame& shadow_frame,
- uint32_t dex_pc_,
- const instrumentation::Instrumentation* instrumentation,
- JValue* save_ref)
- REQUIRES_SHARED(Locks::mutator_lock_) {
- DCHECK(instrumentation->HasDexPcListeners());
- StackHandleScope<2> hs(self);
- Handle<mirror::Throwable> thr(hs.NewHandle(self->GetException()));
- mirror::Object* null_obj = nullptr;
- HandleWrapper<mirror::Object> h(
- hs.NewHandleWrapper(LIKELY(save_ref == nullptr) ? &null_obj : save_ref->GetGCRoot()));
- self->ClearException();
- instrumentation->DexPcMovedEvent(self,
- shadow_frame.GetThisObject(accessor.InsSize()),
- shadow_frame.GetMethod(),
- dex_pc_);
- if (UNLIKELY(self->IsExceptionPending())) {
- // We got a new exception in the dex-pc-moved event.
- // We just let this exception replace the old one.
- // TODO It would be good to add the old exception to the
- // suppressed exceptions of the new one if possible.
- return false; // Pending exception.
- }
- if (UNLIKELY(!thr.IsNull())) {
- self->SetException(thr.Get());
- }
- return true;
- }
-
HANDLER_ATTRIBUTES bool HandleReturn(JValue result) {
Self()->AllowThreadSuspension();
if (!DoMonitorCheckOnExit(Self(), &shadow_frame_)) {
return false;
}
- if (UNLIKELY(NeedsMethodExitEvent(Instrumentation()) &&
- !SendMethodExitEvents(Self(),
- Instrumentation(),
- shadow_frame_,
- shadow_frame_.GetMethod(),
- result))) {
+ if (UNLIKELY(InstrumentationHandler::NeedsMethodExitEvent(Instrumentation()) &&
+ !InstrumentationHandler::SendMethodExitEvents(Self(),
+ Instrumentation(),
+ shadow_frame_,
+ shadow_frame_.GetMethod(),
+ result))) {
DCHECK(Self()->IsExceptionPending());
// Do not raise exception event if it is caused by other instrumentation event.
shadow_frame_.SetSkipNextExceptionEvent(true);
@@ -431,8 +407,9 @@ class InstructionHandler {
if (UNLIKELY(Self()->ObserveAsyncException())) {
return false; // Pending exception.
}
- if (UNLIKELY(Instrumentation()->HasBranchListeners())) {
- Instrumentation()->Branch(Self(), shadow_frame_.GetMethod(), DexPC(), offset);
+ if (UNLIKELY(InstrumentationHandler::HasBranchListeners(Instrumentation()))) {
+ InstrumentationHandler::Branch(
+ Self(), shadow_frame_.GetMethod(), DexPC(), offset, Instrumentation());
}
if (!transaction_active) {
// TODO: Do OSR only on back-edges and check if OSR code is ready here.
@@ -546,13 +523,13 @@ class InstructionHandler {
template<FindFieldType find_type, Primitive::Type field_type>
HANDLER_ATTRIBUTES bool HandleGet() {
return DoFieldGet<find_type, field_type, transaction_active>(
- Self(), shadow_frame_, inst_, inst_data_);
+ Self(), shadow_frame_, inst_, inst_data_, Instrumentation());
}
template<FindFieldType find_type, Primitive::Type field_type>
HANDLER_ATTRIBUTES bool HandlePut() {
return DoFieldPut<find_type, field_type, transaction_active>(
- Self(), shadow_frame_, inst_, inst_data_);
+ Self(), shadow_frame_, inst_, inst_data_, Instrumentation());
}
template<InvokeType type, bool is_range>
@@ -686,14 +663,14 @@ class InstructionHandler {
}
}
result.SetL(obj_result);
- if (UNLIKELY(NeedsMethodExitEvent(Instrumentation()))) {
+ if (UNLIKELY(InstrumentationHandler::NeedsMethodExitEvent(Instrumentation()))) {
StackHandleScope<1> hs(Self());
MutableHandle<mirror::Object> h_result(hs.NewHandle(obj_result));
- if (!SendMethodExitEvents(Self(),
- Instrumentation(),
- shadow_frame_,
- shadow_frame_.GetMethod(),
- h_result)) {
+ if (!InstrumentationHandler::SendMethodExitEvents(Self(),
+ Instrumentation(),
+ shadow_frame_,
+ shadow_frame_.GetMethod(),
+ h_result)) {
DCHECK(Self()->IsExceptionPending());
// Do not raise exception event if it is caused by other instrumentation event.
shadow_frame_.SetSkipNextExceptionEvent(true);