Pass instruction-set from runtime through to spawned dex2oat.

Change-Id: I1727af7beb9f710c29124d4d6bc9175e4856f3cc
diff --git a/compiler/common_compiler_test.h b/compiler/common_compiler_test.h
index 6aa85d4..9a21da0 100644
--- a/compiler/common_compiler_test.h
+++ b/compiler/common_compiler_test.h
@@ -291,7 +291,7 @@
 
       // Take the default set of instruction features from the build.
       InstructionSetFeatures instruction_set_features =
-          ParseFeatureList(STRINGIFY(ART_DEFAULT_INSTRUCTION_SET_FEATURES));
+          ParseFeatureList(Runtime::GetDefaultInstructionSetFeatures());
 
 #if defined(__arm__)
       instruction_set = kThumb2;
diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc
index 72effde..552ec89 100644
--- a/dex2oat/dex2oat.cc
+++ b/dex2oat/dex2oat.cc
@@ -740,7 +740,7 @@
 
   // Take the default set of instruction features from the build.
   InstructionSetFeatures instruction_set_features =
-      ParseFeatureList(STRINGIFY(ART_DEFAULT_INSTRUCTION_SET_FEATURES));
+      ParseFeatureList(Runtime::GetDefaultInstructionSetFeatures());
 
 #if defined(__arm__)
   InstructionSet instruction_set = kThumb2;
diff --git a/runtime/Android.mk b/runtime/Android.mk
index 697d1a3..6523b93 100644
--- a/runtime/Android.mk
+++ b/runtime/Android.mk
@@ -73,6 +73,7 @@
 	hprof/hprof.cc \
 	image.cc \
 	indirect_reference_table.cc \
+	instruction_set.cc \
 	instrumentation.cc \
 	intern_table.cc \
 	interpreter/interpreter.cc \
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index 3957493..19cc23c 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -567,40 +567,12 @@
   argv.push_back("--runtime-arg");
   argv.push_back(Runtime::Current()->GetClassPathString());
 
-  argv.push_back("--runtime-arg");
-  std::string checkstr = "-implicit-checks";
-
-  int nchecks = 0;
-  char checksep = ':';
-
-  if (!Runtime::Current()->ExplicitNullChecks()) {
-    checkstr += checksep;
-    checksep = ',';
-    checkstr += "null";
-    ++nchecks;
-  }
-  if (!Runtime::Current()->ExplicitSuspendChecks()) {
-    checkstr += checksep;
-    checksep = ',';
-    checkstr += "suspend";
-    ++nchecks;
-  }
-
-  if (!Runtime::Current()->ExplicitStackOverflowChecks()) {
-    checkstr += checksep;
-    checksep = ',';
-    checkstr += "stack";
-    ++nchecks;
-  }
-
-  if (nchecks == 0) {
-    checkstr += ":none";
-  }
-  argv.push_back(checkstr);
+  Runtime::Current()->AddCurrentRuntimeFeaturesAsDex2OatArguments(&argv);
 
   if (!kIsTargetBuild) {
     argv.push_back("--host");
   }
+
   argv.push_back(boot_image_option);
   argv.push_back(dex_file_option);
   argv.push_back(oat_fd_option);
diff --git a/runtime/gc/space/image_space.cc b/runtime/gc/space/image_space.cc
index 9a2815a..faa539f 100644
--- a/runtime/gc/space/image_space.cc
+++ b/runtime/gc/space/image_space.cc
@@ -67,36 +67,6 @@
   arg_vector.push_back("--runtime-arg");
   arg_vector.push_back("-Xmx64m");
 
-  arg_vector.push_back("--runtime-arg");
-  std::string checkstr = "-implicit-checks";
-  int nchecks = 0;
-  char checksep = ':';
-
-  if (!Runtime::Current()->ExplicitNullChecks()) {
-    checkstr += checksep;
-    checksep = ',';
-    checkstr += "null";
-    ++nchecks;
-  }
-  if (!Runtime::Current()->ExplicitSuspendChecks()) {
-    checkstr += checksep;
-    checksep = ',';
-    checkstr += "suspend";
-    ++nchecks;
-  }
-
-  if (!Runtime::Current()->ExplicitStackOverflowChecks()) {
-    checkstr += checksep;
-    checksep = ',';
-    checkstr += "stack";
-    ++nchecks;
-  }
-
-  if (nchecks == 0) {
-    checkstr += ":none";
-  }
-
-  arg_vector.push_back(checkstr);
 
   for (size_t i = 0; i < boot_class_path.size(); i++) {
     arg_vector.push_back(std::string("--dex-file=") + boot_class_path[i]);
@@ -108,6 +78,8 @@
   oat_file_option_string += "oat";
   arg_vector.push_back(oat_file_option_string);
 
+  Runtime::Current()->AddCurrentRuntimeFeaturesAsDex2OatArguments(&arg_vector);
+
   arg_vector.push_back(StringPrintf("--base=0x%x", ART_BASE_ADDRESS));
 
   if (kIsTargetBuild) {
diff --git a/runtime/instruction_set.cc b/runtime/instruction_set.cc
new file mode 100644
index 0000000..c964629
--- /dev/null
+++ b/runtime/instruction_set.cc
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+#include "instruction_set.h"
+
+namespace art {
+
+std::string InstructionSetFeatures::GetFeatureString() const {
+  std::string result;
+  if ((mask_ & kHwDiv) != 0) {
+    result += "div";
+  }
+  if (result.size() == 0) {
+    result = "none";
+  }
+  return result;
+}
+
+}  // namespace art
diff --git a/runtime/instruction_set.h b/runtime/instruction_set.h
index cbc9912..c5a4ec8 100644
--- a/runtime/instruction_set.h
+++ b/runtime/instruction_set.h
@@ -33,6 +33,7 @@
   kX86_64,
   kMips
 };
+std::ostream& operator<<(std::ostream& os, const InstructionSet& rhs);
 
 enum InstructionFeatures {
   kHwDiv = 1                  // Supports hardware divide.
@@ -44,6 +45,8 @@
   InstructionSetFeatures() : mask_(0) {}
   explicit InstructionSetFeatures(uint32_t mask) : mask_(mask) {}
 
+  static InstructionSetFeatures GuessInstructionSetFeatures();
+
   bool HasDivideInstruction() const {
       return (mask_ & kHwDiv) != 0;
   }
@@ -52,20 +55,7 @@
     mask_ = (mask_ & ~kHwDiv) | (v ? kHwDiv : 0);
   }
 
-  std::string GetFeatureString() const {
-    std::string result;
-    if ((mask_ & kHwDiv) != 0) {
-      result += "div";
-    }
-    if (result.size() == 0) {
-      result = "none";
-    }
-    return result;
-  }
-
-  uint32_t get_mask() const {
-    return mask_;
-  }
+  std::string GetFeatureString() const;
 
   // Other features in here.
 
@@ -81,8 +71,6 @@
   uint32_t mask_;
 };
 
