Ensure we don't AddLocalReference a bogus value when returning to native code from an upcall that threw.

Also add a few missing CHECKs.

Change-Id: Icf29506b258a2177b5e80c75cd2710761431ba4b
diff --git a/src/class_linker.cc b/src/class_linker.cc
index b9dbf89..344f844 100644
--- a/src/class_linker.cc
+++ b/src/class_linker.cc
@@ -1194,6 +1194,7 @@
       return NULL;
     }
     ScopedLocalRef<jobject> class_loader_object(env, AddLocalReference<jobject>(env, class_loader));
+    CHECK(class_loader_object.get() != NULL);
     ScopedLocalRef<jobject> result(env, env->CallObjectMethod(class_loader_object.get(), mid,
                                                               class_name_object.get()));
     if (env->ExceptionCheck()) {
diff --git a/src/jni_internal.cc b/src/jni_internal.cc
index 3bbd3cd..c5c7c8c 100644
--- a/src/jni_internal.cc
+++ b/src/jni_internal.cc
@@ -83,6 +83,8 @@
     return NULL;
   }
 
+  DCHECK((reinterpret_cast<uintptr_t>(obj) & 0xffff0000) != 0xebad0000);
+
   JNIEnvExt* env = reinterpret_cast<JNIEnvExt*>(public_env);
   IndirectReferenceTable& locals = env->locals;
 
diff --git a/src/oat/runtime/arm/context_arm.cc b/src/oat/runtime/arm/context_arm.cc
index 28f1db9..50c386f 100644
--- a/src/oat/runtime/arm/context_arm.cc
+++ b/src/oat/runtime/arm/context_arm.cc
@@ -25,10 +25,10 @@
 #ifndef NDEBUG
   // Initialize registers with easy to spot debug values
   for (int i = 0; i < 16; i++) {
-    gprs_[i] = 0xEBAD6070+i;
+    gprs_[i] = kBadGprBase + i;
   }
   for (int i = 0; i < 32; i++) {
-    fprs_[i] = 0xEBAD8070+i;
+    fprs_[i] = kBadFprBase + i;
   }
 #endif
 }
@@ -61,6 +61,15 @@
   }
 }
 
+void ArmContext::SmashCallerSaves() {
+  gprs_[0] = 0; // This needs to be 0 because we want a null/zero return value.
+  gprs_[1] = kBadGprBase + 1;
+  gprs_[2] = kBadGprBase + 2;
+  gprs_[3] = kBadGprBase + 3;
+  gprs_[IP] = kBadGprBase + IP;
+  gprs_[LR] = kBadGprBase + LR;
+}
+
 extern "C" void art_do_long_jump(uint32_t*, uint32_t*);
 
 void ArmContext::DoLongJump() {
diff --git a/src/oat/runtime/arm/context_arm.h b/src/oat/runtime/arm/context_arm.h
index 216d282..73cb50f 100644
--- a/src/oat/runtime/arm/context_arm.h
+++ b/src/oat/runtime/arm/context_arm.h
@@ -44,6 +44,7 @@
     return gprs_[reg];
   }
 
+  virtual void SmashCallerSaves();
   virtual void DoLongJump();
 
  private:
diff --git a/src/oat/runtime/context.h b/src/oat/runtime/context.h
index b8852d5..6c7359b 100644
--- a/src/oat/runtime/context.h
+++ b/src/oat/runtime/context.h
@@ -45,8 +45,16 @@
   // Read the given GPR
   virtual uintptr_t GetGPR(uint32_t reg) = 0;
 
+  // Smash the caller save registers. If we're throwing, we don't want to return bogus values.
+  virtual void SmashCallerSaves() = 0;
+
   // Switch execution of the executing context to this context
   virtual void DoLongJump() = 0;
+
+  enum {
+    kBadGprBase = 0xebad6070,
+    kBadFprBase = 0xebad8070,
+  };
 };
 
 class VmapTable {
diff --git a/src/oat/runtime/x86/context_x86.cc b/src/oat/runtime/x86/context_x86.cc
index 2af95bb..d6f45da 100644
--- a/src/oat/runtime/x86/context_x86.cc
+++ b/src/oat/runtime/x86/context_x86.cc
@@ -25,7 +25,7 @@
 #ifndef NDEBUG
   // Initialize registers with easy to spot debug values.
   for (int i = 0; i < 8; i++) {
-    gprs_[i] = 0xEBAD6070+i;
+    gprs_[i] = kBadGprBase + i;
   }
   eip_ = 0xEBAD601F;
 #endif
@@ -48,6 +48,13 @@
   }
 }
 
+void X86Context::SmashCallerSaves() {
+  gprs_[EAX] = 0; // This needs to be 0 because we want a null/zero return value.
+  gprs_[ECX] = kBadGprBase + ECX;
+  gprs_[EDX] = kBadGprBase + EDX;
+  gprs_[EBX] = kBadGprBase + EBX;
+}
+
 void X86Context::DoLongJump() {
 #if defined(__i386__)
   // We push all the registers using memory-memory pushes, we then pop-all to get the registers
diff --git a/src/oat/runtime/x86/context_x86.h b/src/oat/runtime/x86/context_x86.h
index 72dc719..845f6c3 100644
--- a/src/oat/runtime/x86/context_x86.h
+++ b/src/oat/runtime/x86/context_x86.h
@@ -45,6 +45,7 @@
     return gprs_[reg];
   }
 
+  virtual void SmashCallerSaves();
   virtual void DoLongJump();
 
  private:
diff --git a/src/thread.cc b/src/thread.cc
index 125480e..4177913 100644
--- a/src/thread.cc
+++ b/src/thread.cc
@@ -1562,6 +1562,7 @@
   CHECK_NE(catch_native_pc, 0u);
   long_jump_context->SetSP(reinterpret_cast<uintptr_t>(catch_finder.handler_frame_.GetSP()));
   long_jump_context->SetPC(catch_native_pc);
+  long_jump_context->SmashCallerSaves();
   long_jump_context->DoLongJump();
   LOG(FATAL) << "UNREACHABLE";
 }