Merge "Assembler fix" into dalvik-dev
diff --git a/src/calling_convention.h b/src/calling_convention.h
index a1d1b32..8f2a79c 100644
--- a/src/calling_convention.h
+++ b/src/calling_convention.h
@@ -141,7 +141,7 @@
 
   // Returns true if the method register will have been clobbered during argument
   // set up
-  virtual bool IsMethodRegisterCrushedPreCall() = 0;
+  virtual bool IsMethodRegisterClobberedPreCall() = 0;
 
   // Iterator interface
   bool HasNext();
diff --git a/src/calling_convention_arm.cc b/src/calling_convention_arm.cc
index 6e664ca..ed876f0 100644
--- a/src/calling_convention_arm.cc
+++ b/src/calling_convention_arm.cc
@@ -171,7 +171,7 @@
 }
 
 // Will reg be crushed by an outgoing argument?
-bool ArmJniCallingConvention::IsMethodRegisterCrushedPreCall() {
+bool ArmJniCallingConvention::IsMethodRegisterClobberedPreCall() {
   return true;  // The method register R0 is always clobbered by the JNIEnv
 }
 
diff --git a/src/calling_convention_arm.h b/src/calling_convention_arm.h
index 4415254..3d513fe 100644
--- a/src/calling_convention_arm.h
+++ b/src/calling_convention_arm.h
@@ -46,7 +46,7 @@
   virtual uint32_t FpSpillMask() const {
     return 0;  // Floats aren't spilled in JNI down call
   }
-  virtual bool IsMethodRegisterCrushedPreCall();
+  virtual bool IsMethodRegisterClobberedPreCall();
   virtual bool IsCurrentParamInRegister();
   virtual bool IsCurrentParamOnStack();
   virtual ManagedRegister CurrentParamRegister();
diff --git a/src/calling_convention_x86.cc b/src/calling_convention_x86.cc
index a8f5778..9598647 100644
--- a/src/calling_convention_x86.cc
+++ b/src/calling_convention_x86.cc
@@ -86,7 +86,7 @@
   return FrameSize() - kPointerSize;
 }
 