-std::ostream& operator<<(std::ostream& os, const InstructionSet& rhs);
-
 }  // namespace art
 
 #endif  // ART_RUNTIME_INSTRUCTION_SET_H_
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index a830018..b0a6584 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -79,6 +79,8 @@
 namespace art {
 
 static constexpr bool kEnableJavaStackTraceHandler = true;
+const char* Runtime::kDefaultInstructionSetFeatures =
+    STRINGIFY(ART_DEFAULT_INSTRUCTION_SET_FEATURES);
 Runtime* Runtime::instance_ = NULL;
 
 Runtime::Runtime()
@@ -1216,6 +1218,59 @@
   fault_message_ = message;
 }
 
+void Runtime::AddCurrentRuntimeFeaturesAsDex2OatArguments(std::vector<std::string>* argv)
+    const {
+  argv->push_back("--runtime-arg");
+  std::string checkstr = "-implicit-checks";
+
+  int nchecks = 0;
+  char checksep = ':';
+
+  if (!ExplicitNullChecks()) {
+    checkstr += checksep;
+    checksep = ',';
+    checkstr += "null";
+    ++nchecks;
+  }
+  if (!ExplicitSuspendChecks()) {
+    checkstr += checksep;
+    checksep = ',';
+    checkstr += "suspend";
+    ++nchecks;
+  }
+
+  if (!ExplicitStackOverflowChecks()) {
+    checkstr += checksep;
+    checksep = ',';
+    checkstr += "stack";
+    ++nchecks;
+  }
+
+  if (nchecks == 0) {
+    checkstr += ":none";
+  }
+  argv->push_back(checkstr);
+
+  // Make the dex2oat instruction set match that of the launching runtime. If we have multiple
+  // architecture support, dex2oat may be compiled as a different instruction-set than that
+  // currently being executed.
+#if defined(__arm__)
+  argv->push_back("--instruction-set=arm");
+#elif defined(__aarch64__)
+  argv->push_back("--instruction-set=arm64");
+#elif defined(__i386__)
+  argv->push_back("--instruction-set=x86");
+#elif defined(__x86_64__)
+  argv->push_back("--instruction-set=x86_64");
+#elif defined(__mips__)
+  argv->push_back("--instruction-set=mips");
+#endif
+
+  std::string features("--instruction-set-features=");
+  features += GetDefaultInstructionSetFeatures();
+  argv->push_back(features);
+}
+
 void Runtime::UpdateProfilerState(int state) {
   LOG(DEBUG) << "Profiler state updated to " << state;
 }
diff --git a/runtime/runtime.h b/runtime/runtime.h
index ed60d4d..176b71c 100644
--- a/runtime/runtime.h
+++ b/runtime/runtime.h
@@ -407,6 +407,8 @@
     return fault_message_;
   }
 
+  void AddCurrentRuntimeFeaturesAsDex2OatArguments(std::vector<std::string>* arg_vector) const;
+
   bool ExplicitNullChecks() const {
     return null_pointer_handler_ == nullptr;
   }
@@ -423,6 +425,10 @@
     return running_on_valgrind_;
   }
 
+  static const char* GetDefaultInstructionSetFeatures() {
+    return kDefaultInstructionSetFeatures;
+  }
+
  private:
   static void InitPlatformSignalHandlers();
 
@@ -439,15 +445,15 @@
   void StartDaemonThreads();
   void StartSignalCatcher();
 
-  // NOTE: these must match the gc::ProcessState values as they come directly
-  // from the framework.
-  static constexpr int kProfileForground = 0;
-  static constexpr int kProfileBackgrouud = 1;
-
-
   // A pointer to the active runtime or NULL.
   static Runtime* instance_;
 
+  static const char* kDefaultInstructionSetFeatures;
+
+  // NOTE: these must match the gc::ProcessState values as they come directly from the framework.
+  static constexpr int kProfileForground = 0;
+  static constexpr int kProfileBackgrouud = 1;
+
   mirror::ArtMethod* callee_save_methods_[kLastCalleeSaveType];
   mirror::Throwable* pre_allocated_OutOfMemoryError_;
   mirror::ArtMethod* resolution_method_;