Make ART compile with GCC -O0 again.

Tidy up InstructionSetFeatures so that it has a type hierarchy dependent on
architecture.
Add to instruction_set_test to warn when InstructionSetFeatures don't agree
with ones from system properties, AT_HWCAP and /proc/cpuinfo.
Clean-up class linker entry point logic to not return entry points but to
test whether the passed code is the particular entrypoint. This works around
image trampolines that replicate entrypoints.
Bug: 17993736

Change-Id: I5f4b49e88c3b02a79f9bee04f83395146ed7be23
diff --git a/runtime/entrypoints/entrypoint_utils.h b/runtime/entrypoints/entrypoint_utils.h
index ce34993..c46d887 100644
--- a/runtime/entrypoints/entrypoint_utils.h
+++ b/runtime/entrypoints/entrypoint_utils.h
@@ -183,59 +183,6 @@
 bool FillArrayData(mirror::Object* obj, const Instruction::ArrayDataPayload* payload)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-// Entry point for deoptimization.
-extern "C" void art_quick_deoptimize();
-static inline uintptr_t GetQuickDeoptimizationEntryPoint() {
-  return reinterpret_cast<uintptr_t>(art_quick_deoptimize);
-}
-
-// Return address of instrumentation stub.
-extern "C" void art_quick_instrumentation_entry(void*);
-static inline void* GetQuickInstrumentationEntryPoint() {
-  return reinterpret_cast<void*>(art_quick_instrumentation_entry);
-}
-
-// The return_pc of instrumentation exit stub.
-extern "C" void art_quick_instrumentation_exit();
-static inline uintptr_t GetQuickInstrumentationExitPc() {
-  return reinterpret_cast<uintptr_t>(art_quick_instrumentation_exit);
-}
-
-extern "C" void art_portable_to_interpreter_bridge(mirror::ArtMethod*);
-static inline const void* GetPortableToInterpreterBridge() {
-  return reinterpret_cast<void*>(art_portable_to_interpreter_bridge);
-}
-
-static inline const void* GetPortableToQuickBridge() {
-  // TODO: portable to quick bridge. Bug: 8196384
-  return GetPortableToInterpreterBridge();
-}
-
-extern "C" void art_quick_to_interpreter_bridge(mirror::ArtMethod*);
-static inline const void* GetQuickToInterpreterBridge() {
-  return reinterpret_cast<void*>(art_quick_to_interpreter_bridge);
-}
-
-static inline const void* GetQuickToPortableBridge() {
-  // TODO: quick to portable bridge. Bug: 8196384
-  return GetQuickToInterpreterBridge();
-}
-
-extern "C" void art_portable_proxy_invoke_handler();
-static inline const void* GetPortableProxyInvokeHandler() {
-  return reinterpret_cast<void*>(art_portable_proxy_invoke_handler);
-}
-
-extern "C" void art_quick_proxy_invoke_handler();
-static inline const void* GetQuickProxyInvokeHandler() {
-  return reinterpret_cast<void*>(art_quick_proxy_invoke_handler);
-}
-
-extern "C" void* art_jni_dlsym_lookup_stub(JNIEnv*, jobject);
-static inline void* GetJniDlsymLookupStub() {
-  return reinterpret_cast<void*>(art_jni_dlsym_lookup_stub);
-}
-
 template <typename INT_TYPE, typename FLOAT_TYPE>
 static inline INT_TYPE art_float_to_integral(FLOAT_TYPE f);
 
diff --git a/runtime/entrypoints/interpreter/interpreter_entrypoints.cc b/runtime/entrypoints/interpreter/interpreter_entrypoints.cc
index b617636..908d3cd 100644
--- a/runtime/entrypoints/interpreter/interpreter_entrypoints.cc
+++ b/runtime/entrypoints/interpreter/interpreter_entrypoints.cc
@@ -25,7 +25,7 @@
 namespace art {
 
 // TODO: Make the MethodHelper here be compaction safe.
-extern "C" void artInterpreterToCompiledCodeBridge(Thread* self, MethodHelper& mh,
+extern "C" void artInterpreterToCompiledCodeBridge(Thread* self, MethodHelper* mh,
                                                    const DexFile::CodeItem* code_item,
                                                    ShadowFrame* shadow_frame, JValue* result) {
   mirror::ArtMethod* method = shadow_frame->GetMethod();
@@ -54,7 +54,7 @@
   } else {
     method->Invoke(self, shadow_frame->GetVRegArgs(arg_offset),
                    (shadow_frame->NumberOfVRegs() - arg_offset) * sizeof(uint32_t),
-                   result, mh.GetShorty());
+                   result, mh->GetShorty());
   }
 }
 
