mirror of
https://github.com/corda/corda.git
synced 2024-12-28 16:58:55 +00:00
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:
parent
a4b4f36c5b
commit
bd4d9fdeb2
2
makefile
2
makefile
@ -17,7 +17,7 @@ classpath = classpath
|
||||
test = test
|
||||
jscheme = $(HOME)/p/jscheme-7.2/src
|
||||
|
||||
input = $(cls)/References.class
|
||||
input = $(cls)/GC.class
|
||||
|
||||
cxx = g++
|
||||
cc = gcc
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
}
|
||||
|
103
src/heap.cpp
103
src/heap.cpp
@ -27,28 +27,28 @@ void assert(Context*, bool);
|
||||
|
||||
System* system(Context*);
|
||||
|
||||
inline object
|
||||
get(object o, unsigned offsetInWords)
|
||||
inline void*
|
||||
get(void* o, unsigned offsetInWords)
|
||||
{
|
||||
return mask(cast<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);
|
||||
|
@ -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;
|
||||
|
378
src/jnienv.cpp
378
src/jnienv.cpp
@ -5,7 +5,7 @@ using namespace vm;
|
||||
|
||||
namespace {
|
||||
|
||||
jsize
|
||||
jsize JNICALL
|
||||
GetStringUTFLength(Thread* t, jstring s)
|
||||
{
|
||||
ENTER(t, Thread::ActiveState);
|
||||
@ -13,7 +13,7 @@ GetStringUTFLength(Thread* t, jstring s)
|
||||
return stringLength(t, *s);
|
||||
}
|
||||
|
||||
const char*
|
||||
const char* JNICALL
|
||||
GetStringUTFChars(Thread* t, jstring s, jboolean* isCopy)
|
||||
{
|
||||
ENTER(t, Thread::ActiveState);
|
||||
@ -26,13 +26,13 @@ GetStringUTFChars(Thread* t, jstring s, jboolean* isCopy)
|
||||
return chars;
|
||||
}
|
||||
|
||||
void
|
||||
void JNICALL
|
||||
ReleaseStringUTFChars(Thread* t, jstring, const char* chars)
|
||||
{
|
||||
t->vm->system->free(chars);
|
||||
}
|
||||
|
||||
jstring
|
||||
jstring JNICALL
|
||||
NewStringUTF(Thread* t, const char* chars)
|
||||
{
|
||||
ENTER(t, Thread::ActiveState);
|
||||
@ -40,7 +40,7 @@ NewStringUTF(Thread* t, const char* chars)
|
||||
return pushReference(t, makeString(t, "%s", chars));
|
||||
}
|
||||
|
||||
void
|
||||
void JNICALL
|
||||
GetByteArrayRegion(Thread* t, jbyteArray array, jint offset, jint length,
|
||||
jbyte* dst)
|
||||
{
|
||||
@ -49,7 +49,7 @@ GetByteArrayRegion(Thread* t, jbyteArray array, jint offset, jint length,
|
||||
memcpy(dst, &byteArrayBody(t, *array, offset), length);
|
||||
}
|
||||
|
||||
void
|
||||
void JNICALL
|
||||
SetByteArrayRegion(Thread* t, jbyteArray array, jint offset, jint length,
|
||||
const jbyte* src)
|
||||
{
|
||||
@ -58,7 +58,7 @@ SetByteArrayRegion(Thread* t, jbyteArray array, jint offset, jint length,
|
||||
memcpy(&byteArrayBody(t, *array, offset), src, length);
|
||||
}
|
||||
|
||||
jclass
|
||||
jclass JNICALL
|
||||
FindClass(Thread* t, const char* name)
|
||||
{
|
||||
ENTER(t, Thread::ActiveState);
|
||||
@ -69,7 +69,7 @@ FindClass(Thread* t, const char* name)
|
||||
return pushReference(t, resolveClass(t, n));
|
||||
}
|
||||
|
||||
jint
|
||||
jint JNICALL
|
||||
ThrowNew(Thread* t, jclass c, const char* message)
|
||||
{
|
||||
if (t->exception) {
|
||||
@ -95,18 +95,336 @@ ThrowNew(Thread* t, jclass c, const char* message)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
void JNICALL
|
||||
DeleteLocalRef(Thread*, jobject)
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
jboolean
|
||||
jboolean JNICALL
|
||||
ExceptionCheck(Thread* t)
|
||||
{
|
||||
return t->exception != 0;
|
||||
}
|
||||
|
||||
jclass JNICALL
|
||||
GetObjectClass(Thread* t, jobject o)
|
||||
{
|
||||
return pushReference(t, objectClass(t, *o));
|
||||
}
|
||||
|
||||
jboolean JNICALL
|
||||
IsInstanceOf(Thread* t, jobject o, jclass c)
|
||||
{
|
||||
return instanceOf(t, *c, *o);
|
||||
}
|
||||
|
||||
object
|
||||
findMethod(Thread* t, object class_, const char* name, const char* spec)
|
||||
{
|
||||
object n = makeString(t, "%s", name);
|
||||
PROTECT(t, n);
|
||||
|
||||
object s = makeString(t, "%s", spec);
|
||||
return vm::findMethod(t, class_, n, s);
|
||||
}
|
||||
|
||||
// jmethodID JNICALL
|
||||
// GetMethodID(Thread* t, jclass c, const char* name, const char* spec)
|
||||
// {
|
||||
// object method = findMethod(t, *c, name, spec);
|
||||
// if (UNLIKELY(t->exception)) return 0;
|
||||
|
||||
// if (classFlags(t, *c) & ACC_INTERFACE) {
|
||||
// PROTECT(t, method);
|
||||
|
||||
// ACQUIRE(t, t->vm->referenceLock);
|
||||
|
||||
// for (unsigned i = 0; i < vectorSize(t, t->vm->jniInterfaceTable); ++i) {
|
||||
// if (method == vectorBody(t, t->vm->jniInterfaceTable, i)) {
|
||||
// return i;
|
||||
// }
|
||||
// }
|
||||
|
||||
// t->vm->jniInterfaceTable
|
||||
// = vectorAppend(t, t->vm->jniInterfaceTable, method);
|
||||
|
||||
// return (vectorSize(t, t->vm->jniInterfaceTable) - 1) | (1 << BitsPerWord);
|
||||
// } else {
|
||||
// return methodOffset(t, method);
|
||||
// }
|
||||
// }
|
||||
|
||||
// jmethodID JNICALL
|
||||
// GetStaticMethodID(Thread* t, jclass c, const char* name, const char* spec)
|
||||
// {
|
||||
// object method = findMethod(t, *c, name, spec);
|
||||
// if (UNLIKELY(t->exception)) return 0;
|
||||
|
||||
// return methodOffset(t, method);
|
||||
// }
|
||||
|
||||
object
|
||||
findField(Thread* t, object class_, const char* name, const char* spec)
|
||||
{
|
||||
object n = makeString(t, "%s", name);
|
||||
PROTECT(t, n);
|
||||
|
||||
object s = makeString(t, "%s", spec);
|
||||
return vm::findField(t, class_, n, s);
|
||||
}
|
||||
|
||||
jfieldID JNICALL
|
||||
GetFieldID(Thread* t, jclass c, const char* name, const char* spec)
|
||||
{
|
||||
object field = findField(t, *c, name, spec);
|
||||
if (UNLIKELY(t->exception)) return 0;
|
||||
|
||||
return fieldOffset(t, field);
|
||||
}
|
||||
|
||||
jfieldID JNICALL
|
||||
GetStaticFieldID(Thread* t, jclass c, const char* name, const char* spec)
|
||||
{
|
||||
object field = findField(t, *c, name, spec);
|
||||
if (UNLIKELY(t->exception)) return 0;
|
||||
|
||||
return fieldOffset(t, field);
|
||||
}
|
||||
|
||||
jobject JNICALL
|
||||
GetObjectField(Thread* t, jobject o, jfieldID field)
|
||||
{
|
||||
return pushReference(t, cast<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
|
||||
|
129
src/machine.cpp
129
src/machine.cpp
@ -138,7 +138,7 @@ visitRoots(Thread* t, Heap::Visitor* v)
|
||||
|
||||
for (unsigned i = 0; i < t->sp; ++i) {
|
||||
if (t->stack[i * 2] == ObjectTag) {
|
||||
v->visit(reinterpret_cast<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",
|
||||
|
@ -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)
|
||||
{
|
||||
|
66
src/run.cpp
66
src/run.cpp
@ -125,43 +125,6 @@ isSpecialMethod(Thread* t, object method, object class_)
|
||||
and isSuperclass(t, methodClass(t, method), class_);
|
||||
}
|
||||
|
||||
object
|
||||
find(Thread* t, object table, object reference,
|
||||
object& (*name)(Thread*, object),
|
||||
object& (*spec)(Thread*, object))
|
||||
{
|
||||
if (table) {
|
||||
object n = referenceName(t, reference);
|
||||
object s = referenceSpec(t, reference);
|
||||
for (unsigned i = 0; i < arrayLength(t, table); ++i) {
|
||||
object o = arrayBody(t, table, i);
|
||||
|
||||
if (strcmp(&byteArrayBody(t, name(t, o), 0),
|
||||
&byteArrayBody(t, n, 0)) == 0 and
|
||||
strcmp(&byteArrayBody(t, spec(t, o), 0),
|
||||
&byteArrayBody(t, s, 0)) == 0)
|
||||
{
|
||||
return o;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline object
|
||||
findFieldInClass(Thread* t, object class_, object reference)
|
||||
{
|
||||
return find(t, classFieldTable(t, class_), reference, fieldName, fieldSpec);
|
||||
}
|
||||
|
||||
inline object
|
||||
findMethodInClass(Thread* t, object class_, object reference)
|
||||
{
|
||||
return find(t, classMethodTable(t, class_), reference, methodName,
|
||||
methodSpec);
|
||||
}
|
||||
|
||||
inline object
|
||||
resolveClass(Thread* t, object pool, unsigned index)
|
||||
{
|
||||
@ -196,7 +159,7 @@ resolveClass(Thread* t, object container, object& (*class_)(Thread*, object))
|
||||
|
||||
inline object
|
||||
resolve(Thread* t, object pool, unsigned index,
|
||||
object (*find)(Thread*, object, object),
|
||||
object (*find)(Thread*, object, object, object),
|
||||
object (*makeError)(Thread*, object))
|
||||
{
|
||||
object o = arrayBody(t, pool, index);
|
||||
@ -210,26 +173,10 @@ resolve(Thread* t, object pool, unsigned index,
|
||||
object class_ = resolveClass(t, o, referenceClass);
|
||||
if (UNLIKELY(t->exception)) return 0;
|
||||
|
||||
o = 0;
|
||||
if (classFlags(t, class_) & ACC_INTERFACE) {
|
||||
if (classVirtualTable(t, class_)) {
|
||||
o = ::find(t, classVirtualTable(t, class_), arrayBody(t, pool, index),
|
||||
methodName, methodSpec);
|
||||
}
|
||||
} else {
|
||||
for (; o == 0 and class_; class_ = classSuper(t, class_)) {
|
||||
o = find(t, class_, arrayBody(t, pool, index));
|
||||
}
|
||||
}
|
||||
|
||||
if (o == 0) {
|
||||
object message = makeString
|
||||
(t, "%s %s not found in %s",
|
||||
&byteArrayBody(t, referenceName(t, reference), 0),
|
||||
&byteArrayBody(t, referenceSpec(t, reference), 0),
|
||||
&byteArrayBody(t, className(t, referenceClass(t, reference)), 0));
|
||||
t->exception = makeError(t, message);
|
||||
}
|
||||
o = findInHierarchy
|
||||
(t, class_, referenceName(t, reference), referenceSpec(t, reference),
|
||||
find, makeError);
|
||||
if (UNLIKELY(t->exception)) return 0;
|
||||
|
||||
set(t, arrayBody(t, pool, index), o);
|
||||
}
|
||||
@ -2769,7 +2716,8 @@ run(Thread* t, const char* className, const char* methodName,
|
||||
object spec = makeByteArray(t, methodSpec);
|
||||
object reference = makeReference(t, class_, name, spec);
|
||||
|
||||
object method = findMethodInClass(t, class_, reference);
|
||||
object method = findMethodInClass(t, class_, referenceName(t, reference),
|
||||
referenceSpec(t, reference));
|
||||
if (LIKELY(t->exception == 0)) {
|
||||
assert(t, ((methodFlags(t, method) & ACC_STATIC) == 0) xor (this_ == 0));
|
||||
|
||||
|
@ -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*)));
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user