Adds a DEX-to-DEX compilation level.

This CL adds a DEX-to-DEX compilation level which allows the DEX-to-DEX
compiler to ensure correctness on classes with soft-failed verification.

Bug: 9307738
Change-Id: If051336bf81370bca55872c8c75ccd573d8ca391
diff --git a/compiler/dex/dex_to_dex_compiler.cc b/compiler/dex/dex_to_dex_compiler.cc
index 3c491ce..1ee29cb 100644
--- a/compiler/dex/dex_to_dex_compiler.cc
+++ b/compiler/dex/dex_to_dex_compiler.cc
@@ -36,9 +36,11 @@
 class DexCompiler {
  public:
   DexCompiler(art::CompilerDriver& compiler,
-              const DexCompilationUnit& unit)
+              const DexCompilationUnit& unit,
+              DexToDexCompilationLevel dex_to_dex_compilation_level)
     : driver_(compiler),
-      unit_(unit) {}
+      unit_(unit),
+      dex_to_dex_compilation_level_(dex_to_dex_compilation_level) {}
 
   ~DexCompiler() {}
 
@@ -55,6 +57,10 @@
     return *const_cast<DexFile*>(unit_.GetDexFile());
   }
 
+  bool PerformOptimizations() const {
+    return dex_to_dex_compilation_level_ >= kOptimize;
+  }
+
   // Compiles a RETURN-VOID into a RETURN-VOID-BARRIER within a constructor where
   // a barrier is required.
   void CompileReturnVoid(Instruction* inst, uint32_t dex_pc);
@@ -84,6 +90,7 @@
 
   CompilerDriver& driver_;
   const DexCompilationUnit& unit_;
+  const DexToDexCompilationLevel dex_to_dex_compilation_level_;
 
   DISALLOW_COPY_AND_ASSIGN(DexCompiler);
 };
@@ -138,6 +145,7 @@
 };
 
 void DexCompiler::Compile() {
+  DCHECK_GE(dex_to_dex_compilation_level_, kRequired);
   const DexFile::CodeItem* code_item = unit_.GetCodeItem();
   const uint16_t* insns = code_item->insns_;
   const uint32_t insns_size = code_item->insns_size_in_code_units_;
@@ -220,7 +228,7 @@
 }
 
 Instruction* DexCompiler::CompileCheckCast(Instruction* inst, uint32_t dex_pc) {
-  if (!kEnableCheckCastEllision) {
+  if (!kEnableCheckCastEllision || !PerformOptimizations()) {
     return inst;
   }
   MethodReference referrer(&GetDexFile(), unit_.GetDexMethodIndex());
@@ -253,7 +261,7 @@
                                              uint32_t dex_pc,
                                              Instruction::Code new_opcode,
                                              bool is_put) {
-  if (!kEnableQuickening) {
+  if (!kEnableQuickening || !PerformOptimizations()) {
     return;
   }
   uint32_t field_idx = inst->VRegC_22c();
@@ -280,7 +288,7 @@
                                 uint32_t dex_pc,
                                 Instruction::Code new_opcode,
                                 bool is_range) {
-  if (!kEnableQuickening) {
+  if (!kEnableQuickening || !PerformOptimizations()) {
     return;
   }
   uint32_t method_idx = is_range ? inst->VRegB_3rc() : inst->VRegB_35c();
@@ -320,14 +328,15 @@
 }  // namespace optimizer
 }  // namespace art
 
-extern "C" art::CompiledMethod*
-    ArtCompileDEX(art::CompilerDriver& compiler, const art::DexFile::CodeItem* code_item,
+extern "C" void ArtCompileDEX(art::CompilerDriver& compiler, const art::DexFile::CodeItem* code_item,
                   uint32_t access_flags, art::InvokeType invoke_type,
                   uint32_t class_def_idx, uint32_t method_idx, jobject class_loader,
-                  const art::DexFile& dex_file) {
-  art::DexCompilationUnit unit(NULL, class_loader, art::Runtime::Current()->GetClassLinker(),
-                               dex_file, code_item, class_def_idx, method_idx, access_flags);
-  art::optimizer::DexCompiler dex_compiler(compiler, unit);
-  dex_compiler.Compile();
-  return NULL;
+                  const art::DexFile& dex_file,
+                  art::DexToDexCompilationLevel dex_to_dex_compilation_level) {
+  if (dex_to_dex_compilation_level != art::kDontDexToDexCompile) {
+    art::DexCompilationUnit unit(NULL, class_loader, art::Runtime::Current()->GetClassLinker(),
+                                 dex_file, code_item, class_def_idx, method_idx, access_flags);
+    art::optimizer::DexCompiler dex_compiler(compiler, unit, dex_to_dex_compilation_level);
+    dex_compiler.Compile();
+  }
 }