several things: change object typedef to Object* instead of void* to improve type safety; add JNICALL attributes to JNI functions; implement additional JavaVM methods

This commit is contained in:
Joel Dice 2007-09-06 18:21:52 -06:00
parent a4b4f36c5b
commit bd4d9fdeb2
11 changed files with 690 additions and 219 deletions

View File

@ -17,7 +17,7 @@ classpath = classpath
test = test test = test
jscheme = $(HOME)/p/jscheme-7.2/src jscheme = $(HOME)/p/jscheme-7.2/src
input = $(cls)/References.class input = $(cls)/GC.class
cxx = g++ cxx = g++
cc = gcc cc = gcc

View File

@ -13,7 +13,7 @@ replace(char a, char b, char* c)
for (; *c; ++c) if (*c == a) *c = b; for (; *c; ++c) if (*c == a) *c = b;
} }
jstring jstring JNICALL
Object_toString(Thread* t, jobject this_) Object_toString(Thread* t, jobject this_)
{ {
unsigned hash = objectHash(t, *this_); unsigned hash = objectHash(t, *this_);
@ -25,47 +25,47 @@ Object_toString(Thread* t, jobject this_)
return pushReference(t, s); return pushReference(t, s);
} }
jclass jclass JNICALL
Object_getClass(Thread* t, jobject this_) Object_getClass(Thread* t, jobject this_)
{ {
return pushReference(t, objectClass(t, *this_)); return pushReference(t, objectClass(t, *this_));
} }
void void JNICALL
Object_wait(Thread* t, jobject this_, jlong milliseconds) Object_wait(Thread* t, jobject this_, jlong milliseconds)
{ {
vm::wait(t, *this_, milliseconds); vm::wait(t, *this_, milliseconds);
} }
void void JNICALL
Object_notify(Thread* t, jobject this_) Object_notify(Thread* t, jobject this_)
{ {
notify(t, *this_); notify(t, *this_);
} }
void void JNICALL
Object_notifyAll(Thread* t, jobject this_) Object_notifyAll(Thread* t, jobject this_)
{ {
notifyAll(t, *this_); notifyAll(t, *this_);
} }
jint jint JNICALL
Object_hashCode(Thread* t, jobject this_) Object_hashCode(Thread* t, jobject this_)
{ {
return objectHash(t, *this_); return objectHash(t, *this_);
} }
jobject jobject JNICALL
Object_clone(Thread* t, jclass, jobject o) Object_clone(Thread* t, jclass, jobject o)
{ {
object clone = make(t, objectClass(t, *o)); object clone = make(t, objectClass(t, *o));
memcpy(static_cast<void**>(clone) + 1, memcpy(reinterpret_cast<void**>(clone) + 1,
static_cast<void**>(*o) + 1, reinterpret_cast<void**>(*o) + 1,
(baseSize(t, *o, objectClass(t, *o)) - 1) * BytesPerWord); (baseSize(t, *o, objectClass(t, *o)) - 1) * BytesPerWord);
return pushReference(t, clone); return pushReference(t, clone);
} }
jclass jclass JNICALL
ClassLoader_defineClass(Thread* t, jclass, jbyteArray b, jint offset, ClassLoader_defineClass(Thread* t, jclass, jbyteArray b, jint offset,
jint length) 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) SystemClassLoader_findLoadedClass(Thread* t, jclass, jstring name)
{ {
return search(t, name, findLoadedClass, true); return search(t, name, findLoadedClass, true);
} }
jclass jclass JNICALL
SystemClassLoader_findClass(Thread* t, jclass, jstring name) SystemClassLoader_findClass(Thread* t, jclass, jstring name)
{ {
return search(t, name, resolveClass, true); return search(t, name, resolveClass, true);
} }
jboolean jboolean JNICALL
SystemClassLoader_resourceExists(Thread* t, jclass, jstring name) SystemClassLoader_resourceExists(Thread* t, jclass, jstring name)
{ {
if (LIKELY(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) ObjectInputStream_makeInstance(Thread* t, jclass, jclass c)
{ {
return pushReference(t, make(t, *c)); return pushReference(t, make(t, *c));
} }
jclass jclass JNICALL
Class_primitiveClass(Thread* t, jclass, jchar name) Class_primitiveClass(Thread* t, jclass, jchar name)
{ {
switch (name) { switch (name) {
@ -160,13 +160,13 @@ Class_primitiveClass(Thread* t, jclass, jchar name)
} }
} }
void void JNICALL
Class_initialize(Thread* t, jobject this_) Class_initialize(Thread* t, jobject this_)
{ {
initClass(t, *this_); initClass(t, *this_);
} }
jboolean jboolean JNICALL
Class_isAssignableFrom(Thread* t, jobject this_, jclass that) Class_isAssignableFrom(Thread* t, jobject this_, jclass that)
{ {
if (LIKELY(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) Field_getPrimitive(Thread* t, jclass, jobject instance, jint code, jint offset)
{ {
switch (code) { 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) Field_getObject(Thread* t, jclass, jobject instance, jint offset)
{ {
return pushReference(t, cast<object>(*instance, offset)); return pushReference(t, cast<object>(*instance, offset));
} }
void void JNICALL
Field_setPrimitive(Thread* t, jclass, jobject instance, jint code, jint offset, Field_setPrimitive(Thread* t, jclass, jobject instance, jint code, jint offset,
jlong value) 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, Field_setObject(Thread* t, jclass, jobject instance, jint offset,
jobject value) jobject value)
{ {
set(t, cast<object>(*instance, offset), (value ? *value : 0)); set(t, cast<object>(*instance, offset), (value ? *value : 0));
} }
jobject jobject JNICALL
Constructor_make(Thread* t, jclass, jclass c) Constructor_make(Thread* t, jclass, jclass c)
{ {
return pushReference(t, make(t, *c)); return pushReference(t, make(t, *c));
} }
jobject jobject JNICALL
Method_getCaller(Thread* t, jclass) Method_getCaller(Thread* t, jclass)
{ {
return pushReference return pushReference
(t, frameMethod(t, frameNext(t, frameNext(t, t->frame)))); (t, frameMethod(t, frameNext(t, frameNext(t, t->frame))));
} }
jobject jobject JNICALL
Method_invoke(Thread* t, jclass, jobject method, jobject instance, Method_invoke(Thread* t, jclass, jobject method, jobject instance,
jobjectArray arguments) jobjectArray arguments)
{ {
@ -273,7 +273,7 @@ Method_invoke(Thread* t, jclass, jobject method, jobject instance,
return pushReference(t, v); return pushReference(t, v);
} }
jint jint JNICALL
Array_getLength(Thread* t, jclass, jobject array) Array_getLength(Thread* t, jclass, jobject array)
{ {
if (LIKELY(array)) { if (LIKELY(array)) {
@ -291,47 +291,47 @@ Array_getLength(Thread* t, jclass, jobject array)
return 0; return 0;
} }
jobject jobject JNICALL
Array_makeObjectArray(Thread* t, jclass, jclass elementType, jint length) Array_makeObjectArray(Thread* t, jclass, jclass elementType, jint length)
{ {
return pushReference(t, makeObjectArray(t, *elementType, length, true)); return pushReference(t, makeObjectArray(t, *elementType, length, true));
} }
jint jint JNICALL
Float_floatToRawIntBits(Thread*, jclass, jfloat v) Float_floatToRawIntBits(Thread*, jclass, jfloat v)
{ {
int32_t r; memcpy(&r, &v, 4); int32_t r; memcpy(&r, &v, 4);
return r; return r;
} }
jfloat jfloat JNICALL
Float_intBitsToFloat(Thread*, jclass, jint v) Float_intBitsToFloat(Thread*, jclass, jint v)
{ {
jfloat r; memcpy(&r, &v, 4); jfloat r; memcpy(&r, &v, 4);
return r; return r;
} }
jlong jlong JNICALL
Double_doubleToRawLongBits(Thread*, jclass, jdouble v) Double_doubleToRawLongBits(Thread*, jclass, jdouble v)
{ {
int64_t r; memcpy(&r, &v, 8); int64_t r; memcpy(&r, &v, 8);
return r; return r;
} }
jdouble jdouble JNICALL
Double_longBitsToDouble(Thread*, jclass, jlong v) Double_longBitsToDouble(Thread*, jclass, jlong v)
{ {
jdouble r; memcpy(&r, &v, 8); jdouble r; memcpy(&r, &v, 8);
return r; return r;
} }
jobject jobject JNICALL
String_intern(Thread* t, jobject this_) String_intern(Thread* t, jobject this_)
{ {
return pushReference(t, intern(t, *this_)); return pushReference(t, intern(t, *this_));
} }
jstring jstring JNICALL
System_getVMProperty(Thread* t, jclass, jint code) System_getVMProperty(Thread* t, jclass, jint code)
{ {
enum { 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, System_arraycopy(Thread* t, jclass, jobject src, jint srcOffset, jobject dst,
jint dstOffset, jint length) jint dstOffset, jint length)
{ {
@ -388,7 +388,7 @@ System_arraycopy(Thread* t, jclass, jobject src, jint srcOffset, jobject dst,
t->exception = makeArrayStoreException(t); t->exception = makeArrayStoreException(t);
} }
jint jint JNICALL
System_identityHashCode(Thread* t, jclass, jobject o) System_identityHashCode(Thread* t, jclass, jobject o)
{ {
if (LIKELY(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) Runtime_loadLibrary(Thread* t, jobject, jstring name)
{ {
if (LIKELY(name)) { if (LIKELY(name)) {
@ -427,7 +427,7 @@ Runtime_loadLibrary(Thread* t, jobject, jstring name)
} }
} }
void void JNICALL
Runtime_gc(Thread* t, jobject) Runtime_gc(Thread* t, jobject)
{ {
ENTER(t, Thread::ExclusiveState); ENTER(t, Thread::ExclusiveState);
@ -435,20 +435,20 @@ Runtime_gc(Thread* t, jobject)
collect(t, Heap::MajorCollection); collect(t, Heap::MajorCollection);
} }
void void JNICALL
Runtime_exit(Thread* t, jobject, jint code) Runtime_exit(Thread* t, jobject, jint code)
{ {
t->vm->system->exit(code); t->vm->system->exit(code);
} }
jlong jlong JNICALL
Runtime_freeMemory(Thread*, jobject) Runtime_freeMemory(Thread*, jobject)
{ {
// todo // todo
return 0; return 0;
} }
jobject jobject JNICALL
Throwable_trace(Thread* t, jclass, jint skipCount) Throwable_trace(Thread* t, jclass, jint skipCount)
{ {
int frame = t->frame; int frame = t->frame;
@ -471,7 +471,7 @@ Throwable_trace(Thread* t, jclass, jint skipCount)
return pushReference(t, makeTrace(t, frame)); return pushReference(t, makeTrace(t, frame));
} }
jarray jarray JNICALL
Throwable_resolveTrace(Thread* t, jclass, jobject trace) Throwable_resolveTrace(Thread* t, jclass, jobject trace)
{ {
unsigned length = arrayLength(t, *trace); unsigned length = arrayLength(t, *trace);
@ -505,13 +505,13 @@ Throwable_resolveTrace(Thread* t, jclass, jobject trace)
return pushReference(t, array); return pushReference(t, array);
} }
jobject jobject JNICALL
Thread_currentThread(Thread* t, jclass) Thread_currentThread(Thread* t, jclass)
{ {
return pushReference(t, t->javaThread); return pushReference(t, t->javaThread);
} }
jlong jlong JNICALL
Thread_doStart(Thread* t, jobject this_) Thread_doStart(Thread* t, jobject this_)
{ {
Thread* p = new (t->vm->system->allocate(sizeof(Thread))) 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) Thread_interrupt(Thread* t, jclass, jlong peer)
{ {
interrupt(t, reinterpret_cast<Thread*>(peer)); interrupt(t, reinterpret_cast<Thread*>(peer));
} }
jlong jlong JNICALL
ResourceInputStream_open(Thread* t, jclass, jstring path) ResourceInputStream_open(Thread* t, jclass, jstring path)
{ {
if (LIKELY(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) ResourceInputStream_read(Thread*, jclass, jlong peer, jint position)
{ {
Finder::Data* d = reinterpret_cast<Finder::Data*>(peer); Finder::Data* d = reinterpret_cast<Finder::Data*>(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, ResourceInputStream_read2(Thread* t, jclass, jlong peer, jint position,
jbyteArray b, jint offset, jint length) 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) ResourceInputStream_close(Thread*, jclass, jlong peer)
{ {
reinterpret_cast<Finder::Data*>(peer)->dispose(); reinterpret_cast<Finder::Data*>(peer)->dispose();

View File

@ -33,8 +33,6 @@ inline void* operator new(size_t, void* p) throw() { return p; }
namespace vm { namespace vm {
typedef void* object;
const unsigned BytesPerWord = sizeof(uintptr_t); const unsigned BytesPerWord = sizeof(uintptr_t);
const unsigned BitsPerWord = BytesPerWord * 8; const unsigned BitsPerWord = BytesPerWord * 8;
@ -118,7 +116,7 @@ indexOf(unsigned word, unsigned bit)
template <class T> template <class T>
inline T& inline T&
cast(object p, unsigned offset) cast(void* p, unsigned offset)
{ {
return *reinterpret_cast<T*>(static_cast<uint8_t*>(p) + offset); return *reinterpret_cast<T*>(static_cast<uint8_t*>(p) + offset);
} }

View File

@ -27,28 +27,28 @@ void assert(Context*, bool);
System* system(Context*); System* system(Context*);
inline object inline void*
get(object o, unsigned offsetInWords) get(void* o, unsigned offsetInWords)
{ {
return mask(cast<object>(o, offsetInWords * BytesPerWord)); return mask(cast<void*>(o, offsetInWords * BytesPerWord));
} }
inline object* inline void**
getp(object o, unsigned offsetInWords) getp(void* o, unsigned offsetInWords)
{ {
return &cast<object>(o, offsetInWords * BytesPerWord); return &cast<void*>(o, offsetInWords * BytesPerWord);
} }
inline void inline void
set(object* o, object value) set(void** o, void* value)
{ {
*o = reinterpret_cast<object> *o = reinterpret_cast<void*>
(reinterpret_cast<uintptr_t>(value) (reinterpret_cast<uintptr_t>(value)
| reinterpret_cast<uintptr_t>(*o) & (~PointerMask)); | reinterpret_cast<uintptr_t>(*o) & (~PointerMask));
} }
inline void inline void
set(object o, unsigned offsetInWords, object value) set(void* o, unsigned offsetInWords, void* value)
{ {
set(getp(o, offsetInWords), value); set(getp(o, offsetInWords), value);
} }
@ -538,7 +538,7 @@ initNextGen2(Context* c)
} }
inline bool inline bool
fresh(Context* c, object o) fresh(Context* c, void* o)
{ {
return c->nextGen1.contains(o) return c->nextGen1.contains(o)
or c->nextGen2.contains(o) or c->nextGen2.contains(o)
@ -546,43 +546,43 @@ fresh(Context* c, object o)
} }
inline bool 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)); return o and (not fresh(c, o)) and fresh(c, get(o, 0));
} }
inline object inline void*
follow(Context* c UNUSED, object o) follow(Context* c UNUSED, void* o)
{ {
assert(c, wasCollected(c, o)); assert(c, wasCollected(c, o));
return cast<object>(o, 0); return cast<void*>(o, 0);
} }
inline object& inline void*&
parent(Context* c UNUSED, object o) parent(Context* c UNUSED, void* o)
{ {
assert(c, wasCollected(c, o)); assert(c, wasCollected(c, o));
return cast<object>(o, BytesPerWord); return cast<void*>(o, BytesPerWord);
} }
inline uintptr_t* inline uintptr_t*
bitset(Context* c UNUSED, object o) bitset(Context* c UNUSED, void* o)
{ {
assert(c, wasCollected(c, o)); assert(c, wasCollected(c, o));
return &cast<uintptr_t>(o, BytesPerWord * 2); return &cast<uintptr_t>(o, BytesPerWord * 2);
} }
inline object inline void*
copyTo(Context* c, Segment* s, object o, unsigned size) copyTo(Context* c, Segment* s, void* o, unsigned size)
{ {
assert(c, s->remaining() >= size); assert(c, s->remaining() >= size);
object dst = s->allocate(size); void* dst = s->allocate(size);
c->client->copy(o, dst); c->client->copy(o, dst);
return dst; return dst;
} }
object void*
copy2(Context* c, object o) copy2(Context* c, void* o)
{ {
unsigned size = c->client->copiedSizeInWords(o); unsigned size = c->client->copiedSizeInWords(o);
@ -626,10 +626,10 @@ copy2(Context* c, object o)
} }
} }
object void*
copy(Context* c, object o) copy(Context* c, void* o)
{ {
object r = copy2(c, o); void* r = copy2(c, o);
if (Debug) { if (Debug) {
fprintf(stderr, "copy %p (%s) to %p (%s)\n", 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 // leave a pointer to the copy in the original
cast<object>(o, 0) = r; cast<void*>(o, 0) = r;
return r; return r;
} }
object void*
update3(Context* c, object o, bool* needsVisit) update3(Context* c, void* o, bool* needsVisit)
{ {
if (wasCollected(c, o)) { if (wasCollected(c, o)) {
*needsVisit = false; *needsVisit = false;
@ -654,8 +654,8 @@ update3(Context* c, object o, bool* needsVisit)
} }
} }
object void*
update2(Context* c, object o, bool* needsVisit) update2(Context* c, void* o, bool* needsVisit)
{ {
if (c->mode == Heap::MinorCollection and c->gen2.contains(o)) { if (c->mode == Heap::MinorCollection and c->gen2.contains(o)) {
*needsVisit = false; *needsVisit = false;
@ -665,15 +665,15 @@ update2(Context* c, object o, bool* needsVisit)
return update3(c, o, needsVisit); return update3(c, o, needsVisit);
} }
object void*
update(Context* c, object* p, bool* needsVisit) update(Context* c, void** p, bool* needsVisit)
{ {
if (mask(*p) == 0) { if (mask(*p) == 0) {
*needsVisit = false; *needsVisit = false;
return 0; return 0;
} }
object r = update2(c, mask(*p), needsVisit); void* r = update2(c, mask(*p), needsVisit);
// update heap map. // update heap map.
if (r) { if (r) {
@ -803,10 +803,10 @@ bitsetNext(Context* c, uintptr_t* p)
} }
void void
collect(Context* c, object* p) collect(Context* c, void** p)
{ {
object original = mask(*p); void* original = mask(*p);
object parent = 0; void* parent = 0;
if (Debug) { if (Debug) {
fprintf(stderr, "update %p (%s) at %p (%s)\n", fprintf(stderr, "update %p (%s) at %p (%s)\n",
@ -824,11 +824,11 @@ collect(Context* c, object* p)
if (not needsVisit) return; if (not needsVisit) return;
visit: { visit: {
object copy = follow(c, original); void* copy = follow(c, original);
class Walker : public Heap::Walker { class Walker : public Heap::Walker {
public: public:
Walker(Context* c, object copy, uintptr_t* bitset): Walker(Context* c, void* copy, uintptr_t* bitset):
c(c), c(c),
copy(copy), copy(copy),
bitset(bitset), bitset(bitset),
@ -851,7 +851,7 @@ collect(Context* c, object* p)
} }
bool needsVisit; bool needsVisit;
object childCopy = update(c, getp(copy, offset), &needsVisit); void* childCopy = update(c, getp(copy, offset), &needsVisit);
if (Debug) { if (Debug) {
fprintf(stderr, " result: %p (%s) (visit? %d)\n", fprintf(stderr, " result: %p (%s) (visit? %d)\n",
@ -894,7 +894,7 @@ collect(Context* c, object* p)
} }
Context* c; Context* c;
object copy; void* copy;
uintptr_t* bitset; uintptr_t* bitset;
unsigned first; unsigned first;
unsigned second; unsigned second;
@ -926,7 +926,7 @@ collect(Context* c, object* p)
} }
if (original) { if (original) {
object copy = follow(c, original); void* copy = follow(c, original);
class Walker : public Heap::Walker { class Walker : public Heap::Walker {
public: public:
@ -1014,7 +1014,7 @@ collect(Context* c, Segment::Map* map, unsigned start, unsigned end,
} }
} else { } else {
assert(c, map->scale == 1); assert(c, map->scale == 1);
object* p = reinterpret_cast<object*>(map->segment->get(it.next())); void** p = reinterpret_cast<void**>(map->segment->get(it.next()));
map->clearOnly(p); map->clearOnly(p);
if (c->nextGen1.contains(*p)) { if (c->nextGen1.contains(*p)) {
@ -1053,8 +1053,8 @@ collect2(Context* c)
public: public:
Visitor(Context* c): c(c) { } Visitor(Context* c): c(c) { }
virtual void visit(void** p) { virtual void visit(void* p) {
collect(c, p); collect(c, static_cast<void**>(p));
} }
Context* c; Context* c;
@ -1125,14 +1125,19 @@ class MyHeap: public Heap {
::collect(&c, footprint); ::collect(&c, footprint);
} }
virtual bool needsMark(void** p) { virtual bool needsMark(void* p) {
return *p and c.gen2.contains(p) and not c.gen2.contains(*p); return *static_cast<void**>(p)
and c.gen2.contains(p)
and not c.gen2.contains(*static_cast<void**>(p));
} }
virtual void mark(void** p) { virtual void mark(void* p) {
if (Debug) { if (Debug) {
fprintf(stderr, "mark %p (%s) at %p (%s)\n", fprintf(stderr, "mark %p (%s) at %p (%s)\n",
*p, segment(&c, *p), p, segment(&c, p)); *static_cast<void**>(p),
segment(&c, *static_cast<void**>(p)),
p,
segment(&c, p));
} }
c.heapMap.set(p); c.heapMap.set(p);

View File

@ -22,7 +22,7 @@ class Heap {
class Visitor { class Visitor {
public: public:
virtual ~Visitor() { } virtual ~Visitor() { }
virtual void visit(void**) = 0; virtual void visit(void*) = 0;
}; };
class Walker { class Walker {
@ -44,8 +44,8 @@ class Heap {
virtual ~Heap() { } virtual ~Heap() { }
virtual void collect(CollectionType type, Client* client, unsigned footprint) virtual void collect(CollectionType type, Client* client, unsigned footprint)
= 0; = 0;
virtual bool needsMark(void** p) = 0; virtual bool needsMark(void* p) = 0;
virtual void mark(void** p) = 0; virtual void mark(void* p) = 0;
virtual void pad(void* p, unsigned extra) = 0; virtual void pad(void* p, unsigned extra) = 0;
virtual void* follow(void* p) = 0; virtual void* follow(void* p) = 0;
virtual Status status(void* p) = 0; virtual Status status(void* p) = 0;

View File

@ -5,7 +5,7 @@ using namespace vm;
namespace { namespace {
jsize jsize JNICALL
GetStringUTFLength(Thread* t, jstring s) GetStringUTFLength(Thread* t, jstring s)
{ {
ENTER(t, Thread::ActiveState); ENTER(t, Thread::ActiveState);
@ -13,7 +13,7 @@ GetStringUTFLength(Thread* t, jstring s)
return stringLength(t, *s); return stringLength(t, *s);
} }
const char* const char* JNICALL
GetStringUTFChars(Thread* t, jstring s, jboolean* isCopy) GetStringUTFChars(Thread* t, jstring s, jboolean* isCopy)
{ {
ENTER(t, Thread::ActiveState); ENTER(t, Thread::ActiveState);
@ -26,13 +26,13 @@ GetStringUTFChars(Thread* t, jstring s, jboolean* isCopy)
return chars; return chars;
} }
void void JNICALL
ReleaseStringUTFChars(Thread* t, jstring, const char* chars) ReleaseStringUTFChars(Thread* t, jstring, const char* chars)
{ {
t->vm->system->free(chars); t->vm->system->free(chars);
} }
jstring jstring JNICALL
NewStringUTF(Thread* t, const char* chars) NewStringUTF(Thread* t, const char* chars)
{ {
ENTER(t, Thread::ActiveState); ENTER(t, Thread::ActiveState);
@ -40,7 +40,7 @@ NewStringUTF(Thread* t, const char* chars)
return pushReference(t, makeString(t, "%s", chars)); return pushReference(t, makeString(t, "%s", chars));
} }
void void JNICALL
GetByteArrayRegion(Thread* t, jbyteArray array, jint offset, jint length, GetByteArrayRegion(Thread* t, jbyteArray array, jint offset, jint length,
jbyte* dst) jbyte* dst)
{ {
@ -49,7 +49,7 @@ GetByteArrayRegion(Thread* t, jbyteArray array, jint offset, jint length,
memcpy(dst, &byteArrayBody(t, *array, offset), length); memcpy(dst, &byteArrayBody(t, *array, offset), length);
} }
void void JNICALL
SetByteArrayRegion(Thread* t, jbyteArray array, jint offset, jint length, SetByteArrayRegion(Thread* t, jbyteArray array, jint offset, jint length,
const jbyte* src) const jbyte* src)
{ {
@ -58,7 +58,7 @@ SetByteArrayRegion(Thread* t, jbyteArray array, jint offset, jint length,
memcpy(&byteArrayBody(t, *array, offset), src, length); memcpy(&byteArrayBody(t, *array, offset), src, length);
} }
jclass jclass JNICALL
FindClass(Thread* t, const char* name) FindClass(Thread* t, const char* name)
{ {
ENTER(t, Thread::ActiveState); ENTER(t, Thread::ActiveState);
@ -69,7 +69,7 @@ FindClass(Thread* t, const char* name)
return pushReference(t, resolveClass(t, n)); return pushReference(t, resolveClass(t, n));
} }
jint jint JNICALL
ThrowNew(Thread* t, jclass c, const char* message) ThrowNew(Thread* t, jclass c, const char* message)
{ {
if (t->exception) { if (t->exception) {
@ -95,18 +95,336 @@ ThrowNew(Thread* t, jclass c, const char* message)
return 0; return 0;
} }
void void JNICALL
DeleteLocalRef(Thread*, jobject) DeleteLocalRef(Thread*, jobject)
{ {
// do nothing // do nothing
} }
jboolean jboolean JNICALL
ExceptionCheck(Thread* t) ExceptionCheck(Thread* t)
{ {
return t->exception != 0; 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<object>(*o, field));
}
jboolean JNICALL
GetBooleanField(Thread*, jobject o, jfieldID field)
{
return cast<jboolean>(*o, field);
}
jbyte JNICALL
GetByteField(Thread*, jobject o, jfieldID field)
{
return cast<jbyte>(*o, field);
}
jchar JNICALL
GetCharField(Thread*, jobject o, jfieldID field)
{
return cast<jchar>(*o, field);
}
jshort JNICALL
GetShortField(Thread*, jobject o, jfieldID field)
{
return cast<jshort>(*o, field);
}
jint JNICALL
GetIntField(Thread*, jobject o, jfieldID field)
{
return cast<jint>(*o, field);
}
jlong JNICALL
GetLongField(Thread*, jobject o, jfieldID field)
{
return cast<jlong>(*o, field);
}
jfloat JNICALL
GetFloatField(Thread*, jobject o, jfieldID field)
{
return cast<jfloat>(*o, field);
}
jdouble JNICALL
GetDoubleField(Thread*, jobject o, jfieldID field)
{
return cast<jdouble>(*o, field);
}
void JNICALL
SetObjectField(Thread* t, jobject o, jfieldID field, jobject v)
{
set(t, cast<object>(*o, field), (v ? *v : 0));
}
void JNICALL
SetBooleanField(Thread*, jobject o, jfieldID field, jboolean v)
{
cast<jboolean>(*o, field) = v;
}
void JNICALL
SetByteField(Thread*, jobject o, jfieldID field, jbyte v)
{
cast<jbyte>(*o, field) = v;
}
void JNICALL
SetCharField(Thread*, jobject o, jfieldID field, jchar v)
{
cast<jchar>(*o, field) = v;
}
void JNICALL
SetShortField(Thread*, jobject o, jfieldID field, jshort v)
{
cast<jshort>(*o, field) = v;
}
void JNICALL
SetIntField(Thread*, jobject o, jfieldID field, jint v)
{
cast<jint>(*o, field) = v;
}
void JNICALL
SetLongField(Thread*, jobject o, jfieldID field, jlong v)
{
cast<jlong>(*o, field) = v;
}
void JNICALL
SetFloatField(Thread*, jobject o, jfieldID field, jfloat v)
{
cast<jfloat>(*o, field) = v;
}
void JNICALL
SetDoubleField(Thread*, jobject o, jfieldID field, jdouble v)
{
cast<jdouble>(*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<jbyte>
(intValue(t, arrayBody(t, classStaticTable(t, *c), field)));
}
jchar JNICALL
GetStaticCharField(Thread* t, jclass c, jfieldID field)
{
return static_cast<jchar>
(intValue(t, arrayBody(t, classStaticTable(t, *c), field)));
}
jshort JNICALL
GetStaticShortField(Thread* t, jclass c, jfieldID field)
{
return static_cast<jshort>
(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
namespace vm { namespace vm {
@ -126,6 +444,46 @@ populateJNITable(JNIEnvVTable* table)
table->ThrowNew = ::ThrowNew; table->ThrowNew = ::ThrowNew;
table->ExceptionCheck = ::ExceptionCheck; table->ExceptionCheck = ::ExceptionCheck;
table->DeleteLocalRef = ::DeleteLocalRef; 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 } // namespace vm

View File

@ -138,7 +138,7 @@ visitRoots(Thread* t, Heap::Visitor* v)
for (unsigned i = 0; i < t->sp; ++i) { for (unsigned i = 0; i < t->sp; ++i) {
if (t->stack[i * 2] == ObjectTag) { if (t->stack[i * 2] == ObjectTag) {
v->visit(reinterpret_cast<object*>(t->stack + (i * 2) + 1)); v->visit(t->stack + (i * 2) + 1);
} }
} }
@ -1620,7 +1620,7 @@ allocate2(Thread* t, unsigned sizeInBytes)
{ {
t->heap = 0; t->heap = 0;
if (t->vm->heapPoolIndex < Machine::HeapPoolSize) { if (t->vm->heapPoolIndex < Machine::HeapPoolSize) {
t->heap = static_cast<object*> t->heap = static_cast<uintptr_t*>
(t->vm->system->tryAllocate(Thread::HeapSizeInBytes)); (t->vm->system->tryAllocate(Thread::HeapSizeInBytes));
if (t->heap) { if (t->heap) {
t->vm->heapPool[t->vm->heapPoolIndex++] = t->heap; t->vm->heapPool[t->vm->heapPoolIndex++] = t->heap;
@ -1648,8 +1648,8 @@ make(Thread* t, object class_)
PROTECT(t, class_); PROTECT(t, class_);
unsigned sizeInBytes = pad(classFixedSize(t, class_)); unsigned sizeInBytes = pad(classFixedSize(t, class_));
object instance = allocate(t, sizeInBytes); object instance = allocate(t, sizeInBytes);
*static_cast<object*>(instance) = class_; cast<object>(instance, 0) = class_;
memset(static_cast<object*>(instance) + 1, 0, memset(&cast<object>(instance, 0) + 1, 0,
sizeInBytes - sizeof(object)); sizeInBytes - sizeof(object));
if (UNLIKELY(classVmFlags(t, class_) & WeakReferenceFlag)) { if (UNLIKELY(classVmFlags(t, class_) & WeakReferenceFlag)) {
@ -2056,6 +2056,34 @@ listAppend(Thread* t, object list, object value)
set(t, listRear(t, list), p); 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 unsigned
fieldCode(Thread* t, unsigned javaCode) fieldCode(Thread* t, unsigned javaCode)
{ {
@ -2316,6 +2344,59 @@ makeObjectArray(Thread* t, object elementClass, unsigned count, bool clear)
return array; 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 int
lineNumber(Thread* t, object method, unsigned ip) lineNumber(Thread* t, object method, unsigned ip)
{ {
@ -2431,21 +2512,23 @@ collect(Thread* t, Heap::CollectionType type)
postVisit(m->rootThread, v); postVisit(m->rootThread, v);
} }
virtual unsigned sizeInWords(object o) { virtual unsigned sizeInWords(void* p) {
Thread* t = m->rootThread; Thread* t = m->rootThread;
o = m->heap->follow(mask(o)); object o = static_cast<object>(m->heap->follow(mask(p)));
return extendedSize return extendedSize
(t, o, baseSize(t, o, m->heap->follow(objectClass(t, o)))); (t, o, baseSize(t, o, static_cast<object>
(m->heap->follow(objectClass(t, o)))));
} }
virtual unsigned copiedSizeInWords(object o) { virtual unsigned copiedSizeInWords(void* p) {
Thread* t = m->rootThread; Thread* t = m->rootThread;
o = m->heap->follow(mask(o)); object o = static_cast<object>(m->heap->follow(mask(p)));
unsigned n = baseSize(t, o, m->heap->follow(objectClass(t, o))); unsigned n = baseSize(t, o, static_cast<object>
(m->heap->follow(objectClass(t, o))));
if (objectExtended(t, o) or hashTaken(t, o)) { if (objectExtended(t, o) or hashTaken(t, o)) {
++ n; ++ n;
@ -2454,30 +2537,34 @@ collect(Thread* t, Heap::CollectionType type)
return n; return n;
} }
virtual void copy(object o, object dst) { virtual void copy(void* srcp, void* dstp) {
Thread* t = m->rootThread; Thread* t = m->rootThread;
o = m->heap->follow(mask(o)); object src = static_cast<object>(m->heap->follow(mask(srcp)));
object class_ = m->heap->follow(objectClass(t, o)); object class_ = static_cast<object>
(m->heap->follow(objectClass(t, src)));
unsigned base = baseSize(t, o, class_); unsigned base = baseSize(t, src, class_);
unsigned n = extendedSize(t, o, base); unsigned n = extendedSize(t, src, base);
memcpy(dst, o, n * BytesPerWord); object dst = static_cast<object>(dstp);
if (hashTaken(t, o)) { memcpy(dst, src, n * BytesPerWord);
if (hashTaken(t, src)) {
cast<uintptr_t>(dst, 0) &= PointerMask; cast<uintptr_t>(dst, 0) &= PointerMask;
cast<uintptr_t>(dst, 0) |= ExtendedMark; cast<uintptr_t>(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) { virtual void walk(void* p, Heap::Walker* w) {
Thread* t = m->rootThread; Thread* t = m->rootThread;
p = m->heap->follow(mask(p)); object o = static_cast<object>(m->heap->follow(mask(p)));
object class_ = m->heap->follow(objectClass(t, p)); object class_ = static_cast<object>(m->heap->follow(objectClass(t, o)));
object objectMask = m->heap->follow(classObjectMask(t, class_)); object objectMask = static_cast<object>
(m->heap->follow(classObjectMask(t, class_)));
if (objectMask) { if (objectMask) {
// fprintf(stderr, "p: %p; class: %p; mask: %p; mask length: %d\n", // fprintf(stderr, "p: %p; class: %p; mask: %p; mask length: %d\n",

View File

@ -67,6 +67,10 @@ const unsigned ClassInitFlag = 1 << 0;
class Thread; class Thread;
struct Object { };
typedef Object* object;
typedef Thread JNIEnv; typedef Thread JNIEnv;
typedef uint8_t jboolean; typedef uint8_t jboolean;
@ -80,7 +84,7 @@ typedef double jdouble;
typedef jint jsize; typedef jint jsize;
typedef void** jobject; typedef object* jobject;
typedef jobject jclass; typedef jobject jclass;
typedef jobject jthrowable; typedef jobject jthrowable;
@ -98,8 +102,8 @@ typedef jarray jfloatArray;
typedef jarray jdoubleArray; typedef jarray jdoubleArray;
typedef jarray jobjectArray; typedef jarray jobjectArray;
typedef void** jfieldID; typedef uintptr_t jfieldID;
typedef void** jmethodID; typedef uintptr_t jmethodID;
union jvalue { union jvalue {
jboolean z; jboolean z;
@ -1127,7 +1131,7 @@ class Machine {
object tenuredWeakReferences; object tenuredWeakReferences;
bool unsafe; bool unsafe;
JNIEnvVTable jniEnvVTable; JNIEnvVTable jniEnvVTable;
object* heapPool[HeapPoolSize]; uintptr_t* heapPool[HeapPoolSize];
unsigned heapPoolIndex; unsigned heapPoolIndex;
}; };
@ -1229,12 +1233,12 @@ class Thread {
unsigned heapOffset; unsigned heapOffset;
Protector* protector; Protector* protector;
Runnable runnable; Runnable runnable;
object* heap; uintptr_t* heap;
#ifdef VM_STRESS #ifdef VM_STRESS
bool stress; bool stress;
object* defaultHeap; uintptr_t* defaultHeap;
#else // not VM_STRESS #else // not VM_STRESS
object defaultHeap[HeapSizeInWords]; uintptr_t defaultHeap[HeapSizeInWords];
#endif // not VM_STRESS #endif // not VM_STRESS
uintptr_t stack[StackSizeInWords]; uintptr_t stack[StackSizeInWords];
}; };
@ -1365,13 +1369,13 @@ expect(Thread* t, bool v)
inline object inline object
allocateLarge(Thread* t, unsigned sizeInBytes) allocateLarge(Thread* t, unsigned sizeInBytes)
{ {
return t->large = t->vm->system->allocate(sizeInBytes); return t->large = static_cast<object>(t->vm->system->allocate(sizeInBytes));
} }
inline object inline object
allocateSmall(Thread* t, unsigned sizeInBytes) allocateSmall(Thread* t, unsigned sizeInBytes)
{ {
object o = t->heap + t->heapIndex; object o = reinterpret_cast<object>(t->heap + t->heapIndex);
t->heapIndex += ceiling(sizeInBytes, BytesPerWord); t->heapIndex += ceiling(sizeInBytes, BytesPerWord);
return o; return o;
} }
@ -1397,9 +1401,9 @@ allocate(Thread* t, unsigned sizeInBytes)
inline void inline void
mark(Thread* t, object& target) mark(Thread* t, object& target)
{ {
if (t->vm->heap->needsMark(&target)) { if (t->vm->heap->needsMark(reinterpret_cast<void**>(&target))) {
ACQUIRE_RAW(t, t->vm->heapLock); ACQUIRE_RAW(t, t->vm->heapLock);
t->vm->heap->mark(&target); t->vm->heap->mark(reinterpret_cast<void**>(&target));
} }
} }
@ -2082,6 +2086,9 @@ hashMapIteratorNext(Thread* t, object it);
void void
listAppend(Thread* t, object list, object value); listAppend(Thread* t, object list, object value);
object
vectorAppend(Thread* t, object vector, object value);
unsigned unsigned
fieldCode(Thread* t, unsigned javaCode); fieldCode(Thread* t, unsigned javaCode);
@ -2131,6 +2138,44 @@ initClass(Thread* t, object c)
object object
makeObjectArray(Thread* t, object elementClass, unsigned count, bool clear); 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 inline unsigned
objectArrayLength(Thread* t UNUSED, object array) objectArrayLength(Thread* t UNUSED, object array)
{ {

View File

@ -125,43 +125,6 @@ isSpecialMethod(Thread* t, object method, object class_)
and isSuperclass(t, methodClass(t, method), 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 inline object
resolveClass(Thread* t, object pool, unsigned index) resolveClass(Thread* t, object pool, unsigned index)
{ {
@ -196,7 +159,7 @@ resolveClass(Thread* t, object container, object& (*class_)(Thread*, object))
inline object inline object
resolve(Thread* t, object pool, unsigned index, resolve(Thread* t, object pool, unsigned index,
object (*find)(Thread*, object, object), object (*find)(Thread*, object, object, object),
object (*makeError)(Thread*, object)) object (*makeError)(Thread*, object))
{ {
object o = arrayBody(t, pool, index); object o = arrayBody(t, pool, index);
@ -210,26 +173,10 @@ resolve(Thread* t, object pool, unsigned index,
object class_ = resolveClass(t, o, referenceClass); object class_ = resolveClass(t, o, referenceClass);
if (UNLIKELY(t->exception)) return 0; if (UNLIKELY(t->exception)) return 0;
o = 0; o = findInHierarchy
if (classFlags(t, class_) & ACC_INTERFACE) { (t, class_, referenceName(t, reference), referenceSpec(t, reference),
if (classVirtualTable(t, class_)) { find, makeError);
o = ::find(t, classVirtualTable(t, class_), arrayBody(t, pool, index), if (UNLIKELY(t->exception)) return 0;
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);
}
set(t, arrayBody(t, pool, index), o); 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 spec = makeByteArray(t, methodSpec);
object reference = makeReference(t, class_, name, spec); 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)) { if (LIKELY(t->exception == 0)) {
assert(t, ((methodFlags(t, method) & ACC_STATIC) == 0) xor (this_ == 0)); assert(t, ((methodFlags(t, method) & ACC_STATIC) == 0) xor (this_ == 0));

View File

@ -34,6 +34,12 @@ allocate()
return t; return t;
} }
inline bool
equal(const char* a, const char* b)
{
return strcmp(a, b) == 0;
}
class Object { class Object {
public: public:
typedef enum { typedef enum {
@ -126,6 +132,7 @@ class Scalar : public Object {
const char* name; const char* name;
unsigned elementSize; unsigned elementSize;
bool noassert; bool noassert;
bool nogc;
bool hide; bool hide;
static Scalar* make(Object* owner, Object* typeObject, const char* typeName, static Scalar* make(Object* owner, Object* typeObject, const char* typeName,
@ -139,6 +146,7 @@ class Scalar : public Object {
o->name = name; o->name = name;
o->elementSize = size; o->elementSize = size;
o->noassert = false; o->noassert = false;
o->nogc = false;
o->hide = false; o->hide = false;
return o; 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<Scalar*>(o)->nogc;
default:
UNREACHABLE;
}
}
bool
memberGC(Object* o)
{
return not memberNoGC(o) and equal(memberTypeName(o), "object");
}
bool& bool&
memberHide(Object* o) 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 bool
endsWith(char c, const char* s) endsWith(char c, const char* s)
{ {
@ -782,6 +803,10 @@ parseMember(Object* t, Object* p, Object* declarations)
Object* member = parseMember(t, cdr(p), declarations); Object* member = parseMember(t, cdr(p), declarations);
memberNoAssert(member) = true; memberNoAssert(member) = true;
return member; return member;
} else if (equal(spec, "nogc")) {
Object* member = parseMember(t, cdr(p), declarations);
memberNoGC(member) = true;
return member;
} else { } else {
return Scalar::make(t, declaration(spec, declarations), spec, return Scalar::make(t, declaration(spec, declarations), spec,
string(car(cdr(p))), string(car(cdr(p))),
@ -822,6 +847,7 @@ memberEqual(Object* a, Object* b)
case Object::Scalar: case Object::Scalar:
return equal(memberTypeName(a), memberTypeName(b)) return equal(memberTypeName(a), memberTypeName(b))
and memberNoAssert(a) == memberNoAssert(b) and memberNoAssert(a) == memberNoAssert(b)
and memberNoGC(a) == memberNoGC(b)
and memberHide(a) == memberHide(b); and memberHide(a) == memberHide(b);
// todo: compare array fields // todo: compare array fields
@ -1061,7 +1087,7 @@ writeAccessor(Output* out, Object* member, Object* offset, bool unsafe = false)
if (memberOwner(member)->type == Object::Pod) { if (memberOwner(member)->type == Object::Pod) {
out->write(">(o->body"); out->write(">(o->body");
} else { } else {
out->write(">(static_cast<uint8_t*>(o)"); out->write(">(reinterpret_cast<uint8_t*>(o)");
} }
if (member->type != Object::Scalar and memberTypeObject(member)) { if (member->type != Object::Scalar and memberTypeObject(member)) {
out->write(" + "); out->write(" + ");
@ -1433,20 +1459,20 @@ typeObjectMask(Object* type)
switch (m->type) { switch (m->type) {
case Object::Scalar: { case Object::Scalar: {
if (equal(memberTypeName(m), "object")) { if (memberGC(m)) {
set(&mask, offset); set(&mask, offset);
} }
} break; } break;
case Object::Array: { case Object::Array: {
if (equal(memberTypeName(m), "object")) { if (memberGC(m)) {
set(&mask, offset); set(&mask, offset);
} else if (memberTypeObject(m) } else if (memberTypeObject(m)
and memberTypeObject(m)->type == Object::Pod) and memberTypeObject(m)->type == Object::Pod)
{ {
for (MemberIterator it(memberTypeObject(m)); it.hasMore();) { for (MemberIterator it(memberTypeObject(m)); it.hasMore();) {
Object* m = it.next(); Object* m = it.next();
if (equal(memberTypeName(m), "object")) { if (memberGC(m)) {
set(&mask, offset + (it.offset() / sizeof(void*))); set(&mask, offset + (it.offset() / sizeof(void*)));
} }
} }

View File

@ -99,9 +99,9 @@
(object third)) (object third))
(type finalizer (type finalizer
(void* target) (nogc object target)
(void* finalize) (void* finalize)
(void* next)) (nogc object next))
(type hashMap (type hashMap
(uint32_t size) (uint32_t size)
@ -120,6 +120,10 @@
(object front) (object front)
(object rear)) (object rear))
(type vector
(uint32_t size)
(array object body))
(type traceElement (type traceElement
(object method) (object method)
(int32_t ip)) (int32_t ip))
@ -259,9 +263,9 @@
(type jreference java/lang/ref/Reference (type jreference java/lang/ref/Reference
(extends jobject) (extends jobject)
(noassert void* next) (noassert nogc object next)
(void* target) (nogc object target)
(void* queue) (nogc object queue)
(object jnext)) (object jnext))
(type weakReference java/lang/ref/WeakReference (type weakReference java/lang/ref/WeakReference