diff options
-rw-r--r-- | compiler/common_compiler_test.h | 5 | ||||
-rw-r--r-- | compiler/image_writer.cc | 3 | ||||
-rw-r--r-- | runtime/class_linker.cc | 21 | ||||
-rw-r--r-- | runtime/class_linker.h | 7 | ||||
-rw-r--r-- | runtime/entrypoints/entrypoint_utils.h | 9 | ||||
-rw-r--r-- | runtime/mirror/art_method-inl.h | 2 | ||||
-rw-r--r-- | runtime/stack.h | 20 | ||||
-rw-r--r-- | runtime/thread.cc | 9 |
8 files changed, 48 insertions, 28 deletions
diff --git a/compiler/common_compiler_test.h b/compiler/common_compiler_test.h index 586c442227..7a91e47fb1 100644 --- a/compiler/common_compiler_test.h +++ b/compiler/common_compiler_test.h @@ -130,6 +130,9 @@ static inline InstructionSetFeatures ParseFeatureList(std::string str) { 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 @@ class CommonCompilerTest : public CommonRuntimeTest { 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 20a66d4022..eb1c5811c7 100644 --- a/compiler/image_writer.cc +++ b/compiler/image_writer.cc @@ -757,7 +757,8 @@ void ImageWriter::PatchOatCodeAndMethods() { 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 6b98da9747..84a3c5da25 100644 --- a/runtime/class_linker.cc +++ b/runtime/class_linker.cc @@ -191,6 +191,9 @@ ClassLinker::ClassLinker(InternTable* intern_table) 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 @@ void ClassLinker::InitFromCompiler(const std::vector<const DexFile*>& boot_class 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 @@ void ClassLinker::FixupStaticTrampolines(mirror::Class* klass) { // 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 @@ static void LinkCode(const Handle<mirror::ArtMethod>& method, const OatFile::Oat // 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 @@ static void LinkCode(const Handle<mirror::ArtMethod>& method, const OatFile::Oat 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 3dac6e55ae..db780d95fc 100644 --- a/runtime/class_linker.h +++ b/runtime/class_linker.h @@ -355,8 +355,8 @@ class ClassLinker { } 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 @@ class ClassLinker { 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 6998e21572..bfcb58f274 100644 --- a/runtime/entrypoints/entrypoint_utils.h +++ b/runtime/entrypoints/entrypoint_utils.h @@ -737,11 +737,6 @@ static inline const void* GetQuickToInterpreterBridge() { 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 @@ static inline const void* GetQuickImtConflictTrampoline(ClassLinker* class_linke 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 c3e2d22c9e..cde977bfd6 100644 --- a/runtime/mirror/art_method-inl.h +++ b/runtime/mirror/art_method-inl.h @@ -222,7 +222,7 @@ inline QuickMethodFrameInfo ArtMethod::GetQuickFrameInfo() { 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; diff --git a/runtime/stack.h b/runtime/stack.h index 963983a7a6..2e32f51343 100644 --- a/runtime/stack.h +++ b/runtime/stack.h @@ -306,6 +306,11 @@ class ShadowFrame { return method_; } + mirror::ArtMethod** GetMethodAddress() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + DCHECK(method_ != nullptr); + return &method_; + } + mirror::Object* GetThisObject() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); mirror::Object* GetThisObject(uint16_t num_ins) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); @@ -389,12 +394,7 @@ class ShadowFrame { #endif // Link to previous shadow frame or NULL. ShadowFrame* link_; -#if defined(ART_USE_PORTABLE_COMPILER) - // TODO: make const in the portable case. mirror::ArtMethod* method_; -#else - mirror::ArtMethod* const method_; -#endif uint32_t dex_pc_; uint32_t vregs_[0]; @@ -518,6 +518,16 @@ class StackVisitor { } } + mirror::ArtMethod** GetMethodAddress() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + if (cur_shadow_frame_ != nullptr) { + return cur_shadow_frame_->GetMethodAddress(); + } else if (cur_quick_frame_ != nullptr) { + return cur_quick_frame_; + } else { + return nullptr; + } + } + bool IsShadowFrame() const { return cur_shadow_frame_ != nullptr; } diff --git a/runtime/thread.cc b/runtime/thread.cc index 415cc0ba88..488961eec5 100644 --- a/runtime/thread.cc +++ b/runtime/thread.cc @@ -1962,7 +1962,10 @@ class ReferenceMapVisitor : public StackVisitor { } void VisitShadowFrame(ShadowFrame* shadow_frame) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - mirror::ArtMethod* m = shadow_frame->GetMethod(); + mirror::ArtMethod** method_addr = shadow_frame->GetMethodAddress(); + visitor_(reinterpret_cast<mirror::Object**>(method_addr), 0 /*ignored*/, this); + mirror::ArtMethod* m = *method_addr; + DCHECK(m != nullptr); size_t num_regs = shadow_frame->NumberOfVRegs(); if (m->IsNative() || shadow_frame->HasReferenceArray()) { // handle scope for JNI or References for interpreter. @@ -2003,7 +2006,9 @@ class ReferenceMapVisitor : public StackVisitor { private: void VisitQuickFrame() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - mirror::ArtMethod* m = GetMethod(); + mirror::ArtMethod** method_addr = GetMethodAddress(); + visitor_(reinterpret_cast<mirror::Object**>(method_addr), 0 /*ignored*/, this); + mirror::ArtMethod* m = *method_addr; // Process register map (which native and runtime methods don't have) if (!m->IsNative() && !m->IsRuntimeMethod() && !m->IsProxyMethod()) { const uint8_t* native_gc_map = m->GetNativeGcMap(); |