-bool X86JniCallingConvention::IsMethodRegisterCrushedPreCall() {
+bool X86JniCallingConvention::IsMethodRegisterClobberedPreCall() {
   return GetMethod()->IsSynchronized();  // Monitor enter crushes the method register
 }
 
diff --git a/src/calling_convention_x86.h b/src/calling_convention_x86.h
index 8c55472..c3bdc40 100644
--- a/src/calling_convention_x86.h
+++ b/src/calling_convention_x86.h
@@ -49,7 +49,7 @@
   virtual uint32_t FpSpillMask() const {
     return 0;
   }
-  virtual bool IsMethodRegisterCrushedPreCall();
+  virtual bool IsMethodRegisterClobberedPreCall();
   virtual bool IsCurrentParamInRegister();
   virtual bool IsCurrentParamOnStack();
   virtual ManagedRegister CurrentParamRegister();
diff --git a/src/compiler_test.cc b/src/compiler_test.cc
index 712a3a0..c1e666e 100644
--- a/src/compiler_test.cc
+++ b/src/compiler_test.cc
@@ -239,6 +239,7 @@
   CompileVirtualMethod(NULL, "java.lang.Throwable","fillInStackTrace","()Ljava/lang/Throwable;");
   CompileDirectMethod(NULL, "java.lang.Throwable","nativeFillInStackTrace","()Ljava/lang/Object;");
   AssertStaticIntMethod(1579, LoadDex("IntMath"), "IntMath", "catchBlock", "(I)I", 1000);
+  AssertStaticIntMethod(7777, LoadDex("IntMath"), "IntMath", "catchBlock", "(I)I", 7000);
 }
 
 TEST_F(CompilerTest, CatchTestNoThrow) {
diff --git a/src/context_arm.cc b/src/context_arm.cc
index 85ada9d..0d25278 100644
--- a/src/context_arm.cc
+++ b/src/context_arm.cc
@@ -9,6 +9,7 @@
 
 ArmContext::ArmContext() {
 #ifndef NDEBUG
+  // Initialize registers with easy to spot debug values
   for (int i=0; i < 16; i++) {
     gprs_[i] = 0xEBAD6070+i;
   }
diff --git a/src/context_x86.cc b/src/context_x86.cc
index 04976a5..479b950 100644
--- a/src/context_x86.cc
+++ b/src/context_x86.cc
@@ -8,9 +8,13 @@
 namespace x86 {
 
 X86Context::X86Context() {
+#ifndef NDEBUG
+  // Initialize registers with easy to spot debug values
   for (int i=0; i < 8; i++) {
     gprs_[i] = 0xEBAD6070+i;
   }
+  eip_ = 0xEBAD601F;
+#endif
 }
 
 void X86Context::FillCalleeSaves(const Frame& fr) {
diff --git a/src/dex_file.cc b/src/dex_file.cc
index c17a225..7c54018 100644
--- a/src/dex_file.cc
+++ b/src/dex_file.cc
@@ -435,7 +435,6 @@
 }
 
 const DexFile::ClassDef* DexFile::FindClassDef(const StringPiece& descriptor) const {
-  CHECK(!descriptor.empty());
   Index::const_iterator it = index_.find(descriptor);
   if (it == index_.end()) {
     return NULL;
diff --git a/src/dex_verifier.cc b/src/dex_verifier.cc
index e0032b2..a800f20 100644
--- a/src/dex_verifier.cc
+++ b/src/dex_verifier.cc
@@ -3589,7 +3589,7 @@
   }
 
   DCHECK_LT(*start_guess, insns_size);
-  DCHECK(InsnGetWidth(insn_flags, *start_guess) != 0);
+  DCHECK_NE(InsnGetWidth(insn_flags, *start_guess), 0);
 
   return true;
 }
diff --git a/src/java_lang_Class.cc b/src/java_lang_Class.cc
index 3e80c6b..8ad59b4 100644
--- a/src/java_lang_Class.cc
+++ b/src/java_lang_Class.cc
@@ -51,7 +51,7 @@
   DCHECK(name->IsString());
   Object* signature_obj = Decode<Object*>(env, jsignature);
   DCHECK(signature_obj->IsArrayInstance());
-  // check that this is a Class[] by checkin that component type is Class
+  // check that this is a Class[] by checking that component type is Class
   // foo->GetClass()->GetClass() is an idiom for getting java.lang.Class from an arbitrary object
   DCHECK(signature_obj->GetClass()->GetComponentType() == signature_obj->GetClass()->GetClass());
   ObjectArray<Class>* signature = down_cast<ObjectArray<Class>*>(signature_obj);
@@ -80,8 +80,8 @@
     return AddLocalReference<jobject>(env, method);
   }
 
-  for (size_t i = 0; i < klass->NumVirtualMethods(); ++i) {
-    Method* method = klass->GetVirtualMethod(i);
+  for (size_t i = 0; i < klass->NumDirectMethods(); ++i) {
+    Method* method = klass->GetDirectMethod(i);
     if (!method->GetName()->Equals(name)) {
       continue;
     }
diff --git a/src/java_lang_System.cc b/src/java_lang_System.cc
index 4eaaa66..8aeefcd 100644
--- a/src/java_lang_System.cc
+++ b/src/java_lang_System.cc
@@ -185,7 +185,7 @@
   const size_t width = sizeof(Object*);
   if (dstComponentType->IsAssignableFrom(srcComponentType)) {
     // Yes. Bulk copy.
-    DCHECK_EQ(width, sizeof(uint32_t));
+    COMPILE_ASSERT(sizeof(width) == sizeof(uint32_t), move32_assumes_Object_references_are_32_bit);
     move32(dstBytes + dstPos * width, srcBytes + srcPos * width, length * width);
     Heap::WriteBarrier(dstArray);
     return;
diff --git a/src/jni_compiler.cc b/src/jni_compiler.cc
index 9624246..4d454cf 100644
--- a/src/jni_compiler.cc
+++ b/src/jni_compiler.cc
@@ -273,7 +273,7 @@
   }
 
   // 9. Plant call to native code associated with method
-  if (!jni_conv->IsMethodRegisterCrushedPreCall()) {
+  if (!jni_conv->IsMethodRegisterClobberedPreCall()) {
     // Method register shouldn't have been crushed by setting up outgoing
     // arguments
     __ Call(mr_conv->MethodRegister(), Method::NativeMethodOffset(),
diff --git a/src/object.cc b/src/object.cc
index 6490797..63c9237 100644
--- a/src/object.cc
+++ b/src/object.cc
@@ -579,8 +579,14 @@
     // assume that this is some initial value that will always lie in code
     return true;
   } else {
+#if defined(__arm__)
+    pc &= ~0x1;  // clear any possible thumb instruction mode bit
+#endif
     uint32_t rel_offset = pc - reinterpret_cast<uintptr_t>(GetCodeArray()->GetData());
-    return rel_offset < static_cast<uint32_t>(GetCodeArray()->GetLength());
+    // Strictly the following test should be a less-than, however, if the last
+    // instruction is a call to an exception throw we may see return addresses
+    // that are 1 beyond the end of code.
+    return rel_offset <= static_cast<uint32_t>(GetCodeArray()->GetLength());
   }
 }
 
diff --git a/src/runtime_support.S b/src/runtime_support.S
index 8b904b8..5372742 100644
--- a/src/runtime_support.S
+++ b/src/runtime_support.S
@@ -127,7 +127,6 @@
 
     .global art_deliver_exception
     .extern artDeliverExceptionHelper
-    .extern _ZN3art6Thread5self_E
     /*
      * Called by managed code, saves callee saves and then calls artThrowExceptionHelper
      * that will place a mock Method* at the bottom of the stack.
diff --git a/src/runtime_support.h b/src/runtime_support.h
index 4915314..1f8da91 100644
--- a/src/runtime_support.h
+++ b/src/runtime_support.h
@@ -3,13 +3,15 @@
 #ifndef ART_SRC_RUNTIME_SUPPORT_H_
 #define ART_SRC_RUNTIME_SUPPORT_H_
 
+/* Helper for both JNI and regular compiled code */
+extern "C" void art_deliver_exception(void*);
+
 #if defined(__arm__)
   /* Compiler helpers */
   extern "C" uint64_t art_shl_long(uint64_t, uint32_t);
   extern "C" uint64_t art_shr_long(uint64_t, uint32_t);
   extern "C" uint64_t art_ushr_long(uint64_t, uint32_t);
   extern "C" void art_invoke_interface_trampoline(void*, void*, void*, void*);
-  extern "C" void art_deliver_exception(void*);
 
   /* Conversions */
   extern "C" float __aeabi_i2f(int op1);             // OP_INT_TO_FLOAT
@@ -45,8 +47,4 @@
 
 #endif
 
-#if defined(__i386__)
-extern "C" void art_deliver_exception(void*);
-#endif
-
 #endif  // ART_SRC_RUNTIME_SUPPORT_H_
diff --git a/src/thread.cc b/src/thread.cc
index 92b3d4f..e1207d0 100644
--- a/src/thread.cc
+++ b/src/thread.cc
@@ -68,6 +68,10 @@
   // Place a special frame at the TOS that will save all callee saves
   *sp = thread->CalleeSaveMethod();
   thread->SetTopOfStack(sp, 0);
+  if (exception == NULL) {
+    thread->ThrowNewException("Ljava/lang/NullPointerException;", "throw with null exception");
+    exception = thread->GetException();
+  }
   thread->DeliverException(exception);
 }
 
@@ -312,11 +316,8 @@
   pLdivmod = __aeabi_ldivmod;
   pLmul = __aeabi_lmul;
   pInvokeInterfaceTrampoline = art_invoke_interface_trampoline;
-  pDeliverException = art_deliver_exception;
 #endif
-#if defined(__i386__)
   pDeliverException = art_deliver_exception;
-#endif
   pF2l = F2L;
   pD2l = D2L;
   pAllocFromCode = Array::AllocFromCode;
@@ -1304,8 +1305,8 @@
   if (catch_finder.native_method_count_ == 1) {
     PopSirt();
   } else {
-    // We only expect the stack crawl to have passed 1 native method as its terminated
-    // by a up call
+    // We only expect the stack crawl to have passed 1 native method as it's terminated
+    // by an up call
     DCHECK_EQ(catch_finder.native_method_count_, 0u);
   }
   long_jump_context->SetSP(reinterpret_cast<intptr_t>(catch_finder.handler_frame_.GetSP()));
diff --git a/test/IntMath/IntMath.java b/test/IntMath/IntMath.java
index 4c445b7..bffa894 100644
--- a/test/IntMath/IntMath.java
+++ b/test/IntMath/IntMath.java
@@ -103,10 +103,19 @@
         throw new NullPointerException();
     }
 
+    static void throwImplicitNullPointerException() {
+      throw null;
+    }
+
     static int catchBlock(int x) {
         try {
-            x += 123;
-            throwNullPointerException();
+            if (x == 1000) {
+                x += 123;
+                throwNullPointerException();
+            } else {
+                x += 321;
+                throwImplicitNullPointerException();
+            }
         } catch (NullPointerException npe) {
             x += 456;
         }