Merge "ART: Move start of linear mmap_scan out of reserved space"
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;
diff --git a/runtime/stack.h b/runtime/stack.h
index 963983a..2e32f51 100644
--- a/runtime/stack.h
+++ b/runtime/stack.h
@@ -306,6 +306,11 @@
     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 @@
 #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 @@
     }
   }
 
+  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 415cc0b..488961e 100644
--- a/runtime/thread.cc
+++ b/runtime/thread.cc
@@ -1962,7 +1962,10 @@
   }
 
   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 @@
 
  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();