Fix NPE message in LLVM.

Change-Id: Ie65060d065d747a6c9ad22c61d5fb29f6cf3c249
diff --git a/src/compiler_llvm/art_module.ll b/src/compiler_llvm/art_module.ll
index 874377e..434aa7b 100644
--- a/src/compiler_llvm/art_module.ll
+++ b/src/compiler_llvm/art_module.ll
@@ -57,7 +57,7 @@
 declare void @art_throw_div_zero_from_code()
 declare void @art_throw_array_bounds_from_code(i32, i32)
 declare void @art_throw_no_such_method_from_code(i32)
-declare void @art_throw_null_pointer_exception_from_code()
+declare void @art_throw_null_pointer_exception_from_code(i32)
 declare void @art_throw_stack_overflow_from_code()
 declare void @art_throw_exception_from_code(%JavaObject*)
 
diff --git a/src/compiler_llvm/generated/art_module.cc b/src/compiler_llvm/generated/art_module.cc
index 2e46efc..52048eb 100644
--- a/src/compiler_llvm/generated/art_module.cc
+++ b/src/compiler_llvm/generated/art_module.cc
@@ -412,7 +412,7 @@
 Function* func_art_throw_null_pointer_exception_from_code = mod->getFunction("art_throw_null_pointer_exception_from_code");
 if (!func_art_throw_null_pointer_exception_from_code) {
 func_art_throw_null_pointer_exception_from_code = Function::Create(
- /*Type=*/FuncTy_5,
+ /*Type=*/FuncTy_9,
  /*Linkage=*/GlobalValue::ExternalLinkage,
  /*Name=*/"art_throw_null_pointer_exception_from_code", mod); // (external, no body)
 func_art_throw_null_pointer_exception_from_code->setCallingConv(CallingConv::C);
diff --git a/src/compiler_llvm/method_compiler.cc b/src/compiler_llvm/method_compiler.cc
index f4bc3c2..615e600 100644
--- a/src/compiler_llvm/method_compiler.cc
+++ b/src/compiler_llvm/method_compiler.cc
@@ -3776,7 +3776,7 @@
 
   irb_.SetInsertPoint(block_exception);
   EmitUpdateLineNumFromDexPC(dex_pc);
-  irb_.CreateCall(irb_.GetRuntime(ThrowNullPointerException));
+  irb_.CreateCall(irb_.GetRuntime(ThrowNullPointerException), irb_.getInt32(dex_pc));
   EmitBranchExceptionLandingPad(dex_pc);
 
   irb_.SetInsertPoint(block_continue);
diff --git a/src/compiler_llvm/runtime_support_llvm.cc b/src/compiler_llvm/runtime_support_llvm.cc
index 57fd507..36343f7 100644
--- a/src/compiler_llvm/runtime_support_llvm.cc
+++ b/src/compiler_llvm/runtime_support_llvm.cc
@@ -16,6 +16,7 @@
 
 #include "class_linker.h"
 #include "dex_verifier.h"
+#include "nth_caller_visitor.h"
 #include "object.h"
 #include "object_utils.h"
 #include "runtime_support.h"
@@ -108,9 +109,12 @@
                                                 false).c_str());
 }
 
