Add some extra debugging/diagnostic support.

CHECK that we don't bring a class back from a "permanent" error status in the
oat file at runtime.

CHECK that runtime_support.cc doesn't hand out 0 as an address for its caller
to branch to.

Also remove some accidentally left in debugging output.

Also fix a few comment typos.

Change-Id: Ibf4224940e9013184888c7854e675b17e0500ac9
diff --git a/src/class_linker.cc b/src/class_linker.cc
index 0fd184c..00ddeee 100644
--- a/src/class_linker.cc
+++ b/src/class_linker.cc
@@ -2037,10 +2037,16 @@
     }
   }
 
-  // Try to use verification information from oat file, otherwise do runtime verification
+  // Try to use verification information from the oat file, otherwise do runtime verification.
   const DexFile& dex_file = FindDexFile(klass->GetDexCache());
-  if (VerifyClassUsingOatFile(dex_file, klass) ||
-      verifier::DexVerifier::VerifyClass(klass, error_msg)) {
+  Class::Status oat_file_class_status(Class::kStatusNotReady);
+  bool preverified = VerifyClassUsingOatFile(dex_file, klass, oat_file_class_status);
+  bool verified = preverified || verifier::DexVerifier::VerifyClass(klass, error_msg);
+  if (verified) {
+    if (!preverified && oat_file_class_status == Class::kStatusError) {
+      LOG(FATAL) << "Verification failed hard on class " << PrettyDescriptor(klass)
+                 << " at compile time, but succeeded at runtime! The verifier must be broken.";
+    }
     DCHECK(!Thread::Current()->IsExceptionPending());
     // Make sure all classes referenced by catch blocks are resolved
     ResolveClassExceptionHandlerTypes(dex_file, klass);
@@ -2059,7 +2065,8 @@
   }
 }
 
-bool ClassLinker::VerifyClassUsingOatFile(const DexFile& dex_file, Class* klass) {
+bool ClassLinker::VerifyClassUsingOatFile(const DexFile& dex_file, Class* klass,
+                                          Class::Status& oat_file_class_status) {
   if (!Runtime::Current()->IsStarted()) {
     return false;
   }
@@ -2077,11 +2084,11 @@
   UniquePtr<const OatFile::OatClass> oat_class(oat_dex_file->GetOatClass(class_def_index));
   CHECK(oat_class.get() != NULL)
           << dex_file.GetLocation() << " " << PrettyClass(klass) << " " << descriptor;
-  Class::Status status = oat_class->GetStatus();
-  if (status == Class::kStatusVerified || status == Class::kStatusInitialized) {
+  oat_file_class_status = oat_class->GetStatus();
+  if (oat_file_class_status == Class::kStatusVerified || oat_file_class_status == Class::kStatusInitialized) {
     return true;
   }
-  if (status == Class::kStatusError) {
+  if (oat_file_class_status == Class::kStatusError) {
     // Compile time verification failed. Compile time verification can fail because we have
     // incomplete type information. Consider the following:
     // class ... {
@@ -2101,14 +2108,14 @@
     // at compile time).
     return false;
   }
-  if (status == Class::kStatusNotReady) {
+  if (oat_file_class_status == Class::kStatusNotReady) {
     // Status is uninitialized if we couldn't determine the status at compile time, for example,
     // not loading the class.
     // TODO: when the verifier doesn't rely on Class-es failing to resolve/load the type hierarchy
     // isn't a problem and this case shouldn't occur
     return false;
   }
-  LOG(FATAL) << "Unexpected class status: " << status
+  LOG(FATAL) << "Unexpected class status: " << oat_file_class_status
              << " " << dex_file.GetLocation() << " " << PrettyClass(klass) << " " << descriptor;
 
   return false;
@@ -2610,9 +2617,6 @@
 }
 
 bool ClassLinker::EnsureInitialized(Class* c, bool can_run_clinit) {
-  if (PrettyClass(c).find("TestClass") != std::string::npos) {
-    LOG(INFO) << "ClassLinker::EnsureInitialized " << PrettyClass(c);
-  }
   CHECK(c != NULL);
   if (c->IsInitialized()) {
     return true;
diff --git a/src/class_linker.h b/src/class_linker.h
index 9ba79eb..eb76738 100644
--- a/src/class_linker.h
+++ b/src/class_linker.h
@@ -277,7 +277,8 @@
   ObjectArray<StackTraceElement>* AllocStackTraceElementArray(size_t length);
 
   void VerifyClass(Class* klass);
-  bool VerifyClassUsingOatFile(const DexFile& dex_file, Class* klass);
+  bool VerifyClassUsingOatFile(const DexFile& dex_file, Class* klass,
+                               Class::Status& oat_file_class_status);
   void ResolveClassExceptionHandlerTypes(const DexFile& dex_file, Class* klass);
   void ResolveMethodExceptionHandlerTypes(const DexFile& dex_file, Method* klass);
 
diff --git a/src/runtime_support.cc b/src/runtime_support.cc
index b002c5c..af8ce22 100644
--- a/src/runtime_support.cc
+++ b/src/runtime_support.cc
@@ -1013,6 +1013,9 @@
   DCHECK(!self->IsExceptionPending());
   const void* code = method->GetCode();
 
+  // When we return, the caller will branch to this address, so it had better not be 0!
+  CHECK(code != NULL) << PrettyMethod(method);
+
   uint32_t method_uint = reinterpret_cast<uint32_t>(method);
   uint64_t code_uint = reinterpret_cast<uint32_t>(code);
   uint64_t result = ((code_uint << 32) | method_uint);
diff --git a/src/runtime_support_arm.S b/src/runtime_support_arm.S
index be6945b..606fa1f 100644
--- a/src/runtime_support_arm.S
+++ b/src/runtime_support_arm.S
@@ -175,7 +175,7 @@
      * as usual - except instead of loading arg0/r0 with the target Method*, arg0/r0 will contain
      * the method_idx.  This wrapper will save arg1-arg3, load the caller's Method*, align the
      * stack and call the appropriate C helper.
-     * NOTE: "this" is first visable argument of the target, and so can be found in arg1/r1.
+     * NOTE: "this" is first visible argument of the target, and so can be found in arg1/r1.
      *
      * The helper will attempt to locate the target and return a 64-bit result in r0/r1 consisting
      * of the target Method* in r0 and method->code_ in r1.
@@ -195,7 +195,7 @@
     mov    r3, r9                         @ pass Thread::Current
     str    sp, [sp, #0]                   @ pass SP
     bl     \cxx_name                      @ (method_idx, this, caller, Thread*, SP)
-    mov    r12, r1                        @ save r0->code_
+    mov    r12, r1                        @ save Method*->code_
     RESTORE_REF_AND_ARGS_CALLEE_SAVE_FRAME
     cmp    r0, #0                         @ did we find the target?
     bxne   r12                            @ tail call to target if so