Merge "Workaround for test 064 failure" into ics-mr1-plus-art
diff --git a/build/Android.libart-compiler-llvm.mk b/build/Android.libart-compiler-llvm.mk
index bb7b458..1b584d6 100644
--- a/build/Android.libart-compiler-llvm.mk
+++ b/build/Android.libart-compiler-llvm.mk
@@ -83,11 +83,11 @@
     libLLVMARMCodeGen \
     libLLVMARMDesc
 
-  libart_compiler_llvm_mips_STATIC_LIBRARIES := \
-    libLLVMMipsInfo \
-    libLLVMMipsCodeGen \
-    libLLVMMipsDesc \
-    libLLVMMipsAsmPrinter \
+#  libart_compiler_llvm_mips_STATIC_LIBRARIES := \
+#    libLLVMMipsInfo \
+#    libLLVMMipsCodeGen \
+#    libLLVMMipsDesc \
+#    libLLVMMipsAsmPrinter \
 
   libart_compiler_llvm_x86_STATIC_LIBRARIES := \
     libLLVMX86Info \
diff --git a/build/Android.libart.mk b/build/Android.libart.mk
index 5bc8f46..aa00a31 100644
--- a/build/Android.libart.mk
+++ b/build/Android.libart.mk
@@ -88,11 +88,11 @@
       libLLVMARMCodeGen \
       libLLVMARMDesc
 
-    libart_mips_STATIC_LIBRARIES := \
-      libLLVMMipsInfo \
-      libLLVMMipsCodeGen \
-      libLLVMMipsDesc \
-      libLLVMMipsAsmPrinter \
+#    libart_mips_STATIC_LIBRARIES := \
+#      libLLVMMipsInfo \
+#      libLLVMMipsCodeGen \
+#      libLLVMMipsDesc \
+#      libLLVMMipsAsmPrinter \
 
     libart_x86_STATIC_LIBRARIES := \
       libLLVMX86Info \
diff --git a/src/check_jni.cc b/src/check_jni.cc
index b8a492d..8efdd1b 100644
--- a/src/check_jni.cc
+++ b/src/check_jni.cc
@@ -54,6 +54,7 @@
   if (vm->check_jni_abort_hook != NULL) {
     vm->check_jni_abort_hook(os.str());
   } else {
+    self->SetState(Thread::kNative); // Ensure that we get a native stack trace for this thread.
     LOG(FATAL) << os.str();
   }
 }
diff --git a/src/compiler.cc b/src/compiler.cc
index 8e8958b..fe4f4fc 100644
--- a/src/compiler.cc
+++ b/src/compiler.cc
@@ -282,11 +282,9 @@
       support_debugging_(support_debugging),
       stats_(new AOTCompilationStats),
       image_classes_(image_classes),
-#if defined(ART_USE_LLVM_COMPILER)
-      compiler_llvm_(NULL),
-#endif
       compiler_library_(NULL),
       compiler_(NULL),
