From bd4d9fdeb26ce8458e20984692f174ece3ae1999 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Thu, 6 Sep 2007 18:21:52 -0600 Subject: [PATCH] several things: change object typedef to Object* instead of void* to improve type safety; add JNICALL attributes to JNI functions; implement additional JavaVM methods --- makefile | 2 +- src/builtin.cpp | 94 +++++----- src/common.h | 4 +- src/heap.cpp | 103 +++++------ src/heap.h | 6 +- src/jnienv.cpp | 378 +++++++++++++++++++++++++++++++++++++++-- src/machine.cpp | 129 +++++++++++--- src/machine.h | 67 ++++++-- src/run.cpp | 66 +------ src/type-generator.cpp | 46 +++-- src/types.def | 14 +- 11 files changed, 690 insertions(+), 219 deletions(-) diff --git a/makefile b/makefile index f4b84a877e..1cd670ddda 100644 --- a/makefile +++ b/makefile @@ -17,7 +17,7 @@ classpath = classpath test = test jscheme = $(HOME)/p/jscheme-7.2/src -input = $(cls)/References.class +input = $(cls)/GC.class cxx = g++ cc = gcc diff --git a/src/builtin.cpp b/src/builtin.cpp index fe68a052c4..1f0bcfc301 100644 --- a/src/builtin.cpp +++ b/src/builtin.cpp @@ -13,7 +13,7 @@ replace(char a, char b, char* c) for (; *c; ++c) if (*c == a) *c = b; } -jstring +jstring JNICALL Object_toString(Thread* t, jobject this_) { unsigned hash = objectHash(t, *this_); @@ -25,47 +25,47 @@ Object_toString(Thread* t, jobject this_) return pushReference(t, s); } -jclass +jclass JNICALL Object_getClass(Thread* t, jobject this_) { return pushReference(t, objectClass(t, *this_)); } -void +void JNICALL Object_wait(Thread* t, jobject this_, jlong milliseconds) { vm::wait(t, *this_, milliseconds); } -void +void JNICALL Object_notify(Thread* t, jobject this_) { notify(t, *this_); } -void +void JNICALL Object_notifyAll(Thread* t, jobject this_) { notifyAll(t, *this_); } -jint +jint JNICALL Object_hashCode(Thread* t, jobject this_) { return objectHash(t, *this_); } -jobject +jobject JNICALL Object_clone(Thread* t, jclass, jobject o) { object clone = make(t, objectClass(t, *o)); - memcpy(static_cast(clone) + 1, - static_cast(*o) + 1, + memcpy(reinterpret_cast(clone) + 1, + reinterpret_cast(*o) + 1, (baseSize(t, *o, objectClass(t, *o)) - 1) * BytesPerWord); return pushReference(t, clone); } -jclass +jclass JNICALL ClassLoader_defineClass(Thread* t, jclass, jbyteArray b, jint offset, jint length) { @@ -101,19 +101,19 @@ search(Thread* t, jstring name, object (*op)(Thread*, object), } } -jclass +jclass JNICALL SystemClassLoader_findLoadedClass(Thread* t, jclass, jstring name) { return search(t, name, findLoadedClass, true); } -jclass +jclass JNICALL SystemClassLoader_findClass(Thread* t, jclass, jstring name) { return search(t, name, resolveClass, true); } -jboolean +jboolean JNICALL SystemClassLoader_resourceExists(Thread* t, jclass, jstring name) { if (LIKELY(name)) { @@ -126,13 +126,13 @@ SystemClassLoader_resourceExists(Thread* t, jclass, jstring name) } } -jobject +jobject JNICALL ObjectInputStream_makeInstance(Thread* t, jclass, jclass c) { return pushReference(t, make(t, *c)); } -jclass +jclass JNICALL Class_primitiveClass(Thread* t, jclass, jchar name) { switch (name) { @@ -160,13 +160,13 @@ Class_primitiveClass(Thread* t, jclass, jchar name) } } -void +void JNICALL Class_initialize(Thread* t, jobject this_) { initClass(t, *this_); } -jboolean +jboolean JNICALL Class_isAssignableFrom(Thread* t, jobject this_, jclass that) { if (LIKELY(that)) { @@ -177,7 +177,7 @@ Class_isAssignableFrom(Thread* t, jobject this_, jclass that) } } -jlong +jlong JNICALL Field_getPrimitive(Thread* t, jclass, jobject instance, jint code, jint offset) { switch (code) { @@ -202,13 +202,13 @@ Field_getPrimitive(Thread* t, jclass, jobject instance, jint code, jint offset) } } -jobject +jobject JNICALL Field_getObject(Thread* t, jclass, jobject instance, jint offset) { return pushReference(t, cast(*instance, offset)); } -void +void JNICALL Field_setPrimitive(Thread* t, jclass, jobject instance, jint code, jint offset, jlong value) { @@ -242,27 +242,27 @@ Field_setPrimitive(Thread* t, jclass, jobject instance, jint code, jint offset, } } -void +void JNICALL Field_setObject(Thread* t, jclass, jobject instance, jint offset, jobject value) { set(t, cast(*instance, offset), (value ? *value : 0)); } -jobject +jobject JNICALL Constructor_make(Thread* t, jclass, jclass c) { return pushReference(t, make(t, *c)); } -jobject +jobject JNICALL Method_getCaller(Thread* t, jclass) { return pushReference (t, frameMethod(t, frameNext(t, frameNext(t, t->frame)))); } -jobject +jobject JNICALL Method_invoke(Thread* t, jclass, jobject method, jobject instance, jobjectArray arguments) { @@ -273,7 +273,7 @@ Method_invoke(Thread* t, jclass, jobject method, jobject instance, return pushReference(t, v); } -jint +jint JNICALL Array_getLength(Thread* t, jclass, jobject array) { if (LIKELY(array)) { @@ -291,47 +291,47 @@ Array_getLength(Thread* t, jclass, jobject array) return 0; } -jobject +jobject JNICALL Array_makeObjectArray(Thread* t, jclass, jclass elementType, jint length) { return pushReference(t, makeObjectArray(t, *elementType, length, true)); } -jint +jint JNICALL Float_floatToRawIntBits(Thread*, jclass, jfloat v) { int32_t r; memcpy(&r, &v, 4); return r; } -jfloat +jfloat JNICALL Float_intBitsToFloat(Thread*, jclass, jint v) { jfloat r; memcpy(&r, &v, 4); return r; } -jlong +jlong JNICALL Double_doubleToRawLongBits(Thread*, jclass, jdouble v) { int64_t r; memcpy(&r, &v, 8); return r; } -jdouble +jdouble JNICALL Double_longBitsToDouble(Thread*, jclass, jlong v) { jdouble r; memcpy(&r, &v, 8); return r; } -jobject +jobject JNICALL String_intern(Thread* t, jobject this_) { return pushReference(t, intern(t, *this_)); } -jstring +jstring JNICALL System_getVMProperty(Thread* t, jclass, jint code) { enum { @@ -348,7 +348,7 @@ System_getVMProperty(Thread* t, jclass, jint code) } } -void +void JNICALL System_arraycopy(Thread* t, jclass, jobject src, jint srcOffset, jobject dst, jint dstOffset, jint length) { @@ -388,7 +388,7 @@ System_arraycopy(Thread* t, jclass, jobject src, jint srcOffset, jobject dst, t->exception = makeArrayStoreException(t); } -jint +jint JNICALL System_identityHashCode(Thread* t, jclass, jobject o) { if (LIKELY(o)) { @@ -399,7 +399,7 @@ System_identityHashCode(Thread* t, jclass, jobject o) } } -void +void JNICALL Runtime_loadLibrary(Thread* t, jobject, jstring name) { if (LIKELY(name)) { @@ -427,7 +427,7 @@ Runtime_loadLibrary(Thread* t, jobject, jstring name) } } -void +void JNICALL Runtime_gc(Thread* t, jobject) { ENTER(t, Thread::ExclusiveState); @@ -435,20 +435,20 @@ Runtime_gc(Thread* t, jobject) collect(t, Heap::MajorCollection); } -void +void JNICALL Runtime_exit(Thread* t, jobject, jint code) { t->vm->system->exit(code); } -jlong +jlong JNICALL Runtime_freeMemory(Thread*, jobject) { // todo return 0; } -jobject +jobject JNICALL Throwable_trace(Thread* t, jclass, jint skipCount) { int frame = t->frame; @@ -471,7 +471,7 @@ Throwable_trace(Thread* t, jclass, jint skipCount) return pushReference(t, makeTrace(t, frame)); } -jarray +jarray JNICALL Throwable_resolveTrace(Thread* t, jclass, jobject trace) { unsigned length = arrayLength(t, *trace); @@ -505,13 +505,13 @@ Throwable_resolveTrace(Thread* t, jclass, jobject trace) return pushReference(t, array); } -jobject +jobject JNICALL Thread_currentThread(Thread* t, jclass) { return pushReference(t, t->javaThread); } -jlong +jlong JNICALL Thread_doStart(Thread* t, jobject this_) { Thread* p = new (t->vm->system->allocate(sizeof(Thread))) @@ -527,13 +527,13 @@ Thread_doStart(Thread* t, jobject this_) } } -void +void JNICALL Thread_interrupt(Thread* t, jclass, jlong peer) { interrupt(t, reinterpret_cast(peer)); } -jlong +jlong JNICALL ResourceInputStream_open(Thread* t, jclass, jstring path) { if (LIKELY(path)) { @@ -547,7 +547,7 @@ ResourceInputStream_open(Thread* t, jclass, jstring path) } } -jint +jint JNICALL ResourceInputStream_read(Thread*, jclass, jlong peer, jint position) { Finder::Data* d = reinterpret_cast(peer); @@ -558,7 +558,7 @@ ResourceInputStream_read(Thread*, jclass, jlong peer, jint position) } } -jint +jint JNICALL ResourceInputStream_read2(Thread* t, jclass, jlong peer, jint position, jbyteArray b, jint offset, jint length) { @@ -574,7 +574,7 @@ ResourceInputStream_read2(Thread* t, jclass, jlong peer, jint position, } } -void +void JNICALL ResourceInputStream_close(Thread*, jclass, jlong peer) { reinterpret_cast(peer)->dispose(); diff --git a/src/common.h b/src/common.h index a9da64c498..c8ef37489b 100644 --- a/src/common.h +++ b/src/common.h @@ -33,8 +33,6 @@ inline void* operator new(size_t, void* p) throw() { return p; } namespace vm { -typedef void* object; - const unsigned BytesPerWord = sizeof(uintptr_t); const unsigned BitsPerWord = BytesPerWord * 8; @@ -118,7 +116,7 @@ indexOf(unsigned word, unsigned bit) template inline T& -cast(object p, unsigned offset) +cast(void* p, unsigned offset) { return *reinterpret_cast(static_cast(p) + offset); } diff --git a/src/heap.cpp b/src/heap.cpp index 9b0a8d95c5..240df45044 100644 --- a/src/heap.cpp +++ b/src/heap.cpp @@ -27,28 +27,28 @@ void assert(Context*, bool); System* system(Context*); -inline object -get(object o, unsigned offsetInWords) +inline void* +get(void* o, unsigned offsetInWords) { - return mask(cast(o, offsetInWords * BytesPerWord)); + return mask(cast(o, offsetInWords * BytesPerWord)); } -inline object* -getp(object o, unsigned offsetInWords) +inline void** +getp(void* o, unsigned offsetInWords) { - return &cast(o, offsetInWords * BytesPerWord); + return &cast(o, offsetInWords * BytesPerWord); } inline void -set(object* o, object value) +set(void** o, void* value) { - *o = reinterpret_cast + *o = reinterpret_cast (reinterpret_cast(value) | reinterpret_cast(*o) & (~PointerMask)); } inline void -set(object o, unsigned offsetInWords, object value) +set(void* o, unsigned offsetInWords, void* value) { set(getp(o, offsetInWords), value); } @@ -538,7 +538,7 @@ initNextGen2(Context* c) } inline bool -fresh(Context* c, object o) +fresh(Context* c, void* o) { return c->nextGen1.contains(o) or c->nextGen2.contains(o) @@ -546,43 +546,43 @@ fresh(Context* c, object o) } inline bool -wasCollected(Context* c, object o) +wasCollected(Context* c, void* o) { return o and (not fresh(c, o)) and fresh(c, get(o, 0)); } -inline object -follow(Context* c UNUSED, object o) +inline void* +follow(Context* c UNUSED, void* o) { assert(c, wasCollected(c, o)); - return cast(o, 0); + return cast(o, 0); } -inline object& -parent(Context* c UNUSED, object o) +inline void*& +parent(Context* c UNUSED, void* o) { assert(c, wasCollected(c, o)); - return cast(o, BytesPerWord); + return cast(o, BytesPerWord); } inline uintptr_t* -bitset(Context* c UNUSED, object o) +bitset(Context* c UNUSED, void* o) { assert(c, wasCollected(c, o)); return &cast(o, BytesPerWord * 2); } -inline object -copyTo(Context* c, Segment* s, object o, unsigned size) +inline void* +copyTo(Context* c, Segment* s, void* o, unsigned size) { assert(c, s->remaining() >= size); - object dst = s->allocate(size); + void* dst = s->allocate(size); c->client->copy(o, dst); return dst; } -object -copy2(Context* c, object o) +void* +copy2(Context* c, void* o) { unsigned size = c->client->copiedSizeInWords(o); @@ -626,10 +626,10 @@ copy2(Context* c, object o) } } -object -copy(Context* c, object o) +void* +copy(Context* c, void* o) { - object r = copy2(c, o); + void* r = copy2(c, o); if (Debug) { fprintf(stderr, "copy %p (%s) to %p (%s)\n", @@ -637,13 +637,13 @@ copy(Context* c, object o) } // leave a pointer to the copy in the original - cast(o, 0) = r; + cast(o, 0) = r; return r; } -object -update3(Context* c, object o, bool* needsVisit) +void* +update3(Context* c, void* o, bool* needsVisit) { if (wasCollected(c, o)) { *needsVisit = false; @@ -654,8 +654,8 @@ update3(Context* c, object o, bool* needsVisit) } } -object -update2(Context* c, object o, bool* needsVisit) +void* +update2(Context* c, void* o, bool* needsVisit) { if (c->mode == Heap::MinorCollection and c->gen2.contains(o)) { *needsVisit = false; @@ -665,15 +665,15 @@ update2(Context* c, object o, bool* needsVisit) return update3(c, o, needsVisit); } -object -update(Context* c, object* p, bool* needsVisit) +void* +update(Context* c, void** p, bool* needsVisit) { if (mask(*p) == 0) { *needsVisit = false; return 0; } - object r = update2(c, mask(*p), needsVisit); + void* r = update2(c, mask(*p), needsVisit); // update heap map. if (r) { @@ -803,10 +803,10 @@ bitsetNext(Context* c, uintptr_t* p) } void -collect(Context* c, object* p) +collect(Context* c, void** p) { - object original = mask(*p); - object parent = 0; + void* original = mask(*p); + void* parent = 0; if (Debug) { fprintf(stderr, "update %p (%s) at %p (%s)\n", @@ -824,11 +824,11 @@ collect(Context* c, object* p) if (not needsVisit) return; visit: { - object copy = follow(c, original); + void* copy = follow(c, original); class Walker : public Heap::Walker { public: - Walker(Context* c, object copy, uintptr_t* bitset): + Walker(Context* c, void* copy, uintptr_t* bitset): c(c), copy(copy), bitset(bitset), @@ -851,7 +851,7 @@ collect(Context* c, object* p) } bool needsVisit; - object childCopy = update(c, getp(copy, offset), &needsVisit); + void* childCopy = update(c, getp(copy, offset), &needsVisit); if (Debug) { fprintf(stderr, " result: %p (%s) (visit? %d)\n", @@ -894,7 +894,7 @@ collect(Context* c, object* p) } Context* c; - object copy; + void* copy; uintptr_t* bitset; unsigned first; unsigned second; @@ -926,7 +926,7 @@ collect(Context* c, object* p) } if (original) { - object copy = follow(c, original); + void* copy = follow(c, original); class Walker : public Heap::Walker { public: @@ -1014,7 +1014,7 @@ collect(Context* c, Segment::Map* map, unsigned start, unsigned end, } } else { assert(c, map->scale == 1); - object* p = reinterpret_cast(map->segment->get(it.next())); + void** p = reinterpret_cast(map->segment->get(it.next())); map->clearOnly(p); if (c->nextGen1.contains(*p)) { @@ -1053,8 +1053,8 @@ collect2(Context* c) public: Visitor(Context* c): c(c) { } - virtual void visit(void** p) { - collect(c, p); + virtual void visit(void* p) { + collect(c, static_cast(p)); } Context* c; @@ -1125,14 +1125,19 @@ class MyHeap: public Heap { ::collect(&c, footprint); } - virtual bool needsMark(void** p) { - return *p and c.gen2.contains(p) and not c.gen2.contains(*p); + virtual bool needsMark(void* p) { + return *static_cast(p) + and c.gen2.contains(p) + and not c.gen2.contains(*static_cast(p)); } - virtual void mark(void** p) { + virtual void mark(void* p) { if (Debug) { fprintf(stderr, "mark %p (%s) at %p (%s)\n", - *p, segment(&c, *p), p, segment(&c, p)); + *static_cast(p), + segment(&c, *static_cast(p)), + p, + segment(&c, p)); } c.heapMap.set(p); diff --git a/src/heap.h b/src/heap.h index 470fe4f098..3e0a77c97d 100644 --- a/src/heap.h +++ b/src/heap.h @@ -22,7 +22,7 @@ class Heap { class Visitor { public: virtual ~Visitor() { } - virtual void visit(void**) = 0; + virtual void visit(void*) = 0; }; class Walker { @@ -44,8 +44,8 @@ class Heap { virtual ~Heap() { } virtual void collect(CollectionType type, Client* client, unsigned footprint) = 0; - virtual bool needsMark(void** p) = 0; - virtual void mark(void** p) = 0; + virtual bool needsMark(void* p) = 0; + virtual void mark(void* p) = 0; virtual void pad(void* p, unsigned extra) = 0; virtual void* follow(void* p) = 0; virtual Status status(void* p) = 0; diff --git a/src/jnienv.cpp b/src/jnienv.cpp index 4cc8aca274..345997ef8c 100644 --- a/src/jnienv.cpp +++ b/src/jnienv.cpp @@ -5,7 +5,7 @@ using namespace vm; namespace { -jsize +jsize JNICALL GetStringUTFLength(Thread* t, jstring s) { ENTER(t, Thread::ActiveState); @@ -13,7 +13,7 @@ GetStringUTFLength(Thread* t, jstring s) return stringLength(t, *s); } -const char* +const char* JNICALL GetStringUTFChars(Thread* t, jstring s, jboolean* isCopy) { ENTER(t, Thread::ActiveState); @@ -26,13 +26,13 @@ GetStringUTFChars(Thread* t, jstring s, jboolean* isCopy) return chars; } -void +void JNICALL ReleaseStringUTFChars(Thread* t, jstring, const char* chars) { t->vm->system->free(chars); } -jstring +jstring JNICALL NewStringUTF(Thread* t, const char* chars) { ENTER(t, Thread::ActiveState); @@ -40,7 +40,7 @@ NewStringUTF(Thread* t, const char* chars) return pushReference(t, makeString(t, "%s", chars)); } -void +void JNICALL GetByteArrayRegion(Thread* t, jbyteArray array, jint offset, jint length, jbyte* dst) { @@ -49,7 +49,7 @@ GetByteArrayRegion(Thread* t, jbyteArray array, jint offset, jint length, memcpy(dst, &byteArrayBody(t, *array, offset), length); } -void +void JNICALL SetByteArrayRegion(Thread* t, jbyteArray array, jint offset, jint length, const jbyte* src) { @@ -58,7 +58,7 @@ SetByteArrayRegion(Thread* t, jbyteArray array, jint offset, jint length, memcpy(&byteArrayBody(t, *array, offset), src, length); } -jclass +jclass JNICALL FindClass(Thread* t, const char* name) { ENTER(t, Thread::ActiveState); @@ -69,7 +69,7 @@ FindClass(Thread* t, const char* name) return pushReference(t, resolveClass(t, n)); } -jint +jint JNICALL ThrowNew(Thread* t, jclass c, const char* message) { if (t->exception) { @@ -95,18 +95,336 @@ ThrowNew(Thread* t, jclass c, const char* message) return 0; } -void +void JNICALL DeleteLocalRef(Thread*, jobject) { // do nothing } -jboolean +jboolean JNICALL ExceptionCheck(Thread* t) { return t->exception != 0; } +jclass JNICALL +GetObjectClass(Thread* t, jobject o) +{ + return pushReference(t, objectClass(t, *o)); +} + +jboolean JNICALL +IsInstanceOf(Thread* t, jobject o, jclass c) +{ + return instanceOf(t, *c, *o); +} + +object +findMethod(Thread* t, object class_, const char* name, const char* spec) +{ + object n = makeString(t, "%s", name); + PROTECT(t, n); + + object s = makeString(t, "%s", spec); + return vm::findMethod(t, class_, n, s); +} + +// jmethodID JNICALL +// GetMethodID(Thread* t, jclass c, const char* name, const char* spec) +// { +// object method = findMethod(t, *c, name, spec); +// if (UNLIKELY(t->exception)) return 0; + +// if (classFlags(t, *c) & ACC_INTERFACE) { +// PROTECT(t, method); + +// ACQUIRE(t, t->vm->referenceLock); + +// for (unsigned i = 0; i < vectorSize(t, t->vm->jniInterfaceTable); ++i) { +// if (method == vectorBody(t, t->vm->jniInterfaceTable, i)) { +// return i; +// } +// } + +// t->vm->jniInterfaceTable +// = vectorAppend(t, t->vm->jniInterfaceTable, method); + +// return (vectorSize(t, t->vm->jniInterfaceTable) - 1) | (1 << BitsPerWord); +// } else { +// return methodOffset(t, method); +// } +// } + +// jmethodID JNICALL +// GetStaticMethodID(Thread* t, jclass c, const char* name, const char* spec) +// { +// object method = findMethod(t, *c, name, spec); +// if (UNLIKELY(t->exception)) return 0; + +// return methodOffset(t, method); +// } + +object +findField(Thread* t, object class_, const char* name, const char* spec) +{ + object n = makeString(t, "%s", name); + PROTECT(t, n); + + object s = makeString(t, "%s", spec); + return vm::findField(t, class_, n, s); +} + +jfieldID JNICALL +GetFieldID(Thread* t, jclass c, const char* name, const char* spec) +{ + object field = findField(t, *c, name, spec); + if (UNLIKELY(t->exception)) return 0; + + return fieldOffset(t, field); +} + +jfieldID JNICALL +GetStaticFieldID(Thread* t, jclass c, const char* name, const char* spec) +{ + object field = findField(t, *c, name, spec); + if (UNLIKELY(t->exception)) return 0; + + return fieldOffset(t, field); +} + +jobject JNICALL +GetObjectField(Thread* t, jobject o, jfieldID field) +{ + return pushReference(t, cast(*o, field)); +} + +jboolean JNICALL +GetBooleanField(Thread*, jobject o, jfieldID field) +{ + return cast(*o, field); +} + +jbyte JNICALL +GetByteField(Thread*, jobject o, jfieldID field) +{ + return cast(*o, field); +} + +jchar JNICALL +GetCharField(Thread*, jobject o, jfieldID field) +{ + return cast(*o, field); +} + +jshort JNICALL +GetShortField(Thread*, jobject o, jfieldID field) +{ + return cast(*o, field); +} + +jint JNICALL +GetIntField(Thread*, jobject o, jfieldID field) +{ + return cast(*o, field); +} + +jlong JNICALL +GetLongField(Thread*, jobject o, jfieldID field) +{ + return cast(*o, field); +} + +jfloat JNICALL +GetFloatField(Thread*, jobject o, jfieldID field) +{ + return cast(*o, field); +} + +jdouble JNICALL +GetDoubleField(Thread*, jobject o, jfieldID field) +{ + return cast(*o, field); +} + +void JNICALL +SetObjectField(Thread* t, jobject o, jfieldID field, jobject v) +{ + set(t, cast(*o, field), (v ? *v : 0)); +} + +void JNICALL +SetBooleanField(Thread*, jobject o, jfieldID field, jboolean v) +{ + cast(*o, field) = v; +} + +void JNICALL +SetByteField(Thread*, jobject o, jfieldID field, jbyte v) +{ + cast(*o, field) = v; +} + +void JNICALL +SetCharField(Thread*, jobject o, jfieldID field, jchar v) +{ + cast(*o, field) = v; +} + +void JNICALL +SetShortField(Thread*, jobject o, jfieldID field, jshort v) +{ + cast(*o, field) = v; +} + +void JNICALL +SetIntField(Thread*, jobject o, jfieldID field, jint v) +{ + cast(*o, field) = v; +} + +void JNICALL +SetLongField(Thread*, jobject o, jfieldID field, jlong v) +{ + cast(*o, field) = v; +} + +void JNICALL +SetFloatField(Thread*, jobject o, jfieldID field, jfloat v) +{ + cast(*o, field) = v; +} + +void JNICALL +SetDoubleField(Thread*, jobject o, jfieldID field, jdouble v) +{ + cast(*o, field) = v; +} + +jobject JNICALL +GetStaticObjectField(Thread* t, jclass c, jfieldID field) +{ + return pushReference(t, arrayBody(t, classStaticTable(t, *c), field)); +} + +jboolean JNICALL +GetStaticBooleanField(Thread* t, jclass c, jfieldID field) +{ + return intValue(t, arrayBody(t, classStaticTable(t, *c), field)) != 0; +} + +jbyte JNICALL +GetStaticByteField(Thread* t, jclass c, jfieldID field) +{ + return static_cast + (intValue(t, arrayBody(t, classStaticTable(t, *c), field))); +} + +jchar JNICALL +GetStaticCharField(Thread* t, jclass c, jfieldID field) +{ + return static_cast + (intValue(t, arrayBody(t, classStaticTable(t, *c), field))); +} + +jshort JNICALL +GetStaticShortField(Thread* t, jclass c, jfieldID field) +{ + return static_cast + (intValue(t, arrayBody(t, classStaticTable(t, *c), field))); +} + +jint JNICALL +GetStaticIntField(Thread* t, jclass c, jfieldID field) +{ + return intValue(t, arrayBody(t, classStaticTable(t, *c), field)); +} + +jlong JNICALL +GetStaticLongField(Thread* t, jclass c, jfieldID field) +{ + return longValue(t, arrayBody(t, classStaticTable(t, *c), field)); +} + +jfloat JNICALL +GetStaticFloatField(Thread* t, jclass c, jfieldID field) +{ + jint i = intValue(t, arrayBody(t, classStaticTable(t, *c), field)); + jfloat v; memcpy(&v, &i, 4); + return v; +} + +jdouble JNICALL +GetStaticDoubleField(Thread* t, jclass c, jfieldID field) +{ + jlong i = longValue(t, arrayBody(t, classStaticTable(t, *c), field)); + jdouble v; memcpy(&v, &i, 8); + return v; +} + +void JNICALL +SetStaticObjectField(Thread* t, jclass c, jfieldID field, jobject v) +{ + set(t, arrayBody(t, classStaticTable(t, *c), field), (v ? *v : 0)); +} + +void JNICALL +SetStaticBooleanField(Thread* t, jclass c, jfieldID field, jboolean v) +{ + object o = makeInt(t, v ? 1 : 0); + set(t, arrayBody(t, classStaticTable(t, *c), field), o); +} + +void JNICALL +SetStaticByteField(Thread* t, jclass c, jfieldID field, jbyte v) +{ + object o = makeInt(t, v); + set(t, arrayBody(t, classStaticTable(t, *c), field), o); +} + +void JNICALL +SetStaticCharField(Thread* t, jclass c, jfieldID field, jchar v) +{ + object o = makeInt(t, v); + set(t, arrayBody(t, classStaticTable(t, *c), field), o); +} + +void JNICALL +SetStaticShortField(Thread* t, jclass c, jfieldID field, jshort v) +{ + object o = makeInt(t, v); + set(t, arrayBody(t, classStaticTable(t, *c), field), o); +} + +void JNICALL +SetStaticIntField(Thread* t, jclass c, jfieldID field, jint v) +{ + object o = makeInt(t, v); + set(t, arrayBody(t, classStaticTable(t, *c), field), o); +} + +void JNICALL +SetStaticLongField(Thread* t, jclass c, jfieldID field, jlong v) +{ + object o = makeLong(t, v); + set(t, arrayBody(t, classStaticTable(t, *c), field), o); +} + +void JNICALL +SetStaticFloatField(Thread* t, jclass c, jfieldID field, jfloat v) +{ + jint i; memcpy(&i, &v, 4); + object o = makeInt(t, i); + set(t, arrayBody(t, classStaticTable(t, *c), field), o); +} + +void JNICALL +SetStaticDoubleField(Thread* t, jclass c, jfieldID field, jdouble v) +{ + jlong i; memcpy(&i, &v, 8); + object o = makeLong(t, i); + set(t, arrayBody(t, classStaticTable(t, *c), field), o); +} + } // namespace namespace vm { @@ -126,6 +444,46 @@ populateJNITable(JNIEnvVTable* table) table->ThrowNew = ::ThrowNew; table->ExceptionCheck = ::ExceptionCheck; table->DeleteLocalRef = ::DeleteLocalRef; + table->GetObjectClass = ::GetObjectClass; + table->IsInstanceOf = ::IsInstanceOf; + table->GetFieldID = ::GetFieldID; + table->GetStaticFieldID = ::GetStaticFieldID; + table->GetObjectField = ::GetObjectField; + table->GetBooleanField = ::GetBooleanField; + table->GetByteField = ::GetByteField; + table->GetCharField = ::GetCharField; + table->GetShortField = ::GetShortField; + table->GetIntField = ::GetIntField; + table->GetLongField = ::GetLongField; + table->GetFloatField = ::GetFloatField; + table->GetDoubleField = ::GetDoubleField; + table->SetObjectField = ::SetObjectField; + table->SetBooleanField = ::SetBooleanField; + table->SetByteField = ::SetByteField; + table->SetCharField = ::SetCharField; + table->SetShortField = ::SetShortField; + table->SetIntField = ::SetIntField; + table->SetLongField = ::SetLongField; + table->SetFloatField = ::SetFloatField; + table->SetDoubleField = ::SetDoubleField; + table->GetStaticObjectField = ::GetStaticObjectField; + table->GetStaticBooleanField = ::GetStaticBooleanField; + table->GetStaticByteField = ::GetStaticByteField; + table->GetStaticCharField = ::GetStaticCharField; + table->GetStaticShortField = ::GetStaticShortField; + table->GetStaticIntField = ::GetStaticIntField; + table->GetStaticLongField = ::GetStaticLongField; + table->GetStaticFloatField = ::GetStaticFloatField; + table->GetStaticDoubleField = ::GetStaticDoubleField; + table->SetStaticObjectField = ::SetStaticObjectField; + table->SetStaticBooleanField = ::SetStaticBooleanField; + table->SetStaticByteField = ::SetStaticByteField; + table->SetStaticCharField = ::SetStaticCharField; + table->SetStaticShortField = ::SetStaticShortField; + table->SetStaticIntField = ::SetStaticIntField; + table->SetStaticLongField = ::SetStaticLongField; + table->SetStaticFloatField = ::SetStaticFloatField; + table->SetStaticDoubleField = ::SetStaticDoubleField; } } // namespace vm diff --git a/src/machine.cpp b/src/machine.cpp index c7d9761708..57e21ffc14 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -138,7 +138,7 @@ visitRoots(Thread* t, Heap::Visitor* v) for (unsigned i = 0; i < t->sp; ++i) { if (t->stack[i * 2] == ObjectTag) { - v->visit(reinterpret_cast(t->stack + (i * 2) + 1)); + v->visit(t->stack + (i * 2) + 1); } } @@ -1620,7 +1620,7 @@ allocate2(Thread* t, unsigned sizeInBytes) { t->heap = 0; if (t->vm->heapPoolIndex < Machine::HeapPoolSize) { - t->heap = static_cast + t->heap = static_cast (t->vm->system->tryAllocate(Thread::HeapSizeInBytes)); if (t->heap) { t->vm->heapPool[t->vm->heapPoolIndex++] = t->heap; @@ -1648,8 +1648,8 @@ make(Thread* t, object class_) PROTECT(t, class_); unsigned sizeInBytes = pad(classFixedSize(t, class_)); object instance = allocate(t, sizeInBytes); - *static_cast(instance) = class_; - memset(static_cast(instance) + 1, 0, + cast(instance, 0) = class_; + memset(&cast(instance, 0) + 1, 0, sizeInBytes - sizeof(object)); if (UNLIKELY(classVmFlags(t, class_) & WeakReferenceFlag)) { @@ -2056,6 +2056,34 @@ listAppend(Thread* t, object list, object value) set(t, listRear(t, list), p); } +object +vectorAppend(Thread* t, object vector, object value) +{ + if (vectorLength(t, vector) == vectorSize(t, vector)) { + PROTECT(t, vector); + PROTECT(t, value); + + object newVector = makeVector + (t, vectorSize(t, vector), max(16, vectorSize(t, vector) * 2), false); + + if (vectorSize(t, vector)) { + memcpy(&vectorBody(t, newVector, 0), + &vectorBody(t, vector, 0), + vectorSize(t, vector) * BytesPerWord); + } + + memset(&vectorBody(t, newVector, vectorSize(t, vector) + 1), + 0, + (vectorLength(t, newVector) - vectorSize(t, vector) - 1) + * BytesPerWord); + + vector = newVector; + } + + set(t, vectorBody(t, vector, vectorSize(t, vector)++), value); + return vector; +} + unsigned fieldCode(Thread* t, unsigned javaCode) { @@ -2316,6 +2344,59 @@ makeObjectArray(Thread* t, object elementClass, unsigned count, bool clear) return array; } +object +findInTable(Thread* t, object table, object name, object spec, + object& (*getName)(Thread*, object), + object& (*getSpec)(Thread*, object)) +{ + if (table) { + for (unsigned i = 0; i < arrayLength(t, table); ++i) { + object o = arrayBody(t, table, i); + if (strcmp(&byteArrayBody(t, getName(t, o), 0), + &byteArrayBody(t, name, 0)) == 0 and + strcmp(&byteArrayBody(t, getSpec(t, o), 0), + &byteArrayBody(t, spec, 0)) == 0) + { + return o; + } + } + } + + return 0; +} + +object +findInHierarchy(Thread* t, object class_, object name, object spec, + object (*find)(Thread*, object, object, object), + object (*makeError)(Thread*, object)) +{ + object originalClass = class_; + PROTECT(t, class_); + + object o = 0; + if (classFlags(t, class_) & ACC_INTERFACE) { + if (classVirtualTable(t, class_)) { + o = findInTable + (t, classVirtualTable(t, class_), name, spec, methodName, methodSpec); + } + } else { + for (; o == 0 and class_; class_ = classSuper(t, class_)) { + o = find(t, class_, name, spec); + } + } + + if (o == 0) { + object message = makeString + (t, "%s %s not found in %s", + &byteArrayBody(t, name, 0), + &byteArrayBody(t, spec, 0), + &byteArrayBody(t, className(t, originalClass), 0)); + t->exception = makeError(t, message); + } + + return o; +} + int lineNumber(Thread* t, object method, unsigned ip) { @@ -2431,21 +2512,23 @@ collect(Thread* t, Heap::CollectionType type) postVisit(m->rootThread, v); } - virtual unsigned sizeInWords(object o) { + virtual unsigned sizeInWords(void* p) { Thread* t = m->rootThread; - o = m->heap->follow(mask(o)); + object o = static_cast(m->heap->follow(mask(p))); return extendedSize - (t, o, baseSize(t, o, m->heap->follow(objectClass(t, o)))); + (t, o, baseSize(t, o, static_cast + (m->heap->follow(objectClass(t, o))))); } - virtual unsigned copiedSizeInWords(object o) { + virtual unsigned copiedSizeInWords(void* p) { Thread* t = m->rootThread; - o = m->heap->follow(mask(o)); + object o = static_cast(m->heap->follow(mask(p))); - unsigned n = baseSize(t, o, m->heap->follow(objectClass(t, o))); + unsigned n = baseSize(t, o, static_cast + (m->heap->follow(objectClass(t, o)))); if (objectExtended(t, o) or hashTaken(t, o)) { ++ n; @@ -2454,30 +2537,34 @@ collect(Thread* t, Heap::CollectionType type) return n; } - virtual void copy(object o, object dst) { + virtual void copy(void* srcp, void* dstp) { Thread* t = m->rootThread; - o = m->heap->follow(mask(o)); - object class_ = m->heap->follow(objectClass(t, o)); + object src = static_cast(m->heap->follow(mask(srcp))); + object class_ = static_cast + (m->heap->follow(objectClass(t, src))); - unsigned base = baseSize(t, o, class_); - unsigned n = extendedSize(t, o, base); + unsigned base = baseSize(t, src, class_); + unsigned n = extendedSize(t, src, base); - memcpy(dst, o, n * BytesPerWord); + object dst = static_cast(dstp); - if (hashTaken(t, o)) { + memcpy(dst, src, n * BytesPerWord); + + if (hashTaken(t, src)) { cast(dst, 0) &= PointerMask; cast(dst, 0) |= ExtendedMark; - extendedWord(t, dst, base) = takeHash(t, o); + extendedWord(t, dst, base) = takeHash(t, src); } } virtual void walk(void* p, Heap::Walker* w) { Thread* t = m->rootThread; - p = m->heap->follow(mask(p)); - object class_ = m->heap->follow(objectClass(t, p)); - object objectMask = m->heap->follow(classObjectMask(t, class_)); + object o = static_cast(m->heap->follow(mask(p))); + object class_ = static_cast(m->heap->follow(objectClass(t, o))); + object objectMask = static_cast + (m->heap->follow(classObjectMask(t, class_))); if (objectMask) { // fprintf(stderr, "p: %p; class: %p; mask: %p; mask length: %d\n", diff --git a/src/machine.h b/src/machine.h index ba8e475d2c..44df9b4abb 100644 --- a/src/machine.h +++ b/src/machine.h @@ -67,6 +67,10 @@ const unsigned ClassInitFlag = 1 << 0; class Thread; +struct Object { }; + +typedef Object* object; + typedef Thread JNIEnv; typedef uint8_t jboolean; @@ -80,7 +84,7 @@ typedef double jdouble; typedef jint jsize; -typedef void** jobject; +typedef object* jobject; typedef jobject jclass; typedef jobject jthrowable; @@ -98,8 +102,8 @@ typedef jarray jfloatArray; typedef jarray jdoubleArray; typedef jarray jobjectArray; -typedef void** jfieldID; -typedef void** jmethodID; +typedef uintptr_t jfieldID; +typedef uintptr_t jmethodID; union jvalue { jboolean z; @@ -1127,7 +1131,7 @@ class Machine { object tenuredWeakReferences; bool unsafe; JNIEnvVTable jniEnvVTable; - object* heapPool[HeapPoolSize]; + uintptr_t* heapPool[HeapPoolSize]; unsigned heapPoolIndex; }; @@ -1229,12 +1233,12 @@ class Thread { unsigned heapOffset; Protector* protector; Runnable runnable; - object* heap; + uintptr_t* heap; #ifdef VM_STRESS bool stress; - object* defaultHeap; + uintptr_t* defaultHeap; #else // not VM_STRESS - object defaultHeap[HeapSizeInWords]; + uintptr_t defaultHeap[HeapSizeInWords]; #endif // not VM_STRESS uintptr_t stack[StackSizeInWords]; }; @@ -1365,13 +1369,13 @@ expect(Thread* t, bool v) inline object allocateLarge(Thread* t, unsigned sizeInBytes) { - return t->large = t->vm->system->allocate(sizeInBytes); + return t->large = static_cast(t->vm->system->allocate(sizeInBytes)); } inline object allocateSmall(Thread* t, unsigned sizeInBytes) { - object o = t->heap + t->heapIndex; + object o = reinterpret_cast(t->heap + t->heapIndex); t->heapIndex += ceiling(sizeInBytes, BytesPerWord); return o; } @@ -1397,9 +1401,9 @@ allocate(Thread* t, unsigned sizeInBytes) inline void mark(Thread* t, object& target) { - if (t->vm->heap->needsMark(&target)) { + if (t->vm->heap->needsMark(reinterpret_cast(&target))) { ACQUIRE_RAW(t, t->vm->heapLock); - t->vm->heap->mark(&target); + t->vm->heap->mark(reinterpret_cast(&target)); } } @@ -2082,6 +2086,9 @@ hashMapIteratorNext(Thread* t, object it); void listAppend(Thread* t, object list, object value); +object +vectorAppend(Thread* t, object vector, object value); + unsigned fieldCode(Thread* t, unsigned javaCode); @@ -2131,6 +2138,44 @@ initClass(Thread* t, object c) object makeObjectArray(Thread* t, object elementClass, unsigned count, bool clear); +object +findInTable(Thread* t, object table, object name, object spec, + object& (*getName)(Thread*, object), + object& (*getSpec)(Thread*, object)); + +inline object +findFieldInClass(Thread* t, object class_, object name, object spec) +{ + return findInTable + (t, classFieldTable(t, class_), name, spec, fieldName, fieldSpec); +} + +inline object +findMethodInClass(Thread* t, object class_, object name, object spec) +{ + return findInTable + (t, classMethodTable(t, class_), name, spec, methodName, methodSpec); +} + +object +findInHierarchy(Thread* t, object class_, object name, object spec, + object (*find)(Thread*, object, object, object), + object (*makeError)(Thread*, object)); + +inline object +findField(Thread* t, object class_, object name, object spec) +{ + return findInHierarchy + (t, class_, name, spec, findFieldInClass, makeNoSuchFieldError); +} + +inline object +findMethod(Thread* t, object class_, object name, object spec) +{ + return findInHierarchy + (t, class_, name, spec, findMethodInClass, makeNoSuchMethodError); +} + inline unsigned objectArrayLength(Thread* t UNUSED, object array) { diff --git a/src/run.cpp b/src/run.cpp index bc8a8df6c5..8f099d887e 100644 --- a/src/run.cpp +++ b/src/run.cpp @@ -125,43 +125,6 @@ isSpecialMethod(Thread* t, object method, object class_) and isSuperclass(t, methodClass(t, method), class_); } -object -find(Thread* t, object table, object reference, - object& (*name)(Thread*, object), - object& (*spec)(Thread*, object)) -{ - if (table) { - object n = referenceName(t, reference); - object s = referenceSpec(t, reference); - for (unsigned i = 0; i < arrayLength(t, table); ++i) { - object o = arrayBody(t, table, i); - - if (strcmp(&byteArrayBody(t, name(t, o), 0), - &byteArrayBody(t, n, 0)) == 0 and - strcmp(&byteArrayBody(t, spec(t, o), 0), - &byteArrayBody(t, s, 0)) == 0) - { - return o; - } - } - } - - return 0; -} - -inline object -findFieldInClass(Thread* t, object class_, object reference) -{ - return find(t, classFieldTable(t, class_), reference, fieldName, fieldSpec); -} - -inline object -findMethodInClass(Thread* t, object class_, object reference) -{ - return find(t, classMethodTable(t, class_), reference, methodName, - methodSpec); -} - inline object resolveClass(Thread* t, object pool, unsigned index) { @@ -196,7 +159,7 @@ resolveClass(Thread* t, object container, object& (*class_)(Thread*, object)) inline object resolve(Thread* t, object pool, unsigned index, - object (*find)(Thread*, object, object), + object (*find)(Thread*, object, object, object), object (*makeError)(Thread*, object)) { object o = arrayBody(t, pool, index); @@ -210,26 +173,10 @@ resolve(Thread* t, object pool, unsigned index, object class_ = resolveClass(t, o, referenceClass); if (UNLIKELY(t->exception)) return 0; - o = 0; - if (classFlags(t, class_) & ACC_INTERFACE) { - if (classVirtualTable(t, class_)) { - o = ::find(t, classVirtualTable(t, class_), arrayBody(t, pool, index), - methodName, methodSpec); - } - } else { - for (; o == 0 and class_; class_ = classSuper(t, class_)) { - o = find(t, class_, arrayBody(t, pool, index)); - } - } - - if (o == 0) { - object message = makeString - (t, "%s %s not found in %s", - &byteArrayBody(t, referenceName(t, reference), 0), - &byteArrayBody(t, referenceSpec(t, reference), 0), - &byteArrayBody(t, className(t, referenceClass(t, reference)), 0)); - t->exception = makeError(t, message); - } + o = findInHierarchy + (t, class_, referenceName(t, reference), referenceSpec(t, reference), + find, makeError); + if (UNLIKELY(t->exception)) return 0; set(t, arrayBody(t, pool, index), o); } @@ -2769,7 +2716,8 @@ run(Thread* t, const char* className, const char* methodName, object spec = makeByteArray(t, methodSpec); object reference = makeReference(t, class_, name, spec); - object method = findMethodInClass(t, class_, reference); + object method = findMethodInClass(t, class_, referenceName(t, reference), + referenceSpec(t, reference)); if (LIKELY(t->exception == 0)) { assert(t, ((methodFlags(t, method) & ACC_STATIC) == 0) xor (this_ == 0)); diff --git a/src/type-generator.cpp b/src/type-generator.cpp index 6aca1bb77f..d94d0fa83d 100644 --- a/src/type-generator.cpp +++ b/src/type-generator.cpp @@ -34,6 +34,12 @@ allocate() return t; } +inline bool +equal(const char* a, const char* b) +{ + return strcmp(a, b) == 0; +} + class Object { public: typedef enum { @@ -126,6 +132,7 @@ class Scalar : public Object { const char* name; unsigned elementSize; bool noassert; + bool nogc; bool hide; static Scalar* make(Object* owner, Object* typeObject, const char* typeName, @@ -139,6 +146,7 @@ class Scalar : public Object { o->name = name; o->elementSize = size; o->noassert = false; + o->nogc = false; o->hide = false; return o; } @@ -262,6 +270,25 @@ memberNoAssert(Object* o) } } +bool& +memberNoGC(Object* o) +{ + switch (o->type) { + case Object::Scalar: + case Object::Array: + return static_cast(o)->nogc; + + default: + UNREACHABLE; + } +} + +bool +memberGC(Object* o) +{ + return not memberNoGC(o) and equal(memberTypeName(o), "object"); +} + bool& memberHide(Object* o) { @@ -479,12 +506,6 @@ class Singleton : public Object { } }; -bool -equal(const char* a, const char* b) -{ - return strcmp(a, b) == 0; -} - bool endsWith(char c, const char* s) { @@ -782,6 +803,10 @@ parseMember(Object* t, Object* p, Object* declarations) Object* member = parseMember(t, cdr(p), declarations); memberNoAssert(member) = true; return member; + } else if (equal(spec, "nogc")) { + Object* member = parseMember(t, cdr(p), declarations); + memberNoGC(member) = true; + return member; } else { return Scalar::make(t, declaration(spec, declarations), spec, string(car(cdr(p))), @@ -822,6 +847,7 @@ memberEqual(Object* a, Object* b) case Object::Scalar: return equal(memberTypeName(a), memberTypeName(b)) and memberNoAssert(a) == memberNoAssert(b) + and memberNoGC(a) == memberNoGC(b) and memberHide(a) == memberHide(b); // todo: compare array fields @@ -1061,7 +1087,7 @@ writeAccessor(Output* out, Object* member, Object* offset, bool unsafe = false) if (memberOwner(member)->type == Object::Pod) { out->write(">(o->body"); } else { - out->write(">(static_cast(o)"); + out->write(">(reinterpret_cast(o)"); } if (member->type != Object::Scalar and memberTypeObject(member)) { out->write(" + "); @@ -1433,20 +1459,20 @@ typeObjectMask(Object* type) switch (m->type) { case Object::Scalar: { - if (equal(memberTypeName(m), "object")) { + if (memberGC(m)) { set(&mask, offset); } } break; case Object::Array: { - if (equal(memberTypeName(m), "object")) { + if (memberGC(m)) { set(&mask, offset); } else if (memberTypeObject(m) and memberTypeObject(m)->type == Object::Pod) { for (MemberIterator it(memberTypeObject(m)); it.hasMore();) { Object* m = it.next(); - if (equal(memberTypeName(m), "object")) { + if (memberGC(m)) { set(&mask, offset + (it.offset() / sizeof(void*))); } } diff --git a/src/types.def b/src/types.def index 1f0619bfe5..df8c55a215 100644 --- a/src/types.def +++ b/src/types.def @@ -99,9 +99,9 @@ (object third)) (type finalizer - (void* target) + (nogc object target) (void* finalize) - (void* next)) + (nogc object next)) (type hashMap (uint32_t size) @@ -120,6 +120,10 @@ (object front) (object rear)) +(type vector + (uint32_t size) + (array object body)) + (type traceElement (object method) (int32_t ip)) @@ -259,9 +263,9 @@ (type jreference java/lang/ref/Reference (extends jobject) - (noassert void* next) - (void* target) - (void* queue) + (noassert nogc object next) + (nogc object target) + (nogc object queue) (object jnext)) (type weakReference java/lang/ref/WeakReference