maintain a table to look up methods called via JNI

This simplifies the JNI implementation for looking up methods.  It also
fixes a bug where an applications calls GetStaticMethodID with class A
and then calls CallStatic<Type>Method with class B which extends A.  The
old code would look in the wrong method table and thus call the wrong
method.
This commit is contained in:
Joel Dice 2008-08-15 12:32:33 -06:00
parent 78e48996b5
commit c8cc7d931b
5 changed files with 70 additions and 88 deletions

View File

@ -17,6 +17,7 @@ public class Method<T> extends AccessibleObject implements Member {
private byte parameterFootprint; private byte parameterFootprint;
private short flags; private short flags;
private short offset; private short offset;
private int nativeID;
private byte[] name; private byte[] name;
private byte[] spec; private byte[] spec;
private Class<T> class_; private Class<T> class_;

View File

@ -4565,7 +4565,7 @@ class MyProcessor: public Processor {
{ {
return vm::makeMethod return vm::makeMethod
(t, vmFlags, returnCode, parameterCount, parameterFootprint, flags, (t, vmFlags, returnCode, parameterCount, parameterFootprint, flags,
offset, name, spec, class_, code, offset, 0, name, spec, class_, code,
::defaultThunk(static_cast<MyThread*>(t))); ::defaultThunk(static_cast<MyThread*>(t)));
} }
@ -5101,6 +5101,7 @@ compile(MyThread* t, object method)
methodParameterFootprint(t, method), methodParameterFootprint(t, method),
methodFlags(t, method), methodFlags(t, method),
methodOffset(t, method), methodOffset(t, method),
methodNativeID(t, method),
methodName(t, method), methodName(t, method),
methodSpec(t, method), methodSpec(t, method),
methodClass(t, method), methodClass(t, method),

View File

@ -280,6 +280,23 @@ findMethod(Thread* t, jclass c, const char* name, const char* spec)
return vm::findMethod(t, *c, n, s); return vm::findMethod(t, *c, n, s);
} }
jint
methodID(Thread* t, object method)
{
if (methodNativeID(t, method) == 0) {
PROTECT(t, method);
ACQUIRE(t, t->m->referenceLock);
if (methodNativeID(t, method) == 0) {
t->m->jniMethodTable = vectorAppend(t, t->m->jniMethodTable, method);
methodNativeID(t, method) = vectorSize(t, t->m->jniMethodTable);
}
}
return methodNativeID(t, method);
}
jmethodID JNICALL jmethodID JNICALL
GetMethodID(Thread* t, jclass c, const char* name, const char* spec) GetMethodID(Thread* t, jclass c, const char* name, const char* spec)
{ {
@ -288,26 +305,9 @@ GetMethodID(Thread* t, jclass c, const char* name, const char* spec)
object method = findMethod(t, c, name, spec); object method = findMethod(t, c, name, spec);
if (UNLIKELY(t->exception)) return 0; if (UNLIKELY(t->exception)) return 0;
if (classFlags(t, *c) & ACC_INTERFACE) { assert(t, (methodFlags(t, method) & ACC_STATIC) == 0);
PROTECT(t, method);
ACQUIRE(t, t->m->referenceLock); return methodID(t, method);
for (unsigned i = 0; i < vectorSize(t, t->m->jniInterfaceTable); ++i) {
if (method == vectorBody(t, t->m->jniInterfaceTable, i)) {
return i;
}
}
t->m->jniInterfaceTable
= vectorAppend(t, t->m->jniInterfaceTable, method);
return (vectorSize(t, t->m->jniInterfaceTable) - 1) | InterfaceMethodID;
} else if (methodVirtual(t, method)) {
return methodOffset(t, method) + 1;
} else {
return methodOffset(t, method) | NonVirtualMethodID;
}
} }
jmethodID JNICALL jmethodID JNICALL
@ -318,29 +318,19 @@ GetStaticMethodID(Thread* t, jclass c, const char* name, const char* spec)
object method = findMethod(t, c, name, spec); object method = findMethod(t, c, name, spec);
if (UNLIKELY(t->exception)) return 0; if (UNLIKELY(t->exception)) return 0;
return methodOffset(t, method) + 1; assert(t, methodFlags(t, method) & ACC_STATIC);
return methodID(t, method);
} }
inline object inline object
getMethod(Thread* t, object o, jmethodID m) getMethod(Thread* t, jmethodID m)
{ {
if (m & InterfaceMethodID) { object method = vectorBody(t, t->m->jniMethodTable, m - 1);
return vectorBody(t, t->m->jniInterfaceTable, m & (~InterfaceMethodID));
} else {
if (classVmFlags(t, objectClass(t, o)) & BootstrapFlag) {
PROTECT(t, o);
resolveClass(t, className(t, objectClass(t, o))); assert(t, (methodFlags(t, method) & ACC_STATIC) == 0);
if (UNLIKELY(t->exception)) return 0;
}
if (m & NonVirtualMethodID) { return method;
return arrayBody(t, classMethodTable(t, objectClass(t, o)),
m & (~NonVirtualMethodID));
} else {
return arrayBody(t, classVirtualTable(t, objectClass(t, o)), m - 1);
}
}
} }
jobject JNICALL jobject JNICALL
@ -351,7 +341,7 @@ NewObjectV(Thread* t, jclass c, jmethodID m, va_list a)
object o = make(t, *c); object o = make(t, *c);
PROTECT(t, o); PROTECT(t, o);
t->m->processor->invokeList(t, getMethod(t, o, m), o, true, a); t->m->processor->invokeList(t, getMethod(t, m), o, true, a);
return makeLocalReference(t, o); return makeLocalReference(t, o);
} }
@ -374,7 +364,7 @@ CallObjectMethodV(Thread* t, jobject o, jmethodID m, va_list a)
{ {
ENTER(t, Thread::ActiveState); ENTER(t, Thread::ActiveState);
object method = getMethod(t, *o, m); object method = getMethod(t, m);
return makeLocalReference return makeLocalReference
(t, t->m->processor->invokeList(t, method, *o, true, a)); (t, t->m->processor->invokeList(t, method, *o, true, a));
} }
@ -397,7 +387,7 @@ CallBooleanMethodV(Thread* t, jobject o, jmethodID m, va_list a)
{ {
ENTER(t, Thread::ActiveState); ENTER(t, Thread::ActiveState);
object method = getMethod(t, *o, m); object method = getMethod(t, m);
object r = t->m->processor->invokeList(t, method, *o, true, a); object r = t->m->processor->invokeList(t, method, *o, true, a);
return (t->exception ? false : (intValue(t, r) != 0)); return (t->exception ? false : (intValue(t, r) != 0));
} }
@ -420,7 +410,7 @@ CallByteMethodV(Thread* t, jobject o, jmethodID m, va_list a)
{ {
ENTER(t, Thread::ActiveState); ENTER(t, Thread::ActiveState);
object method = getMethod(t, *o, m); object method = getMethod(t, m);
object r = t->m->processor->invokeList(t, method, *o, true, a); object r = t->m->processor->invokeList(t, method, *o, true, a);
return (t->exception ? 0 : intValue(t, r)); return (t->exception ? 0 : intValue(t, r));
} }
@ -443,7 +433,7 @@ CallCharMethodV(Thread* t, jobject o, jmethodID m, va_list a)
{ {
ENTER(t, Thread::ActiveState); ENTER(t, Thread::ActiveState);
object method = getMethod(t, *o, m); object method = getMethod(t, m);
object r = t->m->processor->invokeList(t, method, *o, true, a); object r = t->m->processor->invokeList(t, method, *o, true, a);
return (t->exception ? 0 : intValue(t, r)); return (t->exception ? 0 : intValue(t, r));
} }
@ -466,7 +456,7 @@ CallShortMethodV(Thread* t, jobject o, jmethodID m, va_list a)
{ {
ENTER(t, Thread::ActiveState); ENTER(t, Thread::ActiveState);
object method = getMethod(t, *o, m); object method = getMethod(t, m);
object r = t->m->processor->invokeList(t, method, *o, true, a); object r = t->m->processor->invokeList(t, method, *o, true, a);
return (t->exception ? 0 : intValue(t, r)); return (t->exception ? 0 : intValue(t, r));
} }
@ -489,7 +479,7 @@ CallIntMethodV(Thread* t, jobject o, jmethodID m, va_list a)
{ {
ENTER(t, Thread::ActiveState); ENTER(t, Thread::ActiveState);
object method = getMethod(t, *o, m); object method = getMethod(t, m);
object r = t->m->processor->invokeList(t, method, *o, true, a); object r = t->m->processor->invokeList(t, method, *o, true, a);
return (t->exception ? 0 : intValue(t, r)); return (t->exception ? 0 : intValue(t, r));
} }
@ -512,7 +502,7 @@ CallLongMethodV(Thread* t, jobject o, jmethodID m, va_list a)
{ {
ENTER(t, Thread::ActiveState); ENTER(t, Thread::ActiveState);
object method = getMethod(t, *o, m); object method = getMethod(t, m);
object r = t->m->processor->invokeList(t, method, *o, true, a); object r = t->m->processor->invokeList(t, method, *o, true, a);
return (t->exception ? 0 : longValue(t, r)); return (t->exception ? 0 : longValue(t, r));
} }
@ -535,7 +525,7 @@ CallFloatMethodV(Thread* t, jobject o, jmethodID m, va_list a)
{ {
ENTER(t, Thread::ActiveState); ENTER(t, Thread::ActiveState);
object method = getMethod(t, *o, m); object method = getMethod(t, m);
object r = t->m->processor->invokeList(t, method, *o, true, a); object r = t->m->processor->invokeList(t, method, *o, true, a);
return (t->exception ? 0 : bitsToFloat(intValue(t, r))); return (t->exception ? 0 : bitsToFloat(intValue(t, r)));
} }
@ -558,7 +548,7 @@ CallDoubleMethodV(Thread* t, jobject o, jmethodID m, va_list a)
{ {
ENTER(t, Thread::ActiveState); ENTER(t, Thread::ActiveState);
object method = getMethod(t, *o, m); object method = getMethod(t, m);
object r = t->m->processor->invokeList(t, method, *o, true, a); object r = t->m->processor->invokeList(t, method, *o, true, a);
return (t->exception ? 0 : bitsToDouble(longValue(t, r))); return (t->exception ? 0 : bitsToDouble(longValue(t, r)));
} }
@ -581,7 +571,7 @@ CallVoidMethodV(Thread* t, jobject o, jmethodID m, va_list a)
{ {
ENTER(t, Thread::ActiveState); ENTER(t, Thread::ActiveState);
object method = getMethod(t, *o, m); object method = getMethod(t, m);
t->m->processor->invokeList(t, method, *o, true, a); t->m->processor->invokeList(t, method, *o, true, a);
} }
@ -597,25 +587,22 @@ CallVoidMethod(Thread* t, jobject o, jmethodID m, ...)
} }
inline object inline object
getStaticMethod(Thread* t, object c, jmethodID m) getStaticMethod(Thread* t, jmethodID m)
{ {
if (classVmFlags(t, c) & BootstrapFlag) { object method = vectorBody(t, t->m->jniMethodTable, m - 1);
PROTECT(t, c);
resolveClass(t, className(t, c)); assert(t, methodFlags(t, method) & ACC_STATIC);
if (UNLIKELY(t->exception)) return 0;
}
return arrayBody(t, classMethodTable(t, c), m - 1); return method;
} }
jobject JNICALL jobject JNICALL
CallStaticObjectMethodV(Thread* t, jclass c, jmethodID m, va_list a) CallStaticObjectMethodV(Thread* t, jclass, jmethodID m, va_list a)
{ {
ENTER(t, Thread::ActiveState); ENTER(t, Thread::ActiveState);
return makeLocalReference(t, t->m->processor->invokeList return makeLocalReference(t, t->m->processor->invokeList
(t, getStaticMethod(t, *c, m), 0, true, a)); (t, getStaticMethod(t, m), 0, true, a));
} }
jobject JNICALL jobject JNICALL
@ -632,12 +619,11 @@ CallStaticObjectMethod(Thread* t, jclass c, jmethodID m, ...)
} }
jboolean JNICALL jboolean JNICALL
CallStaticBooleanMethodV(Thread* t, jclass c, jmethodID m, va_list a) CallStaticBooleanMethodV(Thread* t, jclass, jmethodID m, va_list a)
{ {
ENTER(t, Thread::ActiveState); ENTER(t, Thread::ActiveState);
object r = t->m->processor->invokeList object r = t->m->processor->invokeList(t, getStaticMethod(t, m), 0, true, a);
(t, getStaticMethod(t, *c, m), 0, true, a);
return (t->exception ? 0 : (intValue(t, r) != 0)); return (t->exception ? 0 : (intValue(t, r) != 0));
} }
@ -655,12 +641,11 @@ CallStaticBooleanMethod(Thread* t, jclass c, jmethodID m, ...)
} }
jbyte JNICALL jbyte JNICALL
CallStaticByteMethodV(Thread* t, jclass c, jmethodID m, va_list a) CallStaticByteMethodV(Thread* t, jclass, jmethodID m, va_list a)
{ {
ENTER(t, Thread::ActiveState); ENTER(t, Thread::ActiveState);
object r = t->m->processor->invokeList object r = t->m->processor->invokeList(t, getStaticMethod(t, m), 0, true, a);
(t, getStaticMethod(t, *c, m), 0, true, a);
return (t->exception ? 0 : intValue(t, r)); return (t->exception ? 0 : intValue(t, r));
} }
@ -678,12 +663,11 @@ CallStaticByteMethod(Thread* t, jclass c, jmethodID m, ...)
} }
jchar JNICALL jchar JNICALL
CallStaticCharMethodV(Thread* t, jclass c, jmethodID m, va_list a) CallStaticCharMethodV(Thread* t, jclass, jmethodID m, va_list a)
{ {
ENTER(t, Thread::ActiveState); ENTER(t, Thread::ActiveState);
object r = t->m->processor->invokeList object r = t->m->processor->invokeList(t, getStaticMethod(t, m), 0, true, a);
(t, getStaticMethod(t, *c, m), 0, true, a);
return (t->exception ? 0 : intValue(t, r)); return (t->exception ? 0 : intValue(t, r));
} }
@ -701,12 +685,11 @@ CallStaticCharMethod(Thread* t, jclass c, jmethodID m, ...)
} }
jshort JNICALL jshort JNICALL
CallStaticShortMethodV(Thread* t, jclass c, jmethodID m, va_list a) CallStaticShortMethodV(Thread* t, jclass, jmethodID m, va_list a)
{ {
ENTER(t, Thread::ActiveState); ENTER(t, Thread::ActiveState);
object r = t->m->processor->invokeList object r = t->m->processor->invokeList(t, getStaticMethod(t, m), 0, true, a);
(t, getStaticMethod(t, *c, m), 0, true, a);
return (t->exception ? 0 : intValue(t, r)); return (t->exception ? 0 : intValue(t, r));
} }
@ -724,12 +707,11 @@ CallStaticShortMethod(Thread* t, jclass c, jmethodID m, ...)
} }
jint JNICALL jint JNICALL
CallStaticIntMethodV(Thread* t, jclass c, jmethodID m, va_list a) CallStaticIntMethodV(Thread* t, jclass, jmethodID m, va_list a)
{ {
ENTER(t, Thread::ActiveState); ENTER(t, Thread::ActiveState);
object r = t->m->processor->invokeList object r = t->m->processor->invokeList(t, getStaticMethod(t, m), 0, true, a);
(t, getStaticMethod(t, *c, m), 0, true, a);
return (t->exception ? 0 : intValue(t, r)); return (t->exception ? 0 : intValue(t, r));
} }
@ -747,12 +729,11 @@ CallStaticIntMethod(Thread* t, jclass c, jmethodID m, ...)
} }
jlong JNICALL jlong JNICALL
CallStaticLongMethodV(Thread* t, jclass c, jmethodID m, va_list a) CallStaticLongMethodV(Thread* t, jclass, jmethodID m, va_list a)
{ {
ENTER(t, Thread::ActiveState); ENTER(t, Thread::ActiveState);
object r = t->m->processor->invokeList object r = t->m->processor->invokeList(t, getStaticMethod(t, m), 0, true, a);
(t, getStaticMethod(t, *c, m), 0, true, a);
return (t->exception ? 0 : longValue(t, r)); return (t->exception ? 0 : longValue(t, r));
} }
@ -770,12 +751,11 @@ CallStaticLongMethod(Thread* t, jclass c, jmethodID m, ...)
} }
jfloat JNICALL jfloat JNICALL
CallStaticFloatMethodV(Thread* t, jclass c, jmethodID m, va_list a) CallStaticFloatMethodV(Thread* t, jclass, jmethodID m, va_list a)
{ {
ENTER(t, Thread::ActiveState); ENTER(t, Thread::ActiveState);
object r = t->m->processor->invokeList object r = t->m->processor->invokeList(t, getStaticMethod(t, m), 0, true, a);
(t, getStaticMethod(t, *c, m), 0, true, a);
return (t->exception ? 0 : bitsToFloat(intValue(t, r))); return (t->exception ? 0 : bitsToFloat(intValue(t, r)));
} }
@ -793,12 +773,11 @@ CallStaticFloatMethod(Thread* t, jclass c, jmethodID m, ...)
} }
jdouble JNICALL jdouble JNICALL
CallStaticDoubleMethodV(Thread* t, jclass c, jmethodID m, va_list a) CallStaticDoubleMethodV(Thread* t, jclass, jmethodID m, va_list a)
{ {
ENTER(t, Thread::ActiveState); ENTER(t, Thread::ActiveState);
object r = t->m->processor->invokeList object r = t->m->processor->invokeList(t, getStaticMethod(t, m), 0, true, a);
(t, getStaticMethod(t, *c, m), 0, true, a);
return (t->exception ? 0 : bitsToDouble(longValue(t, r))); return (t->exception ? 0 : bitsToDouble(longValue(t, r)));
} }
@ -816,11 +795,11 @@ CallStaticDoubleMethod(Thread* t, jclass c, jmethodID m, ...)
} }
void JNICALL void JNICALL
CallStaticVoidMethodV(Thread* t, jclass c, jmethodID m, va_list a) CallStaticVoidMethodV(Thread* t, jclass, jmethodID m, va_list a)
{ {
ENTER(t, Thread::ActiveState); ENTER(t, Thread::ActiveState);
t->m->processor->invokeList(t, getStaticMethod(t, *c, m), 0, true, a); t->m->processor->invokeList(t, getStaticMethod(t, m), 0, true, a);
} }
void JNICALL void JNICALL

