implement NewDirectByteBuffer etc. properly when building against Classpath; call JNI_OnLoad if found in newly-loaded libraries

This commit is contained in:
Joel Dice 2009-06-10 18:15:00 -06:00
parent b35a5a6db6
commit f239424930
7 changed files with 193 additions and 36 deletions

View File

@ -56,7 +56,7 @@ ifdef gnu
$(gnu)/lib/classpath/libjavanio.a \ $(gnu)/lib/classpath/libjavanio.a \
$(gnu)/lib/classpath/libjavautil.a $(gnu)/lib/classpath/libjavautil.a
gnu-object-dep = $(build)/gnu-object.dep gnu-object-dep = $(build)/gnu-object.dep
gnu-cflags = -DBOOT_BUILTINS=\"javaio,javalang,javalangreflect,javamath,javanet,javanio,javautil\" gnu-cflags = -DBOOT_BUILTINS=\"javaio,javalang,javalangreflect,javamath,javanet,javanio,javautil\" -DAVIAN_GNU
gnu-lflags = -lgmp gnu-lflags = -lgmp
gnu-objects = $(shell find $(build)/gnu-objects -name "*.o") gnu-objects = $(shell find $(build)/gnu-objects -name "*.o")
endif endif
@ -473,7 +473,7 @@ $(test-dep): $(test-sources)
@mkdir -p $(test-build) @mkdir -p $(test-build)
$(javac) -d $(test-build) -bootclasspath $(classpath-build) \ $(javac) -d $(test-build) -bootclasspath $(classpath-build) \
$(shell $(MAKE) -s --no-print-directory $(test-classes)) $(shell $(MAKE) -s --no-print-directory $(test-classes))
$(javac) -source 1.2 -target 1.1 -XDjsrlimit=0 -d $(dir $(@)) \ $(javac) -source 1.2 -target 1.1 -XDjsrlimit=0 -d $(test-build) \
test/Subroutine.java test/Subroutine.java
@touch $(@) @touch $(@)

View File

