Do not resolve types with vdex.

We don't need to, and it's time expensive.

test: test-art-host, 2x faster vdex compilation time.
bug: 30937355

Change-Id: Ic04ebfee9172ed676fbb38e6901615ed3473352a
diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc
index 1b1de78..b6b2575 100644
--- a/compiler/driver/compiler_driver.cc
+++ b/compiler/driver/compiler_driver.cc
@@ -423,7 +423,7 @@
   // Compile:
   // 1) Compile all classes and methods enabled for compilation. May fall back to dex-to-dex
   //    compilation.
-  if (!GetCompilerOptions().VerifyAtRuntime()) {
+  if (!GetCompilerOptions().VerifyAtRuntime() && !GetCompilerOptions().VerifyOnlyProfile()) {
     Compile(class_loader, dex_files, timings);
   }
   if (dump_stats_) {
@@ -492,6 +492,7 @@
     // TODO: we unquicken unconditionnally, as we don't know
     // if the boot image has changed. How exactly we'll know is under
     // experimentation.
+    TimingLogger::ScopedTiming t("Unquicken", timings);
     Unquicken(dex_files, vdex_file->GetQuickeningInfo());
     Runtime::Current()->GetCompilerCallbacks()->SetVerifierDeps(
         new verifier::VerifierDeps(dex_files, vdex_file->GetVerifierDepsData()));
@@ -983,8 +984,10 @@
                << "situations. Please check the log.";
   }
 
-  InitializeClasses(class_loader, dex_files, timings);
-  VLOG(compiler) << "InitializeClasses: " << GetMemoryUsageString(false);
+  if (!verify_only_profile) {
+    InitializeClasses(class_loader, dex_files, timings);
+    VLOG(compiler) << "InitializeClasses: " << GetMemoryUsageString(false);
+  }
 
   UpdateImageClasses(timings);
   VLOG(compiler) << "UpdateImageClasses: " << GetMemoryUsageString(false);
@@ -2060,21 +2063,29 @@
         std::set<dex::TypeIndex> set(unverified_classes.begin(), unverified_classes.end());
         for (uint32_t i = 0; i < dex_file->NumClassDefs(); ++i) {
           const DexFile::ClassDef& class_def = dex_file->GetClassDef(i);
-          const char* descriptor = dex_file->GetClassDescriptor(class_def);
-          cls.Assign(class_linker->FindClass(soa.Self(), descriptor, class_loader));
-          if (cls.Get() == nullptr) {
-            CHECK(soa.Self()->IsExceptionPending());
-            soa.Self()->ClearException();
-          } else if (set.find(class_def.class_idx_) == set.end()) {
-            ObjectLock<mirror::Class> lock(soa.Self(), cls);
-            mirror::Class::SetStatus(cls, mirror::Class::kStatusVerified, soa.Self());
-            // Create `VerifiedMethod`s for each methods, the compiler expects one for
-            // quickening or compiling.
-            // Note that this means:
-            // - We're only going to compile methods that did verify.
-            // - Quickening will not do checkcast ellision.
-            // TODO(ngeoffray): Reconsider this once we refactor compiler filters.
-            PopulateVerifiedMethods(*dex_file, i, verification_results_);
+          if (set.find(class_def.class_idx_) == set.end()) {
+            if (GetCompilerOptions().VerifyOnlyProfile()) {
+              // Just update the compiled_classes_ map. The compiler doesn't need to resolve
+              // the type.
+              compiled_classes_.Overwrite(
+                  ClassReference(dex_file, i), new CompiledClass(mirror::Class::kStatusVerified));
+            } else {
+              // Resolve the type, so later compilation stages know they don't need to verify
+              // the class.
+              const char* descriptor = dex_file->GetClassDescriptor(class_def);
+              cls.Assign(class_linker->FindClass(soa.Self(), descriptor, class_loader));
+              if (cls.Get() != nullptr) {
+                ObjectLock<mirror::Class> lock(soa.Self(), cls);
+                mirror::Class::SetStatus(cls, mirror::Class::kStatusVerified, soa.Self());
+              }
+              // Create `VerifiedMethod`s for each methods, the compiler expects one for
+              // quickening or compiling.
+              // Note that this means:
+              // - We're only going to compile methods that did verify.
+              // - Quickening will not do checkcast ellision.
+              // TODO(ngeoffray): Reconsider this once we refactor compiler filters.
+              PopulateVerifiedMethods(*dex_file, i, verification_results_);
+            }
           }
         }
       }
@@ -2675,29 +2686,29 @@
 }
 
 void CompilerDriver::RecordClassStatus(ClassReference ref, mirror::Class::Status status) {
+  switch (status) {
+    case mirror::Class::kStatusNotReady:
+    case mirror::Class::kStatusError:
+    case mirror::Class::kStatusRetryVerificationAtRuntime:
+    case mirror::Class::kStatusVerified:
+    case mirror::Class::kStatusInitialized:
+    case mirror::Class::kStatusResolved:
+      break;  // Expected states.
+    default:
+      LOG(FATAL) << "Unexpected class status for class "
+          << PrettyDescriptor(ref.first->GetClassDescriptor(ref.first->GetClassDef(ref.second)))
+          << " of " << status;
+  }
+
   MutexLock mu(Thread::Current(), compiled_classes_lock_);
   auto it = compiled_classes_.find(ref);
-  if (it == compiled_classes_.end() || it->second->GetStatus() != status) {
-    // An entry doesn't exist or the status is lower than the new status.
-    if (it != compiled_classes_.end()) {
-      CHECK_GT(status, it->second->GetStatus());
-      delete it->second;
-    }
-    switch (status) {
-      case mirror::Class::kStatusNotReady:
-      case mirror::Class::kStatusError:
-      case mirror::Class::kStatusRetryVerificationAtRuntime:
-      case mirror::Class::kStatusVerified:
-      case mirror::Class::kStatusInitialized:
-      case mirror::Class::kStatusResolved:
-        break;  // Expected states.
-      default:
-        LOG(FATAL) << "Unexpected class status for class "
-            << PrettyDescriptor(ref.first->GetClassDescriptor(ref.first->GetClassDef(ref.second)))
-            << " of " << status;
-    }
+  if (it == compiled_classes_.end()) {
     CompiledClass* compiled_class = new CompiledClass(status);
     compiled_classes_.Overwrite(ref, compiled_class);
+  } else if (status > it->second->GetStatus()) {
+    // Update the status if we now have a greater one. This happens with vdex,
+    // which records a class is verified, but does not resolve it.
+    it->second->SetStatus(status);
   }
 }