diff --git a/runtime/entrypoints/interpreter/interpreter_entrypoints.h b/runtime/entrypoints/interpreter/interpreter_entrypoints.h
index d8b2204..5d646e9 100644
--- a/runtime/entrypoints/interpreter/interpreter_entrypoints.h
+++ b/runtime/entrypoints/interpreter/interpreter_entrypoints.h
@@ -33,10 +33,10 @@
 
 // Pointers to functions that are called by interpreter trampolines via thread-local storage.
 struct PACKED(4) InterpreterEntryPoints {
-  void (*pInterpreterToInterpreterBridge)(Thread* self, MethodHelper& mh,
+  void (*pInterpreterToInterpreterBridge)(Thread* self, MethodHelper* mh,
                                           const DexFile::CodeItem* code_item,
                                           ShadowFrame* shadow_frame, JValue* result);
-  void (*pInterpreterToCompiledCodeBridge)(Thread* self, MethodHelper& mh,
+  void (*pInterpreterToCompiledCodeBridge)(Thread* self, MethodHelper* mh,
                                            const DexFile::CodeItem* code_item,
                                            ShadowFrame* shadow_frame, JValue* result);
 };
diff --git a/runtime/entrypoints/jni/jni_entrypoints.cc b/runtime/entrypoints/jni/jni_entrypoints.cc
index edb3b72..2752407 100644
--- a/runtime/entrypoints/jni/jni_entrypoints.cc
+++ b/runtime/entrypoints/jni/jni_entrypoints.cc
@@ -45,7 +45,7 @@
     return NULL;
   } else {
     // Register so that future calls don't come here
-    method->RegisterNative(self, native_code, false);
+    method->RegisterNative(native_code, false);
     return native_code;
   }
 }
diff --git a/runtime/entrypoints/portable/portable_trampoline_entrypoints.cc b/runtime/entrypoints/portable/portable_trampoline_entrypoints.cc
index 642c94a..c3664bf 100644
--- a/runtime/entrypoints/portable/portable_trampoline_entrypoints.cc
+++ b/runtime/entrypoints/portable/portable_trampoline_entrypoints.cc
@@ -19,6 +19,7 @@
 
 #include "dex_instruction-inl.h"
 #include "entrypoints/entrypoint_utils-inl.h"
+#include "entrypoints/runtime_asm_entrypoints.h"
 #include "interpreter/interpreter.h"
 #include "mirror/art_method-inl.h"
 #include "mirror/object-inl.h"
@@ -222,7 +223,7 @@
       }
     }
 
-    JValue result = interpreter::EnterInterpreterFromStub(self, mh, code_item, *shadow_frame);
+    JValue result = interpreter::EnterInterpreterFromEntryPoint(self, &mh, code_item, shadow_frame);
     // Pop transition.
     self->PopManagedStackFragment(fragment);
     return result.GetJ();
@@ -323,7 +324,7 @@
   uint32_t dex_pc;
   mirror::ArtMethod* caller = self->GetCurrentMethod(&dex_pc);
 
-  ClassLinker* linker = Runtime::Current()->GetClassLinker();
+  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
   InvokeType invoke_type;
   bool is_range;
   if (called->IsRuntimeMethod()) {
@@ -379,7 +380,7 @@
         is_range = true;
     }
     uint32_t dex_method_idx = (is_range) ? instr->VRegB_3rc() : instr->VRegB_35c();
-    called = linker->ResolveMethod(Thread::Current(), dex_method_idx, &caller, invoke_type);
+    called = class_linker->ResolveMethod(Thread::Current(), dex_method_idx, &caller, invoke_type);
     // Incompatible class change should have been handled in resolve method.
     CHECK(!called->CheckIncompatibleClassChange(invoke_type));
     // Refine called method based on receiver.
@@ -399,27 +400,27 @@
     // Ensure that the called method's class is initialized.
     StackHandleScope<1> hs(self);
     Handle<mirror::Class> called_class(hs.NewHandle(called->GetDeclaringClass()));