@ -71,6 +71,15 @@ compatibleArrayTypes(Thread* t, object a, object b)
or (classVmFlags(t, b) & PrimitiveFlag)))); or (classVmFlags(t, b) & PrimitiveFlag))));
} }
void
runOnLoadIfFound(Thread* t, System::Library* library)
{
void* p = library->resolve("JNI_OnLoad");
if (p) {
reinterpret_cast<jint (JNICALL *)(Machine*, void*)>(p)(t->m, 0);
}
}
} // namespace } // namespace
extern "C" JNIEXPORT int64_t JNICALL extern "C" JNIEXPORT int64_t JNICALL
@ -612,6 +621,10 @@ Avian_java_lang_Runtime_load
and (s[length] == ',' or s[length] == 0)) and (s[length] == ',' or s[length] == 0))
{ {
// library is built in to this executable // library is built in to this executable
if (not t->m->triedBuiltinOnLoad) {
t->m->triedBuiltinOnLoad = true;
runOnLoadIfFound(t, t->m->libraries);
}
return; return;
} else { } else {
while (*s and *s != ',') ++ s; while (*s and *s != ',') ++ s;
@ -635,6 +648,7 @@ Avian_java_lang_Runtime_load
System::Library* lib; System::Library* lib;
if (LIKELY(t->m->system->success(t->m->system->load(&lib, n, mapName)))) { if (LIKELY(t->m->system->success(t->m->system->load(&lib, n, mapName)))) {
last->setNext(lib); last->setNext(lib);
runOnLoadIfFound(t, lib);
} else { } else {
object message = makeString(t, "library not found: %s", n); object message = makeString(t, "library not found: %s", n);
t->exception = makeUnsatisfiedLinkError(t, message); t->exception = makeUnsatisfiedLinkError(t, message);

View File

@ -115,7 +115,6 @@ pad(unsigned n)
return pad(n, BytesPerWord); return pad(n, BytesPerWord);
} }
inline unsigned inline unsigned
ceiling(unsigned n, unsigned d) ceiling(unsigned n, unsigned d)
{ {

View File

@ -33,6 +33,89 @@ setProperty(Thread* t, object method, object properties,
} // namespace } // namespace
namespace vm {
jobject JNICALL
NewDirectByteBuffer(Thread* t, void* address, jlong capacity)
{
const char* pointerClassName;
const char* initSpec;
if (BytesPerWord == 8) {
pointerClassName = "gnu/classpath/Pointer64";
initSpec = "(J)V";
} else {
pointerClassName = "gnu/classpath/Pointer32";
initSpec = "(I)V";
}
object pointerClass = resolveClass(t, pointerClassName);
if (UNLIKELY(pointerClass == 0)) return 0;
PROTECT(t, pointerClass);
object pointerConstructor = resolveMethod
(t, pointerClass, "<init>", initSpec);
if (UNLIKELY(pointerConstructor == 0)) return 0;
object pointer = make(t, pointerClass);
PROTECT(t, pointer);
t->m->processor->invoke(t, pointerConstructor, pointer, address);
if (UNLIKELY(t->exception)) return 0;
object bufferClass = resolveClass
(t, "java/nio/DirectByteBufferImpl$ReadWrite");
if (UNLIKELY(bufferClass == 0)) return 0;
PROTECT(t, bufferClass);
object bufferConstructor = resolveMethod
(t, bufferClass, "<init>", "(Lgnu/classpath/Pointer;int)V");
if (UNLIKELY(bufferConstructor == 0)) return 0;
object buffer = make(t, bufferClass);
PROTECT(t, buffer);
t->m->processor->invoke
(t, bufferConstructor, buffer, &pointer, static_cast<jint>(capacity));
if (UNLIKELY(t->exception)) return 0;
return makeLocalReference(t, buffer);
}
void* JNICALL
GetDirectBufferAddress(Thread* t, jobject buffer)
{
object addressField = resolveField
(t, objectClass(t, *buffer), "address", "Lgnu/classpath/Pointer;");
if (UNLIKELY(addressField == 0)) return 0;
object address = cast<object>(*buffer, fieldOffset(t, addressField));
if (address == 0) return 0;
const char* dataSpec;
if (BytesPerWord == 8) {
dataSpec = "J";
} else {
dataSpec = "I";
}
object dataField = resolveField
(t, objectClass(t, address), "data", dataSpec);
if (UNLIKELY(dataField == 0)) return 0;
return cast<void*>(address, fieldOffset(t, dataField));
}
jlong JNICALL
GetDirectBufferCapacity(Thread* t, jobject buffer)
{
object capField = resolveField(t, objectClass(t, *buffer), "cap", "I");
if (UNLIKELY(capField == 0)) return 0;
return cast<jint>(*buffer, fieldOffset(t, capField));
}
} // namespace vm
extern "C" JNIEXPORT void JNICALL extern "C" JNIEXPORT void JNICALL
Avian_gnu_classpath_VMSystemProperties_preInit Avian_gnu_classpath_VMSystemProperties_preInit
(Thread* t, object, uintptr_t* arguments) (Thread* t, object, uintptr_t* arguments)

View File

@ -256,6 +256,7 @@ ExceptionCheck(Thread* t)
return t->exception != 0; return t->exception != 0;
} }
#ifndef AVIAN_GNU
jobject JNICALL jobject JNICALL
NewDirectByteBuffer(Thread*, void*, jlong) NewDirectByteBuffer(Thread*, void*, jlong)
{ {
@ -269,10 +270,11 @@ GetDirectBufferAddress(Thread*, jobject)
} }
jlong JNICALL jlong JNICALL
GetDirectBufferCapacity(JNIEnv*, jobject) GetDirectBufferCapacity(Thread*, jobject)
{ {
return -1; return -1;
} }
#endif// not AVIAN_GNU
jclass JNICALL jclass JNICALL
GetObjectClass(Thread* t, jobject o) GetObjectClass(Thread* t, jobject o)
@ -833,22 +835,12 @@ CallStaticVoidMethod(Thread* t, jclass c, jmethodID m, ...)
va_end(a); va_end(a);
} }
object
findField(Thread* t, jclass c, const char* name, const char* spec)
{
object n = makeByteArray(t, "%s", name);
PROTECT(t, n);
object s = makeByteArray(t, "%s", spec);
return vm::findField(t, *c, n, s);
}
jfieldID JNICALL jfieldID JNICALL
GetFieldID(Thread* t, jclass c, const char* name, const char* spec) GetFieldID(Thread* t, jclass c, const char* name, const char* spec)
{ {
ENTER(t, Thread::ActiveState); ENTER(t, Thread::ActiveState);
object field = findField(t, c, name, spec); object field = resolveField(t, *c, name, spec);
if (UNLIKELY(t->exception)) return 0; if (UNLIKELY(t->exception)) return 0;
return fieldOffset(t, field); return fieldOffset(t, field);
@ -859,7 +851,7 @@ GetStaticFieldID(Thread* t, jclass c, const char* name, const char* spec)
{ {
ENTER(t, Thread::ActiveState); ENTER(t, Thread::ActiveState);
object field = findField(t, c, name, spec); object field = resolveField(t, *c, name, spec);
if (UNLIKELY(t->exception)) return 0; if (UNLIKELY(t->exception)) return 0;
return fieldOffset(t, field); return fieldOffset(t, field);
@ -1899,6 +1891,17 @@ append(char** p, const char* value, unsigned length, char tail)
namespace vm { namespace vm {
#ifdef AVIAN_GNU
jobject JNICALL
NewDirectByteBuffer(Thread*, void*, jlong);
void* JNICALL
GetDirectBufferAddress(Thread*, jobject);
jlong JNICALL
GetDirectBufferCapacity(Thread*, jobject);
#endif//AVIAN_GNU
void void
populateJNITables(JavaVMVTable* vmTable, JNIEnvVTable* envTable) populateJNITables(JavaVMVTable* vmTable, JNIEnvVTable* envTable)
{ {

View File

@ -1800,6 +1800,7 @@ Machine::Machine(System* system, Heap* heap, Finder* finder,
weakReferences(0), weakReferences(0),
tenuredWeakReferences(0), tenuredWeakReferences(0),
unsafe(false), unsafe(false),
triedBuiltinOnLoad(false),
heapPoolIndex(0) heapPoolIndex(0)
{ {
heap->setClient(heapClient); heap->setClient(heapClient);
@ -2600,33 +2601,55 @@ resolveClass(Thread* t, object spec)
} }
object object
resolveMethod(Thread* t, const char* className, const char* methodName, resolveMethod(Thread* t, object class_, const char* methodName,
const char* methodSpec) const char* methodSpec)
{ {
object class_ = resolveClass(t, makeByteArray(t, "%s", className)); PROTECT(t, class_);
if (LIKELY(t->exception == 0)) {
PROTECT(t, class_);
object name = makeByteArray(t, methodName); object name = makeByteArray(t, methodName);
PROTECT(t, name); PROTECT(t, name);
object spec = makeByteArray(t, methodSpec); object spec = makeByteArray(t, methodSpec);
object reference = makeReference(t, class_, name, spec);
object method = findMethodInClass(t, class_, referenceName(t, reference), object method = findMethodInClass(t, class_, name, spec);
referenceSpec(t, reference));
if (t->exception == 0 and method == 0) { if (t->exception == 0 and method == 0) {
object message = makeString object message = makeString
(t, "%s %s not found in %s", methodName, methodSpec, className); (t, "%s %s not found in %s", methodName, methodSpec, className);
t->exception = makeNoSuchMethodError(t, message); t->exception = makeNoSuchMethodError(t, message);
} else { return 0;
return method; } else {
} return method;
}
}
object
resolveField(Thread* t, object class_, const char* fieldName,
const char* fieldSpec)
{
PROTECT(t, class_);
object name = makeByteArray(t, fieldName);
PROTECT(t, name);
object spec = makeByteArray(t, fieldSpec);
PROTECT(t, spec);
object field = 0;
for (; class_ != 0 and field == 0; class_ = classSuper(t, class_)) {
field = findFieldInClass(t, class_, name, spec);
} }
return 0; if (t->exception == 0 and field == 0) {
object message = makeString
(t, "%s %s not found in %s", fieldName, fieldSpec, className);
t->exception = makeNoSuchFieldError(t, message);
return 0;
} else {
return field;
}
} }
object object

View File

@ -1195,6 +1195,7 @@ class Machine {
object weakReferences; object weakReferences;
object tenuredWeakReferences; object tenuredWeakReferences;
bool unsafe; bool unsafe;
bool triedBuiltinOnLoad;
JavaVMVTable javaVMVTable; JavaVMVTable javaVMVTable;
JNIEnvVTable jniEnvVTable; JNIEnvVTable jniEnvVTable;
uintptr_t* heapPool[ThreadHeapPoolSize]; uintptr_t* heapPool[ThreadHeapPoolSize];
@ -2049,12 +2050,46 @@ object
parseClass(Thread* t, const uint8_t* data, unsigned length); parseClass(Thread* t, const uint8_t* data, unsigned length);
object object
resolveClass(Thread* t, object spec); resolveClass(Thread* t, object name);
inline object
resolveClass(Thread* t, const char* name)
{
return resolveClass(t, makeByteArray(t, "%s", name));
}
object object
resolveMethod(Thread* t, const char* className, const char* methodName, resolveMethod(Thread* t, object class_, const char* methodName,
const char* methodSpec); const char* methodSpec);
inline object
resolveMethod(Thread* t, const char* className, const char* methodName,
const char* methodSpec)
{
object class_ = resolveClass(t, className);
if (LIKELY(t->exception == 0)) {
return resolveMethod(t, class_, methodName, methodSpec);
} else {
return 0;
}
}
object
resolveField(Thread* t, object class_, const char* fieldName,
const char* fieldSpec);
inline object
resolveField(Thread* t, const char* className, const char* fieldName,
const char* fieldSpec)
{
object class_ = resolveClass(t, className);
if (LIKELY(t->exception == 0)) {
return resolveField(t, class_, fieldName, fieldSpec);
} else {
return 0;
}
}
object object
resolveObjectArrayClass(Thread* t, object elementSpec); resolveObjectArrayClass(Thread* t, object elementSpec);