+      compiler_context_(NULL),
       jni_compiler_(NULL),
       create_invoke_stub_(NULL)
 {
diff --git a/src/compiler.h b/src/compiler.h
index 55273b7..aa32854 100644
--- a/src/compiler.h
+++ b/src/compiler.h
@@ -32,18 +32,11 @@
 
 namespace art {
 
-#if defined(ART_USE_LLVM_COMPILER)
-namespace compiler_llvm {
-class CompilerLLVM;
-}
-#endif
-
 class AOTCompilationStats;
 class Context;
 class OatCompilationUnit;
 class TimingLogger;
 
-
 class Compiler {
  public:
   // Create a compiler targeting the requested "instruction_set".
@@ -129,15 +122,16 @@
   void SetBitcodeFileName(std::string const& filename);
   std::string const& GetElfFileName();
   std::string const& GetBitcodeFileName();
-
-  void SetCompilerLLVM(compiler_llvm::CompilerLLVM* compiler_llvm) {
-    compiler_llvm_ = compiler_llvm;
-  }
-  compiler_llvm::CompilerLLVM* GetCompilerLLVM() const {
-    return compiler_llvm_;
-  }
 #endif
 
+  void SetCompilerContext(void* compiler_context) {
+    compiler_context_ = compiler_context;
+  }
+
+  void* GetCompilerContext() const {
+    return compiler_context_;
+  }
+
  private:
 
   // Checks if class specified by type_idx is one of the image_classes_
@@ -202,7 +196,6 @@
   const std::set<std::string>* image_classes_;
 
 #if defined(ART_USE_LLVM_COMPILER)
-  compiler_llvm::CompilerLLVM* compiler_llvm_;
   std::string elf_filename_;
   std::string bitcode_filename_;
   typedef void (*CompilerCallbackFn)(Compiler& compiler);
@@ -217,6 +210,8 @@
                                         const DexFile& dex_file);
   CompilerFn compiler_;
 
+  void* compiler_context_;
+
   typedef CompiledMethod* (*JniCompilerFn)(Compiler& compiler,
                                            uint32_t access_flags, uint32_t method_idx,
                                            const ClassLoader* class_loader,
diff --git a/src/compiler_llvm/compiler_llvm.cc b/src/compiler_llvm/compiler_llvm.cc
index 5ef1710..dc3b7cb 100644
--- a/src/compiler_llvm/compiler_llvm.cc
+++ b/src/compiler_llvm/compiler_llvm.cc
@@ -206,32 +206,25 @@
   return upcall_compiler->CreateStub(is_static, shorty);
 }
 
+CompilerLLVM* EnsureCompilerLLVM(art::Compiler& compiler) {
+  if (compiler.GetCompilerContext() == NULL) {
+    compiler.SetCompilerContext(new CompilerLLVM(&compiler, compiler.GetInstructionSet()));
+  }
+  CompilerLLVM* compiler_llvm = reinterpret_cast<CompilerLLVM*>(compiler.GetCompilerContext());
+  compiler_llvm->SetElfFileName(compiler.GetElfFileName());
+  compiler_llvm->SetBitcodeFileName(compiler.GetBitcodeFileName());
+  return compiler_llvm;
+}
 
 } // namespace compiler_llvm
 } // namespace art
 
-namespace {
-
-void ensureCompilerLLVM(art::Compiler& compiler) {
-  if (compiler.GetCompilerLLVM() == NULL) {
-    compiler.SetCompilerLLVM(new art::compiler_llvm::CompilerLLVM(&compiler,
-                                                                  compiler.GetInstructionSet()));
-  }
-  art::compiler_llvm::CompilerLLVM* compiler_llvm = compiler.GetCompilerLLVM();
-  compiler_llvm->SetElfFileName(compiler.GetElfFileName());
-  compiler_llvm->SetBitcodeFileName(compiler.GetBitcodeFileName());
-}
-
-}  // anonymous namespace
-
 extern "C" art::CompiledMethod* ArtCompileMethod(art::Compiler& compiler,
                                                  const art::DexFile::CodeItem* code_item,
                                                  uint32_t access_flags, uint32_t method_idx,
                                                  const art::ClassLoader* class_loader,
                                                  const art::DexFile& dex_file)
 {
-  ensureCompilerLLVM(compiler);
-
   art::ClassLinker *class_linker = art::Runtime::Current()->GetClassLinker();
   art::DexCache *dex_cache = class_linker->FindDexCache(dex_file);
 
@@ -239,15 +232,13 @@
     class_loader, class_linker, dex_file, *dex_cache, code_item,
     method_idx, access_flags);
 
-  return compiler.GetCompilerLLVM()->CompileDexMethod(&oat_compilation_unit);
+  return art::compiler_llvm::EnsureCompilerLLVM(compiler)->CompileDexMethod(&oat_compilation_unit);
 }
 
 extern "C" art::CompiledMethod* ArtJniCompileMethod(art::Compiler& compiler,
                                                     uint32_t access_flags, uint32_t method_idx,
                                                     const art::ClassLoader* class_loader,
                                                     const art::DexFile& dex_file) {
-  ensureCompilerLLVM(compiler);
-
   art::ClassLinker *class_linker = art::Runtime::Current()->GetClassLinker();
   art::DexCache *dex_cache = class_linker->FindDexCache(dex_file);
 
@@ -255,30 +246,26 @@
     class_loader, class_linker, dex_file, *dex_cache, NULL,
     method_idx, access_flags);
 
