Fixed slow path for invoke-direct with null this pointer.
Moved the null pointer check until after the class linker tries to
resolve the method on the slow path.
Change-Id: Ie0f9e279a98a7e3a40899fee92337ef454c9a468
diff --git a/src/interpreter/interpreter.cc b/src/interpreter/interpreter.cc
index f4091be..636bb85 100644
--- a/src/interpreter/interpreter.cc
+++ b/src/interpreter/interpreter.cc
@@ -378,11 +378,6 @@
receiver = NULL;
} else {
receiver = shadow_frame.GetVRegReference(dec_insn.vC);
- if (UNLIKELY(receiver == NULL)) {
- ThrowNullPointerExceptionForMethodAccess(shadow_frame.GetMethod(), dec_insn.vB, type);
- result->SetJ(0);
- return;
- }
}
uint32_t method_idx = dec_insn.vB;
AbstractMethod* target_method = FindMethodFromCode(method_idx, receiver,
diff --git a/src/oat/runtime/support_invoke.cc b/src/oat/runtime/support_invoke.cc
index 4f16afe..7a49489 100644
--- a/src/oat/runtime/support_invoke.cc
+++ b/src/oat/runtime/support_invoke.cc
@@ -137,10 +137,6 @@
AbstractMethod* method = FindMethodFast(method_idx, this_object, caller_method, access_check, type);
if (UNLIKELY(method == NULL)) {
FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsAndArgs);
- if (UNLIKELY(this_object == NULL && type != kDirect && type != kStatic)) {
- ThrowNullPointerExceptionForMethodAccess(caller_method, method_idx, type);
- return 0; // failure
- }
method = FindMethodFromCode(method_idx, this_object, caller_method, self, access_check, type);
if (UNLIKELY(method == NULL)) {
CHECK(self->IsExceptionPending());
diff --git a/src/runtime_support.cc b/src/runtime_support.cc
index 92c5e3a..856e877 100644
--- a/src/runtime_support.cc
+++ b/src/runtime_support.cc
@@ -208,7 +208,7 @@
}
// Slow path method resolution
-AbstractMethod* FindMethodFromCode(uint32_t method_idx, Object* this_object, const AbstractMethod* referrer,
+AbstractMethod* FindMethodFromCode(uint32_t method_idx, Object* this_object, AbstractMethod* referrer,
Thread* self, bool access_check, InvokeType type) {
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
bool is_direct = type == kStatic || type == kDirect;
@@ -216,6 +216,11 @@
if (UNLIKELY(resolved_method == NULL)) {
DCHECK(self->IsExceptionPending()); // Throw exception and unwind.
return NULL; // Failure.
+ } else if (UNLIKELY(this_object == NULL && type != kStatic)) {
+ // Maintain interpreter-like semantics where NullPointerException is thrown
+ // after potential NoSuchMethodError from class linker.
+ ThrowNullPointerExceptionForMethodAccess(referrer, method_idx, type);
+ return NULL; // Failure.
} else {
if (!access_check) {
if (is_direct) {
diff --git a/src/runtime_support.h b/src/runtime_support.h
index d0a6209..adeedb7 100644
--- a/src/runtime_support.h
+++ b/src/runtime_support.h
@@ -223,7 +223,7 @@
}
}
-extern AbstractMethod* FindMethodFromCode(uint32_t method_idx, Object* this_object, const AbstractMethod* referrer,
+extern AbstractMethod* FindMethodFromCode(uint32_t method_idx, Object* this_object, AbstractMethod* referrer,
Thread* self, bool access_check, InvokeType type)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);