Revert "Revert "Ensure void type is resolved when running without image""

Accept the verification status of image classes out of oat files even
when the image could not be loaded. This is necessary as the dex files
might be quickened and the verifier can't work on them when the runtime
is not started.

This reverts commit fe382b5296ef132316d8883a0bdf8cb00d40d16b.

Bug: 18338511
Bug: 18705942
Change-Id: I3516acaaa65f05395c14da0701d1049ba80acb12
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index 1f4cf8f..00f2851 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -575,6 +575,23 @@
                FindSystemClass(self, "[Ljava/lang/StackTraceElement;"));
   mirror::StackTraceElement::SetClass(GetClassRoot(kJavaLangStackTraceElement));
 
+  // Ensure void type is resolved in the core's dex cache so java.lang.Void is correctly
+  // initialized.
+  {
+    const DexFile& dex_file = java_lang_Object->GetDexFile();
+    const DexFile::StringId* void_string_id = dex_file.FindStringId("V");
+    CHECK(void_string_id != nullptr);
+    uint32_t void_string_index = dex_file.GetIndexForStringId(*void_string_id);
+    const DexFile::TypeId* void_type_id = dex_file.FindTypeId(void_string_index);
+    CHECK(void_type_id != nullptr);
+    uint16_t void_type_idx = dex_file.GetIndexForTypeId(*void_type_id);
+    // Now we resolve void type so the dex cache contains it. We use java.lang.Object class
+    // as referrer so the used dex cache is core's one.
+    mirror::Class* resolved_type = ResolveType(dex_file, void_type_idx, java_lang_Object.Get());
+    CHECK_EQ(resolved_type, GetClassRoot(kPrimitiveVoid));
+    self->AssertNoPendingException();
+  }
+
   FinishInit(self);
 
   VLOG(startup) << "ClassLinker::InitFromCompiler exiting";
@@ -3710,6 +3727,19 @@
     return false;
   }
 
+  // We may be running with a preopted oat file but without image. In this case,
+  // we don't skip verification of preverified classes to ensure we initialize
+  // dex caches with all types resolved during verification.
+  // We need to trust image classes, as these might be coming out of a pre-opted, quickened boot
+  // image (that we just failed loading), and the verifier can't be run on quickened opcodes when
+  // the runtime isn't started. On the other hand, app classes can be re-verified even if they are
+  // already pre-opted, as then the runtime is started.
+  if (!Runtime::Current()->IsCompiler() &&
+      !Runtime::Current()->GetHeap()->HasImageSpace() &&
+      klass->GetClassLoader() != nullptr) {
+    return false;
+  }
+
   uint16_t class_def_index = klass->GetDexClassDefIndex();
   oat_file_class_status = oat_dex_file->GetOatClass(class_def_index).GetStatus();
   if (oat_file_class_status == mirror::Class::kStatusVerified ||
diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc
index 59efebf..73978c5 100644
--- a/runtime/verifier/method_verifier.cc
+++ b/runtime/verifier/method_verifier.cc
@@ -3418,7 +3418,9 @@
 
 mirror::ArtMethod* MethodVerifier::VerifyInvokeVirtualQuickArgs(const Instruction* inst,
                                                                 bool is_range) {
-  DCHECK(Runtime::Current()->IsStarted() || verify_to_dump_);
+  DCHECK(Runtime::Current()->IsStarted() || verify_to_dump_)
+      << PrettyMethod(dex_method_idx_, *dex_file_, true) << "@" << work_insn_idx_;
+
   mirror::ArtMethod* res_method = GetQuickInvokedMethod(inst, work_line_.get(),
                                                              is_range);
   if (res_method == nullptr) {