-  art::CompiledMethod* result =
-      compiler.GetCompilerLLVM()->CompileNativeMethod(&oat_compilation_unit);
-  compiler.GetCompilerLLVM()->MaterializeIfThresholdReached();
+  art::compiler_llvm::CompilerLLVM* compiler_llvm = art::compiler_llvm::EnsureCompilerLLVM(compiler);
+  art::CompiledMethod* result = compiler_llvm->CompileNativeMethod(&oat_compilation_unit);
+  compiler_llvm->MaterializeIfThresholdReached();
   return result;
 }
 
 extern "C" art::CompiledInvokeStub* ArtCreateInvokeStub(art::Compiler& compiler, bool is_static,
                                                         const char* shorty, uint32_t shorty_len) {
-  ensureCompilerLLVM(compiler);
-  //shorty_len = 0; // To make the compiler happy
-  return compiler.GetCompilerLLVM()->CreateInvokeStub(is_static, shorty);
+  return art::compiler_llvm::EnsureCompilerLLVM(compiler)->CreateInvokeStub(is_static, shorty);
 }
 
 extern "C" void compilerLLVMMaterializeRemainder(art::Compiler& compiler) {
-  ensureCompilerLLVM(compiler);
-  compiler.GetCompilerLLVM()->MaterializeRemainder();
+  art::compiler_llvm::EnsureCompilerLLVM(compiler)->MaterializeRemainder();
 }
 
 // Note: Using this function carefully!!! This is temporary solution, we will remove it.
 extern "C" art::MutexLock* compilerLLVMMutexLock(art::Compiler& compiler) {
-  ensureCompilerLLVM(compiler);
-  return new art::MutexLock(compiler.GetCompilerLLVM()->compiler_lock_);
+  return new art::MutexLock(art::compiler_llvm::EnsureCompilerLLVM(compiler)->compiler_lock_);
 }
 
 extern "C" void compilerLLVMDispose(art::Compiler& compiler) {
-  delete compiler.GetCompilerLLVM();
+  delete art::compiler_llvm::EnsureCompilerLLVM(compiler);
 }
diff --git a/src/java_lang_reflect_Field.cc b/src/java_lang_reflect_Field.cc
index eb56edb..fc1ea4e 100644
--- a/src/java_lang_reflect_Field.cc
+++ b/src/java_lang_reflect_Field.cc
@@ -208,7 +208,7 @@
   // Unbox the value, if necessary.
   Object* boxed_value = Decode<Object*>(env, javaValue);
   JValue unboxed_value;
