summaryrefslogtreecommitdiff
path: root/runtime/interpreter/interpreter.cc
diff options
context:
space:
mode:
author Nicolas Geoffray <ngeoffray@google.com> 2020-10-09 10:24:15 +0100
committer Nicolas Geoffray <ngeoffray@google.com> 2020-10-11 14:41:19 +0000
commit384dae4c7e51c34e1fd047c6f58dde63e08ab6a3 (patch)
tree03303fdae65bbdfe5cab7fe9b2b8a650e7ceb144 /runtime/interpreter/interpreter.cc
parent4d23e51e67a419291598af3cb308aadaed1afd62 (diff)
Support access checks in mterp.
This is to start not treating access checks failure as soft failures. Test: test.py Bug: 112676029 Change-Id: I9cde52e5a2f6e00450616403ce6d9aa822a8380e
Diffstat (limited to 'runtime/interpreter/interpreter.cc')
-rw-r--r--runtime/interpreter/interpreter.cc117
1 files changed, 54 insertions, 63 deletions
diff --git a/runtime/interpreter/interpreter.cc b/runtime/interpreter/interpreter.cc
index 67644d66cd..0586ad9e76 100644
--- a/runtime/interpreter/interpreter.cc
+++ b/runtime/interpreter/interpreter.cc
@@ -244,6 +244,30 @@ static constexpr InterpreterImplKind kInterpreterImplKind = kSwitchImplKind;
static constexpr InterpreterImplKind kInterpreterImplKind = kMterpImplKind;
#endif
+static JValue ExecuteSwitch(Thread* self,
+ const CodeItemDataAccessor& accessor,
+ ShadowFrame& shadow_frame,
+ JValue result_register,
+ bool interpret_one_instruction) REQUIRES_SHARED(Locks::mutator_lock_) {
+ if (Runtime::Current()->IsActiveTransaction()) {
+ if (shadow_frame.GetMethod()->SkipAccessChecks()) {
+ return ExecuteSwitchImpl<false, true>(
+ self, accessor, shadow_frame, result_register, interpret_one_instruction);
+ } else {
+ return ExecuteSwitchImpl<true, true>(
+ self, accessor, shadow_frame, result_register, interpret_one_instruction);
+ }
+ } else {
+ if (shadow_frame.GetMethod()->SkipAccessChecks()) {
+ return ExecuteSwitchImpl<false, false>(
+ self, accessor, shadow_frame, result_register, interpret_one_instruction);
+ } else {
+ return ExecuteSwitchImpl<true, false>(
+ self, accessor, shadow_frame, result_register, interpret_one_instruction);
+ }
+ }
+}
+
static inline JValue Execute(
Thread* self,
const CodeItemDataAccessor& accessor,
@@ -341,72 +365,39 @@ static inline JValue Execute(
// reduction of template parameters, we gate it behind access-checks mode.
DCHECK(!method->SkipAccessChecks() || !method->MustCountLocks());
- bool transaction_active = Runtime::Current()->IsActiveTransaction();
VLOG(interpreter) << "Interpreting " << method->PrettyMethod();
- if (LIKELY(method->SkipAccessChecks())) {
- // Enter the "without access check" interpreter.
- if (kInterpreterImplKind == kMterpImplKind) {
- if (transaction_active) {
- // No Mterp variant - just use the switch interpreter.
- return ExecuteSwitchImpl<false, true>(self, accessor, shadow_frame, result_register,
- false);
- } else if (UNLIKELY(!Runtime::Current()->IsStarted())) {
- return ExecuteSwitchImpl<false, false>(self, accessor, shadow_frame, result_register,
- false);
- } else {
- while (true) {
- // Mterp does not support all instrumentation/debugging.
- if (!self->UseMterp()) {
- return ExecuteSwitchImpl<false, false>(self, accessor, shadow_frame, result_register,
- false);
- }
- bool returned = ExecuteMterpImpl(self,
- accessor.Insns(),
- &shadow_frame,
- &result_register);
- if (returned) {
- return result_register;
- } else {
- // Mterp didn't like that instruction. Single-step it with the reference interpreter.
- result_register = ExecuteSwitchImpl<false, false>(self, accessor, shadow_frame,
- result_register, true);
- if (shadow_frame.GetDexPC() == dex::kDexNoIndex) {
- // Single-stepped a return or an exception not handled locally. Return to caller.
- return result_register;
- }
- }
- }
- }
- } else {
- DCHECK_EQ(kInterpreterImplKind, kSwitchImplKind);
- if (transaction_active) {
- return ExecuteSwitchImpl<false, true>(self, accessor, shadow_frame, result_register,
- false);
- } else {
- return ExecuteSwitchImpl<false, false>(self, accessor, shadow_frame, result_register,
- false);
- }
- }
- } else {
- // Enter the "with access check" interpreter.
- if (kInterpreterImplKind == kMterpImplKind) {
- // No access check variants for Mterp. Just use the switch version.
- if (transaction_active) {
- return ExecuteSwitchImpl<true, true>(self, accessor, shadow_frame, result_register,
- false);
- } else {
- return ExecuteSwitchImpl<true, false>(self, accessor, shadow_frame, result_register,
- false);
- }
+ // Note that mterp doesn't support non-compilable methods, nor methods on
+ // which we must count locks.
+ if (kInterpreterImplKind == kSwitchImplKind ||
+ UNLIKELY(!Runtime::Current()->IsStarted()) ||
+ !method->IsCompilable() ||
+ method->MustCountLocks() ||
+ Runtime::Current()->IsActiveTransaction()) {
+ return ExecuteSwitch(
+ self, accessor, shadow_frame, result_register, /*interpret_one_instruction=*/ false);
+ }
+
+ CHECK_EQ(kInterpreterImplKind, kMterpImplKind);
+ while (true) {
+ // Mterp does not support all instrumentation/debugging.
+ if (!self->UseMterp()) {
+ return ExecuteSwitch(
+ self, accessor, shadow_frame, result_register, /*interpret_one_instruction=*/ false);
+ }
+ bool returned = ExecuteMterpImpl(self,
+ accessor.Insns(),
+ &shadow_frame,
+ &result_register);
+ if (returned) {
+ return result_register;
} else {
- DCHECK_EQ(kInterpreterImplKind, kSwitchImplKind);
- if (transaction_active) {
- return ExecuteSwitchImpl<true, true>(self, accessor, shadow_frame, result_register,
- false);
- } else {
- return ExecuteSwitchImpl<true, false>(self, accessor, shadow_frame, result_register,
- false);
+ // Mterp didn't like that instruction. Single-step it with the reference interpreter.
+ result_register = ExecuteSwitch(
+ self, accessor, shadow_frame, result_register, /*interpret_one_instruction=*/ true);
+ if (shadow_frame.GetDexPC() == dex::kDexNoIndex) {
+ // Single-stepped a return or an exception not handled locally. Return to caller.
+ return result_register;
}
}
}