return result;
}
+const void* ClassLinker::GetOatMethodQuickCodeFor(mirror::ArtMethod* method) {
+ if (method->IsNative() || method->IsAbstract() || method->IsProxyMethod()) {
+ return nullptr;
+ }
+ bool found;
+ OatFile::OatMethod oat_method = FindOatMethodFor(method, &found);
+ return found ? oat_method.GetQuickCode() : nullptr;
+}
+
+const void* ClassLinker::GetOatMethodPortableCodeFor(mirror::ArtMethod* method) {
+ if (method->IsNative() || method->IsAbstract() || method->IsProxyMethod()) {
+ return nullptr;
+ }
+ bool found;
+ OatFile::OatMethod oat_method = FindOatMethodFor(method, &found);
+ return found ? oat_method.GetPortableCode() : nullptr;
+}
+
const void* ClassLinker::GetQuickOatCodeFor(const DexFile& dex_file, uint16_t class_def_idx,
uint32_t method_idx) {
bool found;
const void* GetPortableOatCodeFor(const DexFile& dex_file, uint16_t class_def_idx, uint32_t method_idx)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ // Get compiled code for a method, return null if no code
+ // exists. This is unlike Get..OatCodeFor which will return a bridge
+ // or interpreter entrypoint.
+ const void* GetOatMethodQuickCodeFor(mirror::ArtMethod* method)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ const void* GetOatMethodPortableCodeFor(mirror::ArtMethod* method)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
pid_t GetClassesLockOwner(); // For SignalCatcher.
pid_t GetDexLockOwner(); // For SignalCatcher.
return found_dex_pc;
}
+bool ArtMethod::IsEntrypointInterpreter() {
+ ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
+ const void* oat_quick_code = class_linker->GetOatMethodQuickCodeFor(this);
+ const void* oat_portable_code = class_linker->GetOatMethodPortableCodeFor(this);
+ if (!IsPortableCompiled()) { // Quick.
+ return oat_quick_code == nullptr ||
+ oat_quick_code != GetEntryPointFromQuickCompiledCode();
+ } else { // Portable.
+ return oat_portable_code == nullptr ||
+ oat_portable_code != GetEntryPointFromPortableCompiledCode();
+ }
+}
+
void ArtMethod::Invoke(Thread* self, uint32_t* args, uint32_t args_size, JValue* result,
const char* shorty) {
if (UNLIKELY(__builtin_frame_address(0) < self->GetStackEnd())) {
have_quick_code ? GetEntryPointFromQuickCompiledCode()
: GetEntryPointFromPortableCompiledCode());
}
+
+ // Ensure that we won't be accidentally calling quick/portable compiled code when -Xint.
+ if (kIsDebugBuild && Runtime::Current()->GetInstrumentation()->IsForcedInterpretOnly()) {
+ CHECK(IsEntrypointInterpreter())
+ << "Don't call compiled code when -Xint " << PrettyMethod(this);
+ }
+
if (!IsPortableCompiled()) {
#ifdef __LP64__
if (!IsStatic()) {
void AssertPcIsWithinQuickCode(uintptr_t pc) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ // Returns true if the entrypoint points to the interpreter, as
+ // opposed to the compiled code, that is, this method will be
+ // interpretered on invocation.
+ bool IsEntrypointInterpreter() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
uint32_t GetQuickOatCodeOffset() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
uint32_t GetPortableOatCodeOffset() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
void SetQuickOatCodeOffset(uint32_t code_offset) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);