Make ICCE logic common, refactor throws.

There were 2 sets of ICCE logic in ClassLinker::ResolveMethod and
Method::CheckIncompatibleClassChange, merged into just 1 piece of logic
in Method::CheckIncompatibleClassChange.

Move Throw... routines into own file and make adding the dex location to
the detail message more thorough.

Change-Id: I953dbfa3fed3767f35799b2f82b16637c437dbbe
diff --git a/build/Android.common.mk b/build/Android.common.mk
index 7dbe04c..d02b998 100644
--- a/build/Android.common.mk
+++ b/build/Android.common.mk
@@ -146,6 +146,7 @@
 	src/card_table.cc \
 	src/check_jni.cc \
 	src/class_linker.cc \
+	src/common_throws.cc \
 	src/compiled_method.cc \
 	src/compiler.cc \
 	src/debugger.cc \
diff --git a/src/class_linker.cc b/src/class_linker.cc
index 8ee3b1e..f6fb470 100644
--- a/src/class_linker.cc
+++ b/src/class_linker.cc
@@ -118,7 +118,9 @@
   // a NoClassDefFoundError (v2 2.17.5).  The exception to this rule is if we
   // failed in verification, in which case v2 5.4.1 says we need to re-throw
   // the previous error.
-  LOG(INFO) << "Rejecting re-init on previously-failed class " << PrettyClass(c);
+  if (!Runtime::Current()->IsCompiler()) {  // Give info if this occurs at runtime.
+    LOG(INFO) << "Rejecting re-init on previously-failed class " << PrettyClass(c);
+  }
 
   CHECK(c->IsErroneous()) << PrettyClass(c) << " " << c->GetStatus();
   if (c->GetVerifyErrorClass() != NULL) {
@@ -3465,31 +3467,8 @@
   }
   if (resolved != NULL) {
     // We found a method, check for incompatible class changes.
-    switch (type) {
-      case kDirect:
-        if (resolved->IsStatic()) {
-          resolved = NULL;  // Incompatible class change.
-        }
-        break;
-      case kStatic:
-        if (!resolved->IsStatic()) {
-          resolved = NULL;  // Incompatible class change.
-        }
-        break;
-      case kInterface:
-        if (resolved->IsConstructor() || !resolved->GetDeclaringClass()->IsInterface()) {
-          resolved = NULL;  // Incompatible class change.
-        }
-        break;
-      case kSuper:
-        // TODO: appropriate checks for call to super class.
-        break;
-      case kVirtual:
-        if (resolved->IsConstructor() || (resolved->GetDeclaringClass()->IsInterface() &&
-                                          !resolved->IsMiranda())) {
-          resolved = NULL;  // Incompatible class change.
-        }
-        break;
+    if (resolved->CheckIncompatibleClassChange(type)) {
+      resolved = NULL;
     }
   }
   if (resolved != NULL) {
@@ -3518,12 +3497,12 @@
       Class* methods_class = resolved->GetDeclaringClass();
       Class* referring_class = referrer->GetDeclaringClass();
       if (!referring_class->CanAccess(methods_class)) {
-        ThrowNewIllegalAccessErrorClassForMethodDispatch(Thread::Current(), referring_class, methods_class,
-                                                         referrer, resolved, type);
+        ThrowIllegalAccessErrorClassForMethodDispatch(referring_class, methods_class,
+                                                      referrer, resolved, type);
         return NULL;
       } else if (!referring_class->CanAccessMember(methods_class,
                                                    resolved->GetAccessFlags())) {
-        ThrowNewIllegalAccessErrorMethod(Thread::Current(), referring_class, resolved);
+        ThrowIllegalAccessErrorMethod(referring_class, resolved);
         return NULL;
       }
     }
diff --git a/src/common_throws.cc b/src/common_throws.cc
new file mode 100644
index 0000000..5bd30b4
--- /dev/null
+++ b/src/common_throws.cc
@@ -0,0 +1,250 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "common_throws.h"
+
+#include "dex_instruction.h"
+#include "invoke_type.h"
+#include "logging.h"
+#include "object_utils.h"
+#include "thread.h"
+
+#include <sstream>
+
+namespace art {
+
+static void AddReferrerLocation(std::ostream& os, const Method* referrer)
+    SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_) {
+  if (referrer != NULL) {
+    ClassHelper kh(referrer->GetDeclaringClass());
+    std::string location(kh.GetLocation());
+    if (!location.empty()) {
+      os << " (accessed from " << location << ")";
+    }
+  }
+}
+
+static void AddReferrerLocationFromClass(std::ostream& os, Class* referrer)
+    SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_) {
+  if (referrer != NULL) {
+    ClassHelper kh(referrer);
+    std::string location(kh.GetLocation());
+    if (!location.empty()) {
+      os << " (declaration of '" << PrettyDescriptor(referrer)
+            << "' appears in " << location << ")";
+    }
+  }
+}
+
+// NullPointerException
+
+void ThrowNullPointerExceptionForFieldAccess(Field* field, bool is_read) {
+  std::ostringstream msg;
+  msg << "Attempt to " << (is_read ? "read from" : "write to")
+      << " field '" << PrettyField(field, true) << "' on a null object reference";
+  Thread::Current()->ThrowNewException("Ljava/lang/NullPointerException;", msg.str().c_str());
+}
+
+void ThrowNullPointerExceptionForMethodAccess(Method* caller, uint32_t method_idx,
+                                              InvokeType type) {
+  DexCache* dex_cache = caller->GetDeclaringClass()->GetDexCache();
+  const DexFile& dex_file = Runtime::Current()->GetClassLinker()->FindDexFile(dex_cache);
+  std::ostringstream msg;
+  msg << "Attempt to invoke " << ToStr<InvokeType>(type).str() << " method '"
+      << PrettyMethod(method_idx, dex_file, true) << "' on a null object reference";
+  Thread::Current()->ThrowNewException("Ljava/lang/NullPointerException;", msg.str().c_str());
+}
+
+void ThrowNullPointerExceptionFromDexPC(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(throw_method, dec_insn.vB, kDirect);
+      break;
+    case Instruction::INVOKE_VIRTUAL:
+    case Instruction::INVOKE_VIRTUAL_RANGE:
+      ThrowNullPointerExceptionForMethodAccess(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(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(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:
+      Thread::Current()->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:
+      Thread::Current()->ThrowNewException("Ljava/lang/NullPointerException;",
+                                           "Attempt to write to null array");
+      break;
+    case Instruction::ARRAY_LENGTH:
+      Thread::Current()->ThrowNewException("Ljava/lang/NullPointerException;",
+                                           "Attempt to get length of 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 += "'";
+      Thread::Current()->ThrowNewException("Ljava/lang/NullPointerException;", message.c_str());
+      break;
+    }
+  }
+}
+
+// IllegalAccessError
+
+void ThrowIllegalAccessErrorClass(Class* referrer, Class* accessed) {
+  std::ostringstream msg;
+  msg << "Illegal class access: '" << PrettyDescriptor(referrer) << "' -> '"
+      << PrettyDescriptor(accessed) << "'";
+  AddReferrerLocationFromClass(msg, referrer);
+  Thread::Current()->ThrowNewException("Ljava/lang/IllegalAccessError;", msg.str().c_str());
+}
+
+void ThrowIllegalAccessErrorClassForMethodDispatch(Class* referrer, Class* accessed,
+                                                   const Method* caller,
+                                                   const Method* called,
+                                                   InvokeType type) {
+  std::ostringstream msg;
+  msg << "Illegal class access ('" << PrettyDescriptor(referrer) << "' -> '"
+      << PrettyDescriptor(accessed) << "') in attempt to invoke " << ToStr<InvokeType>(type).str()
+      << " method " << PrettyMethod(called).c_str();
+  AddReferrerLocation(msg, caller);
+  Thread::Current()->ThrowNewException("Ljava/lang/IllegalAccessError;", msg.str().c_str());
+}
+
+void ThrowIllegalAccessErrorMethod(Class* referrer, Method* accessed) {
+  std::ostringstream msg;
+  msg << "Method '" << PrettyMethod(accessed) << "' is inaccessible to class '"
+      << PrettyDescriptor(referrer) << "'";
+  AddReferrerLocationFromClass(msg, referrer);
+  Thread::Current()->ThrowNewException("Ljava/lang/IllegalAccessError;", msg.str().c_str());
+}
+
+void ThrowIllegalAccessErrorField(Class* referrer, Field* accessed) {
+  std::ostringstream msg;
+  msg << "Field '" << PrettyField(accessed, false) << "' is inaccessible to class '"
+      << PrettyDescriptor(referrer) << "'";
+  AddReferrerLocationFromClass(msg, referrer);
+  Thread::Current()->ThrowNewException("Ljava/lang/IllegalAccessError;", msg.str().c_str());
+}
+
+void ThrowIllegalAccessErrorFinalField(const Method* referrer, Field* accessed) {
+  std::ostringstream msg;
+  msg << "Final field '" << PrettyField(accessed, false) << "' cannot be written to by method '"
+      << PrettyMethod(referrer) << "'";
+  AddReferrerLocation(msg, referrer);
+  Thread::Current()->ThrowNewException("Ljava/lang/IllegalAccessError;", msg.str().c_str());
+}
+
+// IncompatibleClassChangeError
+
+void ThrowIncompatibleClassChangeError(InvokeType expected_type, InvokeType found_type,
+                                       Method* method, const Method* referrer) {
+  std::ostringstream msg;
+  msg << "The method '" << PrettyMethod(method) << "' was expected to be of type "
+      << expected_type << " but instead was found to be of type " << found_type;
+  AddReferrerLocation(msg, referrer);
+  Thread::Current()->ThrowNewException("Ljava/lang/IncompatibleClassChangeError;",
+                                       msg.str().c_str());
+}
+
+void ThrowIncompatibleClassChangeErrorClassForInterfaceDispatch(const Method* interface_method,
+                                                                Object* this_object,
+                                                                const Method* referrer) {
+  // Referrer is calling interface_method on this_object, however, the interface_method isn't
+  // implemented by this_object.
+  CHECK(this_object != NULL);
+  std::ostringstream msg;
+  msg << "Class '" << PrettyDescriptor(this_object->GetClass())
+      << "' does not implement interface '"
+      << PrettyDescriptor(interface_method->GetDeclaringClass())
+      << "' in call to '" << PrettyMethod(interface_method) << "'";
+  AddReferrerLocation(msg, referrer);
+  Thread::Current()->ThrowNewException("Ljava/lang/IncompatibleClassChangeError;",
+                                       msg.str().c_str());
+}
+
+void ThrowIncompatibleClassChangeErrorField(const Field* resolved_field, bool is_static,
+                                            const Method* referrer) {
+  std::ostringstream msg;
+  msg << "Expected '" << PrettyField(resolved_field) << "' to be a "
+      << (is_static ? "static" : "instance") << " field";
+  AddReferrerLocation(msg, referrer);
+  Thread::Current()->ThrowNewException("Ljava/lang/IncompatibleClassChangeError;",
+                                       msg.str().c_str());
+}
+
+// NoSuchMethodError
+
+void ThrowNoSuchMethodError(InvokeType type, Class* c, const StringPiece& name,
+                            const StringPiece& signature, const Method* referrer) {
+  std::ostringstream msg;
+  ClassHelper kh(c);
+  msg << "No " << type << " method " << name << signature
+      << " in class " << kh.GetDescriptor() << " or its super classes";
+  AddReferrerLocation(msg, referrer);
+  Thread::Current()->ThrowNewException("Ljava/lang/NoSuchMethodError;", msg.str().c_str());
+}
+
+void ThrowNoSuchMethodError(uint32_t method_idx, const Method* referrer) {
+  DexCache* dex_cache = referrer->GetDeclaringClass()->GetDexCache();
+  const DexFile& dex_file = Runtime::Current()->GetClassLinker()->FindDexFile(dex_cache);
+  std::ostringstream msg;
+  msg << "No method '" << PrettyMethod(method_idx, dex_file, true) << "'";
+  AddReferrerLocation(msg, referrer);
+  Thread::Current()->ThrowNewException("Ljava/lang/NoSuchMethodError;", msg.str().c_str());
+}
+
+}  // namespace art
diff --git a/src/common_throws.h b/src/common_throws.h
new file mode 100644
index 0000000..47186b0
--- /dev/null
+++ b/src/common_throws.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_SRC_COMMON_THROWS__H_
+#define ART_SRC_COMMON_THROWS_H_
+
+#include "mutex.h"
+#include "object.h"
+
+namespace art {
+
+// NullPointerException
+
+void ThrowNullPointerExceptionForFieldAccess(Field* field, bool is_read)
+    SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_);
+
+void ThrowNullPointerExceptionForMethodAccess(Method* caller, uint32_t method_idx, InvokeType type)
+    SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_);
+
+void ThrowNullPointerExceptionFromDexPC(Method* throw_method, uint32_t dex_pc)
+    SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_);
+
+// IllegalAccessError
+
+void ThrowIllegalAccessErrorClass(Class* referrer, Class* accessed)
+    SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_);
+
+void ThrowIllegalAccessErrorClassForMethodDispatch(Class* referrer, Class* accessed,
+                                                   const Method* caller, const Method* called,
+                                                   InvokeType type)
+    SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_);
+
+void ThrowIllegalAccessErrorMethod(Class* referrer, Method* accessed)
+    SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_);
+
+void ThrowIllegalAccessErrorField(Class* referrer, Field* accessed)
+    SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_);
+
+void ThrowIllegalAccessErrorFinalField(const Method* referrer, Field* accessed)
+    SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_);
+
+// IncompatibleClassChangeError
+
+void ThrowIncompatibleClassChangeError(InvokeType expected_type, InvokeType found_type,
+                                       Method* method, const Method* referrer)
+    SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_);
+
+void ThrowIncompatibleClassChangeErrorClassForInterfaceDispatch(const Method* interface_method,
+                                                                Object* this_object,
+                                                                const Method* referrer)
+    SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_);
+
+void ThrowIncompatibleClassChangeErrorField(const Field* resolved_field, bool is_static,
+                                            const Method* referrer)
+    SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_);
+
+// NoSuchMethodError
+
+void ThrowNoSuchMethodError(InvokeType type, Class* c, const StringPiece& name,
+                            const StringPiece& signature, const Method* referrer)
+    SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_);
+
+void ThrowNoSuchMethodError(uint32_t method_idx, const Method* referrer)
+    SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_);
+
+}  // namespace art
+
+#endif  // ART_SRC_COMMON_THROWS_H_
diff --git a/src/compiler_llvm/runtime_support_llvm.cc b/src/compiler_llvm/runtime_support_llvm.cc
index a6fa80d..dd56ac8 100644
--- a/src/compiler_llvm/runtime_support_llvm.cc
+++ b/src/compiler_llvm/runtime_support_llvm.cc
@@ -133,11 +133,7 @@
   Thread* thread = art_get_current_thread_from_code();
   // We need the calling method as context for the method_idx
   Method* method = thread->GetCurrentMethod();
