diff options
| author | 2020-10-09 10:24:15 +0100 | |
|---|---|---|
| committer | 2020-10-11 14:41:19 +0000 | |
| commit | 384dae4c7e51c34e1fd047c6f58dde63e08ab6a3 (patch) | |
| tree | 03303fdae65bbdfe5cab7fe9b2b8a650e7ceb144 /runtime/interpreter/interpreter.cc | |
| parent | 4d23e51e67a419291598af3cb308aadaed1afd62 (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.cc | 117 |
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; } } } |