From 400b3633d7d9b4f8fbebf452149fe7e87628a41a Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sun, 24 Jun 2007 19:34:07 -0600 Subject: [PATCH] more JNI work --- classpath/Hello.java | 5 + {input => classpath}/Test.java | 0 {input => classpath}/java/lang/Class.java | 0 {input => classpath}/java/lang/Object.java | 0 {input => classpath}/java/lang/String.java | 0 classpath/java/lang/System.cpp | 13 + classpath/java/lang/System.java | 15 + {input => classpath}/java/lang/Throwable.java | 0 makefile | 32 +- src/jni.h | 1010 +++++++++++++++++ src/main.cpp | 19 +- src/system.h | 4 +- src/vm.cpp | 308 +++-- 13 files changed, 1291 insertions(+), 115 deletions(-) create mode 100644 classpath/Hello.java rename {input => classpath}/Test.java (100%) rename {input => classpath}/java/lang/Class.java (100%) rename {input => classpath}/java/lang/Object.java (100%) rename {input => classpath}/java/lang/String.java (100%) create mode 100644 classpath/java/lang/System.cpp create mode 100644 classpath/java/lang/System.java rename {input => classpath}/java/lang/Throwable.java (100%) create mode 100644 src/jni.h diff --git a/classpath/Hello.java b/classpath/Hello.java new file mode 100644 index 0000000000..d7d4f91935 --- /dev/null +++ b/classpath/Hello.java @@ -0,0 +1,5 @@ +public class Hello { + public static void main(String[] args) { + System.out.println("hello, world!"); + } +} diff --git a/input/Test.java b/classpath/Test.java similarity index 100% rename from input/Test.java rename to classpath/Test.java diff --git a/input/java/lang/Class.java b/classpath/java/lang/Class.java similarity index 100% rename from input/java/lang/Class.java rename to classpath/java/lang/Class.java diff --git a/input/java/lang/Object.java b/classpath/java/lang/Object.java similarity index 100% rename from input/java/lang/Object.java rename to classpath/java/lang/Object.java diff --git a/input/java/lang/String.java b/classpath/java/lang/String.java similarity index 100% rename from input/java/lang/String.java rename to classpath/java/lang/String.java diff --git a/classpath/java/lang/System.cpp b/classpath/java/lang/System.cpp new file mode 100644 index 0000000000..5c7e7cfc29 --- /dev/null +++ b/classpath/java/lang/System.cpp @@ -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); +} diff --git a/classpath/java/lang/System.java b/classpath/java/lang/System.java new file mode 100644 index 0000000000..8a7dd91297 --- /dev/null +++ b/classpath/java/lang/System.java @@ -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); + } +} diff --git a/input/java/lang/Throwable.java b/classpath/java/lang/Throwable.java similarity index 100% rename from input/java/lang/Throwable.java rename to classpath/java/lang/Throwable.java diff --git a/makefile b/makefile index 1953bd27d9..3378690e2e 100644 --- a/makefile +++ b/makefile @@ -2,7 +2,7 @@ bld = build src = src -inp = input +classpath = classpath cxx = g++ cc = gcc @@ -22,7 +22,7 @@ thread-lflags = -lpthread cflags = $(warnings) -fPIC -fno-rtti -fno-exceptions -fvisibility=hidden \ -I$(src) -I$(bld) $(thread-cflags) -lflags = $(thread-lflags) +lflags = $(thread-lflags) -ldl test-cflags = -DDEBUG_MEMORY 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-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 = \ $(bld)/type-enums.cpp \ $(bld)/type-declarations.cpp \ @@ -75,11 +82,10 @@ fast-objects = $(patsubst $(bld)/%,$(bld)/fast-%,$(interpreter-objects)) fast-executable = $(bld)/fast-vm fast-cflags = $(fast) $(cflags) -input = $(bld)/classes/Test.class +input = $(bld)/classes/Hello.class input-depends = \ - $(bld)/classes/java/lang/Object.class \ - $(bld)/classes/java/lang/Class.class \ - $(bld)/classes/vm/VM.class + $(bld)/classes/java/lang/System.class \ + $(jni-library) gen-run-arg = $(shell echo $(1) | sed -e 's:$(bld)/classes/\(.*\)\.class:\1:') 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: \ $(generator-headers) -$(bld)/classes/%.class: $(inp)/%.java +$(bld)/classes/%.class: $(classpath)/%.java @echo "compiling $(@)" @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 @echo "compiling $(@)" @@ -177,6 +184,15 @@ $(fast-objects): $(bld)/fast-%.o: $(src)/%.cpp $(interpreter-depends) @mkdir -p $(dir $(@)) $(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) @echo "linking $(@)" $(cc) $(lflags) $(^) -o $(@) diff --git a/src/jni.h b/src/jni.h new file mode 100644 index 0000000000..8e2a59351b --- /dev/null +++ b/src/jni.h @@ -0,0 +1,1010 @@ +#ifndef JNI_H +#define JNI_H + +#include "stdint.h" +#include "stdarg.h" + +#define JNIEXPORT +#define JNIIMPORT +#define JNICALL + +typedef uint8_t jboolean; +typedef int8_t jbyte; +typedef uint16_t jchar; +typedef int16_t jshort; +typedef int32_t jint; +typedef int64_t jlong; +typedef float jfloat; +typedef double jdouble; + +typedef jint jsize; + +typedef void** jobject; + +typedef jobject jclass; +typedef jobject jthrowable; +typedef jobject jstring; +typedef jobject jweak; + +typedef jobject jarray; +typedef jarray jbooleanArray; +typedef jarray jbyteArray; +typedef jarray jcharArray; +typedef jarray jshortArray; +typedef jarray jintArray; +typedef jarray jlongArray; +typedef jarray jfloatArray; +typedef jarray jdoubleArray; +typedef jarray jobjectArray; + +typedef void** jfieldID; +typedef void** jmethodID; + +union jvalue { + jboolean z; + jbyte b; + jchar c; + jshort s; + jint i; + jlong j; + jfloat f; + jdouble d; + jobject l; +}; + +struct JNINativeMethod { + char* name; + char* signature; + void* function; +}; + +struct JavaVM { + void* reserved0; + void* reserved1; + void* reserved2; + + jint + (JNICALL *DestroyJavaVM) + (JavaVM*); + + jint + (JNICALL *AttachCurrentThread) + (JavaVM*, void**, void*); + + jint + (JNICALL *DetachCurrentThread) + (JavaVM*); + + jint + (JNICALL *GetEnv) + (JavaVM*, void**, jint); + + jint + (JNICALL *AttachCurrentThreadAsDaemon) + (JavaVM*, void**, void*); +}; + +struct JNIEnv { + void* reserved0; + void* reserved1; + void* reserved2; + void* reserved3; + + jint + (JNICALL *GetVersion) + (JNIEnv*); + + jclass + (JNICALL *DefineClass) + (JNIEnv*, const char*, jobject, const jbyte*, jsize); + + jclass + (JNICALL *FindClass) + (JNIEnv*, const char*); + + jmethodID + (JNICALL *FromReflectedMethod) + (JNIEnv*, jobject); + + jfieldID + (JNICALL *FromReflectedField) + (JNIEnv*, jobject); + + jobject + (JNICALL *ToReflectedMethod) + (JNIEnv*, jclass, jmethodID, jboolean); + + jclass + (JNICALL *GetSuperclass) + (JNIEnv*, jclass); + + jboolean + (JNICALL *IsAssignableFrom) + (JNIEnv*, jclass, jclass); + + jobject + (JNICALL *ToReflectedField) + (JNIEnv*, jclass, jfieldID, jboolean); + + jint + (JNICALL *Throw) + (JNIEnv*, jthrowable); + + jint + (JNICALL *ThrowNew) + (JNIEnv*, jclass, const char*); + + jthrowable + (JNICALL *ExceptionOccurred) + (JNIEnv*); + + void + (JNICALL *ExceptionDescribe) + (JNIEnv*); + + void + (JNICALL *ExceptionClear) + (JNIEnv*); + + void + (JNICALL *FatalError) + (JNIEnv*, const char*); + + jint + (JNICALL *PushLocalFrame) + (JNIEnv*, jint); + + jobject + (JNICALL *PopLocalFrame) + (JNIEnv*, jobject); + + jobject + (JNICALL *NewGlobalRef) + (JNIEnv*, jobject); + + void + (JNICALL *DeleteGlobalRef) + (JNIEnv*, jobject); + + void + (JNICALL *DeleteLocalRef) + (JNIEnv*, jobject); + + jboolean + (JNICALL *IsSameObject) + (JNIEnv*, jobject, jobject); + + jobject + (JNICALL *NewLocalRef) + (JNIEnv*, jobject); + + jint + (JNICALL *EnsureLocalCapacity) + (JNIEnv*, jint); + + jobject + (JNICALL *AllocObject) + (JNIEnv*, jclass); + + jobject + (JNICALL *NewObject) + (JNIEnv*, jclass, jmethodID, ...); + + jobject + (JNICALL *NewObjectV) + (JNIEnv*, jclass, jmethodID, va_list); + + jobject + (JNICALL *NewObjectA) + (JNIEnv*, jclass, jmethodID, const jvalue*); + + jclass + (JNICALL *GetObjectClass) + (JNIEnv*, jobject); + + jboolean + (JNICALL *IsInstanceOf) + (JNIEnv*, jobject, jclass); + + jmethodID + (JNICALL *GetMethodID) + (JNIEnv*, jclass, const char*, const char*); + + jobject + (JNICALL *CallObjectMethod) + (JNIEnv*, jobject, jmethodID, ...); + + jobject + (JNICALL *CallObjectMethodV) + (JNIEnv*, jobject, jmethodID, va_list); + + jobject + (JNICALL *CallObjectMethodA) + (JNIEnv*, jobject, jmethodID, const jvalue*); + + jboolean + (JNICALL *CallBooleanMethod) + (JNIEnv*, jobject, jmethodID, ...); + + jboolean + (JNICALL *CallBooleanMethodV) + (JNIEnv*, jobject, jmethodID, va_list); + + jboolean + (JNICALL *CallBooleanMethodA) + (JNIEnv*, jobject, jmethodID, const jvalue*); + + jbyte + (JNICALL *CallByteMethod) + (JNIEnv*, jobject, jmethodID, ...); + + jbyte + (JNICALL *CallByteMethodV) + (JNIEnv*, jobject, jmethodID, va_list); + + jbyte + (JNICALL *CallByteMethodA) + (JNIEnv*, jobject, jmethodID, const jvalue*); + + jchar + (JNICALL *CallCharMethod) + (JNIEnv*, jobject, jmethodID, ...); + + jchar + (JNICALL *CallCharMethodV) + (JNIEnv*, jobject, jmethodID, va_list); + + jchar + (JNICALL *CallCharMethodA) + (JNIEnv*, jobject, jmethodID, const jvalue*); + + jshort + (JNICALL *CallShortMethod) + (JNIEnv*, jobject, jmethodID, ...); + + jshort + (JNICALL *CallShortMethodV) + (JNIEnv*, jobject, jmethodID, va_list); + + jshort + (JNICALL *CallShortMethodA) + (JNIEnv*, jobject, jmethodID, const jvalue*); + + jint + (JNICALL *CallIntMethod) + (JNIEnv*, jobject, jmethodID, ...); + + jint + (JNICALL *CallIntMethodV) + (JNIEnv*, jobject, jmethodID, va_list); + + jint + (JNICALL *CallIntMethodA) + (JNIEnv*, jobject, jmethodID, const jvalue*); + + jlong + (JNICALL *CallLongMethod) + (JNIEnv*, jobject, jmethodID, ...); + + jlong + (JNICALL *CallLongMethodV) + (JNIEnv*, jobject, jmethodID, va_list); + + jlong + (JNICALL *CallLongMethodA) + (JNIEnv*, jobject, jmethodID, const jvalue*); + + jfloat + (JNICALL *CallFloatMethod) + (JNIEnv*, jobject, jmethodID, ...); + + jfloat + (JNICALL *CallFloatMethodV) + (JNIEnv*, jobject, jmethodID, va_list); + + jfloat + (JNICALL *CallFloatMethodA) + (JNIEnv*, jobject, jmethodID, const jvalue*); + + jdouble + (JNICALL *CallDoubleMethod) + (JNIEnv*, jobject, jmethodID, ...); + + jdouble + (JNICALL *CallDoubleMethodV) + (JNIEnv*, jobject, jmethodID, va_list); + + jdouble + (JNICALL *CallDoubleMethodA) + (JNIEnv*, jobject, jmethodID, const jvalue*); + + void + (JNICALL *CallVoidMethod) + (JNIEnv*, jobject, jmethodID, ...); + + void + (JNICALL *CallVoidMethodV) + (JNIEnv*, jobject, jmethodID, va_list); + + void + (JNICALL *CallVoidMethodA) + (JNIEnv*, jobject, jmethodID, const jvalue*); + + jobject + (JNICALL *CallNonvirtualObjectMethod) + (JNIEnv*, jobject, jclass, jmethodID, ...); + + jobject + (JNICALL *CallNonvirtualObjectMethodV) + (JNIEnv*, jobject, jclass, jmethodID, va_list); + + jobject + (JNICALL *CallNonvirtualObjectMethodA) + (JNIEnv*, jobject, jclass, jmethodID, const jvalue*); + + jboolean + (JNICALL *CallNonvirtualBooleanMethod) + (JNIEnv*, jobject, jclass, jmethodID, ...); + + jboolean + (JNICALL *CallNonvirtualBooleanMethodV) + (JNIEnv*, jobject, jclass, jmethodID, va_list); + + jboolean + (JNICALL *CallNonvirtualBooleanMethodA) + (JNIEnv*, jobject, jclass, jmethodID, const jvalue*); + + jbyte + (JNICALL *CallNonvirtualByteMethod) + (JNIEnv*, jobject, jclass, jmethodID, ...); + + jbyte + (JNICALL *CallNonvirtualByteMethodV) + (JNIEnv*, jobject, jclass, jmethodID, va_list); + + jbyte + (JNICALL *CallNonvirtualByteMethodA) + (JNIEnv*, jobject, jclass, jmethodID, const jvalue*); + + jchar + (JNICALL *CallNonvirtualCharMethod) + (JNIEnv*, jobject, jclass, jmethodID, ...); + + jchar + (JNICALL *CallNonvirtualCharMethodV) + (JNIEnv*, jobject, jclass, jmethodID, va_list); + + jchar + (JNICALL *CallNonvirtualCharMethodA) + (JNIEnv*, jobject, jclass, jmethodID, const jvalue*); + + jshort + (JNICALL *CallNonvirtualShortMethod) + (JNIEnv*, jobject, jclass, jmethodID, ...); + + jshort + (JNICALL *CallNonvirtualShortMethodV) + (JNIEnv*, jobject, jclass, jmethodID, + va_list); + + jshort + (JNICALL *CallNonvirtualShortMethodA) + (JNIEnv*, jobject, jclass, jmethodID, + const jvalue*); + + jint + (JNICALL *CallNonvirtualIntMethod) + (JNIEnv*, jobject, jclass, jmethodID, ...); + + jint + (JNICALL *CallNonvirtualIntMethodV) + (JNIEnv*, jobject, jclass, jmethodID, + va_list); + + jint + (JNICALL *CallNonvirtualIntMethodA) + (JNIEnv*, jobject, jclass, jmethodID, + const jvalue*); + + jlong + (JNICALL *CallNonvirtualLongMethod) + (JNIEnv*, jobject, jclass, jmethodID, ...); + + jlong + (JNICALL *CallNonvirtualLongMethodV) + (JNIEnv*, jobject, jclass, jmethodID, + va_list); + jlong + (JNICALL *CallNonvirtualLongMethodA) + (JNIEnv*, jobject, jclass, jmethodID, const jvalue*); + + jfloat + (JNICALL *CallNonvirtualFloatMethod) + (JNIEnv*, jobject, jclass, jmethodID, ...); + + jfloat + (JNICALL *CallNonvirtualFloatMethodV) + (JNIEnv*, jobject, jclass, jmethodID, va_list); + + jfloat + (JNICALL *CallNonvirtualFloatMethodA) + (JNIEnv*, jobject, jclass, jmethodID, const jvalue*); + + jdouble + (JNICALL *CallNonvirtualDoubleMethod) + (JNIEnv*, jobject, jclass, jmethodID, ...); + + jdouble + (JNICALL *CallNonvirtualDoubleMethodV) + (JNIEnv*, jobject, jclass, jmethodID, va_list); + + jdouble + (JNICALL *CallNonvirtualDoubleMethodA) + (JNIEnv*, jobject, jclass, jmethodID, const jvalue*); + + void + (JNICALL *CallNonvirtualVoidMethod) + (JNIEnv*, jobject, jclass, jmethodID, ...); + + void + (JNICALL *CallNonvirtualVoidMethodV) + (JNIEnv*, jobject, jclass, jmethodID, va_list); + + void + (JNICALL *CallNonvirtualVoidMethodA) + (JNIEnv*, jobject, jclass, jmethodID, const jvalue*); + + jfieldID + (JNICALL *GetFieldID) + (JNIEnv*, jclass, const char*, const char*); + + jobject + (JNICALL *GetObjectField) + (JNIEnv*, jobject, jfieldID); + + jboolean + (JNICALL *GetBooleanField) + (JNIEnv*, jobject, jfieldID); + + jbyte + (JNICALL *GetByteField) + (JNIEnv*, jobject, jfieldID); + + jchar + (JNICALL *GetCharField) + (JNIEnv*, jobject, jfieldID); + + jshort + (JNICALL *GetShortField) + (JNIEnv*, jobject, jfieldID); + + jint + (JNICALL *GetIntField) + (JNIEnv*, jobject, jfieldID); + + jlong + (JNICALL *GetLongField) + (JNIEnv*, jobject, jfieldID); + + jfloat + (JNICALL *GetFloatField) + (JNIEnv*, jobject, jfieldID); + + jdouble + (JNICALL *GetDoubleField) + (JNIEnv*, jobject, jfieldID); + + void + (JNICALL *SetObjectField) + (JNIEnv*, jobject, jfieldID, jobject); + + void + (JNICALL *SetBooleanField) + (JNIEnv*, jobject, jfieldID, jboolean); + + void + (JNICALL *SetByteField) + (JNIEnv*, jobject, jfieldID, jbyte); + + void + (JNICALL *SetCharField) + (JNIEnv*, jobject, jfieldID, jchar); + + void + (JNICALL *SetShortField) + (JNIEnv*, jobject, jfieldID, jshort); + + void + (JNICALL *SetIntField) + (JNIEnv*, jobject, jfieldID, jint); + + void + (JNICALL *SetLongField) + (JNIEnv*, jobject, jfieldID, jlong); + + void + (JNICALL *SetFloatField) + (JNIEnv*, jobject, jfieldID, jfloat); + + void + (JNICALL *SetDoubleField) + (JNIEnv*, jobject, jfieldID, jdouble); + + jmethodID + (JNICALL *GetStaticMethodID) + (JNIEnv*, jclass, const char*, const char*); + + jobject + (JNICALL *CallStaticObjectMethod) + (JNIEnv*, jclass, jmethodID, ...); + + jobject + (JNICALL *CallStaticObjectMethodV) + (JNIEnv*, jclass, jmethodID, va_list); + + jobject + (JNICALL *CallStaticObjectMethodA) + (JNIEnv*, jclass, jmethodID, const jvalue*); + + jboolean + (JNICALL *CallStaticBooleanMethod) + (JNIEnv*, jclass, jmethodID, ...); + + jboolean + (JNICALL *CallStaticBooleanMethodV) + (JNIEnv*, jclass, jmethodID, va_list); + + jboolean + (JNICALL *CallStaticBooleanMethodA) + (JNIEnv*, jclass, jmethodID, const jvalue*); + + jbyte + (JNICALL *CallStaticByteMethod) + (JNIEnv*, jclass, jmethodID, ...); + + jbyte + (JNICALL *CallStaticByteMethodV) + (JNIEnv*, jclass, jmethodID, va_list); + + jbyte + (JNICALL *CallStaticByteMethodA) + (JNIEnv*, jclass, jmethodID, const jvalue*); + + jchar + (JNICALL *CallStaticCharMethod) + (JNIEnv*, jclass, jmethodID, ...); + + jchar + (JNICALL *CallStaticCharMethodV) + (JNIEnv*, jclass, jmethodID, va_list); + + jchar + (JNICALL *CallStaticCharMethodA) + (JNIEnv*, jclass, jmethodID, const jvalue*); + + jshort + (JNICALL *CallStaticShortMethod) + (JNIEnv*, jclass, jmethodID, ...); + + jshort + (JNICALL *CallStaticShortMethodV) + (JNIEnv*, jclass, jmethodID, va_list); + + jshort + (JNICALL *CallStaticShortMethodA) + (JNIEnv*, jclass, jmethodID, const jvalue*); + + jint + (JNICALL *CallStaticIntMethod) + (JNIEnv*, jclass, jmethodID, ...); + + jint + (JNICALL *CallStaticIntMethodV) + (JNIEnv*, jclass, jmethodID, va_list); + + jint + (JNICALL *CallStaticIntMethodA) + (JNIEnv*, jclass, jmethodID, const jvalue*); + + jlong + (JNICALL *CallStaticLongMethod) + (JNIEnv*, jclass, jmethodID, ...); + + jlong + (JNICALL *CallStaticLongMethodV) + (JNIEnv*, jclass, jmethodID, va_list); + + jlong + (JNICALL *CallStaticLongMethodA) + (JNIEnv*, jclass, jmethodID, const jvalue*); + + jfloat + (JNICALL *CallStaticFloatMethod) + (JNIEnv*, jclass, jmethodID, ...); + + jfloat + (JNICALL *CallStaticFloatMethodV) + (JNIEnv*, jclass, jmethodID, va_list); + + jfloat + (JNICALL *CallStaticFloatMethodA) + (JNIEnv*, jclass, jmethodID, const jvalue*); + + jdouble + (JNICALL *CallStaticDoubleMethod) + (JNIEnv*, jclass, jmethodID, ...); + + jdouble + (JNICALL *CallStaticDoubleMethodV) + (JNIEnv*, jclass, jmethodID, va_list); + + jdouble + (JNICALL *CallStaticDoubleMethodA) + (JNIEnv*, jclass, jmethodID, const jvalue*); + + void + (JNICALL *CallStaticVoidMethod) + (JNIEnv*, jclass, jmethodID, ...); + + void + (JNICALL *CallStaticVoidMethodV) + (JNIEnv*, jclass, jmethodID, va_list); + + void + (JNICALL *CallStaticVoidMethodA) + (JNIEnv*, jclass, jmethodID, const jvalue*); + + jfieldID + (JNICALL *GetStaticFieldID) + (JNIEnv*, jclass, const char*, const char*); + + jobject + (JNICALL *GetStaticObjectField) + (JNIEnv*, jclass, jfieldID); + + jboolean + (JNICALL *GetStaticBooleanField) + (JNIEnv*, jclass, jfieldID); + + jbyte + (JNICALL *GetStaticByteField) + (JNIEnv*, jclass, jfieldID); + + jchar + (JNICALL *GetStaticCharField) + (JNIEnv*, jclass, jfieldID); + + jshort + (JNICALL *GetStaticShortField) + (JNIEnv*, jclass, jfieldID); + + jint + (JNICALL *GetStaticIntField) + (JNIEnv*, jclass, jfieldID); + + jlong + (JNICALL *GetStaticLongField) + (JNIEnv*, jclass, jfieldID); + + jfloat + (JNICALL *GetStaticFloatField) + (JNIEnv*, jclass, jfieldID); + + jdouble + (JNICALL *GetStaticDoubleField) + (JNIEnv*, jclass, jfieldID); + + void + (JNICALL *SetStaticObjectField) + (JNIEnv*, jclass, jfieldID, jobject); + + void + (JNICALL *SetStaticBooleanField) + (JNIEnv*, jclass, jfieldID, jboolean); + + void + (JNICALL *SetStaticByteField) + (JNIEnv*, jclass, jfieldID, jbyte); + + void + (JNICALL *SetStaticCharField) + (JNIEnv*, jclass, jfieldID, jchar); + + void + (JNICALL *SetStaticShortField) + (JNIEnv*, jclass, jfieldID, jshort); + + void + (JNICALL *SetStaticIntField) + (JNIEnv*, jclass, jfieldID, jint); + + void + (JNICALL *SetStaticLongField) + (JNIEnv*, jclass, jfieldID, jlong); + + void + (JNICALL *SetStaticFloatField) + (JNIEnv*, jclass, jfieldID, jfloat); + + void + (JNICALL *SetStaticDoubleField) + (JNIEnv*, jclass, jfieldID, jdouble); + + jstring + (JNICALL *NewString) + (JNIEnv*, const jchar*, jsize); + + jsize + (JNICALL *GetStringLength) + (JNIEnv*, jstring); + + const jchar* + (JNICALL *GetStringChars) + (JNIEnv*, jstring, jboolean*); + + void + (JNICALL *ReleaseStringChars) + (JNIEnv*, jstring, const jchar*); + + jstring + (JNICALL *NewStringUTF) + (JNIEnv*, const char*); + + jsize + (JNICALL *GetStringUTFLength) + (JNIEnv*, jstring); + + const char* + (JNICALL *GetStringUTFChars) + (JNIEnv*, jstring, jboolean*); + + void + (JNICALL *ReleaseStringUTFChars) + (JNIEnv*, jstring, const char*); + + jsize + (JNICALL *GetArrayLength) + (JNIEnv*, jarray); + + jobjectArray + (JNICALL *NewObjectArray) + (JNIEnv*, jsize, jclass, jobject); + + jobject + (JNICALL *GetObjectArrayElement) + (JNIEnv*, jobjectArray, jsize); + + void + (JNICALL *SetObjectArrayElement) + (JNIEnv*, jobjectArray, jsize, jobject); + + jbooleanArray + (JNICALL *NewBooleanArray) + (JNIEnv*, jsize); + + jbyteArray + (JNICALL *NewByteArray) + (JNIEnv*, jsize); + + jcharArray + (JNICALL *NewCharArray) + (JNIEnv*, jsize); + + jshortArray + (JNICALL *NewShortArray) + (JNIEnv*, jsize); + + jintArray + (JNICALL *NewIntArray) + (JNIEnv*, jsize); + + jlongArray + (JNICALL *NewLongArray) + (JNIEnv*, jsize); + + jfloatArray + (JNICALL *NewFloatArray) + (JNIEnv*, jsize); + + jdoubleArray + (JNICALL *NewDoubleArray) + (JNIEnv*, jsize); + + jboolean* + (JNICALL *GetBooleanArrayElements) + (JNIEnv*, jbooleanArray, jboolean*); + + jbyte* + (JNICALL *GetByteArrayElements) + (JNIEnv*, jbyteArray, jboolean*); + + jchar* + (JNICALL *GetCharArrayElements) + (JNIEnv*, jcharArray, jboolean*); + + jshort* + (JNICALL *GetShortArrayElements) + (JNIEnv*, jshortArray, jboolean*); + + jint* + (JNICALL *GetIntArrayElements) + (JNIEnv*, jintArray, jboolean*); + + jlong* + (JNICALL *GetLongArrayElements) + (JNIEnv*, jlongArray, jboolean*); + + jfloat* + (JNICALL *GetFloatArrayElements) + (JNIEnv*, jfloatArray, jboolean*); + + jdouble* + (JNICALL *GetDoubleArrayElements) + (JNIEnv*, jdoubleArray, jboolean*); + + void + (JNICALL *ReleaseBooleanArrayElements) + (JNIEnv*, jbooleanArray, jboolean*, jint); + + void + (JNICALL *ReleaseByteArrayElements) + (JNIEnv*, jbyteArray, jbyte*, jint); + + void + (JNICALL *ReleaseCharArrayElements) + (JNIEnv*, jcharArray, jchar*, jint); + + void + (JNICALL *ReleaseShortArrayElements) + (JNIEnv*, jshortArray, jshort*, jint); + + void + (JNICALL *ReleaseIntArrayElements) + (JNIEnv*, jintArray, jint*, jint); + + void + (JNICALL *ReleaseLongArrayElements) + (JNIEnv*, jlongArray, jlong*, jint); + + void + (JNICALL *ReleaseFloatArrayElements) + (JNIEnv*, jfloatArray, jfloat*, jint); + + void + (JNICALL *ReleaseDoubleArrayElements) + (JNIEnv*, jdoubleArray, jdouble*, jint); + + void + (JNICALL *GetBooleanArrayRegion) + (JNIEnv*, jbooleanArray, jsize, jsize, jboolean*); + + void + (JNICALL *GetByteArrayRegion) + (JNIEnv*, jbyteArray, jsize, jsize, jbyte*); + + void + (JNICALL *GetCharArrayRegion) + (JNIEnv*, jcharArray, jsize, jsize, jchar*); + + void + (JNICALL *GetShortArrayRegion) + (JNIEnv*, jshortArray, jsize, jsize, jshort*); + + void + (JNICALL *GetIntArrayRegion) + (JNIEnv*, jintArray, jsize, jsize, jint*); + + void + (JNICALL *GetLongArrayRegion) + (JNIEnv*, jlongArray, jsize, jsize, jlong*); + + void + (JNICALL *GetFloatArrayRegion) + (JNIEnv*, jfloatArray, jsize, jsize, jfloat*); + + void + (JNICALL *GetDoubleArrayRegion) + (JNIEnv*, jdoubleArray, jsize, jsize, jdouble*); + + void + (JNICALL *SetBooleanArrayRegion) + (JNIEnv*, jbooleanArray, jsize, jsize, const jboolean*); + + void + (JNICALL *SetByteArrayRegion) + (JNIEnv*, jbyteArray, jsize, jsize, const jbyte*); + + void + (JNICALL *SetCharArrayRegion) + (JNIEnv*, jcharArray, jsize, jsize, const jchar*); + + void + (JNICALL *SetShortArrayRegion) + (JNIEnv*, jshortArray, jsize, jsize, const jshort*); + + void + (JNICALL *SetIntArrayRegion) + (JNIEnv*, jintArray, jsize, jsize, const jint*); + + void + (JNICALL *SetLongArrayRegion) + (JNIEnv*, jlongArray, jsize, jsize, const jlong*); + + void + (JNICALL *SetFloatArrayRegion) + (JNIEnv*, jfloatArray, jsize, jsize, const jfloat*); + + void + (JNICALL *SetDoubleArrayRegion) + (JNIEnv*, jdoubleArray, jsize, jsize, const jdouble*); + + jint + (JNICALL *RegisterNatives) + (JNIEnv*, jclass, const JNINativeMethod*, jint); + + jint + (JNICALL *UnregisterNatives) + (JNIEnv*, jclass); + + jint + (JNICALL *MonitorEnter) + (JNIEnv*, jobject); + + jint + (JNICALL *MonitorExit) + (JNIEnv*, jobject); + + jint + (JNICALL *GetJavaVM) + (JNIEnv*, JavaVM**); + + void + (JNICALL *GetStringRegion) + (JNIEnv*, jstring, jsize, jsize, jchar*); + + void + (JNICALL *GetStringUTFRegion) + (JNIEnv*, jstring, jsize, jsize, char*); + + void* + (JNICALL *GetPrimitiveArrayCritical) + (JNIEnv*, jarray, jboolean*); + + void + (JNICALL *ReleasePrimitiveArrayCritical) + (JNIEnv*, jarray, void*, jint); + + const jchar* + (JNICALL *GetStringCritical) + (JNIEnv*, jstring, jboolean*); + + void + (JNICALL *ReleaseStringCritical) + (JNIEnv*, jstring, const jchar*); + + jweak + (JNICALL *NewWeakGlobalRef) + (JNIEnv*, jobject); + + void + (JNICALL *DeleteWeakGlobalRef) + (JNIEnv*, jweak); + + jboolean + (JNICALL *ExceptionCheck) + (JNIEnv*); + + jobject + (JNICALL *NewDirectByteBuffer) + (JNIEnv*, void*, jlong); + + void* + (JNICALL *GetDirectBufferAddress) + (JNIEnv* env, jobject); + + jlong + (JNICALL *GetDirectBufferCapacity) + (JNIEnv*, jobject); +}; + +#endif//JNI_H diff --git a/src/main.cpp b/src/main.cpp index 6d0a1e28df..609edbc41f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -66,6 +66,8 @@ class System: public vm::System { } virtual void* tryAllocate(unsigned size) { + // todo: synchronize access + if (Verbose) { fprintf(stderr, "try %d; count: %d; limit: %d\n", size, count, limit); @@ -85,6 +87,8 @@ class System: public vm::System { } virtual void free(const void* p) { + // todo: synchronize access + if (p) { const uintptr_t* up = static_cast(p) - 1; if (count < *up) { @@ -110,14 +114,19 @@ class System: public vm::System { return 0; } - virtual uint64_t call(void* function, unsigned argumentCount, - uint32_t* argumentTable, uint8_t* argumentSizeTable, - unsigned returnSize) + virtual uint64_t call(void* ,//function, + unsigned ,//argumentCount, + 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); if (p) { *lib = new (vm::System::allocate(sizeof(Library))) diff --git a/src/system.h b/src/system.h index f899c7fa26..cee0f8a285 100644 --- a/src/system.h +++ b/src/system.h @@ -44,8 +44,8 @@ class System { virtual Status make(Monitor**) = 0; virtual uint64_t call(void* function, unsigned argumentCount, uint32_t* argumentTable, uint8_t* argumentSizeTable, - unsigned returnSize); - virtual Status load(Library**, const char* name, Library* next); + unsigned returnSize) = 0; + virtual Status load(Library**, const char* name, Library* next) = 0; virtual void abort() = 0; void* allocate(unsigned size) { diff --git a/src/vm.cpp b/src/vm.cpp index 98a7fc18eb..8b9f63f25c 100644 --- a/src/vm.cpp +++ b/src/vm.cpp @@ -4,6 +4,7 @@ #include "class_finder.h" #include "stream.h" #include "constants.h" +#include "jni.h" #include "vm.h" #define PROTECT(thread, name) \ @@ -30,7 +31,6 @@ object& arrayBodyUnsafe(Thread*, object, unsigned); void set(Thread*, object&, object); object makeString(Thread*, const char*, ...); object makeByteArray(Thread*, const char*, ...); -unsigned objectSize(Thread* t, object o); object& objectClass(object o) @@ -152,10 +152,11 @@ class Thread { unsigned ip; unsigned sp; unsigned heapIndex; - object stack[StackSizeInWords]; - object heap[HeapSizeInWords]; Protector* protector; Chain* chain; + object stack[StackSizeInWords]; + object heap[HeapSizeInWords]; + JNIEnv jniEnv; }; #include "type-declarations.cpp" @@ -458,77 +459,6 @@ top(Thread* t) 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(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 Thread::dispose() { @@ -864,6 +794,22 @@ make(Thread* t, object class_) 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(o, classFixedSize(t, class_) - 4), + BytesPerWord); + } + + return n; +} + object makeByteArray(Thread* t, const char* format, va_list a) { @@ -915,6 +861,14 @@ makeTrace(Thread* t) return trace; } +object +makeRuntimeException(Thread* t, object message) +{ + PROTECT(t, message); + object trace = makeTrace(t); + return makeClassCastException(t, message, trace, 0); +} + object makeArrayIndexOutOfBoundsException(Thread* t, object message) { @@ -1891,7 +1845,7 @@ updateBootstrapClass(Thread* t, object bootstrapClass, object class_) enter(t, Thread::ExclusiveState); - memcpy(bootstrapClass, class_, objectSize(t, class_)); + memcpy(bootstrapClass, class_, objectSize(t, class_) * BytesPerWord); enter(t, Thread::ActiveState); } @@ -2013,12 +1967,12 @@ makeNativeMethodData(Thread* t, object method, void* function, bool builtin) methodParameterCount(t, method), false); - unsigned argumentTableSize = sizeof(void*) / 4; + unsigned argumentTableSize = BytesPerWord / 4; unsigned index = 0; if ((methodFlags(t, method) & ACC_STATIC) == 0) { nativeMethodDataParameterCodes(t, data, index++) = ObjectField; - argumentTableSize += 1; + argumentTableSize += BytesPerWord / 4; } const char* s = reinterpret_cast @@ -2030,13 +1984,13 @@ makeNativeMethodData(Thread* t, object method, void* function, bool builtin) switch (*s) { case 'L': - argumentTableSize += 1; + argumentTableSize += BytesPerWord / 4; while (*s and *s != ';') ++ s; ++ s; break; case '[': - argumentTableSize += 1; + argumentTableSize += BytesPerWord / 4; while (*s == '[') ++ s; break; @@ -2108,35 +2062,29 @@ invokeNative(Thread* t, object method) uint8_t sizes[parameterCount + 1]; unsigned offset = 0; - switch (sizeof(uintptr_t)) { - case 4: { - sizes[0] = 4; - args[offset++] = reinterpret_cast(t); - } break; - - case 8: { - sizes[0] = 8; - uint64_t v = reinterpret_cast(t); - args[offset++] = static_cast(v >> 32); - args[offset++] = static_cast(v & 0xFFFFFFFF); - } break; - - default: - abort(t); - } + sizes[0] = BytesPerWord; + JNIEnv* e = &(t->jniEnv); + memcpy(args + offset, &e, BytesPerWord); + offset += BytesPerWord / 4; for (unsigned i = 0; i < parameterCount; ++i) { unsigned code = nativeMethodDataParameterCodes(t, data, i); if (code == ObjectField) { - sizes[i + 1] = 4; - args[offset++] = t->sp + i + 1; + sizes[i + 1] = BytesPerWord; + 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 { sizes[i + 1] = primitiveSize(t, code); uint64_t v = primitiveValue(t, code, t->stack[t->sp + i]); if (sizes[i + 1] == 8) { - args[offset++] = static_cast(v >> 32); - args[offset++] = static_cast(v & 0xFFFFFFFF); + memcpy(args + offset, &v, 8); + offset += 2; } else { args[offset++] = v; } @@ -2167,12 +2115,172 @@ invokeNative(Thread* t, object method) if (UNLIKELY(t->exception) or returnCode == VoidField) { return 0; } else if (returnCode == ObjectField) { - return (rv == 0 ? 0 : t->stack[rv - 1]); + return (rv == 0 ? 0 : + *reinterpret_cast(static_cast(rv))); } else { return makePrimitive(t, returnCode, rv); } } +void +builtinLoadLibrary(JNIEnv* e, jstring nameString) +{ + Thread* t = static_cast(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(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(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(e->reserved0); + enter(t, Thread::ActiveState); + + char* chars = 0; + if (LIKELY(s)) { + chars = static_cast(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(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(builtinToString) }, + { "Java_java_lang_System_load", + reinterpret_cast(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 run(Thread* t) {