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/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 $(@)
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
@ -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)
|
||||||
{
|
{
|
||||||
|
83
src/gnu.cpp
83
src/gnu.cpp
@ -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)
|
||||||
|
@ -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)
|
||||||
{
|
{
|
||||||
|
@ -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
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user