mirror of
https://github.com/corda/corda.git
synced 2025-01-17 02:09:50 +00:00
implement NewDirectByteBuffer etc. properly when building against Classpath; call JNI_OnLoad if found in newly-loaded libraries
This commit is contained in:
parent
b35a5a6db6
commit
f239424930
4
makefile
4
makefile
@ -56,7 +56,7 @@ ifdef gnu
|
||||
$(gnu)/lib/classpath/libjavanio.a \
|
||||
$(gnu)/lib/classpath/libjavautil.a
|
||||
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-objects = $(shell find $(build)/gnu-objects -name "*.o")
|
||||
endif
|
||||
@ -473,7 +473,7 @@ $(test-dep): $(test-sources)
|
||||
@mkdir -p $(test-build)
|
||||
$(javac) -d $(test-build) -bootclasspath $(classpath-build) \
|
||||
$(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
|
||||
@touch $(@)
|
||||
|
||||
|
@ -71,6 +71,15 @@ compatibleArrayTypes(Thread* t, object a, object b)
|
||||
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
|
||||
|
||||
extern "C" JNIEXPORT int64_t JNICALL
|
||||
@ -612,6 +621,10 @@ Avian_java_lang_Runtime_load
|
||||
and (s[length] == ',' or s[length] == 0))
|
||||
{
|
||||
// library is built in to this executable
|
||||
if (not t->m->triedBuiltinOnLoad) {
|
||||
t->m->triedBuiltinOnLoad = true;
|
||||
runOnLoadIfFound(t, t->m->libraries);
|
||||
}
|
||||
return;
|
||||
} else {
|
||||
while (*s and *s != ',') ++ s;
|
||||
@ -635,6 +648,7 @@ Avian_java_lang_Runtime_load
|
||||
System::Library* lib;
|
||||
if (LIKELY(t->m->system->success(t->m->system->load(&lib, n, mapName)))) {
|
||||
last->setNext(lib);
|
||||
runOnLoadIfFound(t, lib);
|
||||
} else {
|
||||
object message = makeString(t, "library not found: %s", n);
|
||||
t->exception = makeUnsatisfiedLinkError(t, message);
|
||||
|
@ -115,7 +115,6 @@ pad(unsigned n)
|
||||
return pad(n, BytesPerWord);
|
||||
}
|
||||
|
||||
|
||||
inline unsigned
|
||||
ceiling(unsigned n, unsigned d)
|
||||
{
|
||||
|
83
src/gnu.cpp
83
src/gnu.cpp
@ -33,6 +33,89 @@ setProperty(Thread* t, object method, object properties,
|
||||
|
||||
} // 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
|
||||
Avian_gnu_classpath_VMSystemProperties_preInit
|
||||
(Thread* t, object, uintptr_t* arguments)
|
||||
|
@ -256,6 +256,7 @@ ExceptionCheck(Thread* t)
|
||||
return t->exception != 0;
|
||||
}
|
||||
|
||||
#ifndef AVIAN_GNU
|
||||
jobject JNICALL
|
||||
NewDirectByteBuffer(Thread*, void*, jlong)
|
||||
{
|
||||
@ -269,10 +270,11 @@ GetDirectBufferAddress(Thread*, jobject)
|
||||
}
|
||||
|
||||
jlong JNICALL
|
||||
GetDirectBufferCapacity(JNIEnv*, jobject)
|
||||
GetDirectBufferCapacity(Thread*, jobject)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
#endif// not AVIAN_GNU
|
||||
|
||||
jclass JNICALL
|
||||
GetObjectClass(Thread* t, jobject o)
|
||||
@ -833,22 +835,12 @@ CallStaticVoidMethod(Thread* t, jclass c, jmethodID m, ...)
|
||||
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
|
||||
GetFieldID(Thread* t, jclass c, const char* name, const char* spec)
|
||||
{
|
||||
ENTER(t, Thread::ActiveState);
|
||||
|
||||
object field = findField(t, c, name, spec);
|
||||
object field = resolveField(t, *c, name, spec);
|
||||
if (UNLIKELY(t->exception)) return 0;
|
||||
|
||||
return fieldOffset(t, field);
|
||||
@ -859,7 +851,7 @@ GetStaticFieldID(Thread* t, jclass c, const char* name, const char* spec)
|
||||
{
|
||||
ENTER(t, Thread::ActiveState);
|
||||
|
||||
object field = findField(t, c, name, spec);
|
||||
object field = resolveField(t, *c, name, spec);
|
||||
if (UNLIKELY(t->exception)) return 0;
|
||||
|
||||
return fieldOffset(t, field);
|
||||
@ -1899,6 +1891,17 @@ append(char** p, const char* value, unsigned length, char tail)
|
||||
|
||||
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
|
||||
populateJNITables(JavaVMVTable* vmTable, JNIEnvVTable* envTable)
|
||||
{
|
||||
|
@ -1800,6 +1800,7 @@ Machine::Machine(System* system, Heap* heap, Finder* finder,
|
||||
weakReferences(0),
|
||||
tenuredWeakReferences(0),
|
||||
unsafe(false),
|
||||
triedBuiltinOnLoad(false),
|
||||
heapPoolIndex(0)
|
||||
{
|
||||
heap->setClient(heapClient);
|
||||
@ -2600,33 +2601,55 @@ resolveClass(Thread* t, object spec)
|
||||
}
|
||||
|
||||
object
|
||||
resolveMethod(Thread* t, const char* className, const char* methodName,
|
||||
resolveMethod(Thread* t, object class_, const char* methodName,
|
||||
const char* methodSpec)
|
||||
{
|
||||
object class_ = resolveClass(t, makeByteArray(t, "%s", className));
|
||||
if (LIKELY(t->exception == 0)) {
|
||||
PROTECT(t, class_);
|
||||
PROTECT(t, class_);
|
||||
|
||||
object name = makeByteArray(t, methodName);
|
||||
PROTECT(t, name);
|
||||
object name = makeByteArray(t, methodName);
|
||||
PROTECT(t, name);
|
||||
|
||||
object spec = makeByteArray(t, methodSpec);
|
||||
object reference = makeReference(t, class_, name, spec);
|
||||
object spec = makeByteArray(t, methodSpec);
|
||||
|
||||
object method = findMethodInClass(t, class_, referenceName(t, reference),
|
||||
referenceSpec(t, reference));
|
||||
object method = findMethodInClass(t, class_, name, spec);
|
||||
|
||||
if (t->exception == 0 and method == 0) {
|
||||
object message = makeString
|
||||
(t, "%s %s not found in %s", methodName, methodSpec, className);
|
||||
if (t->exception == 0 and method == 0) {
|
||||
object message = makeString
|
||||
(t, "%s %s not found in %s", methodName, methodSpec, className);
|
||||
|
||||
t->exception = makeNoSuchMethodError(t, message);
|
||||
} else {
|
||||
return method;
|
||||
}
|
||||
t->exception = makeNoSuchMethodError(t, message);
|
||||
return 0;
|
||||
} 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
|
||||
|
@ -1195,6 +1195,7 @@ class Machine {
|
||||
object weakReferences;
|
||||
object tenuredWeakReferences;
|
||||
bool unsafe;
|
||||
bool triedBuiltinOnLoad;
|
||||
JavaVMVTable javaVMVTable;
|
||||
JNIEnvVTable jniEnvVTable;
|
||||
uintptr_t* heapPool[ThreadHeapPoolSize];
|
||||
@ -2049,12 +2050,46 @@ object
|
||||
parseClass(Thread* t, const uint8_t* data, unsigned length);
|
||||
|
||||
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
|
||||
resolveMethod(Thread* t, const char* className, const char* methodName,
|
||||
resolveMethod(Thread* t, object class_, const char* methodName,
|
||||
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
|
||||
resolveObjectArrayClass(Thread* t, object elementSpec);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user