mirror of
https://github.com/corda/corda.git
synced 2024-12-29 09:18:58 +00:00
more JNI work
This commit is contained in:
parent
f606f2d30a
commit
400b3633d7
5
classpath/Hello.java
Normal file
5
classpath/Hello.java
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
public class Hello {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
System.out.println("hello, world!");
|
||||||
|
}
|
||||||
|
}
|
13
classpath/java/lang/System.cpp
Normal file
13
classpath/java/lang/System.cpp
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
#include "stdio.h"
|
||||||
|
#include "jni.h"
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT void JNICALL
|
||||||
|
Java_java_lang_System_Output_println(JNIEnv* e, jobject, jstring s)
|
||||||
|
{
|
||||||
|
jboolean isCopy;
|
||||||
|
const char* chars = e->GetStringUTFChars(s, &isCopy);
|
||||||
|
if (chars) {
|
||||||
|
printf("%s", chars);
|
||||||
|
}
|
||||||
|
e->ReleaseStringUTFChars(s, chars);
|
||||||
|
}
|
15
classpath/java/lang/System.java
Normal file
15
classpath/java/lang/System.java
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
package java.lang;
|
||||||
|
|
||||||
|
public abstract class System {
|
||||||
|
public static final Output out = new Output();
|
||||||
|
|
||||||
|
static {
|
||||||
|
loadLibrary("natives");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static native void loadLibrary(String name);
|
||||||
|
|
||||||
|
public static class Output {
|
||||||
|
public native void println(String s);
|
||||||
|
}
|
||||||
|
}
|
32
makefile
32
makefile
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
bld = build
|
bld = build
|
||||||
src = src
|
src = src
|
||||||
inp = input
|
classpath = classpath
|
||||||
|
|
||||||
cxx = g++
|
cxx = g++
|
||||||
cc = gcc
|
cc = gcc
|
||||||
@ -22,7 +22,7 @@ thread-lflags = -lpthread
|
|||||||
|
|
||||||
cflags = $(warnings) -fPIC -fno-rtti -fno-exceptions -fvisibility=hidden \
|
cflags = $(warnings) -fPIC -fno-rtti -fno-exceptions -fvisibility=hidden \
|
||||||
-I$(src) -I$(bld) $(thread-cflags)
|
-I$(src) -I$(bld) $(thread-cflags)
|
||||||
lflags = $(thread-lflags)
|
lflags = $(thread-lflags) -ldl
|
||||||
test-cflags = -DDEBUG_MEMORY
|
test-cflags = -DDEBUG_MEMORY
|
||||||
stress-cflags = -DDEBUG_MEMORY -DDEBUG_MEMORY_MAJOR
|
stress-cflags = -DDEBUG_MEMORY -DDEBUG_MEMORY_MAJOR
|
||||||
|
|
||||||
@ -32,6 +32,13 @@ stdcpp-sources = $(src)/stdc++.cpp
|
|||||||
stdcpp-objects = $(call cpp-objects,$(stdcpp-sources),$(src))
|
stdcpp-objects = $(call cpp-objects,$(stdcpp-sources),$(src))
|
||||||
stdcpp-cflags = $(fast) $(cflags)
|
stdcpp-cflags = $(fast) $(cflags)
|
||||||
|
|
||||||
|
jni-sources = $(classpath)/java/lang/System.cpp
|
||||||
|
jni-objects = $(call cpp-objects,$(jni-sources),$(classpath))
|
||||||
|
jni-cflags = -I/usr/lib/jvm/java-6-sun-1.6.0.00/include \
|
||||||
|
-I/usr/lib/jvm/java-6-sun-1.6.0.00/include/linux \
|
||||||
|
$(cflags)
|
||||||
|
jni-library = $(bld)/libnatives.so
|
||||||
|
|
||||||
generated-code = \
|
generated-code = \
|
||||||
$(bld)/type-enums.cpp \
|
$(bld)/type-enums.cpp \
|
||||||
$(bld)/type-declarations.cpp \
|
$(bld)/type-declarations.cpp \
|
||||||
@ -75,11 +82,10 @@ fast-objects = $(patsubst $(bld)/%,$(bld)/fast-%,$(interpreter-objects))
|
|||||||
fast-executable = $(bld)/fast-vm
|
fast-executable = $(bld)/fast-vm
|
||||||
fast-cflags = $(fast) $(cflags)
|
fast-cflags = $(fast) $(cflags)
|
||||||
|
|
||||||
input = $(bld)/classes/Test.class
|
input = $(bld)/classes/Hello.class
|
||||||
input-depends = \
|
input-depends = \
|
||||||
$(bld)/classes/java/lang/Object.class \
|
$(bld)/classes/java/lang/System.class \
|
||||||
$(bld)/classes/java/lang/Class.class \
|
$(jni-library)
|
||||||
$(bld)/classes/vm/VM.class
|
|
||||||
|
|
||||||
gen-run-arg = $(shell echo $(1) | sed -e 's:$(bld)/classes/\(.*\)\.class:\1:')
|
gen-run-arg = $(shell echo $(1) | sed -e 's:$(bld)/classes/\(.*\)\.class:\1:')
|
||||||
args = -cp $(bld)/classes -hs 67108864 $(call gen-run-arg,$(input))
|
args = -cp $(bld)/classes -hs 67108864 $(call gen-run-arg,$(input))
|
||||||
@ -142,10 +148,11 @@ $(generated-code): %.cpp: $(src)/types.def $(generator-executable)
|
|||||||
$(bld)/type-generator.o: \
|
$(bld)/type-generator.o: \
|
||||||
$(generator-headers)
|
$(generator-headers)
|
||||||
|
|
||||||
$(bld)/classes/%.class: $(inp)/%.java
|
$(bld)/classes/%.class: $(classpath)/%.java
|
||||||
@echo "compiling $(@)"
|
@echo "compiling $(@)"
|
||||||
@mkdir -p $(dir $(@))
|
@mkdir -p $(dir $(@))
|
||||||
$(javac) -bootclasspath $(inp) -classpath $(inp) -d $(bld)/classes $(<)
|
$(javac) -bootclasspath $(classpath) -classpath $(classpath) \
|
||||||
|
-d $(bld)/classes $(<)
|
||||||
|
|
||||||
$(stdcpp-objects): $(bld)/%.o: $(src)/%.cpp
|
$(stdcpp-objects): $(bld)/%.o: $(src)/%.cpp
|
||||||
@echo "compiling $(@)"
|
@echo "compiling $(@)"
|
||||||
@ -177,6 +184,15 @@ $(fast-objects): $(bld)/fast-%.o: $(src)/%.cpp $(interpreter-depends)
|
|||||||
@mkdir -p $(dir $(@))
|
@mkdir -p $(dir $(@))
|
||||||
$(cxx) $(fast-cflags) -c $(<) -o $(@)
|
$(cxx) $(fast-cflags) -c $(<) -o $(@)
|
||||||
|
|
||||||
|
$(jni-objects): $(bld)/%.o: $(classpath)/%.cpp
|
||||||
|
@echo "compiling $(@)"
|
||||||
|
@mkdir -p $(dir $(@))
|
||||||
|
$(cxx) $(jni-cflags) -c $(<) -o $(@)
|
||||||
|
|
||||||
|
$(jni-library): $(jni-objects)
|
||||||
|
@echo "linking $(@)"
|
||||||
|
$(cc) $(lflags) -shared $(^) -o $(@)
|
||||||
|
|
||||||
$(executable): $(interpreter-objects) $(stdcpp-objects)
|
$(executable): $(interpreter-objects) $(stdcpp-objects)
|
||||||
@echo "linking $(@)"
|
@echo "linking $(@)"
|
||||||
$(cc) $(lflags) $(^) -o $(@)
|
$(cc) $(lflags) $(^) -o $(@)
|
||||||
|
19
src/main.cpp
19
src/main.cpp
@ -66,6 +66,8 @@ class System: public vm::System {
|
|||||||
}
|
}
|
||||||
|
|
||||||
virtual void* tryAllocate(unsigned size) {
|
virtual void* tryAllocate(unsigned size) {
|
||||||
|
// todo: synchronize access
|
||||||
|
|
||||||
if (Verbose) {
|
if (Verbose) {
|
||||||
fprintf(stderr, "try %d; count: %d; limit: %d\n",
|
fprintf(stderr, "try %d; count: %d; limit: %d\n",
|
||||||
size, count, limit);
|
size, count, limit);
|
||||||
@ -85,6 +87,8 @@ class System: public vm::System {
|
|||||||
}
|
}
|
||||||
|
|
||||||
virtual void free(const void* p) {
|
virtual void free(const void* p) {
|
||||||
|
// todo: synchronize access
|
||||||
|
|
||||||
if (p) {
|
if (p) {
|
||||||
const uintptr_t* up = static_cast<const uintptr_t*>(p) - 1;
|
const uintptr_t* up = static_cast<const uintptr_t*>(p) - 1;
|
||||||
if (count < *up) {
|
if (count < *up) {
|
||||||
@ -110,14 +114,19 @@ class System: public vm::System {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual uint64_t call(void* function, unsigned argumentCount,
|
virtual uint64_t call(void* ,//function,
|
||||||
uint32_t* argumentTable, uint8_t* argumentSizeTable,
|
unsigned ,//argumentCount,
|
||||||
unsigned returnSize)
|
uint32_t* ,//argumentTable,
|
||||||
|
uint8_t* ,//argumentSizeTable,
|
||||||
|
unsigned )//returnSize)
|
||||||
{
|
{
|
||||||
|
::abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual Status load(Library** lib, const char* name, Library* next) {
|
virtual Status load(vm::System::Library** lib,
|
||||||
|
const char* name,
|
||||||
|
vm::System::Library* next)
|
||||||
|
{
|
||||||
void* p = dlopen(name, RTLD_LAZY);
|
void* p = dlopen(name, RTLD_LAZY);
|
||||||
if (p) {
|
if (p) {
|
||||||
*lib = new (vm::System::allocate(sizeof(Library)))
|
*lib = new (vm::System::allocate(sizeof(Library)))
|
||||||
|
@ -44,8 +44,8 @@ class System {
|
|||||||
virtual Status make(Monitor**) = 0;
|
virtual Status make(Monitor**) = 0;
|
||||||
virtual uint64_t call(void* function, unsigned argumentCount,
|
virtual uint64_t call(void* function, unsigned argumentCount,
|
||||||
uint32_t* argumentTable, uint8_t* argumentSizeTable,
|
uint32_t* argumentTable, uint8_t* argumentSizeTable,
|
||||||
unsigned returnSize);
|
unsigned returnSize) = 0;
|
||||||
virtual Status load(Library**, const char* name, Library* next);
|
virtual Status load(Library**, const char* name, Library* next) = 0;
|
||||||
virtual void abort() = 0;
|
virtual void abort() = 0;
|
||||||
|
|
||||||
void* allocate(unsigned size) {
|
void* allocate(unsigned size) {
|
||||||
|
308
src/vm.cpp
308
src/vm.cpp
@ -4,6 +4,7 @@
|
|||||||
#include "class_finder.h"
|
#include "class_finder.h"
|
||||||
#include "stream.h"
|
#include "stream.h"
|
||||||
#include "constants.h"
|
#include "constants.h"
|
||||||
|
#include "jni.h"
|
||||||
#include "vm.h"
|
#include "vm.h"
|
||||||
|
|
||||||
#define PROTECT(thread, name) \
|
#define PROTECT(thread, name) \
|
||||||
@ -30,7 +31,6 @@ object& arrayBodyUnsafe(Thread*, object, unsigned);
|
|||||||
void set(Thread*, object&, object);
|
void set(Thread*, object&, object);
|
||||||
object makeString(Thread*, const char*, ...);
|
object makeString(Thread*, const char*, ...);
|
||||||
object makeByteArray(Thread*, const char*, ...);
|
object makeByteArray(Thread*, const char*, ...);
|
||||||
unsigned objectSize(Thread* t, object o);
|
|
||||||
|
|
||||||
object&
|
object&
|
||||||
objectClass(object o)
|
objectClass(object o)
|
||||||
@ -152,10 +152,11 @@ class Thread {
|
|||||||
unsigned ip;
|
unsigned ip;
|
||||||
unsigned sp;
|
unsigned sp;
|
||||||
unsigned heapIndex;
|
unsigned heapIndex;
|
||||||
object stack[StackSizeInWords];
|
|
||||||
object heap[HeapSizeInWords];
|
|
||||||
Protector* protector;
|
Protector* protector;
|
||||||
Chain* chain;
|
Chain* chain;
|
||||||
|
object stack[StackSizeInWords];
|
||||||
|
object heap[HeapSizeInWords];
|
||||||
|
JNIEnv jniEnv;
|
||||||
};
|
};
|
||||||
|
|
||||||
#include "type-declarations.cpp"
|
#include "type-declarations.cpp"
|
||||||
@ -458,77 +459,6 @@ top(Thread* t)
|
|||||||
return t->stack[t->sp - 1];
|
return t->stack[t->sp - 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t
|
|
||||||
builtinToString(Thread* t, int32_t this_)
|
|
||||||
{
|
|
||||||
object o = t->stack[this_ - 1];
|
|
||||||
object s = makeString(t, "%s@%p",
|
|
||||||
&byteArrayBody(t, className(t, objectClass(o)), 0),
|
|
||||||
o);
|
|
||||||
pushSafe(t, s);
|
|
||||||
return t->sp;
|
|
||||||
}
|
|
||||||
|
|
||||||
Thread::Thread(Machine* m):
|
|
||||||
vm(m),
|
|
||||||
next(0),
|
|
||||||
child(0),
|
|
||||||
state(NoState),
|
|
||||||
thread(0),
|
|
||||||
frame(0),
|
|
||||||
code(0),
|
|
||||||
exception(0),
|
|
||||||
ip(0),
|
|
||||||
sp(0),
|
|
||||||
heapIndex(0),
|
|
||||||
protector(0),
|
|
||||||
chain(0)
|
|
||||||
{
|
|
||||||
if (m->rootThread == 0) {
|
|
||||||
m->rootThread = this;
|
|
||||||
m->unsafe = true;
|
|
||||||
|
|
||||||
Thread* t = this;
|
|
||||||
|
|
||||||
#include "type-initializations.cpp"
|
|
||||||
|
|
||||||
object arrayClass = arrayBody(t, t->vm->types, Machine::ArrayType);
|
|
||||||
set(t, objectClass(t->vm->types), arrayClass);
|
|
||||||
|
|
||||||
object classClass = arrayBody(t, m->types, Machine::ClassType);
|
|
||||||
set(t, objectClass(classClass), classClass);
|
|
||||||
|
|
||||||
object intArrayClass = arrayBody(t, m->types, Machine::IntArrayType);
|
|
||||||
set(t, objectClass(intArrayClass), classClass);
|
|
||||||
|
|
||||||
m->unsafe = false;
|
|
||||||
|
|
||||||
m->bootstrapClassMap = makeHashMap(this, 0, 0);
|
|
||||||
|
|
||||||
#include "type-java-initializations.cpp"
|
|
||||||
|
|
||||||
m->classMap = makeHashMap(this, 0, 0);
|
|
||||||
m->builtinMap = makeHashMap(this, 0, 0);
|
|
||||||
|
|
||||||
struct {
|
|
||||||
const char* key;
|
|
||||||
void* value;
|
|
||||||
} builtins[] = {
|
|
||||||
{ "Java_java_lang_Object_toString",
|
|
||||||
reinterpret_cast<void*>(builtinToString) },
|
|
||||||
{ 0, 0 }
|
|
||||||
};
|
|
||||||
|
|
||||||
for (unsigned i = 0; builtins[i].key; ++i) {
|
|
||||||
object key = makeByteArray(t, builtins[i].key);
|
|
||||||
PROTECT(t, key);
|
|
||||||
object value = makePointer(t, builtins[i].value);
|
|
||||||
|
|
||||||
hashMapInsert(t, m->builtinMap, key, value, byteArrayHash);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
Thread::dispose()
|
Thread::dispose()
|
||||||
{
|
{
|
||||||
@ -864,6 +794,22 @@ make(Thread* t, object class_)
|
|||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned
|
||||||
|
objectSize(Thread* t, object o)
|
||||||
|
{
|
||||||
|
object class_ = objectClass(o);
|
||||||
|
|
||||||
|
unsigned n = divide(classFixedSize(t, class_), BytesPerWord);
|
||||||
|
|
||||||
|
if (classArrayElementSize(t, class_)) {
|
||||||
|
n += divide(classArrayElementSize(t, class_)
|
||||||
|
* cast<uint32_t>(o, classFixedSize(t, class_) - 4),
|
||||||
|
BytesPerWord);
|
||||||
|
}
|
||||||
|
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
object
|
object
|
||||||
makeByteArray(Thread* t, const char* format, va_list a)
|
makeByteArray(Thread* t, const char* format, va_list a)
|
||||||
{
|
{
|
||||||
@ -915,6 +861,14 @@ makeTrace(Thread* t)
|
|||||||
return trace;
|
return trace;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
object
|
||||||
|
makeRuntimeException(Thread* t, object message)
|
||||||
|
{
|
||||||
|
PROTECT(t, message);
|
||||||
|
object trace = makeTrace(t);
|
||||||
|
return makeClassCastException(t, message, trace, 0);
|
||||||
|
}
|
||||||
|
|
||||||
object
|
object
|
||||||
makeArrayIndexOutOfBoundsException(Thread* t, object message)
|
makeArrayIndexOutOfBoundsException(Thread* t, object message)
|
||||||
{
|
{
|
||||||
@ -1891,7 +1845,7 @@ updateBootstrapClass(Thread* t, object bootstrapClass, object class_)
|
|||||||
|
|
||||||
enter(t, Thread::ExclusiveState);
|
enter(t, Thread::ExclusiveState);
|
||||||
|
|
||||||
memcpy(bootstrapClass, class_, objectSize(t, class_));
|
memcpy(bootstrapClass, class_, objectSize(t, class_) * BytesPerWord);
|
||||||
|
|
||||||
enter(t, Thread::ActiveState);
|
enter(t, Thread::ActiveState);
|
||||||
}
|
}
|
||||||
@ -2013,12 +1967,12 @@ makeNativeMethodData(Thread* t, object method, void* function, bool builtin)
|
|||||||
methodParameterCount(t, method),
|
methodParameterCount(t, method),
|
||||||
false);
|
false);
|
||||||
|
|
||||||
unsigned argumentTableSize = sizeof(void*) / 4;
|
unsigned argumentTableSize = BytesPerWord / 4;
|
||||||
unsigned index = 0;
|
unsigned index = 0;
|
||||||
|
|
||||||
if ((methodFlags(t, method) & ACC_STATIC) == 0) {
|
if ((methodFlags(t, method) & ACC_STATIC) == 0) {
|
||||||
nativeMethodDataParameterCodes(t, data, index++) = ObjectField;
|
nativeMethodDataParameterCodes(t, data, index++) = ObjectField;
|
||||||
argumentTableSize += 1;
|
argumentTableSize += BytesPerWord / 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* s = reinterpret_cast<const char*>
|
const char* s = reinterpret_cast<const char*>
|
||||||
@ -2030,13 +1984,13 @@ makeNativeMethodData(Thread* t, object method, void* function, bool builtin)
|
|||||||
|
|
||||||
switch (*s) {
|
switch (*s) {
|
||||||
case 'L':
|
case 'L':
|
||||||
argumentTableSize += 1;
|
argumentTableSize += BytesPerWord / 4;
|
||||||
while (*s and *s != ';') ++ s;
|
while (*s and *s != ';') ++ s;
|
||||||
++ s;
|
++ s;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '[':
|
case '[':
|
||||||
argumentTableSize += 1;
|
argumentTableSize += BytesPerWord / 4;
|
||||||
while (*s == '[') ++ s;
|
while (*s == '[') ++ s;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -2108,35 +2062,29 @@ invokeNative(Thread* t, object method)
|
|||||||
uint8_t sizes[parameterCount + 1];
|
uint8_t sizes[parameterCount + 1];
|
||||||
unsigned offset = 0;
|
unsigned offset = 0;
|
||||||
|
|
||||||
switch (sizeof(uintptr_t)) {
|
sizes[0] = BytesPerWord;
|
||||||
case 4: {
|
JNIEnv* e = &(t->jniEnv);
|
||||||
sizes[0] = 4;
|
memcpy(args + offset, &e, BytesPerWord);
|
||||||
args[offset++] = reinterpret_cast<uintptr_t>(t);
|
offset += BytesPerWord / 4;
|
||||||
} break;
|
|
||||||
|
|
||||||
case 8: {
|
|
||||||
sizes[0] = 8;
|
|
||||||
uint64_t v = reinterpret_cast<uint64_t>(t);
|
|
||||||
args[offset++] = static_cast<uint32_t>(v >> 32);
|
|
||||||
args[offset++] = static_cast<uint32_t>(v & 0xFFFFFFFF);
|
|
||||||
} break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
abort(t);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (unsigned i = 0; i < parameterCount; ++i) {
|
for (unsigned i = 0; i < parameterCount; ++i) {
|
||||||
unsigned code = nativeMethodDataParameterCodes(t, data, i);
|
unsigned code = nativeMethodDataParameterCodes(t, data, i);
|
||||||
|
|
||||||
if (code == ObjectField) {
|
if (code == ObjectField) {
|
||||||
sizes[i + 1] = 4;
|
sizes[i + 1] = BytesPerWord;
|
||||||
args[offset++] = t->sp + i + 1;
|
unsigned position = (t->sp - parameterCount) + i;
|
||||||
|
if (t->stack[position]) {
|
||||||
|
memcpy(args + offset, t->stack + position, BytesPerWord);
|
||||||
|
} else {
|
||||||
|
memset(args + offset, 0, BytesPerWord);
|
||||||
|
}
|
||||||
|
offset += BytesPerWord / 4;
|
||||||
} else {
|
} else {
|
||||||
sizes[i + 1] = primitiveSize(t, code);
|
sizes[i + 1] = primitiveSize(t, code);
|
||||||
uint64_t v = primitiveValue(t, code, t->stack[t->sp + i]);
|
uint64_t v = primitiveValue(t, code, t->stack[t->sp + i]);
|
||||||
if (sizes[i + 1] == 8) {
|
if (sizes[i + 1] == 8) {
|
||||||
args[offset++] = static_cast<uint32_t>(v >> 32);
|
memcpy(args + offset, &v, 8);
|
||||||
args[offset++] = static_cast<uint32_t>(v & 0xFFFFFFFF);
|
offset += 2;
|
||||||
} else {
|
} else {
|
||||||
args[offset++] = v;
|
args[offset++] = v;
|
||||||
}
|
}
|
||||||
@ -2167,12 +2115,172 @@ invokeNative(Thread* t, object method)
|
|||||||
if (UNLIKELY(t->exception) or returnCode == VoidField) {
|
if (UNLIKELY(t->exception) or returnCode == VoidField) {
|
||||||
return 0;
|
return 0;
|
||||||
} else if (returnCode == ObjectField) {
|
} else if (returnCode == ObjectField) {
|
||||||
return (rv == 0 ? 0 : t->stack[rv - 1]);
|
return (rv == 0 ? 0 :
|
||||||
|
*reinterpret_cast<object*>(static_cast<uintptr_t>(rv)));
|
||||||
} else {
|
} else {
|
||||||
return makePrimitive(t, returnCode, rv);
|
return makePrimitive(t, returnCode, rv);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
builtinLoadLibrary(JNIEnv* e, jstring nameString)
|
||||||
|
{
|
||||||
|
Thread* t = static_cast<Thread*>(e->reserved0);
|
||||||
|
|
||||||
|
if (LIKELY(nameString)) {
|
||||||
|
object n = *nameString;
|
||||||
|
char name[stringLength(t, n) + 1];
|
||||||
|
memcpy(name,
|
||||||
|
&byteArrayBody(t, stringBytes(t, n), stringOffset(t, n)),
|
||||||
|
stringLength(t, n));
|
||||||
|
name[stringLength(t, n)] = 0;
|
||||||
|
|
||||||
|
System::Library* lib;
|
||||||
|
if (LIKELY(t->vm->system->success
|
||||||
|
(t->vm->system->load(&lib, name, t->vm->libraries))))
|
||||||
|
{
|
||||||
|
t->vm->libraries = lib;
|
||||||
|
} else {
|
||||||
|
object message = makeString(t, "library not found: %s", name);
|
||||||
|
t->exception = makeRuntimeException(t, message);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
t->exception = makeNullPointerException(t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
jstring
|
||||||
|
builtinToString(JNIEnv* e, jobject this_)
|
||||||
|
{
|
||||||
|
Thread* t = static_cast<Thread*>(e->reserved0);
|
||||||
|
|
||||||
|
object s = makeString
|
||||||
|
(t, "%s@%p",
|
||||||
|
&byteArrayBody(t, className(t, objectClass(*this_)), 0),
|
||||||
|
*this_);
|
||||||
|
|
||||||
|
pushSafe(t, s);
|
||||||
|
return t->stack + (t->sp - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
jsize
|
||||||
|
GetStringUTFLength(JNIEnv* e, jstring s)
|
||||||
|
{
|
||||||
|
Thread* t = static_cast<Thread*>(e->reserved0);
|
||||||
|
enter(t, Thread::ActiveState);
|
||||||
|
|
||||||
|
jsize length = 0;
|
||||||
|
if (LIKELY(s)) {
|
||||||
|
length = stringLength(t, *s);
|
||||||
|
} else {
|
||||||
|
t->exception = makeNullPointerException(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
enter(t, Thread::IdleState);
|
||||||
|
|
||||||
|
return length;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char*
|
||||||
|
GetStringUTFChars(JNIEnv* e, jstring s, jboolean* isCopy)
|
||||||
|
{
|
||||||
|
Thread* t = static_cast<Thread*>(e->reserved0);
|
||||||
|
enter(t, Thread::ActiveState);
|
||||||
|
|
||||||
|
char* chars = 0;
|
||||||
|
if (LIKELY(s)) {
|
||||||
|
chars = static_cast<char*>(t->vm->system->allocate(stringLength(t, *s)));
|
||||||
|
|
||||||
|
memcpy(chars,
|
||||||
|
&byteArrayBody(t, stringBytes(t, *s), stringOffset(t, *s)),
|
||||||
|
stringLength(t, *s));
|
||||||
|
|
||||||
|
chars[stringLength(t, *s)] = 0;
|
||||||
|
} else {
|
||||||
|
t->exception = makeNullPointerException(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
enter(t, Thread::IdleState);
|
||||||
|
|
||||||
|
*isCopy = true;
|
||||||
|
return chars;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ReleaseStringUTFChars(JNIEnv* e, jstring, const char* chars)
|
||||||
|
{
|
||||||
|
Thread* t = static_cast<Thread*>(e->reserved0);
|
||||||
|
t->vm->system->free(chars);
|
||||||
|
}
|
||||||
|
|
||||||
|
Thread::Thread(Machine* m):
|
||||||
|
vm(m),
|
||||||
|
next(0),
|
||||||
|
child(0),
|
||||||
|
state(NoState),
|
||||||
|
thread(0),
|
||||||
|
frame(0),
|
||||||
|
code(0),
|
||||||
|
exception(0),
|
||||||
|
ip(0),
|
||||||
|
sp(0),
|
||||||
|
heapIndex(0),
|
||||||
|
protector(0),
|
||||||
|
chain(0)
|
||||||
|
{
|
||||||
|
memset(&jniEnv, 0, sizeof(JNIEnv));
|
||||||
|
jniEnv.reserved0 = this;
|
||||||
|
jniEnv.GetStringUTFLength = GetStringUTFLength;
|
||||||
|
jniEnv.GetStringUTFChars = GetStringUTFChars;
|
||||||
|
jniEnv.ReleaseStringUTFChars = ReleaseStringUTFChars;
|
||||||
|
|
||||||
|
if (m->rootThread == 0) {
|
||||||
|
m->rootThread = this;
|
||||||
|
m->unsafe = true;
|
||||||
|
|
||||||
|
Thread* t = this;
|
||||||
|
|
||||||
|
#include "type-initializations.cpp"
|
||||||
|
|
||||||
|
object arrayClass = arrayBody(t, t->vm->types, Machine::ArrayType);
|
||||||
|
set(t, objectClass(t->vm->types), arrayClass);
|
||||||
|
|
||||||
|
object classClass = arrayBody(t, m->types, Machine::ClassType);
|
||||||
|
set(t, objectClass(classClass), classClass);
|
||||||
|
|
||||||
|
object intArrayClass = arrayBody(t, m->types, Machine::IntArrayType);
|
||||||
|
set(t, objectClass(intArrayClass), classClass);
|
||||||
|
|
||||||
|
m->unsafe = false;
|
||||||
|
|
||||||
|
m->bootstrapClassMap = makeHashMap(this, 0, 0);
|
||||||
|
|
||||||
|
#include "type-java-initializations.cpp"
|
||||||
|
|
||||||
|
m->classMap = makeHashMap(this, 0, 0);
|
||||||
|
m->builtinMap = makeHashMap(this, 0, 0);
|
||||||
|
|
||||||
|
struct {
|
||||||
|
const char* key;
|
||||||
|
void* value;
|
||||||
|
} builtins[] = {
|
||||||
|
{ "Java_java_lang_Object_toString",
|
||||||
|
reinterpret_cast<void*>(builtinToString) },
|
||||||
|
{ "Java_java_lang_System_load",
|
||||||
|
reinterpret_cast<void*>(builtinLoadLibrary) },
|
||||||
|
{ 0, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
for (unsigned i = 0; builtins[i].key; ++i) {
|
||||||
|
object key = makeByteArray(t, builtins[i].key);
|
||||||
|
PROTECT(t, key);
|
||||||
|
object value = makePointer(t, builtins[i].value);
|
||||||
|
|
||||||
|
hashMapInsert(t, m->builtinMap, key, value, byteArrayHash);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
object
|
object
|
||||||
run(Thread* t)
|
run(Thread* t)
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user