-  if (!UnboxPrimitive(env, boxed_value, FieldHelper(f).GetType(), unboxed_value)) {
+  if (!UnboxPrimitive(env, boxed_value, FieldHelper(f).GetType(), unboxed_value, "field")) {
     return;
   }
 
diff --git a/src/reflection.cc b/src/reflection.cc
index 46b2ff3..c317be0 100644
--- a/src/reflection.cc
+++ b/src/reflection.cc
@@ -91,7 +91,8 @@
     Object* arg = objects->Get(i);
     Class* dst_class = mh.GetClassFromTypeIdx(classes->GetTypeItem(i).type_idx_);
     if (dst_class->IsPrimitive()) {
-      if (!UnboxPrimitive(env, arg, dst_class, decoded_args[i])) {
+      std::string what(StringPrintf("argument %d", i + 1)); // Humans count from 1.
+      if (!UnboxPrimitive(env, arg, dst_class, decoded_args[i], what.c_str())) {
         return NULL;
       }
     } else {
@@ -119,16 +120,17 @@
 }
 
 bool VerifyObjectInClass(JNIEnv* env, Object* o, Class* c) {
+  const char* exception = NULL;
   if (o == NULL) {
-    jniThrowNullPointerException(env, "receiver for non-static field access was null");
-    return false;
+    exception = "java/lang/NullPointerException";
+  } else if (!o->InstanceOf(c)) {
+    exception = "java/lang/IllegalArgumentException";
   }
-  if (!o->InstanceOf(c)) {
-    std::string expectedClassName(PrettyDescriptor(c));
-    std::string actualClassName(PrettyTypeOf(o));
-    jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
-        "expected receiver of type %s, but got %s",
-        expectedClassName.c_str(), actualClassName.c_str());
+  if (exception != NULL) {
+    std::string expected_class_name(PrettyDescriptor(c));
+    std::string actual_class_name(PrettyTypeOf(o));
+    jniThrowExceptionFmt(env, exception, "expected receiver of type %s, but got %s",
+                         expected_class_name.c_str(), actual_class_name.c_str());
     return false;
   }
   return true;
@@ -281,26 +283,30 @@
   m->Invoke(self, NULL, args.get(), &value);
 }
 
-bool UnboxPrimitive(JNIEnv* env, Object* o, Class* dst_class, JValue& unboxed_value) {
+bool UnboxPrimitive(JNIEnv* env, Object* o, Class* dst_class, JValue& unboxed_value, const char* what) {
   if (!dst_class->IsPrimitive()) {
     if (o != NULL && !o->InstanceOf(dst_class)) {
-      jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
-          "expected object of type %s, but got %s",
-          PrettyDescriptor(dst_class).c_str(),
-          PrettyTypeOf(o).c_str());
+      Thread::Current()->ThrowNewExceptionF("Ljava/lang/IllegalArgumentException;",
+                                            "boxed object for %s should have type %s, but got %s",
+                                            what,
+                                            PrettyDescriptor(dst_class).c_str(),
+                                            PrettyTypeOf(o).c_str());
       return false;
     }
     unboxed_value.l = o;
     return true;
   } else if (dst_class->GetPrimitiveType() == Primitive::kPrimVoid) {
-    Thread::Current()->ThrowNewException("Ljava/lang/IllegalArgumentException;",
-        "can't unbox to void");
+    Thread::Current()->ThrowNewExceptionF("Ljava/lang/IllegalArgumentException;",
+                                          "can't unbox %s to void",
+                                          what);
     return false;
   }
 
   if (o == NULL) {
-    Thread::Current()->ThrowNewException("Ljava/lang/IllegalArgumentException;",
-        "null passed for boxed primitive type");
+    Thread::Current()->ThrowNewExceptionF("Ljava/lang/IllegalArgumentException;",
+                                          "%s should have type %s, got null",
+                                          what,
+                                          PrettyDescriptor(dst_class).c_str());
     return false;
   }
 
@@ -335,7 +341,10 @@
     boxed_value.i = primitive_field->GetShort(o);  // and extend read value to 32bits
   } else {
     Thread::Current()->ThrowNewExceptionF("Ljava/lang/IllegalArgumentException;",
-        "%s is not a boxed primitive type", PrettyDescriptor(src_descriptor.c_str()).c_str());
+                                          "%s should have type %s, got %s",
+                                          what,
+                                          PrettyDescriptor(dst_class).c_str(),
+                                          PrettyDescriptor(src_descriptor.c_str()).c_str());
     return false;
   }
 
diff --git a/src/reflection.h b/src/reflection.h
index e832c3d..a286a57 100644
--- a/src/reflection.h
+++ b/src/reflection.h
@@ -28,7 +28,7 @@
 
 void InitBoxingMethods();
 void BoxPrimitive(JNIEnv* env, Primitive::Type src_class, JValue& value);
-bool UnboxPrimitive(JNIEnv* env, Object* o, Class* dst_class, JValue& unboxed_value);
+bool UnboxPrimitive(JNIEnv* env, Object* o, Class* dst_class, JValue& unboxed_value, const char* what);
 
 bool ConvertPrimitiveValue(Primitive::Type src_class, Primitive::Type dst_class, const JValue& src, JValue& dst);
 
diff --git a/src/runtime_support.cc b/src/runtime_support.cc
index 8dc518e..f5edebf 100644
--- a/src/runtime_support.cc
+++ b/src/runtime_support.cc
@@ -1147,7 +1147,8 @@
     Object* result_ref = self->DecodeJObject(result);
     if (result_ref != NULL) {
       JValue result_unboxed;
-      UnboxPrimitive(env, result_ref, proxy_mh.GetReturnType(), result_unboxed);
+      bool unboxed_okay = UnboxPrimitive(env, result_ref, proxy_mh.GetReturnType(), result_unboxed, "result");
+      CHECK(unboxed_okay);
       *reinterpret_cast<JValue*>(stack_args) = result_unboxed;
     } else {
       *reinterpret_cast<jobject*>(stack_args) = NULL;