-  thread->ThrowNewException("Ljava/lang/NoSuchMethodError;",
-                            MethodNameFromIndex(method,
-                                                method_idx,
-                                                verifier::VERIFY_ERROR_REF_METHOD,
-                                                false).c_str());
+  ThrowNoSuchMethodError(method_idx, method);
 }
 
 void art_throw_null_pointer_exception_from_code(uint32_t dex_pc)
@@ -146,7 +142,7 @@
   NthCallerVisitor visitor(thread->GetManagedStack(), thread->GetTraceStack(), 0);
   visitor.WalkStack();
   Method* throw_method = visitor.caller;
-  ThrowNullPointerExceptionFromDexPC(thread, throw_method, dex_pc);
+  ThrowNullPointerExceptionFromDexPC(throw_method, dex_pc);
 }
 
 void art_throw_stack_overflow_from_code()
@@ -226,17 +222,17 @@
 Object* art_alloc_array_from_code(uint32_t type_idx,
                                   Method* referrer,
                                   uint32_t length,
-                                  Thread* thread)
+                                  Thread* /*thread*/)
     SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_) {
-  return AllocArrayFromCode(type_idx, referrer, length, thread, false);
+  return AllocArrayFromCode(type_idx, referrer, length, false);
 }
 
 Object* art_alloc_array_from_code_with_access_check(uint32_t type_idx,
                                                     Method* referrer,
                                                     uint32_t length,
-                                                    Thread* thread)
+                                                    Thread* /*thread*/)
     SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_) {
-  return AllocArrayFromCode(type_idx, referrer, length, thread, true);
+  return AllocArrayFromCode(type_idx, referrer, length, true);
 }
 
 Object* art_check_and_alloc_array_from_code(uint32_t type_idx,
diff --git a/src/oat/runtime/support_alloc.cc b/src/oat/runtime/support_alloc.cc
index 4a03f98..528198d 100644
--- a/src/oat/runtime/support_alloc.cc
+++ b/src/oat/runtime/support_alloc.cc
@@ -37,7 +37,7 @@
                                         Thread* self, Method** sp)
     SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_) {
   FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
-  return AllocArrayFromCode(type_idx, method, component_count, self, false);
+  return AllocArrayFromCode(type_idx, method, component_count, false);
 }
 
 extern "C" Array* artAllocArrayFromCodeWithAccessCheck(uint32_t type_idx, Method* method,
@@ -45,7 +45,7 @@
                                                        Thread* self, Method** sp)
     SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_) {
   FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
-  return AllocArrayFromCode(type_idx, method, component_count, self, true);
+  return AllocArrayFromCode(type_idx, method, component_count, true);
 }
 
 extern "C" Array* artCheckAndAllocArrayFromCode(uint32_t type_idx, Method* method,
diff --git a/src/oat/runtime/support_field.cc b/src/oat/runtime/support_field.cc
index 289553e..fe8974b 100644
--- a/src/oat/runtime/support_field.cc
+++ b/src/oat/runtime/support_field.cc
@@ -77,7 +77,7 @@
   field = FindFieldFromCode(field_idx, referrer, self, InstancePrimitiveRead, sizeof(int32_t));
   if (LIKELY(field != NULL)) {
     if (UNLIKELY(obj == NULL)) {
-      ThrowNullPointerExceptionForFieldAccess(self, field, true);
+      ThrowNullPointerExceptionForFieldAccess(field, true);
     } else {
       return field->Get32(obj);
     }
@@ -96,7 +96,7 @@
   field = FindFieldFromCode(field_idx, referrer, self, InstancePrimitiveRead, sizeof(int64_t));
   if (LIKELY(field != NULL)) {
     if (UNLIKELY(obj == NULL)) {
-      ThrowNullPointerExceptionForFieldAccess(self, field, true);
+      ThrowNullPointerExceptionForFieldAccess(field, true);
     } else {
       return field->Get64(obj);
     }
@@ -115,7 +115,7 @@
   field = FindFieldFromCode(field_idx, referrer, self, InstanceObjectRead, sizeof(Object*));
   if (LIKELY(field != NULL)) {
     if (UNLIKELY(obj == NULL)) {
-      ThrowNullPointerExceptionForFieldAccess(self, field, true);
+      ThrowNullPointerExceptionForFieldAccess(field, true);
     } else {
       return field->GetObj(obj);
     }
@@ -188,7 +188,7 @@
   field = FindFieldFromCode(field_idx, referrer, self, InstancePrimitiveWrite, sizeof(int32_t));
   if (LIKELY(field != NULL)) {
     if (UNLIKELY(obj == NULL)) {
-      ThrowNullPointerExceptionForFieldAccess(self, field, false);
+      ThrowNullPointerExceptionForFieldAccess(field, false);
     } else {
       field->Set32(obj, new_value);
       return 0;  // success
@@ -212,7 +212,7 @@
   field = FindFieldFromCode(field_idx, referrer, self, InstancePrimitiveWrite, sizeof(int64_t));
   if (LIKELY(field != NULL)) {
     if (UNLIKELY(obj == NULL)) {
-      ThrowNullPointerExceptionForFieldAccess(self, field, false);
+      ThrowNullPointerExceptionForFieldAccess(field, false);
     } else {
       field->Set64(obj, new_value);
       return 0;  // success
@@ -233,7 +233,7 @@
   field = FindFieldFromCode(field_idx, referrer, self, InstanceObjectWrite, sizeof(Object*));
   if (LIKELY(field != NULL)) {
     if (UNLIKELY(obj == NULL)) {
-      ThrowNullPointerExceptionForFieldAccess(self, field, false);
+      ThrowNullPointerExceptionForFieldAccess(field, false);
     } else {
       field->SetObj(obj, new_value);
       return 0;  // success
diff --git a/src/oat/runtime/support_invoke.cc b/src/oat/runtime/support_invoke.cc
index 9c7b3a2..b2867ef 100644
--- a/src/oat/runtime/support_invoke.cc
+++ b/src/oat/runtime/support_invoke.cc
@@ -26,7 +26,7 @@
   if (UNLIKELY(method == NULL)) {
     FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsAndArgs);
     if (UNLIKELY(this_object == NULL && type != kDirect && type != kStatic)) {
-      ThrowNullPointerExceptionForMethodAccess(self, caller_method, method_idx, type);
+      ThrowNullPointerExceptionForMethodAccess(caller_method, method_idx, type);
       return 0;  // failure
     }
     method = FindMethodFromCode(method_idx, this_object, caller_method, self, access_check, type);
diff --git a/src/oat/runtime/support_throw.cc b/src/oat/runtime/support_throw.cc
index 9776290..0abdb04 100644
--- a/src/oat/runtime/support_throw.cc
+++ b/src/oat/runtime/support_throw.cc
@@ -54,7 +54,7 @@
   FinishCalleeSaveFrameSetup(self, sp, Runtime::kSaveAll);
   uint32_t dex_pc;
   Method* throw_method = self->GetCurrentMethod(&dex_pc);
-  ThrowNullPointerExceptionFromDexPC(self, throw_method, dex_pc);
+  ThrowNullPointerExceptionFromDexPC(throw_method, dex_pc);
   self->DeliverException();
 }
 
@@ -93,8 +93,7 @@
     SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_) {
   FinishCalleeSaveFrameSetup(self, sp, Runtime::kSaveAll);
   Method* method = self->GetCurrentMethod();
-  self->ThrowNewException("Ljava/lang/NoSuchMethodError;",
-      MethodNameFromIndex(method, method_idx, verifier::VERIFY_ERROR_REF_METHOD, false).c_str());
+  ThrowNoSuchMethodError(method_idx, method);
   self->DeliverException();
 }
 
diff --git a/src/object.h b/src/object.h
index 85b1721..6d686f4 100644
--- a/src/object.h
+++ b/src/object.h
@@ -2452,27 +2452,25 @@
 }
 
 inline bool Method::CheckIncompatibleClassChange(InvokeType type) {
-  bool icce = true;
   switch (type) {
     case kStatic:
-      icce = !IsStatic();
-      break;
+      return !IsStatic();
     case kDirect:
-      icce = !IsDirect();
-      break;
-    case kVirtual:
-      icce = IsDirect();
-      break;
+      return !IsDirect() || IsStatic();
+    case kVirtual: {
+      Class* methods_class = GetDeclaringClass();
+      return IsDirect() || (methods_class->IsInterface() && !IsMiranda());
+    }
     case kSuper:
-      icce = false;
-      break;
+      return false;  // TODO: appropriate checks for call to super class.
     case kInterface: {
       Class* methods_class = GetDeclaringClass();
-      icce = IsDirect() || !(methods_class->IsInterface() || methods_class->IsObjectClass());
-      break;
+      return IsDirect() || !(methods_class->IsInterface() || methods_class->IsObjectClass());
     }
+    default:
+      LOG(FATAL) << "UNREACHABLE";
+      return true;
   }
-  return icce;
 }
 
 inline void Method::AssertPcIsWithinCode(uintptr_t pc) const {
diff --git a/src/runtime_support.cc b/src/runtime_support.cc
index 16406c4..01bdf9a 100644
--- a/src/runtime_support.cc
+++ b/src/runtime_support.cc
@@ -89,259 +89,6 @@
 
 namespace art {
 
-void ThrowNewIllegalAccessErrorClass(Thread* self,
-                                     Class* referrer,
-                                     Class* accessed) {
-  self->ThrowNewExceptionF("Ljava/lang/IllegalAccessError;",
-                           "Illegal class access: '%s' -> '%s'",
-                           PrettyDescriptor(referrer).c_str(),
-                           PrettyDescriptor(accessed).c_str());
-}
-
-void ThrowNewIllegalAccessErrorClassForMethodDispatch(Thread* self,
-                                                      Class* referrer,
-                                                      Class* accessed,
-                                                      const Method* caller,
-                                                      const Method* called,
-                                                      InvokeType type) {
-  self->ThrowNewExceptionF("Ljava/lang/IllegalAccessError;",
-                           "Illegal class access ('%s' -> '%s')"
-                           "in attempt to invoke %s method '%s' from '%s'",
-                           PrettyDescriptor(referrer).c_str(),
-                           PrettyDescriptor(accessed).c_str(),
-                           ToStr<InvokeType>(type).c_str(),
-                           PrettyMethod(called).c_str(),
-                           PrettyMethod(caller).c_str());
-}
-
-static void ThrowNewIncompatibleClassChangeErrorClassForInterfaceDispatch(Thread* self,
-                                                                          const Method* interface_method,
-                                                                          Object* this_object)
-    SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_) {
-  std::string interface_method_name(PrettyMethod(interface_method));
-  if (this_object != NULL) {
-    std::string this_class_descriptor(PrettyDescriptor(this_object->GetClass()));
-    std::string interface_class_descriptor(PrettyDescriptor(interface_method->GetDeclaringClass()));
-    self->ThrowNewExceptionF("Ljava/lang/IncompatibleClassChangeError;",
-                             "Class '%s' does not implement interface '%s' in call to '%s'",
-                             this_class_descriptor.c_str(),
-                             interface_class_descriptor.c_str(),
-                             interface_method_name.c_str());
-  } else {
-    self->ThrowNewExceptionF("Ljava/lang/IncompatibleClassChangeError;",
-                             "Expected '%s' to be an interface method",
-                             interface_method_name.c_str());
-  }
-}
-
-static void ThrowNewIncompatibleClassChangeErrorField(Thread* self, const Field* resolved_field,
-                                               bool is_static)
-    SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_) {
-  self->ThrowNewExceptionF("Ljava/lang/IncompatibleClassChangeError;",
-                           "Expected '%s' to be a %s field",
-                           PrettyField(resolved_field).c_str(),
-                           is_static ? "static" : "instance");
-}
-
-void ThrowIncompatibleClassChangeError(InvokeType expected_type, InvokeType found_type,
-                                       Method* method, const Method* referrer) {
-  std::ostringstream msg;
-  msg << "The method '" << PrettyMethod(method) << "' was expected to be of type "
-      << expected_type << " but instead was found to be of type " << found_type;
-  if (referrer != NULL) {
-    ClassHelper kh(referrer->GetDeclaringClass());
-    std::string location(kh.GetLocation());
-    if (!location.empty()) {
-      msg << " (accessed from " << location << ")";
-    }
-  }
-  Thread::Current()->ThrowNewException("Ljava/lang/IncompatibleClassChangeError;",
-                                       msg.str().c_str());
-}
-
-void ThrowNoSuchMethodError(InvokeType type, Class* c, const StringPiece& name,
-                            const StringPiece& signature, const Method* referrer) {
-  ClassHelper kh(c);
-  std::ostringstream msg;
-  msg << "No " << type << " method " << name << signature
-      << " in class " << kh.GetDescriptor() << " or its superclasses";
-  if (referrer != NULL) {
-    kh.ChangeClass(referrer->GetDeclaringClass());
-    std::string location(kh.GetLocation());
-    if (!location.empty()) {
-      msg << " (accessed from " << location << ")";
-    }
-  }
-  Thread::Current()->ThrowNewException("Ljava/lang/NoSuchMethodError;", msg.str().c_str());
-}
-
-void ThrowNewIllegalAccessErrorField(Thread* self,
-                                     Class* referrer,
-                                     Field* accessed) {
-  self->ThrowNewExceptionF("Ljava/lang/IllegalAccessError;",
-                           "Field '%s' is inaccessible to class '%s'",
-                           PrettyField(accessed, false).c_str(),
-                           PrettyDescriptor(referrer).c_str());
-}
-
-void ThrowNewIllegalAccessErrorFinalField(Thread* self,
-                                          const Method* referrer,
-                                          Field* accessed) {
-  self->ThrowNewExceptionF("Ljava/lang/IllegalAccessError;",
-                           "Final field '%s' cannot be written to by method '%s'",
-                           PrettyField(accessed, false).c_str(),
-                           PrettyMethod(referrer).c_str());
-}
-
-void ThrowNewIllegalAccessErrorMethod(Thread* self,
-                                      Class* referrer,
-                                      Method* accessed) {
-  self->ThrowNewExceptionF("Ljava/lang/IllegalAccessError;",
-                           "Method '%s' is inaccessible to class '%s'",
-                           PrettyMethod(accessed).c_str(),
-                           PrettyDescriptor(referrer).c_str());
-}
-
-void ThrowNullPointerExceptionForFieldAccess(Thread* self,
-                                                           Field* field,
-                                                           bool is_read) {
-  self->ThrowNewExceptionF("Ljava/lang/NullPointerException;",
-                           "Attempt to %s field '%s' on a null object reference",
-                           is_read ? "read from" : "write to",
-                           PrettyField(field, true).c_str());
-}
-
-void ThrowNullPointerExceptionForMethodAccess(Thread* self,
-                                              Method* caller,
-                                              uint32_t method_idx,
-                                              InvokeType type) {
-  const DexFile& dex_file =
-      Runtime::Current()->GetClassLinker()->FindDexFile(caller->GetDeclaringClass()->GetDexCache());
-  self->ThrowNewExceptionF("Ljava/lang/NullPointerException;",
-                           "Attempt to invoke %s method '%s' on a null object reference",
-                           ToStr<InvokeType>(type).c_str(),
-                           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;
-    case Instruction::ARRAY_LENGTH:
-      self->ThrowNewException("Ljava/lang/NullPointerException;",
-                              "Attempt to get length of 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));
-
-  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
-  const DexFile& dex_file = class_linker->FindDexFile(method->GetDeclaringClass()->GetDexCache());
-
-  const DexFile::FieldId& id = dex_file.GetFieldId(ref);
-  std::string class_name(PrettyDescriptor(dex_file.GetFieldDeclaringClassDescriptor(id)));
-  const char* field_name = dex_file.StringDataByIdx(id.name_idx_);
-  if (!access) {
-    return class_name + "." + field_name;
-  }
-
-  std::string result;
-  result += "tried to access field ";
-  result += class_name + "." + field_name;
-  result += " from class ";
-  result += PrettyDescriptor(method->GetDeclaringClass());
-  return result;
-}
-
-std::string MethodNameFromIndex(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_METHOD));
-
-  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
-  const DexFile& dex_file = class_linker->FindDexFile(method->GetDeclaringClass()->GetDexCache());
-
-  const DexFile::MethodId& id = dex_file.GetMethodId(ref);
-  std::string class_name(PrettyDescriptor(dex_file.GetMethodDeclaringClassDescriptor(id)));
-  const char* method_name = dex_file.StringDataByIdx(id.name_idx_);
-  if (!access) {
-    return class_name + "." + method_name;
-  }
-
-  std::string result;
-  result += "tried to access method ";
-  result += class_name + "." + method_name + ":" +
-      dex_file.CreateMethodSignature(id.proto_idx_, NULL);
-  result += " from class ";
-  result += PrettyDescriptor(method->GetDeclaringClass());
-  return result;
-}
-
 // Helper function to allocate array for FILLED_NEW_ARRAY.
 Array* CheckAndAllocArrayFromCode(uint32_t type_idx, Method* method, int32_t component_count,
                                   Thread* self, bool access_check) {
@@ -372,7 +119,7 @@
     if (access_check) {
       Class* referrer = method->GetDeclaringClass();
       if (UNLIKELY(!referrer->CanAccess(klass))) {
-        ThrowNewIllegalAccessErrorClass(self, referrer, klass);
+        ThrowIllegalAccessErrorClass(referrer, klass);
         return NULL;  // Failure
       }
     }
@@ -404,7 +151,7 @@
     return NULL;  // Failure.
   } else {
     if (resolved_field->IsStatic() != is_static) {
-      ThrowNewIncompatibleClassChangeErrorField(self, resolved_field, is_static);
+      ThrowIncompatibleClassChangeErrorField(resolved_field, is_static, referrer);
       return NULL;
     }
     Class* fields_class = resolved_field->GetDeclaringClass();
@@ -420,16 +167,16 @@
                                                dex_file.GetFieldId(field_idx).class_idx_,
                                                referring_class);
       if (UNLIKELY(!referring_class->CanAccess(fields_class))) {
-        ThrowNewIllegalAccessErrorClass(self, referring_class, fields_class);
+        ThrowIllegalAccessErrorClass(referring_class, fields_class);
         return NULL;  // failure
       } else if (UNLIKELY(!referring_class->CanAccessMember(fields_class,
                                                             resolved_field->GetAccessFlags()))) {
-        ThrowNewIllegalAccessErrorField(self, referring_class, resolved_field);
+        ThrowIllegalAccessErrorField(referring_class, resolved_field);
         return NULL;  // failure
       }
     }
     if (UNLIKELY(is_set && resolved_field->IsFinal() && (fields_class != referring_class))) {
-      ThrowNewIllegalAccessErrorFinalField(self, referrer, resolved_field);
+      ThrowIllegalAccessErrorFinalField(referrer, resolved_field);
       return NULL;  // failure
     } else {
       FieldHelper fh(resolved_field);
@@ -477,9 +224,8 @@
         Method* interface_method =
             this_object->GetClass()->FindVirtualMethodForInterface(resolved_method);
         if (UNLIKELY(interface_method == NULL)) {
-          ThrowNewIncompatibleClassChangeErrorClassForInterfaceDispatch(self,
-                                                                        resolved_method,
-                                                                        this_object);
+          ThrowIncompatibleClassChangeErrorClassForInterfaceDispatch(resolved_method, this_object,
+                                                                     referrer);
           return NULL;  // Failure.
         } else {
           return interface_method;
@@ -515,12 +261,12 @@
                                                   dex_file.GetMethodId(method_idx).class_idx_,
                                                   referring_class);
         if (UNLIKELY(!referring_class->CanAccess(methods_class))) {
-          ThrowNewIllegalAccessErrorClassForMethodDispatch(self, referring_class, methods_class,
-                                                           referrer, resolved_method, type);
+          ThrowIllegalAccessErrorClassForMethodDispatch(referring_class, methods_class,
+                                                        referrer, resolved_method, type);
           return NULL;  // Failure.
         } else if (UNLIKELY(!referring_class->CanAccessMember(methods_class,
                                                               resolved_method->GetAccessFlags()))) {
-          ThrowNewIllegalAccessErrorMethod(self, referring_class, resolved_method);
+          ThrowIllegalAccessErrorMethod(referring_class, resolved_method);
           return NULL;  // Failure.
         }
       }
@@ -530,9 +276,8 @@
         Method* interface_method =
             this_object->GetClass()->FindVirtualMethodForInterface(resolved_method);
         if (UNLIKELY(interface_method == NULL)) {
-          ThrowNewIncompatibleClassChangeErrorClassForInterfaceDispatch(self,
-                                                                        resolved_method,
-                                                                        this_object);
+          ThrowIncompatibleClassChangeErrorClassForInterfaceDispatch(resolved_method, this_object,
+                                                                     referrer);
           return NULL;  // Failure.
         } else {
           return interface_method;
@@ -576,7 +321,7 @@
   // Perform access check if necessary.
   Class* referring_class = referrer->GetDeclaringClass();
   if (verify_access && UNLIKELY(!referring_class->CanAccess(klass))) {
-    ThrowNewIllegalAccessErrorClass(self, referring_class, klass);
+    ThrowIllegalAccessErrorClass(referring_class, klass);
     return NULL;  // Failure - Indicate to caller to deliver exception
   }
   // If we're just implementing const-class, we shouldn't call <clinit>.
diff --git a/src/runtime_support.h b/src/runtime_support.h
index 2956ea7..8f6b655 100644
--- a/src/runtime_support.h
+++ b/src/runtime_support.h
@@ -18,6 +18,7 @@
 #define ART_SRC_RUNTIME_SUPPORT_H_
 
 #include "class_linker.h"
+#include "common_throws.h"
 #include "dex_file.h"
 #include "invoke_type.h"
 #include "object.h"
@@ -43,47 +44,6 @@
 class Method;
 class Object;
 
-// Helpers to give consistent descriptive exception messages
-void ThrowNewIllegalAccessErrorClass(Thread* self, Class* referrer, Class* accessed)
-    SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_);
-void ThrowNewIllegalAccessErrorClassForMethodDispatch(Thread* self, Class* referrer,
-                                                      Class* accessed,
-                                                      const Method* caller,
-                                                      const Method* called,
-                                                      InvokeType type)
-    SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_);
-void ThrowNewIncompatibleClassChangeErrorClassForInterfaceDispatch(Thread* self,
-                                                                   const Method* referrer,
-                                                                   const Method* interface_method,
-                                                                   Object* this_object)
-    SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_);
-void ThrowIncompatibleClassChangeError(InvokeType expected_type, InvokeType found_type,
-                                       Method* method, const Method* referrer)
-    SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_);
-void ThrowNoSuchMethodError(InvokeType type, Class* c, const StringPiece& name,
-                            const StringPiece& signature, const Method* referrer)
-    SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_);
-void ThrowNewIllegalAccessErrorField(Thread* self, Class* referrer, Field* accessed)
-    SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_);
-void ThrowNewIllegalAccessErrorFinalField(Thread* self, const Method* referrer, Field* accessed)
-    SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_);
-void ThrowNewIllegalAccessErrorMethod(Thread* self, Class* referrer, Method* accessed)
-    SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_);
-void ThrowNullPointerExceptionForFieldAccess(Thread* self, Field* field, bool is_read)
-    SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_);
-void ThrowNullPointerExceptionForMethodAccess(Thread* self, Method* caller, uint32_t method_idx,
-                                              InvokeType type)
-    SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_);
-void ThrowNullPointerExceptionFromDexPC(Thread* self, Method* caller, uint32_t dex_pc)
-    SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_);
-
-std::string FieldNameFromIndex(const Method* method, uint32_t ref,
-                               verifier::VerifyErrorRefType ref_type, bool access)
-    SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_);
-std::string MethodNameFromIndex(const Method* method, uint32_t ref,
-                                verifier::VerifyErrorRefType ref_type, bool access)
-    SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_);
-
 // Given the context of a calling Method, use its DexCache to resolve a type to a Class. If it
 // cannot be resolved, throw an error. If it can, use it to create an instance.
 // When verification/compiler hasn't been able to verify access, optionally perform an access
@@ -108,7 +68,7 @@
     }
     Class* referrer = method->GetDeclaringClass();
     if (UNLIKELY(!referrer->CanAccess(klass))) {
-      ThrowNewIllegalAccessErrorClass(self, referrer, klass);
+      ThrowIllegalAccessErrorClass(referrer, klass);
       return NULL;  // Failure
     }
   }
@@ -124,7 +84,7 @@
 // When verification/compiler hasn't been able to verify access, optionally perform an access
 // check.
 static inline Array* AllocArrayFromCode(uint32_t type_idx, Method* method, int32_t component_count,
-                                        Thread* self, bool access_check)
+                                        bool access_check)
     SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_) {
   if (UNLIKELY(component_count < 0)) {
     Thread::Current()->ThrowNewExceptionF("Ljava/lang/NegativeArraySizeException;", "%d",
@@ -143,7 +103,7 @@
   if (access_check) {
     Class* referrer = method->GetDeclaringClass();
     if (UNLIKELY(!referrer->CanAccess(klass))) {
-      ThrowNewIllegalAccessErrorClass(self, referrer, klass);
+      ThrowIllegalAccessErrorClass(referrer, klass);
       return NULL;  // Failure
     }
   }