View File

@ -1088,6 +1088,7 @@ parseMethodTable(Thread* t, Stream& s, object class_, object pool)
methodParameterFootprint(t, method), methodParameterFootprint(t, method),
methodFlags(t, method), methodFlags(t, method),
virtualCount++, virtualCount++,
0,
methodName(t, method), methodName(t, method),
methodSpec(t, method), methodSpec(t, method),
class_, class_,
@ -1538,7 +1539,7 @@ class HeapClient: public Heap::Client {
v->visit(&(m->monitorMap)); v->visit(&(m->monitorMap));
v->visit(&(m->stringMap)); v->visit(&(m->stringMap));
v->visit(&(m->types)); v->visit(&(m->types));
v->visit(&(m->jniInterfaceTable)); v->visit(&(m->jniMethodTable));
for (Reference* r = m->jniReferences; r; r = r->next) { for (Reference* r = m->jniReferences; r; r = r->next) {
v->visit(&(r->target)); v->visit(&(r->target));
@ -1658,7 +1659,7 @@ Machine::Machine(System* system, Heap* heap, Finder* finder,
monitorMap(0), monitorMap(0),
stringMap(0), stringMap(0),
types(0), types(0),
jniInterfaceTable(0), jniMethodTable(0),
finalizers(0), finalizers(0),
tenuredFinalizers(0), tenuredFinalizers(0),
finalizeQueue(0), finalizeQueue(0),
@ -1819,14 +1820,14 @@ Thread::init()
m->monitorMap = makeWeakHashMap(this, 0, 0); m->monitorMap = makeWeakHashMap(this, 0, 0);
m->stringMap = makeWeakHashMap(this, 0, 0); m->stringMap = makeWeakHashMap(this, 0, 0);
m->jniInterfaceTable = makeVector(this, 0, 0, false); m->jniMethodTable = makeVector(this, 0, 0, false);
m->localThread->set(this); m->localThread->set(this);
{ object bootCode = makeCode(t, 0, 0, 0, 0, 0, 1, false); { object bootCode = makeCode(t, 0, 0, 0, 0, 0, 1, false);
codeBody(t, bootCode, 0) = impdep1; codeBody(t, bootCode, 0) = impdep1;
object bootMethod = makeMethod object bootMethod = makeMethod
(t, 0, 0, 0, 0, 0, 0, 0, 0, 0, bootCode, 0); (t, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, bootCode, 0);
PROTECT(t, bootMethod); PROTECT(t, bootMethod);
#include "type-java-initializations.cpp" #include "type-java-initializations.cpp"

View File

@ -1158,7 +1158,7 @@ class Machine {
object monitorMap; object monitorMap;
object stringMap; object stringMap;
object types; object types;
object jniInterfaceTable; object jniMethodTable;
object finalizers; object finalizers;
object tenuredFinalizers; object tenuredFinalizers;
object finalizeQueue; object finalizeQueue;