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
jscheme = $(HOME)/p/jscheme-7.2/src
input = $(cls)/References.class
input = $(cls)/GC.class
cxx = g++
cc = gcc

View File

@ -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<void**>(clone) + 1,
static_cast<void**>(*o) + 1,
memcpy(reinterpret_cast<void**>(clone) + 1,
reinterpret_cast<void**>(*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<object>(*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<object>(*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<Thread*>(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<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,
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<Finder::Data*>(peer)->dispose();

View File

@ -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 <class T>
inline T&
cast(object p, unsigned offset)
cast(void* p, unsigned offset)
{
return *reinterpret_cast<T*>(static_cast<uint8_t*>(p) + offset);
}

View File

@ -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<object>(o, offsetInWords * BytesPerWord));
return mask(cast<void*>(o, offsetInWords * BytesPerWord));
}
inline object*
getp(object o, unsigned offsetInWords)
inline void**
getp(void* o, unsigned offsetInWords)
{
return &cast<object>(o, offsetInWords * BytesPerWord);
return &cast<void*>(o, offsetInWords * BytesPerWord);
}
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>(*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<object>(o, 0);
return cast<void*>(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<object>(o, BytesPerWord);
return cast<void*>(o, BytesPerWord);
}
inline uintptr_t*
bitset(Context* c UNUSED, object o)
bitset(Context* c UNUSED, void* o)
{
assert(c, wasCollected(c, o));
return &cast<uintptr_t>(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<object>(o, 0) = r;
cast<void*>(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<object*>(map->segment->get(it.next()));
void** p = reinterpret_cast<void**>(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<void**>(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<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) {
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);

View File

@ -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;

View File

@ -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<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 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

View File

@ -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<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;
if (t->vm->heapPoolIndex < Machine::HeapPoolSize) {
t->heap = static_cast<object*>
t->heap = static_cast<uintptr_t*>
(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<object*>(instance) = class_;
memset(static_cast<object*>(instance) + 1, 0,
cast<object>(instance, 0) = class_;
memset(&cast<object>(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<object>(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<object>
(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<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)) {
++ 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<object>(m->heap->follow(mask(srcp)));
object class_ = static_cast<object>
(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<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) |= 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<object>(m->heap->follow(mask(p)));
object class_ = static_cast<object>(m->heap->follow(objectClass(t, o)));
object objectMask = static_cast<object>
(m->heap->follow(classObjectMask(t, class_)));
if (objectMask) {
// 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;
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<object>(t->vm->system->allocate(sizeInBytes));
}
inline object
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);
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<void**>(&target))) {
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
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)
{

View File

@ -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));

View File

@ -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<Scalar*>(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<uint8_t*>(o)");
out->write(">(reinterpret_cast<uint8_t*>(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*)));
}
}

View File

@ -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