-    linker->EnsureInitialized(self, called_class, true, true);
+    class_linker->EnsureInitialized(self, called_class, true, true);
     if (LIKELY(called_class->IsInitialized())) {
       code = called->GetEntryPointFromPortableCompiledCode();
       // TODO: remove this after we solve the link issue.
       if (code == nullptr) {
         bool have_portable_code;
-        code = linker->GetPortableOatCodeFor(called, &have_portable_code);
+        code = class_linker->GetPortableOatCodeFor(called, &have_portable_code);
       }
     } else if (called_class->IsInitializing()) {
       if (invoke_type == kStatic) {
         // Class is still initializing, go to oat and grab code (trampoline must be left in place
         // until class is initialized to stop races between threads).
         bool have_portable_code;
-        code = linker->GetPortableOatCodeFor(called, &have_portable_code);
+        code = class_linker->GetPortableOatCodeFor(called, &have_portable_code);
       } else {
         // No trampoline for non-static methods.
         code = called->GetEntryPointFromPortableCompiledCode();
         // TODO: remove this after we solve the link issue.
         if (code == nullptr) {
           bool have_portable_code;
-          code = linker->GetPortableOatCodeFor(called, &have_portable_code);
+          code = class_linker->GetPortableOatCodeFor(called, &have_portable_code);
         }
       }
     } else {
@@ -430,7 +431,7 @@
     // Expect class to at least be initializing.
     DCHECK(called->GetDeclaringClass()->IsInitializing());
     // Don't want infinite recursion.
-    DCHECK(code != linker->GetPortableResolutionTrampoline());
+    DCHECK(!class_linker->IsPortableResolutionStub(code));
     // Set up entry into main method
     *called_addr = called;
   }
diff --git a/runtime/entrypoints/quick/quick_instrumentation_entrypoints.cc b/runtime/entrypoints/quick/quick_instrumentation_entrypoints.cc
index 42ace40..bb0e5e3 100644
--- a/runtime/entrypoints/quick/quick_instrumentation_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_instrumentation_entrypoints.cc
@@ -15,6 +15,7 @@
  */
 
 #include "callee_save_frame.h"
+#include "entrypoints/runtime_asm_entrypoints.h"
 #include "instruction_set.h"
 #include "instrumentation.h"
 #include "mirror/art_method-inl.h"
@@ -38,8 +39,7 @@
   } else {
     result = instrumentation->GetQuickCodeFor(method);
   }
-  DCHECK((result != Runtime::Current()->GetClassLinker()->GetQuickToInterpreterBridgeTrampoline())
-         || !Runtime::Current()->GetHeap()->HasImageSpace());
+  DCHECK(!Runtime::Current()->GetClassLinker()->IsQuickToInterpreterBridge(result));
   bool interpreter_entry = (result == GetQuickToInterpreterBridge());
   instrumentation->PushInstrumentationStackFrame(self, method->IsStatic() ? nullptr : this_object,
                                                  method, lr, interpreter_entry);
diff --git a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
index 96903db..224756b 100644
--- a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
@@ -19,6 +19,7 @@
 #include "dex_file-inl.h"
 #include "dex_instruction-inl.h"
 #include "entrypoints/entrypoint_utils-inl.h"
+#include "entrypoints/runtime_asm_entrypoints.h"
 #include "gc/accounting/card_table-inl.h"
 #include "instruction_set.h"
 #include "interpreter/interpreter.h"
@@ -504,7 +505,7 @@
         return 0;
       }
     }
-    JValue result = interpreter::EnterInterpreterFromStub(self, mh, code_item, *shadow_frame);
+    JValue result = interpreter::EnterInterpreterFromEntryPoint(self, &mh, code_item, shadow_frame);
     // Pop transition.
     self->PopManagedStackFragment(fragment);
     // No need to restore the args since the method has already been run by the interpreter.
diff --git a/runtime/entrypoints/quick/quick_trampoline_entrypoints_test.cc b/runtime/entrypoints/quick/quick_trampoline_entrypoints_test.cc
index 02b8a5b..41af88e 100644
--- a/runtime/entrypoints/quick/quick_trampoline_entrypoints_test.cc
+++ b/runtime/entrypoints/quick/quick_trampoline_entrypoints_test.cc
@@ -55,9 +55,10 @@
       NO_THREAD_SAFETY_ANALYSIS {
     mirror::ArtMethod* save_method = CreateCalleeSaveMethod(isa, type);
     QuickMethodFrameInfo frame_info = save_method->GetQuickFrameInfo();
-    EXPECT_EQ(save_method->GetReturnPcOffsetInBytes(), pc_offset) << "Expected and real pc offset"
-        " differs for " << type << " core spills=" << std::hex << frame_info.CoreSpillMask() <<
-        " fp spills=" << frame_info.FpSpillMask() << std::dec << " ISA " << isa;
+    EXPECT_EQ(save_method->GetReturnPcOffset().SizeValue(), pc_offset)
+        << "Expected and real pc offset differs for " << type
+        << " core spills=" << std::hex << frame_info.CoreSpillMask()
+        << " fp spills=" << frame_info.FpSpillMask() << std::dec << " ISA " << isa;
   }
 };
 
