From 256bcf04e0862e30d0f18f70f99b4927b5c5b2eb Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Wed, 22 Aug 2007 21:30:37 -0600 Subject: [PATCH] fix Method.invoke() to handle polymorphism properly --- src/builtin.cpp | 11 +---------- src/machine.h | 17 +++++++++++++++++ src/run.cpp | 35 +++++++++++++++++++++++++++++------ 3 files changed, 47 insertions(+), 16 deletions(-) diff --git a/src/builtin.cpp b/src/builtin.cpp index 4307107f15..479d721407 100644 --- a/src/builtin.cpp +++ b/src/builtin.cpp @@ -163,16 +163,7 @@ Class_primitiveClass(Thread* t, jclass, jchar name) void Class_initialize(Thread* t, jobject this_) { - acquire(t, t->vm->classLock); - object c = *this_; - if (classVmFlags(t, c) & NeedInitFlag - and (classVmFlags(t, c) & InitFlag) == 0) - { - classVmFlags(t, c) |= InitFlag; - run(t, classInitializer(t, c), 0); - } else { - release(t, t->vm->classLock); - } + initClass(t, *this_); } jboolean diff --git a/src/machine.h b/src/machine.h index 07af002c86..ba8e475d2c 100644 --- a/src/machine.h +++ b/src/machine.h @@ -1131,6 +1131,9 @@ class Machine { unsigned heapPoolIndex; }; +object +run(Thread* t, object method, object this_, ...); + object run(Thread* t, const char* className, const char* methodName, const char* methodSpec, object this_, ...); @@ -2111,6 +2114,20 @@ resolveClass(Thread* t, object spec); object resolveObjectArrayClass(Thread* t, object elementSpec); +inline void +initClass(Thread* t, object c) +{ + acquire(t, t->vm->classLock); + if (classVmFlags(t, c) & NeedInitFlag + and (classVmFlags(t, c) & InitFlag) == 0) + { + classVmFlags(t, c) |= InitFlag; + run(t, classInitializer(t, c), 0); + } else { + release(t, t->vm->classLock); + } +} + object makeObjectArray(Thread* t, object elementClass, unsigned count, bool clear); diff --git a/src/run.cpp b/src/run.cpp index 0509a92ef3..89effc597d 100644 --- a/src/run.cpp +++ b/src/run.cpp @@ -85,10 +85,10 @@ popFrame(Thread* t) } object -findInterfaceMethod(Thread* t, object method, object o) +findInterfaceMethod(Thread* t, object method, object class_) { object interface = methodClass(t, method); - object itable = classInterfaceTable(t, objectClass(t, o)); + object itable = classInterfaceTable(t, class_); for (unsigned i = 0; i < arrayLength(t, itable); i += 2) { if (arrayBody(t, itable, i) == interface) { return arrayBody(t, arrayBody(t, itable, i + 1), @@ -1594,9 +1594,7 @@ run(Thread* t) unsigned parameterFootprint = methodParameterFootprint(t, method); if (LIKELY(peekObject(t, sp - parameterFootprint))) { code = findInterfaceMethod - (t, method, peekObject(t, sp - parameterFootprint)); - if (UNLIKELY(exception)) goto throw_; - + (t, method, objectClass(t, peekObject(t, sp - parameterFootprint))); goto invoke; } else { exception = makeNullPointerException(t); @@ -1669,7 +1667,7 @@ run(Thread* t) if (UNLIKELY(classInit(t, class_, 3))) goto invoke; } - code = findMethod(t, method, class_); + code = findMethod(t, method, class_); goto invoke; } else { exception = makeNullPointerException(t); @@ -2575,6 +2573,31 @@ pushArguments(Thread* t, object this_, const char* spec, object a) object invoke(Thread* t, object method) { + PROTECT(t, method); + + object class_; + PROTECT(t, class_); + + if (methodFlags(t, method) & ACC_STATIC) { + class_ = methodClass(t, method); + } else { + unsigned parameterFootprint = methodParameterFootprint(t, method); + class_ = objectClass(t, peekObject(t, t->sp - parameterFootprint)); + + if (classFlags(t, methodClass(t, method)) & ACC_INTERFACE) { + method = findInterfaceMethod(t, method, class_); + } else { + if (classVirtualTable(t, class_) == 0) { + resolveClass(t, className(t, class_)); + if (UNLIKELY(t->exception)) return 0; + } + + method = findMethod(t, method, class_); + } + } + + initClass(t, class_); + object result = 0; if (methodFlags(t, method) & ACC_NATIVE) {