Improve performance of invokevirtual/invokeinterface with embedded imt/vtable

Add an embedded version of imt/vtable into class object. Both tables start at
fixed offset within class object so method/entry point can be loaded directly
from class object for invokeinterface/invokevirtual.

Bug: 8142917
Change-Id: I4240d58cfbe9250107c95c0708c036854c455968
diff --git a/runtime/instrumentation.cc b/runtime/instrumentation.cc
index 0e05b62..05320ce 100644
--- a/runtime/instrumentation.cc
+++ b/runtime/instrumentation.cc
@@ -93,16 +93,17 @@
     method->ClearIsPortableCompiled();
   }
   if (!method->IsResolutionMethod()) {
+    ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
     if (quick_code == GetQuickToInterpreterBridge() ||
-        quick_code == GetQuickToInterpreterBridgeTrampoline(Runtime::Current()->GetClassLinker()) ||
-        (quick_code == GetQuickResolutionTrampoline(Runtime::Current()->GetClassLinker()) &&
+        quick_code == class_linker->GetQuickToInterpreterBridgeTrampoline() ||
+        (quick_code == class_linker->GetQuickResolutionTrampoline() &&
          Runtime::Current()->GetInstrumentation()->IsForcedInterpretOnly()
          && !method->IsNative() && !method->IsProxyMethod())) {
       if (kIsDebugBuild) {
         if (quick_code == GetQuickToInterpreterBridge()) {
           DCHECK(portable_code == GetPortableToInterpreterBridge());
-        } else if (quick_code == GetQuickResolutionTrampoline(Runtime::Current()->GetClassLinker())) {
-          DCHECK(portable_code == GetPortableResolutionTrampoline(Runtime::Current()->GetClassLinker()));
+        } else if (quick_code == class_linker->GetQuickResolutionTrampoline()) {
+          DCHECK(portable_code == class_linker->GetPortableResolutionTrampoline());
         }
       }
       DCHECK(!method->IsNative()) << PrettyMethod(method);
@@ -133,8 +134,8 @@
       new_portable_code = class_linker->GetPortableOatCodeFor(method, &have_portable_code);
       new_quick_code = class_linker->GetQuickOatCodeFor(method);
     } else {
-      new_portable_code = GetPortableResolutionTrampoline(class_linker);
-      new_quick_code = GetQuickResolutionTrampoline(class_linker);
+      new_portable_code = class_linker->GetPortableResolutionTrampoline();
+      new_quick_code = class_linker->GetQuickResolutionTrampoline();
     }
   } else {  // !uninstall
     if ((interpreter_stubs_installed_ || forced_interpret_only_ || IsDeoptimized(method)) &&
@@ -152,11 +153,11 @@
         } else {
           new_portable_code = class_linker->GetPortableOatCodeFor(method, &have_portable_code);
           new_quick_code = class_linker->GetQuickOatCodeFor(method);
-          DCHECK(new_quick_code != GetQuickToInterpreterBridgeTrampoline(class_linker));
+          DCHECK(new_quick_code != class_linker->GetQuickToInterpreterBridgeTrampoline());
         }
       } else {
-        new_portable_code = GetPortableResolutionTrampoline(class_linker);
-        new_quick_code = GetQuickResolutionTrampoline(class_linker);
+        new_portable_code = class_linker->GetPortableResolutionTrampoline();
+        new_quick_code = class_linker->GetQuickResolutionTrampoline();
       }
     }
   }
@@ -592,22 +593,25 @@
       new_portable_code = GetPortableToInterpreterBridge();
       new_quick_code = GetQuickToInterpreterBridge();
       new_have_portable_code = false;
-    } else if (quick_code == GetQuickResolutionTrampoline(Runtime::Current()->GetClassLinker()) ||
-        quick_code == GetQuickToInterpreterBridgeTrampoline(Runtime::Current()->GetClassLinker()) ||
-        quick_code == GetQuickToInterpreterBridge()) {
-      DCHECK((portable_code == GetPortableResolutionTrampoline(Runtime::Current()->GetClassLinker())) ||
-             (portable_code == GetPortableToInterpreterBridge()));
-      new_portable_code = portable_code;
-      new_quick_code = quick_code;
-      new_have_portable_code = have_portable_code;
-    } else if (entry_exit_stubs_installed_) {
-      new_quick_code = GetQuickInstrumentationEntryPoint();
-      new_portable_code = GetPortableToInterpreterBridge();
-      new_have_portable_code = false;
     } else {
-      new_portable_code = portable_code;
-      new_quick_code = quick_code;
-      new_have_portable_code = have_portable_code;
+      ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
+      if (quick_code == class_linker->GetQuickResolutionTrampoline() ||
+          quick_code == class_linker->GetQuickToInterpreterBridgeTrampoline() ||
+          quick_code == GetQuickToInterpreterBridge()) {
+        DCHECK((portable_code == class_linker->GetPortableResolutionTrampoline()) ||
+               (portable_code == GetPortableToInterpreterBridge()));
+        new_portable_code = portable_code;
+        new_quick_code = quick_code;
+        new_have_portable_code = have_portable_code;
+      } else if (entry_exit_stubs_installed_) {
+        new_quick_code = GetQuickInstrumentationEntryPoint();
+        new_portable_code = GetPortableToInterpreterBridge();
+        new_have_portable_code = false;
+      } else {
+        new_portable_code = portable_code;
+        new_quick_code = quick_code;
+        new_have_portable_code = have_portable_code;
+      }
     }
   }
   UpdateEntrypoints(method, new_quick_code, new_portable_code, new_have_portable_code);
@@ -661,8 +665,9 @@
     ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
     if (method->IsStatic() && !method->IsConstructor() &&
         !method->GetDeclaringClass()->IsInitialized()) {
-      UpdateEntrypoints(method, GetQuickResolutionTrampoline(class_linker),
-                        GetPortableResolutionTrampoline(class_linker), false);
+      // TODO: we're updating to entrypoints in the image here, we can avoid the trampoline.
+      UpdateEntrypoints(method, class_linker->GetQuickResolutionTrampoline(),
+                        class_linker->GetPortableResolutionTrampoline(), false);
     } else {
       bool have_portable_code = false;
       const void* quick_code = class_linker->GetQuickOatCodeFor(method);
@@ -742,8 +747,9 @@
   if (LIKELY(!instrumentation_stubs_installed_)) {
     const void* code = method->GetEntryPointFromQuickCompiledCode();
     DCHECK(code != nullptr);
-    if (LIKELY(code != GetQuickResolutionTrampoline(runtime->GetClassLinker())) &&
-        LIKELY(code != GetQuickToInterpreterBridgeTrampoline(runtime->GetClassLinker())) &&
+    ClassLinker* class_linker = runtime->GetClassLinker();
+    if (LIKELY(code != class_linker->GetQuickResolutionTrampoline()) &&
+        LIKELY(code != class_linker->GetQuickToInterpreterBridgeTrampoline()) &&
         LIKELY(code != GetQuickToInterpreterBridge())) {
       return code;
     }