-void art_throw_null_pointer_exception_from_code() {
+void art_throw_null_pointer_exception_from_code(uint32_t dex_pc) {
   Thread* thread = Thread::Current();
-  thread->ThrowNewException("Ljava/lang/NullPointerException;", NULL);
+  NthCallerVisitor visitor(0);
+  thread->WalkStack(&visitor);
+  Method* throw_method = visitor.caller;
+  ThrowNullPointerExceptionFromDexPC(thread, throw_method, dex_pc);
 }
 
 void art_throw_stack_overflow_from_code() {
diff --git a/src/compiler_llvm/runtime_support_llvm.h b/src/compiler_llvm/runtime_support_llvm.h
index 1040b90..1dbd71d 100644
--- a/src/compiler_llvm/runtime_support_llvm.h
+++ b/src/compiler_llvm/runtime_support_llvm.h
@@ -43,7 +43,7 @@
 
 void art_throw_no_such_method_from_code(int32_t method_idx);
 
-void art_throw_null_pointer_exception_from_code();
+void art_throw_null_pointer_exception_from_code(uint32_t dex_pc);
 
 void art_throw_stack_overflow_from_code();
 
diff --git a/src/dalvik_system_VMStack.cc b/src/dalvik_system_VMStack.cc
index 8401ec1..e0862c3 100644
--- a/src/dalvik_system_VMStack.cc
+++ b/src/dalvik_system_VMStack.cc
@@ -47,7 +47,7 @@
 static jobject VMStack_getCallingClassLoader(JNIEnv* env, jclass) {
   NthCallerVisitor visitor(2);
   Thread::Current()->WalkStack(&visitor);
-  return AddLocalReference<jobject>(env, visitor.class_loader);
+  return AddLocalReference<jobject>(env, visitor.caller->GetDeclaringClass()->GetClassLoader());
 }
 
 static jobject VMStack_getClosestUserClassLoader(JNIEnv* env, jclass, jobject javaBootstrap, jobject javaSystem) {
@@ -79,7 +79,7 @@
 static jclass VMStack_getStackClass2(JNIEnv* env, jclass) {
   NthCallerVisitor visitor(3);
   Thread::Current()->WalkStack(&visitor);
-  return AddLocalReference<jclass>(env, visitor.declaring_class);
+  return AddLocalReference<jclass>(env, visitor.caller->GetDeclaringClass());
 }
 
 static jobjectArray VMStack_getThreadStackTrace(JNIEnv* env, jclass, jobject javaThread) {
diff --git a/src/java_lang_Class.cc b/src/java_lang_Class.cc
index c1d6eb0..2cd7090 100644
--- a/src/java_lang_Class.cc
+++ b/src/java_lang_Class.cc
@@ -426,7 +426,7 @@
 
   NthCallerVisitor visitor(2);
   Thread::Current()->WalkStack(&visitor);
-  Class* caller_class = visitor.declaring_class;
+  Class* caller_class = visitor.caller->GetDeclaringClass();
 
   ClassHelper caller_ch(caller_class);
   if (!caller_class->CanAccess(c)) {
diff --git a/src/nth_caller_visitor.h b/src/nth_caller_visitor.h
index 6f82fa9..07b9e49 100644
--- a/src/nth_caller_visitor.h
+++ b/src/nth_caller_visitor.h
@@ -24,21 +24,18 @@
 
 // Walks up the stack 'n' callers, when used with Thread::WalkStack.
 struct NthCallerVisitor : public Thread::StackVisitor {
-  NthCallerVisitor(size_t n) : n(n), count(0), declaring_class(NULL), class_loader(NULL) {}
+  NthCallerVisitor(size_t n) : n(n), count(0), caller(NULL) {}
   bool VisitFrame(const Frame& f, uintptr_t) {
-    DCHECK(class_loader == NULL);
+    DCHECK(caller == NULL);
     if (count++ == n) {
-      Method* m = f.GetMethod();
-      declaring_class = m->GetDeclaringClass();
-      class_loader = declaring_class->GetClassLoader();
+      caller = f.GetMethod();
       return false;
     }
     return true;
   }
   size_t n;
   size_t count;
-  Class* declaring_class;
-  Object* class_loader;
+  Method* caller;
 };
 
 }  // namespace art
diff --git a/src/oat/runtime/support_throw.cc b/src/oat/runtime/support_throw.cc
index 45600fd..7d198c9 100644
--- a/src/oat/runtime/support_throw.cc
+++ b/src/oat/runtime/support_throw.cc
@@ -55,73 +55,7 @@
   frame.Next();
   Method* throw_method = frame.GetMethod();
   uint32_t dex_pc = throw_method->ToDexPC(throw_native_pc - 2);
-  const DexFile::CodeItem* code = MethodHelper(throw_method).GetCodeItem();
-  CHECK_LT(dex_pc, code->insns_size_in_code_units_);
-  const Instruction* instr = Instruction::At(&code->insns_[dex_pc]);
-  DecodedInstruction dec_insn(instr);
-  switch (instr->Opcode()) {
-    case Instruction::INVOKE_DIRECT:
-    case Instruction::INVOKE_DIRECT_RANGE:
-      ThrowNullPointerExceptionForMethodAccess(self, throw_method, dec_insn.vB, kDirect);
-      break;
-    case Instruction::INVOKE_VIRTUAL:
-    case Instruction::INVOKE_VIRTUAL_RANGE:
-      ThrowNullPointerExceptionForMethodAccess(self, throw_method, dec_insn.vB, kVirtual);
-      break;
-    case Instruction::IGET:
-    case Instruction::IGET_WIDE:
-    case Instruction::IGET_OBJECT:
-    case Instruction::IGET_BOOLEAN:
-    case Instruction::IGET_BYTE:
-    case Instruction::IGET_CHAR:
-    case Instruction::IGET_SHORT: {
-      Field* field =
-          Runtime::Current()->GetClassLinker()->ResolveField(dec_insn.vC, throw_method, false);
-      ThrowNullPointerExceptionForFieldAccess(self, field, true /* read */);
-      break;
-    }
-    case Instruction::IPUT:
-    case Instruction::IPUT_WIDE:
-    case Instruction::IPUT_OBJECT:
-    case Instruction::IPUT_BOOLEAN:
-    case Instruction::IPUT_BYTE:
-    case Instruction::IPUT_CHAR:
-    case Instruction::IPUT_SHORT: {
-      Field* field =
-          Runtime::Current()->GetClassLinker()->ResolveField(dec_insn.vC, throw_method, false);
-      ThrowNullPointerExceptionForFieldAccess(self, field, false /* write */);
-      break;
-    }
-    case Instruction::AGET:
-    case Instruction::AGET_WIDE:
-    case Instruction::AGET_OBJECT:
-    case Instruction::AGET_BOOLEAN:
-    case Instruction::AGET_BYTE:
-    case Instruction::AGET_CHAR:
-    case Instruction::AGET_SHORT:
-      self->ThrowNewException("Ljava/lang/NullPointerException;",
-                              "Attempt to read from null array");
-      break;
-    case Instruction::APUT:
-    case Instruction::APUT_WIDE:
-    case Instruction::APUT_OBJECT:
-    case Instruction::APUT_BOOLEAN:
-    case Instruction::APUT_BYTE:
-    case Instruction::APUT_CHAR:
-    case Instruction::APUT_SHORT:
-      self->ThrowNewException("Ljava/lang/NullPointerException;",
-                              "Attempt to write to null array");
-      break;
-    default: {
-      const DexFile& dex_file = Runtime::Current()->GetClassLinker()
-          ->FindDexFile(throw_method->GetDeclaringClass()->GetDexCache());
-      std::string message("Null pointer exception during instruction '");
-      message += instr->DumpString(&dex_file);
-      message += "'";
-      self->ThrowNewException("Ljava/lang/NullPointerException;", message.c_str());
-      break;
-    }
-  }
+  ThrowNullPointerExceptionFromDexPC(self, throw_method, dex_pc);
   self->DeliverException();
 }
 
diff --git a/src/runtime_support.cc b/src/runtime_support.cc
index 7b907ae..40b43c1 100644
--- a/src/runtime_support.cc
+++ b/src/runtime_support.cc
@@ -106,6 +106,76 @@
                            PrettyMethod(method_idx, dex_file, true).c_str());
 }
 
+void ThrowNullPointerExceptionFromDexPC(Thread* self, Method* throw_method, uint32_t dex_pc) {
+  const DexFile::CodeItem* code = MethodHelper(throw_method).GetCodeItem();
+  CHECK_LT(dex_pc, code->insns_size_in_code_units_);
+  const Instruction* instr = Instruction::At(&code->insns_[dex_pc]);
+  DecodedInstruction dec_insn(instr);
+  switch (instr->Opcode()) {
+    case Instruction::INVOKE_DIRECT:
+    case Instruction::INVOKE_DIRECT_RANGE:
+      ThrowNullPointerExceptionForMethodAccess(self, throw_method, dec_insn.vB, kDirect);
+      break;
+    case Instruction::INVOKE_VIRTUAL:
+    case Instruction::INVOKE_VIRTUAL_RANGE:
+      ThrowNullPointerExceptionForMethodAccess(self, throw_method, dec_insn.vB, kVirtual);
+      break;
+    case Instruction::IGET:
+    case Instruction::IGET_WIDE:
+    case Instruction::IGET_OBJECT:
+    case Instruction::IGET_BOOLEAN:
+    case Instruction::IGET_BYTE:
+    case Instruction::IGET_CHAR:
+    case Instruction::IGET_SHORT: {
+      Field* field =
+          Runtime::Current()->GetClassLinker()->ResolveField(dec_insn.vC, throw_method, false);
+      ThrowNullPointerExceptionForFieldAccess(self, field, true /* read */);
+      break;
+    }
+    case Instruction::IPUT:
+    case Instruction::IPUT_WIDE:
+    case Instruction::IPUT_OBJECT:
+    case Instruction::IPUT_BOOLEAN:
+    case Instruction::IPUT_BYTE:
+    case Instruction::IPUT_CHAR:
+    case Instruction::IPUT_SHORT: {
+      Field* field =
+          Runtime::Current()->GetClassLinker()->ResolveField(dec_insn.vC, throw_method, false);
+      ThrowNullPointerExceptionForFieldAccess(self, field, false /* write */);
+      break;
+    }
+    case Instruction::AGET:
+    case Instruction::AGET_WIDE:
+    case Instruction::AGET_OBJECT:
+    case Instruction::AGET_BOOLEAN:
+    case Instruction::AGET_BYTE:
+    case Instruction::AGET_CHAR:
+    case Instruction::AGET_SHORT:
+      self->ThrowNewException("Ljava/lang/NullPointerException;",
+                              "Attempt to read from null array");
+      break;
+    case Instruction::APUT:
+    case Instruction::APUT_WIDE:
+    case Instruction::APUT_OBJECT:
+    case Instruction::APUT_BOOLEAN:
+    case Instruction::APUT_BYTE:
+    case Instruction::APUT_CHAR:
+    case Instruction::APUT_SHORT:
+      self->ThrowNewException("Ljava/lang/NullPointerException;",
+                              "Attempt to write to null array");
+      break;
+    default: {
+      const DexFile& dex_file = Runtime::Current()->GetClassLinker()
+          ->FindDexFile(throw_method->GetDeclaringClass()->GetDexCache());
+      std::string message("Null pointer exception during instruction '");
+      message += instr->DumpString(&dex_file);
+      message += "'";
+      self->ThrowNewException("Ljava/lang/NullPointerException;", message.c_str());
+      break;
+    }
+  }
+}
+
 std::string FieldNameFromIndex(const Method* method, uint32_t ref,
                                verifier::VerifyErrorRefType ref_type, bool access) {
   CHECK_EQ(static_cast<int>(ref_type), static_cast<int>(verifier::VERIFY_ERROR_REF_FIELD));
diff --git a/src/runtime_support.h b/src/runtime_support.h
index 0229bc1..0cbfd59 100644
--- a/src/runtime_support.h
+++ b/src/runtime_support.h
@@ -54,6 +54,7 @@
 void ThrowNullPointerExceptionForFieldAccess(Thread* self, Field* field, bool is_read);
 void ThrowNullPointerExceptionForMethodAccess(Thread* self, Method* caller, uint32_t method_idx,
                                               InvokeType type);
+void ThrowNullPointerExceptionFromDexPC(Thread* self, Method* caller, uint32_t dex_pc);
 
 std::string FieldNameFromIndex(const Method* method, uint32_t ref,
                                verifier::VerifyErrorRefType ref_type, bool access);