return oat_class.GetOatMethod(oat_method_idx).GetQuickCode();
}
-bool ClassLinker::CanUseAOTCode(ArtMethod* method, const void* quick_code) {
+// Returns true if the method must run with interpreter, false otherwise.
+static bool NeedsInterpreter(ArtMethod* method, const void* quick_code)
+ SHARED_REQUIRES(Locks::mutator_lock_) {
if (quick_code == nullptr) {
// No code: need interpreter.
- return false;
- }
-
- if (UNLIKELY(method->IsNative() || method->IsProxyMethod())) {
+ // May return true for native code, in the case of generic JNI
+ // DCHECK(!method->IsNative());
return true;
}
-
- Runtime* runtime = Runtime::Current();
- instrumentation::Instrumentation* instr = runtime->GetInstrumentation();
- if (instr->InterpretOnly()) {
- return false;
- }
-
- if (runtime->GetClassLinker()->IsQuickToInterpreterBridge(quick_code)) {
- // Doing this check avoids doing compiled/interpreter transitions.
- return false;
- }
-
- if (Dbg::IsForcedInterpreterNeededForCalling(Thread::Current(), method)) {
- // Force the use of interpreter when it is required by the debugger.
- return false;
- }
-
- if (runtime->UseJit() && runtime->GetJit()->JitAtFirstUse()) {
- // Don't use AOT code in force JIT mode.
- return false;
- }
- return true;
+ // If interpreter mode is enabled, every method (except native and proxy) must
+ // be run with interpreter.
+ return Runtime::Current()->GetInstrumentation()->InterpretOnly() &&
+ !method->IsNative() && !method->IsProxyMethod();
}
void ClassLinker::FixupStaticTrampolines(mirror::Class* klass) {
OatFile::OatMethod oat_method = oat_class.GetOatMethod(method_index);
quick_code = oat_method.GetQuickCode();
}
- if (!CanUseAOTCode(method, quick_code)) {
+ const bool enter_interpreter = NeedsInterpreter(method, quick_code);
+ if (enter_interpreter) {
// Use interpreter entry point.
// Check whether the method is native, in which case it's generic JNI.
if (quick_code == nullptr && method->IsNative()) {
oat_method.LinkMethod(method);
}
- bool has_usable_oat_code = CanUseAOTCode(method, method->GetEntryPointFromQuickCompiledCode());
+ // Install entry point from interpreter.
+ bool enter_interpreter = NeedsInterpreter(method, method->GetEntryPointFromQuickCompiledCode());
if (!method->IsInvokable()) {
EnsureThrowsInvocationError(method);
// It will be replaced by the proper entry point by ClassLinker::FixupStaticTrampolines
// after initializing class (see ClassLinker::InitializeClass method).
method->SetEntryPointFromQuickCompiledCode(GetQuickResolutionStub());
- } else if (!has_usable_oat_code) {
+ } else if (enter_interpreter) {
if (!method->IsNative()) {
// Set entry point from compiled code if there's no code or in interpreter only mode.
method->SetEntryPointFromQuickCompiledCode(GetQuickToInterpreterBridge());
// Unregistering restores the dlsym lookup stub.
method->UnregisterNative();
- if (!has_usable_oat_code) {
+ if (enter_interpreter) {
// We have a native method here without code. Then it should have either the generic JNI
// trampoline as entrypoint (non-static), or the resolution trampoline (static).
// TODO: this doesn't handle all the cases where trampolines may be installed.
REQUIRES(!Locks::classlinker_classes_lock_)
SHARED_REQUIRES(Locks::mutator_lock_);
- static bool CanUseAOTCode(ArtMethod* method, const void* quick_code)
- SHARED_REQUIRES(Locks::mutator_lock_);
-
struct DexCacheData {
// Weak root to the DexCache. Note: Do not decode this unnecessarily or else class unloading may
// not work properly.
#include "unstarted_runtime.h"
#include "mterp/mterp.h"
#include "jit/jit.h"
-#include "jit/jit_code_cache.h"
namespace art {
namespace interpreter {
method, 0);
}
- jit::Jit* jit = Runtime::Current()->GetJit();
- if (UNLIKELY(jit != nullptr &&
- jit->JitAtFirstUse() &&
- jit->GetCodeCache()->ContainsMethod(method))) {
+ if (UNLIKELY(Runtime::Current()->GetJit() != nullptr &&
+ Runtime::Current()->GetJit()->JitAtFirstUse() &&
+ method->HasAnyCompiledCode())) {
JValue result;
// Pop the shadow frame before calling into compiled code.
#include "debugger.h"
#include "entrypoints/runtime_asm_entrypoints.h"
-#include "jit/jit.h"
#include "mirror/array-inl.h"
#include "stack.h"
#include "unstarted_runtime.h"
uint32_t (&arg)[kVarArgMax],
uint32_t vregC) ALWAYS_INLINE;
+SHARED_REQUIRES(Locks::mutator_lock_)
+static inline bool NeedsInterpreter(Thread* self, ShadowFrame* new_shadow_frame) ALWAYS_INLINE;
+
+static inline bool NeedsInterpreter(Thread* self, ShadowFrame* new_shadow_frame) {
+ ArtMethod* target = new_shadow_frame->GetMethod();
+ if (UNLIKELY(target->IsNative() || target->IsProxyMethod())) {
+ return false;
+ }
+ Runtime* runtime = Runtime::Current();
+ ClassLinker* class_linker = runtime->GetClassLinker();
+ return runtime->GetInstrumentation()->IsForcedInterpretOnly() ||
+ // Doing this check avoids doing compiled/interpreter transitions.
+ class_linker->IsQuickToInterpreterBridge(target->GetEntryPointFromQuickCompiledCode()) ||
+ // Force the use of interpreter when it is required by the debugger.
+ Dbg::IsForcedInterpreterNeededForCalling(self, target);
+}
+
void ArtInterpreterToCompiledCodeBridge(Thread* self,
const DexFile::CodeItem* code_item,
ShadowFrame* shadow_frame,
// Do the call now.
if (LIKELY(Runtime::Current()->IsStarted())) {
- ArtMethod* target = new_shadow_frame->GetMethod();
- if (ClassLinker::CanUseAOTCode(target, target->GetEntryPointFromQuickCompiledCode())) {
- ArtInterpreterToCompiledCodeBridge(self, code_item, new_shadow_frame, result);
- } else {
+ if (NeedsInterpreter(self, new_shadow_frame)) {
ArtInterpreterToInterpreterBridge(self, code_item, new_shadow_frame, result);
+ } else {
+ ArtInterpreterToCompiledCodeBridge(self, code_item, new_shadow_frame, result);
}
} else {
UnstartedRuntime::Invoke(self, code_item, new_shadow_frame, result, first_dest_reg);
DEBUG_ENABLE_JNI_LOGGING = 1 << 4,
DEBUG_GENERATE_DEBUG_INFO = 1 << 5,
DEBUG_ALWAYS_JIT = 1 << 6,
- DEBUG_NATIVE_DEBUGGABLE = 1 << 7,
};
Runtime* const runtime = Runtime::Current();
debug_flags &= ~DEBUG_ALWAYS_JIT;
}
- if ((debug_flags & DEBUG_NATIVE_DEBUGGABLE) != 0) {
- runtime->AddCompilerOption("--native-debuggable");
- debug_flags &= ~DEBUG_NATIVE_DEBUGGABLE;
- }
-
if (debug_flags != 0) {
LOG(ERROR) << StringPrintf("Unknown bits set in debug_flags: %#x", debug_flags);
}