Fix generic jni issue in ArtMethod::GetQuickFrameInfo
The 64-bit host mode fails to start due to incorrect
detection of GetQuickGenericJniTrampoline.
The quick_code is 32-bit and taken from oat file, but
GetQuickGenericJniTrampoline returnf 0x7fffxx (64-bit)
address of trampoline and execution went to incorrect way.
Some clean-up.
Original Author: Dmitry Petrochenko <dmitry.petrochenko@intel.com>
Signed-off-by: Dmitry Petrochenko <dmitry.petrochenko@intel.com>
Signed-off-by: Serguei Katkov <serguei.i.katkov@intel.com>
Change-Id: I0952443b2a9f6833ad37ec373837ae208681fad7
diff --git a/compiler/common_compiler_test.h b/compiler/common_compiler_test.h
index 586c442..7a91e47 100644
--- a/compiler/common_compiler_test.h
+++ b/compiler/common_compiler_test.h
@@ -130,6 +130,9 @@
return result;
}
+// Normally the ClassLinker supplies this.
+extern "C" void art_quick_generic_jni_trampoline(mirror::ArtMethod*);
+
class CommonCompilerTest : public CommonRuntimeTest {
public:
// Create an OatMethod based on pointers (for unit tests).
@@ -217,7 +220,7 @@
oat_method.LinkMethod(method);
method->SetEntryPointFromInterpreter(interpreter::artInterpreterToInterpreterBridge);
} else {
- const void* method_code = GetQuickGenericJniTrampoline();
+ const void* method_code = reinterpret_cast<void*>(art_quick_generic_jni_trampoline);
OatFile::OatMethod oat_method = CreateOatMethod(method_code, nullptr);
oat_method.LinkMethod(method);
diff --git a/compiler/image_writer.cc b/compiler/image_writer.cc
index 20a66d4..eb1c581 100644
--- a/compiler/image_writer.cc
+++ b/compiler/image_writer.cc
@@ -757,7 +757,8 @@
uintptr_t value = quick_code - patch_location + patch->RelativeOffset();
SetPatchLocation(patch, value);
} else {
- if (quick_code == reinterpret_cast<uintptr_t>(GetQuickToInterpreterBridge())) {
+ if (quick_code == reinterpret_cast<uintptr_t>(GetQuickToInterpreterBridge()) ||
+ quick_code == reinterpret_cast<uintptr_t>(class_linker->GetQuickGenericJniTrampoline())) {
if (target->IsNative()) {
// generic JNI, not interpreter bridge from GetQuickOatCodeFor().
code_offset = quick_generic_jni_trampoline_offset_;
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index 6b98da9..84a3c5d 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -191,6 +191,9 @@
memset(find_array_class_cache_, 0, kFindArrayCacheSize * sizeof(mirror::Class*));
}
+// To set a value for generic JNI. May be necessary in compiler tests.
+extern "C" void art_quick_generic_jni_trampoline(mirror::ArtMethod*);
+
void ClassLinker::InitFromCompiler(const std::vector<const DexFile*>& boot_class_path) {
VLOG(startup) << "ClassLinker::Init";
CHECK(Runtime::Current()->IsCompiler());
@@ -343,6 +346,10 @@
runtime->SetImtConflictMethod(runtime->CreateImtConflictMethod());
runtime->SetDefaultImt(runtime->CreateDefaultImt(this));
+ // Set up GenericJNI entrypoint. That is mainly a hack for common_compiler_test.h so that
+ // we do not need friend classes or a publicly exposed setter.
+ quick_generic_jni_trampoline_ = reinterpret_cast<void*>(art_quick_generic_jni_trampoline);
+
// Object, String and DexCache need to be rerun through FindSystemClass to finish init
java_lang_Object->SetStatus(mirror::Class::kStatusNotReady, self);
mirror::Class* Object_class = FindSystemClass(self, "Ljava/lang/Object;");
@@ -1776,9 +1783,10 @@
// Ignore virtual methods on the iterator.
}
-static void LinkCode(const Handle<mirror::ArtMethod>& method, const OatFile::OatClass* oat_class,
- const DexFile& dex_file, uint32_t dex_method_index, uint32_t method_index)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+void ClassLinker::LinkCode(const Handle<mirror::ArtMethod>& method,
+ const OatFile::OatClass* oat_class,
+ const DexFile& dex_file, uint32_t dex_method_index,
+ uint32_t method_index) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
// Method shouldn't have already been linked.
DCHECK(method->GetEntryPointFromQuickCompiledCode() == nullptr);
DCHECK(method->GetEntryPointFromPortableCompiledCode() == nullptr);
@@ -1809,8 +1817,8 @@
// For static methods excluding the class initializer, install the trampoline.
// It will be replaced by the proper entry point by ClassLinker::FixupStaticTrampolines
// after initializing class (see ClassLinker::InitializeClass method).
- method->SetEntryPointFromQuickCompiledCode(GetQuickResolutionTrampoline(runtime->GetClassLinker()));
- method->SetEntryPointFromPortableCompiledCode(GetPortableResolutionTrampoline(runtime->GetClassLinker()));
+ method->SetEntryPointFromQuickCompiledCode(GetQuickResolutionTrampoline());
+ method->SetEntryPointFromPortableCompiledCode(GetPortableResolutionTrampoline());
} else if (enter_interpreter) {
if (!method->IsNative()) {
// Set entry point from compiled code if there's no code or in interpreter only mode.
@@ -1836,8 +1844,7 @@
if (enter_interpreter) {
// We have a native method here without code. Then it should have either the GenericJni
// trampoline as entrypoint (non-static), or the Resolution trampoline (static).
- DCHECK(method->GetEntryPointFromQuickCompiledCode() ==
- GetQuickResolutionTrampoline(runtime->GetClassLinker())
+ DCHECK(method->GetEntryPointFromQuickCompiledCode() == GetQuickResolutionTrampoline()
|| method->GetEntryPointFromQuickCompiledCode() == GetQuickGenericJniTrampoline());
}
}
diff --git a/runtime/class_linker.h b/runtime/class_linker.h
index 3dac6e5..db780d9 100644
--- a/runtime/class_linker.h
+++ b/runtime/class_linker.h
@@ -355,8 +355,8 @@
}
const void* GetQuickGenericJniTrampoline() const {
- return quick_generic_jni_trampoline_;
- }
+ return quick_generic_jni_trampoline_;
+ }
const void* GetQuickResolutionTrampoline() const {
return quick_resolution_trampoline_;
@@ -511,6 +511,9 @@
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
bool LinkFields(const Handle<mirror::Class>& klass, bool is_static)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ void LinkCode(const Handle<mirror::ArtMethod>& method, const OatFile::OatClass* oat_class,
+ const DexFile& dex_file, uint32_t dex_method_index, uint32_t method_index)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
void CreateReferenceInstanceOffsets(const Handle<mirror::Class>& klass)
diff --git a/runtime/entrypoints/entrypoint_utils.h b/runtime/entrypoints/entrypoint_utils.h
index 6998e21..bfcb58f 100644
--- a/runtime/entrypoints/entrypoint_utils.h
+++ b/runtime/entrypoints/entrypoint_utils.h
@@ -737,11 +737,6 @@
return reinterpret_cast<void*>(art_quick_to_interpreter_bridge);
}
-extern "C" void art_quick_generic_jni_trampoline(mirror::ArtMethod*);
-static inline const void* GetQuickGenericJniTrampoline() {
- return reinterpret_cast<void*>(art_quick_generic_jni_trampoline);
-}
-
static inline const void* GetQuickToPortableBridge() {
// TODO: quick to portable bridge. Bug: 8196384
return GetQuickToInterpreterBridge();
@@ -763,10 +758,6 @@
return class_linker->GetQuickImtConflictTrampoline();
}
-static inline const void* GetQuickGenericJniTrampoline(ClassLinker* class_linker) {
- return class_linker->GetQuickGenericJniTrampoline();
-}
-
static inline const void* GetQuickToInterpreterBridgeTrampoline(ClassLinker* class_linker) {
return class_linker->GetQuickToInterpreterBridgeTrampoline();
}
diff --git a/runtime/mirror/art_method-inl.h b/runtime/mirror/art_method-inl.h
index c3e2d22..cde977b 100644
--- a/runtime/mirror/art_method-inl.h
+++ b/runtime/mirror/art_method-inl.h
@@ -222,7 +222,7 @@
DCHECK(entry_point != GetQuickToInterpreterBridgeTrampoline(runtime->GetClassLinker()));
CHECK(entry_point != GetQuickToInterpreterBridge());
- if (UNLIKELY(entry_point == GetQuickGenericJniTrampoline())) {
+ if (UNLIKELY(entry_point == runtime->GetClassLinker()->GetQuickGenericJniTrampoline())) {
// Generic JNI frame.
DCHECK(IsNative());
uint32_t handle_refs = MethodHelper(this).GetNumberOfReferenceArgsWithoutReceiver() + 1;