diff --git a/runtime/entrypoints/runtime_asm_entrypoints.h b/runtime/entrypoints/runtime_asm_entrypoints.h
new file mode 100644
index 0000000..db36a73
--- /dev/null
+++ b/runtime/entrypoints/runtime_asm_entrypoints.h
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_RUNTIME_ENTRYPOINTS_RUNTIME_ASM_ENTRYPOINTS_H_
+#define ART_RUNTIME_ENTRYPOINTS_RUNTIME_ASM_ENTRYPOINTS_H_
+
+namespace art {
+
+#ifndef BUILDING_LIBART
+#error "File and symbols only for use within libart."
+#endif
+
+extern "C" void* art_jni_dlsym_lookup_stub(JNIEnv*, jobject);
+static inline const void* GetJniDlsymLookupStub() {
+  return reinterpret_cast<const void*>(art_jni_dlsym_lookup_stub);
+}
+
+// Return the address of portable stub code for handling IMT conflicts.
+extern "C" void art_portable_imt_conflict_trampoline(mirror::ArtMethod*);
+static inline const void* GetPortableImtConflictStub() {
+  return reinterpret_cast<const void*>(art_portable_imt_conflict_trampoline);
+}
+
+// Return the address of quick stub code for handling IMT conflicts.
+extern "C" void art_quick_imt_conflict_trampoline(mirror::ArtMethod*);
+static inline const void* GetQuickImtConflictStub() {
+  return reinterpret_cast<const void*>(art_quick_imt_conflict_trampoline);
+}
+
+// Return the address of portable stub code for bridging from portable code to the interpreter.
+extern "C" void art_portable_to_interpreter_bridge(mirror::ArtMethod*);
+static inline const void* GetPortableToInterpreterBridge() {
+  return reinterpret_cast<const void*>(art_portable_to_interpreter_bridge);
+}
+
+// Return the address of quick stub code for bridging from quick code to the interpreter.
+extern "C" void art_quick_to_interpreter_bridge(mirror::ArtMethod*);
+static inline const void* GetQuickToInterpreterBridge() {
+  return reinterpret_cast<const void*>(art_quick_to_interpreter_bridge);
+}
+
+// Return the address of portable stub code for bridging from portable code to quick.
+static inline const void* GetPortableToQuickBridge() {
+  // TODO: portable to quick bridge. Bug: 8196384
+  return GetPortableToInterpreterBridge();
+}
+
+// Return the address of quick stub code for bridging from quick code to portable.
+static inline const void* GetQuickToPortableBridge() {
+  // TODO: quick to portable bridge. Bug: 8196384
+  return GetQuickToInterpreterBridge();
+}
+
+// Return the address of quick stub code for handling JNI calls.
+extern "C" void art_quick_generic_jni_trampoline(mirror::ArtMethod*);
+static inline const void* GetQuickGenericJniStub() {
+  return reinterpret_cast<const void*>(art_quick_generic_jni_trampoline);
+}
+
+// Return the address of portable stub code for handling transitions into the proxy invoke handler.
+extern "C" void art_portable_proxy_invoke_handler();
+static inline const void* GetPortableProxyInvokeHandler() {
+  return reinterpret_cast<const void*>(art_portable_proxy_invoke_handler);
+}
+
+// Return the address of quick stub code for handling transitions into the proxy invoke handler.
+extern "C" void art_quick_proxy_invoke_handler();
+static inline const void* GetQuickProxyInvokeHandler() {
+  return reinterpret_cast<const void*>(art_quick_proxy_invoke_handler);
+}
+
+// Return the address of portable stub code for resolving a method at first call.
+extern "C" void art_portable_resolution_trampoline(mirror::ArtMethod*);
+static inline const void* GetPortableResolutionStub() {
+  return reinterpret_cast<const void*>(art_portable_resolution_trampoline);
+}
+
+// Return the address of quick stub code for resolving a method at first call.
+extern "C" void art_quick_resolution_trampoline(mirror::ArtMethod*);
+static inline const void* GetQuickResolutionStub() {
+  return reinterpret_cast<const void*>(art_quick_resolution_trampoline);
+}
+
+// Entry point for quick code that performs deoptimization.
+extern "C" void art_quick_deoptimize();
+static inline const void* GetQuickDeoptimizationEntryPoint() {
+  return reinterpret_cast<const void*>(art_quick_deoptimize);
+}
+
+// Return address of instrumentation entry point used by non-interpreter based tracing.
+extern "C" void art_quick_instrumentation_entry(void*);
+static inline const void* GetQuickInstrumentationEntryPoint() {
+  return reinterpret_cast<const void*>(art_quick_instrumentation_entry);
+}
+
+// The return_pc of instrumentation exit stub.
+extern "C" void art_quick_instrumentation_exit();
+static inline const void* GetQuickInstrumentationExitPc() {
+  return reinterpret_cast<const void*>(art_quick_instrumentation_exit);
+}
+
+}  // namespace art
+
+#endif  // ART_RUNTIME_ENTRYPOINTS_RUNTIME_ASM_ENTRYPOINTS_H_