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/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc
index 2a7d998..664e0b1 100644
--- a/dex2oat/dex2oat.cc
+++ b/dex2oat/dex2oat.cc
@@ -251,13 +251,23 @@
                      const CompilerOptions& compiler_options,
                      Compiler::Kind compiler_kind,
                      InstructionSet instruction_set,
-                     InstructionSetFeatures instruction_set_features,
+                     const InstructionSetFeatures* instruction_set_features,
                      VerificationResults* verification_results,
                      DexFileToMethodInlinerMap* method_inliner_map,
                      size_t thread_count)
       SHARED_TRYLOCK_FUNCTION(true, Locks::mutator_lock_) {
     CHECK(verification_results != nullptr);
     CHECK(method_inliner_map != nullptr);
+    if (instruction_set == kRuntimeISA) {
+      std::unique_ptr<const InstructionSetFeatures> runtime_features(
+          InstructionSetFeatures::FromCppDefines());
+      if (!instruction_set_features->Equals(runtime_features.get())) {
+        LOG(WARNING) << "Mismatch between dex2oat instruction set features ("
+            << *instruction_set_features << ") and those of dex2oat executable ("
+            << *runtime_features <<") for the command line:\n"
+            << CommandLine();
+      }
+    }
     std::unique_ptr<Dex2Oat> dex2oat(new Dex2Oat(&compiler_options,
                                                  compiler_kind,
                                                  instruction_set,
@@ -482,7 +492,7 @@
   explicit Dex2Oat(const CompilerOptions* compiler_options,
                    Compiler::Kind compiler_kind,
                    InstructionSet instruction_set,
-                   InstructionSetFeatures instruction_set_features,
+                   const InstructionSetFeatures* instruction_set_features,
                    VerificationResults* verification_results,
                    DexFileToMethodInlinerMap* method_inliner_map,
                    size_t thread_count)
@@ -527,7 +537,7 @@
   static void OpenClassPathFiles(const std::string& class_path,
                                  std::vector<const DexFile*>& dex_files) {
     std::vector<std::string> parsed;
-    Split(class_path, ':', parsed);
+    Split(class_path, ':', &parsed);
     // Take Locks::mutator_lock_ so that lock ordering on the ClassLinker::dex_lock_ is maintained.
     ScopedObjectAccess soa(Thread::Current());
     for (size_t i = 0; i < parsed.size(); ++i) {
@@ -556,7 +566,7 @@
   const Compiler::Kind compiler_kind_;
 
   const InstructionSet instruction_set_;
-  const InstructionSetFeatures instruction_set_features_;
+  const InstructionSetFeatures* const instruction_set_features_;
 
   VerificationResults* const verification_results_;
   DexFileToMethodInlinerMap* const method_inliner_map_;
@@ -728,38 +738,6 @@
 const unsigned int WatchDog::kWatchDogWarningSeconds;
 const unsigned int WatchDog::kWatchDogTimeoutSeconds;
 
-// Given a set of instruction features from the build, parse it.  The
-// input 'str' is a comma separated list of feature names.  Parse it and
-// return the InstructionSetFeatures object.
-static InstructionSetFeatures ParseFeatureList(std::string str) {
-  InstructionSetFeatures result;
-  typedef std::vector<std::string> FeatureList;
-  FeatureList features;
-  Split(str, ',', features);
-  for (FeatureList::iterator i = features.begin(); i != features.end(); i++) {
-    std::string feature = Trim(*i);
-    if (feature == "default") {
-      // Nothing to do.
-    } else if (feature == "div") {
-      // Supports divide instruction.
-       result.SetHasDivideInstruction(true);
-    } else if (feature == "nodiv") {
-      // Turn off support for divide instruction.
-      result.SetHasDivideInstruction(false);
-    } else if (feature == "lpae") {
-      // Supports Large Physical Address Extension.
-      result.SetHasLpae(true);
-    } else if (feature == "nolpae") {
-      // Turn off support for Large Physical Address Extension.
-      result.SetHasLpae(false);
-    } else {
-      Usage("Unknown instruction set feature: '%s'", feature.c_str());
-    }
-  }
-  // others...
-  return result;
-}
-
 void ParseStringAfterChar(const std::string& s, char c, std::string* parsed_value) {
   std::string::size_type colon = s.find(c);
   if (colon == std::string::npos) {
@@ -854,11 +832,12 @@
   int tiny_method_threshold = CompilerOptions::kDefaultTinyMethodThreshold;
   int num_dex_methods_threshold = CompilerOptions::kDefaultNumDexMethodsThreshold;
 
-  // Take the default set of instruction features from the build.
-  InstructionSetFeatures instruction_set_features =
-      ParseFeatureList(Runtime::GetDefaultInstructionSetFeatures());
-
+  // Initialize ISA and ISA features to default values.
   InstructionSet instruction_set = kRuntimeISA;
+  std::string error_msg;
+  std::unique_ptr<const InstructionSetFeatures> instruction_set_features(
+      InstructionSetFeatures::FromFeatureString(instruction_set, "default", &error_msg));
+  CHECK(instruction_set_features.get() != nullptr) << error_msg;
 
   // Profile file to use
   std::string profile_file;
@@ -961,9 +940,20 @@
       } else if (instruction_set_str == "x86_64") {
         instruction_set = kX86_64;
       }
+    } else if (option.starts_with("--instruction-set-variant=")) {
+      StringPiece str = option.substr(strlen("--instruction-set-variant=")).data();
+      instruction_set_features.reset(
+          InstructionSetFeatures::FromVariant(instruction_set, str.as_string(), &error_msg));
+      if (instruction_set_features.get() == nullptr) {
+        Usage("%s", error_msg.c_str());
+      }
     } else if (option.starts_with("--instruction-set-features=")) {
       StringPiece str = option.substr(strlen("--instruction-set-features=")).data();
-      instruction_set_features = ParseFeatureList(str.as_string());
+      instruction_set_features.reset(
+          InstructionSetFeatures::FromFeatureString(instruction_set, str.as_string(), &error_msg));
+      if (instruction_set_features.get() == nullptr) {
+        Usage("%s", error_msg.c_str());
+      }
     } else if (option.starts_with("--compiler-backend=")) {
       StringPiece backend_str = option.substr(strlen("--compiler-backend=")).data();
       if (backend_str == "Quick") {
@@ -1283,8 +1273,7 @@
   QuickCompilerCallbacks callbacks(verification_results.get(), &method_inliner_map);
   runtime_options.push_back(std::make_pair("compilercallbacks", &callbacks));
   runtime_options.push_back(
-      std::make_pair("imageinstructionset",
-                     reinterpret_cast<const void*>(GetInstructionSetString(instruction_set))));
+      std::make_pair("imageinstructionset", GetInstructionSetString(instruction_set)));
 
   Dex2Oat* p_dex2oat;
   if (!Dex2Oat::Create(&p_dex2oat,
@@ -1292,7 +1281,7 @@
                        *compiler_options,
                        compiler_kind,
                        instruction_set,
-                       instruction_set_features,
+                       instruction_set_features.get(),
                        verification_results.get(),
                        &method_inliner_map,
                        thread_count)) {