summaryrefslogtreecommitdiff
path: root/runtime/interpreter/interpreter_common.h
diff options
context:
space:
mode:
Diffstat (limited to 'runtime/interpreter/interpreter_common.h')
-rw-r--r--runtime/interpreter/interpreter_common.h53
1 files changed, 27 insertions, 26 deletions
diff --git a/runtime/interpreter/interpreter_common.h b/runtime/interpreter/interpreter_common.h
index e515d9df52..bf84227560 100644
--- a/runtime/interpreter/interpreter_common.h
+++ b/runtime/interpreter/interpreter_common.h
@@ -124,31 +124,8 @@ template<bool is_range, bool do_assignability_check>
bool DoCall(ArtMethod* called_method, Thread* self, ShadowFrame& shadow_frame,
const Instruction* inst, uint16_t inst_data, JValue* result);
-template<InvokeType type>
-static ALWAYS_INLINE bool UseInterpreterToInterpreterFastPath(ArtMethod* method)
- REQUIRES_SHARED(Locks::mutator_lock_) {
- Runtime* runtime = Runtime::Current();
- const void* quick_code = method->GetEntryPointFromQuickCompiledCode();
- DCHECK(runtime->IsStarted());
- if (!runtime->GetClassLinker()->IsQuickToInterpreterBridge(quick_code)) {
- return false;
- }
- if (!method->SkipAccessChecks() || method->IsNative() || method->IsProxyMethod()) {
- return false;
- }
- if (method->GetDeclaringClass()->IsStringClass() && method->IsConstructor()) {
- return false;
- }
- if (type == kStatic && !method->GetDeclaringClass()->IsInitialized()) {
- return false;
- }
- DCHECK(!runtime->IsActiveTransaction());
- ProfilingInfo* profiling_info = method->GetProfilingInfo(kRuntimePointerSize);
- if ((profiling_info != nullptr) && (profiling_info->GetSavedEntryPoint() != nullptr)) {
- return false;
- }
- return true;
-}
+bool UseFastInterpreterToInterpreterInvoke(ArtMethod* method)
+ REQUIRES_SHARED(Locks::mutator_lock_);
// Throws exception if we are getting close to the end of the stack.
NO_INLINE bool CheckStackOverflow(Thread* self, size_t frame_size)
@@ -238,7 +215,31 @@ static ALWAYS_INLINE bool DoInvoke(Thread* self,
}
}
- if (is_mterp && self->UseMterp() && UseInterpreterToInterpreterFastPath<type>(called_method)) {
+ // Check whether we can use the fast path. The result is cached in the ArtMethod.
+ // If the bit is not set, we explicitly recheck all the conditions.
+ // If any of the conditions get falsified, it is important to clear the bit.
+ bool use_fast_path = false;
+ if (is_mterp && self->UseMterp()) {
+ use_fast_path = called_method->UseFastInterpreterToInterpreterInvoke();
+ if (!use_fast_path) {
+ use_fast_path = UseFastInterpreterToInterpreterInvoke(called_method);
+ if (use_fast_path) {
+ called_method->SetFastInterpreterToInterpreterInvokeFlag();
+ }
+ }
+ }
+
+ if (use_fast_path) {
+ DCHECK(Runtime::Current()->IsStarted());
+ DCHECK(!Runtime::Current()->IsActiveTransaction());
+ DCHECK(called_method->SkipAccessChecks());
+ DCHECK(!called_method->IsNative());
+ DCHECK(!called_method->IsProxyMethod());
+ DCHECK(!called_method->IsIntrinsic());
+ DCHECK(!(called_method->GetDeclaringClass()->IsStringClass() &&
+ called_method->IsConstructor()));
+ DCHECK(type != kStatic || called_method->GetDeclaringClass()->IsInitialized());
+
const uint16_t number_of_inputs =
(is_range) ? inst->VRegA_3rc(inst_data) : inst->VRegA_35c(inst_data);
CodeItemDataAccessor accessor(called_method->DexInstructionData());