progress towards thread support

This includes support for using the least significant bits of the class
pointer to indicate object state, which we'll use to indicate the
presence of a monitor pointer, among other things.
This commit is contained in:
Joel Dice 2007-07-01 15:34:22 -06:00
parent 051e3bc7a8
commit 38cea04322
9 changed files with 282 additions and 103 deletions

View File

@ -5,7 +5,9 @@ public class TestExceptions {
} }
private static void moreDangerous() { private static void moreDangerous() {
// synchronized (TestExceptions.class) {
evenMoreDangerous(); evenMoreDangerous();
// }
} }
private static void dangerous() { private static void dangerous() {

View File

@ -1,4 +1,4 @@
public class Test { public class TestGC {
private static void small() { private static void small() {
for (int i = 0; i < 1024; ++i) { for (int i = 0; i < 1024; ++i) {

View File

@ -127,7 +127,7 @@ fast-cflags = $(fast) $(cflags)
classpath-sources = $(shell find $(classpath)/java -name '*.java') classpath-sources = $(shell find $(classpath)/java -name '*.java')
classpath-classes = $(call java-classes,$(classpath-sources),$(classpath)) classpath-classes = $(call java-classes,$(classpath-sources),$(classpath))
input = $(bld)/classes/TestExceptions.class input = $(bld)/classes/Test.class
input-depends = \ input-depends = \
$(classpath-classes) \ $(classpath-classes) \
$(jni-library) $(jni-library)

View File

@ -26,6 +26,9 @@ 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;
const uintptr_t PointerMask
= ((~static_cast<uintptr_t>(0)) / BytesPerWord) * BytesPerWord;
const unsigned LikelyPageSizeInBytes = 4 * 1024; const unsigned LikelyPageSizeInBytes = 4 * 1024;
inline unsigned inline unsigned
@ -109,6 +112,13 @@ cast(object p, unsigned offset)
return *reinterpret_cast<T*>(static_cast<uint8_t*>(p) + offset); return *reinterpret_cast<T*>(static_cast<uint8_t*>(p) + offset);
} }
template <class T>
inline T*
mask(T* p)
{
return reinterpret_cast<T*>(reinterpret_cast<uintptr_t>(p) & PointerMask);
}
} }
#endif//COMMON_H #endif//COMMON_H

View File

@ -26,6 +26,32 @@ System* system(Context*);
void NO_RETURN abort(Context*); void NO_RETURN abort(Context*);
void assert(Context*, bool); void assert(Context*, bool);
inline object
get(object o, unsigned offsetInWords)
{
return mask(cast<object>(o, offsetInWords * BytesPerWord));
}
inline object*
getp(object o, unsigned offsetInWords)
{
return &cast<object>(o, offsetInWords * BytesPerWord);
}
inline void
set(object* o, object value)
{
*o = reinterpret_cast<object>
(reinterpret_cast<uintptr_t>(value)
| reinterpret_cast<uintptr_t>(*o) & (~PointerMask));
}
inline void
set(object o, unsigned offsetInWords, object value)
{
set(getp(o, offsetInWords), value);
}
class Segment { class Segment {
public: public:
class Map { class Map {
@ -662,7 +688,7 @@ fresh(Context* c, object o)
inline bool inline bool
wasCollected(Context* c, object o) wasCollected(Context* c, object o)
{ {
return o and (not fresh(c, o)) and fresh(c, cast<object>(o, 0)); return o and (not fresh(c, o)) and fresh(c, get(o, 0));
} }
inline object inline object
@ -779,55 +805,55 @@ copy(Context* c, object o)
} }
object object
update3(Context* c, object* p, bool* needsVisit) update3(Context* c, object o, bool* needsVisit)
{ {
if (wasCollected(c, *p)) { if (wasCollected(c, o)) {
*needsVisit = false; *needsVisit = false;
return follow(c, *p); return follow(c, o);
} else { } else {
*needsVisit = true; *needsVisit = true;
return copy(c, *p); return copy(c, o);
} }
} }
object object
update2(Context* c, object* p, bool* needsVisit) update2(Context* c, object o, bool* needsVisit)
{ {
switch (c->mode) { switch (c->mode) {
case MinorCollection: case MinorCollection:
case OverflowCollection: case OverflowCollection:
if (c->gen2.contains(*p)) { if (c->gen2.contains(o)) {
*needsVisit = false; *needsVisit = false;
return *p; return o;
} }
break; break;
case Gen2Collection: case Gen2Collection:
if (c->gen2.contains(*p)) { if (c->gen2.contains(o)) {
return update3(c, p, needsVisit); return update3(c, o, needsVisit);
} else { } else {
assert(c, c->nextGen1.contains(*p) or c->nextGen2.contains(*p)); assert(c, c->nextGen1.contains(o) or c->nextGen2.contains(o));
*needsVisit = false; *needsVisit = false;
return *p; return o;
} }
break; break;
default: break; default: break;
} }
return update3(c, p, needsVisit); return update3(c, o, needsVisit);
} }
object object
update(Context* c, object* p, bool* needsVisit) update(Context* c, object* p, bool* needsVisit)
{ {
if (*p == 0) { if (mask(*p) == 0) {
*needsVisit = false; *needsVisit = false;
return *p; return 0;
} }
object r = update2(c, p, needsVisit); object r = update2(c, mask(*p), needsVisit);
// update heap map. // update heap map.
if (r) { if (r) {
@ -956,22 +982,22 @@ bitsetNext(Context* c, uintptr_t* p)
} }
void void
collect(Context* c, void** p) collect(Context* c, object* p)
{ {
object original = *p; object original = mask(*p);
object parent = 0; object parent = 0;
if (Debug) { if (Debug) {
fprintf(stderr, "update %p (%s) at %p (%s)\n", fprintf(stderr, "update %p (%s) at %p (%s)\n",
*p, segment(c, *p), p, segment(c, p)); mask(*p), segment(c, *p), p, segment(c, p));
} }
bool needsVisit; bool needsVisit;
*p = update(c, p, &needsVisit); set(p, update(c, mask(p), &needsVisit));
if (Debug) { if (Debug) {
fprintf(stderr, " result: %p (%s) (visit? %d)\n", fprintf(stderr, " result: %p (%s) (visit? %d)\n",
*p, segment(c, *p), needsVisit); mask(*p), segment(c, *p), needsVisit);
} }
if (not needsVisit) return; if (not needsVisit) return;
@ -995,17 +1021,16 @@ collect(Context* c, void** p)
virtual bool visit(unsigned offset) { virtual bool visit(unsigned offset) {
if (Debug) { if (Debug) {
fprintf(stderr, " update %p (%s) at %p - offset %d from %p (%s)\n", fprintf(stderr, " update %p (%s) at %p - offset %d from %p (%s)\n",
cast<object>(copy, offset * BytesPerWord), get(copy, offset),
segment(c, cast<object>(copy, offset * BytesPerWord)), segment(c, get(copy, offset)),
&cast<object>(copy, offset * BytesPerWord), getp(copy, offset),
offset, offset,
copy, copy,
segment(c, copy)); segment(c, copy));
} }
bool needsVisit; bool needsVisit;
object childCopy = update object childCopy = update(c, getp(copy, offset), &needsVisit);
(c, &cast<object>(copy, offset * BytesPerWord), &needsVisit);
if (Debug) { if (Debug) {
fprintf(stderr, " result: %p (%s) (visit? %d)\n", fprintf(stderr, " result: %p (%s) (visit? %d)\n",
@ -1027,7 +1052,7 @@ collect(Context* c, void** p)
second = offset; second = offset;
} }
} else { } else {
cast<object>(copy, offset * BytesPerWord) = childCopy; set(copy, offset, childCopy);
} }
if (visits > 1 and total > 2 and (second or needsVisit)) { if (visits > 1 and total > 2 and (second or needsVisit)) {
@ -1070,8 +1095,8 @@ collect(Context* c, void** p)
parent = original; parent = original;
} }
original = cast<object>(copy, walker.first * BytesPerWord); original = get(copy, walker.first);
cast<object>(copy, walker.first * BytesPerWord) = follow(c, original); set(copy, walker.first, follow(c, original));
goto visit; goto visit;
} else { } else {
// ascend // ascend
@ -1131,16 +1156,16 @@ collect(Context* c, void** p)
if (Debug) { if (Debug) {
fprintf(stderr, " next is %p (%s) at %p - offset %d from %p (%s)\n", fprintf(stderr, " next is %p (%s) at %p - offset %d from %p (%s)\n",
cast<object>(copy, walker.next * BytesPerWord), get(copy, walker.next),
segment(c, cast<object>(copy, walker.next * BytesPerWord)), segment(c, get(copy, walker.next)),
&cast<object>(copy, walker.next * BytesPerWord), getp(copy, walker.next),
walker.next, walker.next,
copy, copy,
segment(c, copy)); segment(c, copy));
} }
original = cast<object>(copy, walker.next * BytesPerWord); original = get(copy, walker.next);
cast<object>(copy, walker.next * BytesPerWord) = follow(c, original); set(copy, walker.next, follow(c, original));
goto visit; goto visit;
} else { } else {
return; return;
@ -1236,7 +1261,7 @@ collect(Context* c, Segment* s, unsigned limit)
Walker(Context* c, object p): c(c), p(p) { } Walker(Context* c, object p): c(c), p(p) { }
virtual bool visit(unsigned offset) { virtual bool visit(unsigned offset) {
collect(c, &cast<object>(p, offset * BytesPerWord)); collect(c, getp(p, offset));
return true; return true;
} }

View File

@ -1,8 +1,12 @@
#include "sys/mman.h" #include "sys/mman.h"
#include "sys/types.h" #include "sys/types.h"
#include "sys/stat.h" #include "sys/stat.h"
#include <sys/time.h>
#include <time.h>
#include "fcntl.h" #include "fcntl.h"
#include "dlfcn.h" #include "dlfcn.h"
#include "errno.h"
#include "pthread.h"
#include "common.h" #include "common.h"
#include "system.h" #include "system.h"
#include "heap.h" #include "heap.h"
@ -86,6 +90,22 @@ dynamicCall(void* function, uint64_t* arguments, uint8_t* argumentTypes,
namespace { namespace {
void*
run(void* t)
{
static_cast<vm::System::Thread*>(t)->run();
return 0;
}
int64_t
now()
{
timeval tv = { 0, 0 };
gettimeofday(&tv, 0);
return (static_cast<int64_t>(tv.tv_sec) * 1000) +
(static_cast<int64_t>(tv.tv_usec) / 1000);
}
const char* const char*
append(vm::System* s, const char* a, const char* b, const char* c, append(vm::System* s, const char* a, const char* b, const char* c,
const char* d) const char* d)
@ -108,17 +128,95 @@ class System: public vm::System {
public: public:
class Monitor: public vm::System::Monitor { class Monitor: public vm::System::Monitor {
public: public:
Monitor(vm::System* s): s(s) { } Monitor(vm::System* s): s(s), context(0), depth(0) {
pthread_mutex_init(&mutex, 0);
pthread_cond_init(&condition, 0);
}
virtual bool tryAcquire(void*) { return true; } virtual bool tryAcquire(void* context) {
virtual void acquire(void*) { } if (this->context == context) {
virtual void release(void*) { } ++ depth;
virtual void wait(void*) { } return true;
virtual void notify(void*) { } } else {
virtual void notifyAll(void*) { } switch (pthread_mutex_trylock(&mutex)) {
virtual void dispose() { s->free(this); } case EBUSY:
return false;
case 0:
this->context = context;
++ depth;
return true;
default:
vm::abort(s);
}
}
}
virtual void acquire(void* context) {
if (this->context != context) {
pthread_mutex_lock(&mutex);
this->context = context;
}
++ depth;
}
virtual void release(void* context) {
if (this->context == context) {
if (-- depth == 0) {
this->context = 0;
pthread_mutex_unlock(&mutex);
}
} else {
vm::abort(s);
}
}
virtual void wait(void* context, int64_t time) {
if (this->context == context) {
if (time) {
int64_t then = now() + time;
timespec ts = { then / 1000, (then % 1000) * 1000 * 1000 };
int rv = pthread_cond_timedwait(&condition, &mutex, &ts);
assert(s, rv == 0);
} else {
int rv = pthread_cond_wait(&condition, &mutex);
assert(s, rv == 0);
}
} else {
vm::abort(s);
}
}
virtual void notify(void* context) {
if (this->context == context) {
int rv = pthread_cond_signal(&condition);
assert(s, rv == 0);
} else {
vm::abort(s);
}
}
virtual void notifyAll(void* context) {
if (this->context == context) {
int rv = pthread_cond_broadcast(&condition);
assert(s, rv == 0);
} else {
vm::abort(s);
}
}
virtual void dispose() {
pthread_mutex_destroy(&mutex);
pthread_cond_destroy(&condition);
s->free(this);
}
vm::System* s; vm::System* s;
pthread_mutex_t mutex;
pthread_cond_t condition;
void* context;
unsigned depth;
}; };
class Library: public vm::System::Library { class Library: public vm::System::Library {
@ -149,14 +247,20 @@ class System: public vm::System {
vm::System::Library* next_; vm::System::Library* next_;
}; };
System(unsigned limit): limit(limit), count(0) { } System(unsigned limit): limit(limit), count(0) {
pthread_mutex_init(&mutex, 0);
}
~System() {
pthread_mutex_destroy(&mutex);
}
virtual bool success(Status s) { virtual bool success(Status s) {
return s == 0; return s == 0;
} }
virtual void* tryAllocate(unsigned size) { virtual void* tryAllocate(unsigned size) {
// todo: synchronize access pthread_mutex_lock(&mutex);
if (Verbose) { if (Verbose) {
fprintf(stderr, "try %d; count: %d; limit: %d\n", fprintf(stderr, "try %d; count: %d; limit: %d\n",
@ -164,20 +268,26 @@ class System: public vm::System {
} }
if (count + size > limit) { if (count + size > limit) {
pthread_mutex_unlock(&mutex);
return 0; return 0;
} } else {
uintptr_t* up = static_cast<uintptr_t*>
uintptr_t* up = static_cast<uintptr_t*>(malloc(size + sizeof(uintptr_t))); (malloc(size + sizeof(uintptr_t)));
if (up == 0) abort(); if (up == 0) {
pthread_mutex_unlock(&mutex);
vm::abort(this);
} else {
*up = size; *up = size;
count += *up; count += *up;
pthread_mutex_unlock(&mutex);
return up + 1; return up + 1;
} }
}
}
virtual void free(const void* p) { virtual void free(const void* p) {
// todo: synchronize access pthread_mutex_lock(&mutex);
if (p) { if (p) {
const uintptr_t* up = static_cast<const uintptr_t*>(p) - 1; const uintptr_t* up = static_cast<const uintptr_t*>(p) - 1;
@ -193,10 +303,15 @@ class System: public vm::System {
::free(const_cast<uintptr_t*>(up)); ::free(const_cast<uintptr_t*>(up));
} }
pthread_mutex_unlock(&mutex);
} }
virtual Status start(Thread*) { virtual Status start(Thread* t) {
return 1; pthread_t thread;
int rv = pthread_create(&thread, 0, run, t);
assert(this, rv == 0);
return 0;
} }
virtual Status make(vm::System::Monitor** m) { virtual Status make(vm::System::Monitor** m) {
@ -232,6 +347,7 @@ class System: public vm::System {
::abort(); ::abort();
} }
pthread_mutex_t mutex;
unsigned limit; unsigned limit;
unsigned count; unsigned count;
}; };

View File

@ -21,7 +21,7 @@ class System {
virtual bool tryAcquire(void* id) = 0; virtual bool tryAcquire(void* id) = 0;
virtual void acquire(void* id) = 0; virtual void acquire(void* id) = 0;
virtual void release(void* id) = 0; virtual void release(void* id) = 0;
virtual void wait(void* id) = 0; virtual void wait(void* id, int64_t time) = 0;
virtual void notify(void* id) = 0; virtual void notify(void* id) = 0;
virtual void notifyAll(void* id) = 0; virtual void notifyAll(void* id) = 0;
virtual void dispose() = 0; virtual void dispose() = 0;

View File

@ -995,7 +995,7 @@ writeSubtypeAssertions(Output* out, Object* o)
{ {
for (Object* p = typeSubtypes(o); p; p = cdr(p)) { for (Object* p = typeSubtypes(o); p; p = cdr(p)) {
Object* st = car(p); Object* st = car(p);
out->write(" or objectClass(o) == arrayBodyUnsafe"); out->write(" or objectClass(t, o) == arrayBodyUnsafe");
out->write("(t, t->vm->types, Machine::"); out->write("(t, t->vm->types, Machine::");
out->write(capitalize(typeName(st))); out->write(capitalize(typeName(st)));
out->write("Type)"); out->write("Type)");
@ -1035,8 +1035,8 @@ writeAccessor(Output* out, Object* member, Object* offset, bool unsafe = false)
if (unsafe) { if (unsafe) {
out->write(" assert(t, true);"); out->write(" assert(t, true);");
} else { } else {
out->write(" assert(t, t->vm->unsafe or objectClass(o) == 0 or "); out->write(" assert(t, t->vm->unsafe or ");
out->write("objectClass(o) == arrayBodyUnsafe"); out->write("objectClass(t, o) == arrayBodyUnsafe");
out->write("(t, t->vm->types, Machine::"); out->write("(t, t->vm->types, Machine::");
out->write(capitalize(::typeName(memberOwner(member)))); out->write(capitalize(::typeName(memberOwner(member))));
out->write("Type)"); out->write("Type)");
@ -1320,7 +1320,8 @@ writeConstructors(Output* out, Object* declarations)
writeOffset(out, typeOffset(o), true); writeOffset(out, typeOffset(o), true);
out->write(");\n"); out->write(");\n");
out->write(" objectClass(o) = arrayBody(t, t->vm->types, Machine::"); out->write(" cast<object>(o, 0) ");
out->write("= arrayBody(t, t->vm->types, Machine::");
out->write(capitalize(typeName(o))); out->write(capitalize(typeName(o)));
out->write("Type);\n"); out->write("Type);\n");
@ -1538,7 +1539,7 @@ writeInitializations(Output* out, Object* declarations)
out->write("t->vm->types = allocate(t, pad(("); out->write("t->vm->types = allocate(t, pad((");
out->write(count); out->write(count);
out->write(" * sizeof(void*)) + 4 + sizeof(void*)));\n"); out->write(" * sizeof(void*)) + 4 + sizeof(void*)));\n");
out->write("objectClass(t->vm->types) = 0;\n"); out->write("cast<object>(t->vm->types, 0) = 0;\n");
out->write("arrayLength(t, t->vm->types) = "); out->write("arrayLength(t, t->vm->types) = ");
out->write(count); out->write(count);
out->write(";\n"); out->write(";\n");

View File

@ -33,12 +33,6 @@ void set(Thread*, object&, object);
object makeString(Thread*, const char*, ...); object makeString(Thread*, const char*, ...);
object makeByteArray(Thread*, const char*, ...); object makeByteArray(Thread*, const char*, ...);
object&
objectClass(object o)
{
return cast<object>(o, 0);
}
enum FieldCode { enum FieldCode {
VoidField, VoidField,
ByteField, ByteField,
@ -163,6 +157,12 @@ class Thread : public JNIEnv {
object heap[HeapSizeInWords]; object heap[HeapSizeInWords];
}; };
inline object
objectClass(Thread*, object o)
{
return mask(cast<object>(o, 0));
}
#include "type-declarations.cpp" #include "type-declarations.cpp"
#include "type-constructors.cpp" #include "type-constructors.cpp"
@ -489,8 +489,8 @@ collect(Machine* m, Heap::CollectionType type)
virtual unsigned sizeInWords(void* p) { virtual unsigned sizeInWords(void* p) {
Thread* t = m->rootThread; Thread* t = m->rootThread;
p = m->heap->follow(p); p = m->heap->follow(mask(p));
object class_ = m->heap->follow(objectClass(p)); object class_ = m->heap->follow(objectClass(t, p));
unsigned n = divide(classFixedSize(t, class_), BytesPerWord); unsigned n = divide(classFixedSize(t, class_), BytesPerWord);
@ -505,8 +505,8 @@ collect(Machine* m, Heap::CollectionType type)
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(p); p = m->heap->follow(mask(p));
object class_ = m->heap->follow(objectClass(p)); object class_ = m->heap->follow(objectClass(t, p));
object objectMask = m->heap->follow(classObjectMask(t, class_)); object objectMask = m->heap->follow(classObjectMask(t, class_));
if (objectMask) { if (objectMask) {
@ -599,7 +599,7 @@ enter(Thread* t, Thread::State s)
t->vm->exclusive = t; t->vm->exclusive = t;
while (t->vm->activeCount > 1) { while (t->vm->activeCount > 1) {
t->vm->stateLock->wait(t); t->vm->stateLock->wait(t, 0);
} }
} break; } break;
@ -639,7 +639,7 @@ enter(Thread* t, Thread::State s)
case Thread::NoState: case Thread::NoState:
case Thread::IdleState: { case Thread::IdleState: {
while (t->vm->exclusive) { while (t->vm->exclusive) {
t->vm->stateLock->wait(t); t->vm->stateLock->wait(t, 0);
} }
++ t->vm->activeCount; ++ t->vm->activeCount;
@ -669,7 +669,7 @@ enter(Thread* t, Thread::State s)
t->state = s; t->state = s;
while (t->vm->liveCount > 1) { while (t->vm->liveCount > 1) {
t->vm->stateLock->wait(t); t->vm->stateLock->wait(t, 0);
} }
} break; } break;
@ -762,7 +762,7 @@ make(Thread* t, object class_)
unsigned unsigned
objectSize(Thread* t, object o) objectSize(Thread* t, object o)
{ {
object class_ = objectClass(o); object class_ = objectClass(t, o);
unsigned n = divide(classFixedSize(t, class_), BytesPerWord); unsigned n = divide(classFixedSize(t, class_), BytesPerWord);
@ -921,8 +921,8 @@ makeUnsatisfiedLinkError(Thread* t, object message)
inline bool inline bool
isLongOrDouble(Thread* t, object o) isLongOrDouble(Thread* t, object o)
{ {
return objectClass(o) == arrayBody(t, t->vm->types, Machine::LongType) return objectClass(t, o) == arrayBody(t, t->vm->types, Machine::LongType)
or objectClass(o) == arrayBody(t, t->vm->types, Machine::DoubleType); or objectClass(t, o) == arrayBody(t, t->vm->types, Machine::DoubleType);
} }
unsigned unsigned
@ -1139,10 +1139,10 @@ instanceOf(Thread* t, object class_, object o)
return false; return false;
} }
if (objectClass(class_) if (objectClass(t, class_)
== arrayBody(t, t->vm->types, Machine::InterfaceType)) == arrayBody(t, t->vm->types, Machine::InterfaceType))
{ {
for (object oc = objectClass(o); oc; oc = classSuper(t, oc)) { for (object oc = objectClass(t, o); oc; oc = classSuper(t, oc)) {
object itable = classInterfaceTable(t, oc); object itable = classInterfaceTable(t, oc);
for (unsigned i = 0; i < arrayLength(t, itable); i += 2) { for (unsigned i = 0; i < arrayLength(t, itable); i += 2) {
if (arrayBody(t, itable, i) == class_) { if (arrayBody(t, itable, i) == class_) {
@ -1151,7 +1151,7 @@ instanceOf(Thread* t, object class_, object o)
} }
} }
} else { } else {
for (object oc = objectClass(o); oc; oc = classSuper(t, oc)) { for (object oc = objectClass(t, o); oc; oc = classSuper(t, oc)) {
if (oc == class_) { if (oc == class_) {
return true; return true;
} }
@ -1165,7 +1165,7 @@ object
findInterfaceMethod(Thread* t, object method, object o) findInterfaceMethod(Thread* t, object method, object o)
{ {
object interface = methodClass(t, method); object interface = methodClass(t, method);
object itable = classInterfaceTable(t, objectClass(o)); object itable = classInterfaceTable(t, objectClass(t, o));
for (unsigned i = 0; i < arrayLength(t, itable); i += 2) { for (unsigned i = 0; i < arrayLength(t, itable); i += 2) {
if (arrayBody(t, itable, i) == interface) { if (arrayBody(t, itable, i) == interface) {
return arrayBody(t, arrayBody(t, itable, i + 1), return arrayBody(t, arrayBody(t, itable, i + 1),
@ -1185,7 +1185,7 @@ findMethod(Thread* t, object method, object class_)
inline object inline object
findVirtualMethod(Thread* t, object method, object o) findVirtualMethod(Thread* t, object method, object o)
{ {
return findMethod(t, method, objectClass(o)); return findMethod(t, method, objectClass(t, o));
} }
bool bool
@ -1336,7 +1336,8 @@ parsePool(Thread* t, Stream& s)
for (unsigned i = 0; i < poolCount; ++i) { for (unsigned i = 0; i < poolCount; ++i) {
object o = arrayBody(t, pool, i); object o = arrayBody(t, pool, i);
if (objectClass(o) == arrayBody(t, t->vm->types, Machine::IntArrayType)) { if (objectClass(t, o) == arrayBody(t, t->vm->types, Machine::IntArrayType))
{
switch (intArrayBody(t, o, 0)) { switch (intArrayBody(t, o, 0)) {
case CONSTANT_Class: { case CONSTANT_Class: {
set(t, arrayBody(t, pool, i), set(t, arrayBody(t, pool, i),
@ -1361,7 +1362,8 @@ parsePool(Thread* t, Stream& s)
for (unsigned i = 0; i < poolCount; ++i) { for (unsigned i = 0; i < poolCount; ++i) {
object o = arrayBody(t, pool, i); object o = arrayBody(t, pool, i);
if (objectClass(o) == arrayBody(t, t->vm->types, Machine::IntArrayType)) { if (objectClass(t, o) == arrayBody(t, t->vm->types, Machine::IntArrayType))
{
switch (intArrayBody(t, o, 0)) { switch (intArrayBody(t, o, 0)) {
case CONSTANT_Fieldref: case CONSTANT_Fieldref:
case CONSTANT_Methodref: case CONSTANT_Methodref:
@ -2064,7 +2066,8 @@ inline object
resolveClass(Thread* t, object pool, unsigned index) resolveClass(Thread* t, object pool, unsigned index)
{ {
object o = arrayBody(t, pool, index); object o = arrayBody(t, pool, index);
if (objectClass(o) == arrayBody(t, t->vm->types, Machine::ByteArrayType)) { if (objectClass(t, o) == arrayBody(t, t->vm->types, Machine::ByteArrayType))
{
PROTECT(t, pool); PROTECT(t, pool);
o = resolveClass(t, o); o = resolveClass(t, o);
@ -2079,7 +2082,8 @@ inline object
resolveClass(Thread* t, object container, object& (*class_)(Thread*, object)) resolveClass(Thread* t, object container, object& (*class_)(Thread*, object))
{ {
object o = class_(t, container); object o = class_(t, container);
if (objectClass(o) == arrayBody(t, t->vm->types, Machine::ByteArrayType)) { if (objectClass(t, o) == arrayBody(t, t->vm->types, Machine::ByteArrayType))
{
PROTECT(t, container); PROTECT(t, container);
o = resolveClass(t, o); o = resolveClass(t, o);
@ -2095,7 +2099,8 @@ resolve(Thread* t, object pool, unsigned index,
object (*find)(Thread*, object, object)) object (*find)(Thread*, object, object))
{ {
object o = arrayBody(t, pool, index); object o = arrayBody(t, pool, index);
if (objectClass(o) == arrayBody(t, t->vm->types, Machine::ReferenceType)) { if (objectClass(t, o) == arrayBody(t, t->vm->types, Machine::ReferenceType))
{
PROTECT(t, pool); PROTECT(t, pool);
object class_ = resolveClass(t, o, referenceClass); object class_ = resolveClass(t, o, referenceClass);
@ -2179,7 +2184,7 @@ makeNativeMethodData(Thread* t, object method, void* function, bool builtin)
inline object inline object
resolveNativeMethodData(Thread* t, object method) resolveNativeMethodData(Thread* t, object method)
{ {
if (objectClass(methodCode(t, method)) if (objectClass(t, methodCode(t, method))
== arrayBody(t, t->vm->types, Machine::ByteArrayType)) == arrayBody(t, t->vm->types, Machine::ByteArrayType))
{ {
object data = 0; object data = 0;
@ -2333,7 +2338,7 @@ toString(JNIEnv* e, jobject this_)
object s = makeString object s = makeString
(t, "%s@%p", (t, "%s@%p",
&byteArrayBody(t, className(t, objectClass(*this_)), 0), &byteArrayBody(t, className(t, objectClass(t, *this_)), 0),
*this_); *this_);
pushSafe(t, s); pushSafe(t, s);
@ -2493,13 +2498,13 @@ Thread::Thread(Machine* m):
#include "type-initializations.cpp" #include "type-initializations.cpp"
object arrayClass = arrayBody(t, t->vm->types, Machine::ArrayType); object arrayClass = arrayBody(t, t->vm->types, Machine::ArrayType);
set(t, objectClass(t->vm->types), arrayClass); set(t, cast<object>(t->vm->types, 0), arrayClass);
object classClass = arrayBody(t, m->types, Machine::ClassType); object classClass = arrayBody(t, m->types, Machine::ClassType);
set(t, objectClass(classClass), classClass); set(t, cast<object>(classClass, 0), classClass);
object intArrayClass = arrayBody(t, m->types, Machine::IntArrayType); object intArrayClass = arrayBody(t, m->types, Machine::IntArrayType);
set(t, objectClass(intArrayClass), classClass); set(t, cast<object>(intArrayClass, 0), classClass);
m->unsafe = false; m->unsafe = false;
@ -2668,7 +2673,7 @@ run(Thread* t)
case arraylength: { case arraylength: {
object array = pop(t); object array = pop(t);
if (LIKELY(array)) { if (LIKELY(array)) {
if (objectClass(array) if (objectClass(t, array)
== arrayBody(t, t->vm->types, Machine::ObjectArrayType)) == arrayBody(t, t->vm->types, Machine::ObjectArrayType))
{ {
push(t, makeInt(t, objectArrayLength(t, array))); push(t, makeInt(t, objectArrayLength(t, array)));
@ -2832,7 +2837,7 @@ run(Thread* t)
if (not instanceOf(t, class_, stack[sp - 1])) { if (not instanceOf(t, class_, stack[sp - 1])) {
object message = makeString object message = makeString
(t, "%s as %s", (t, "%s as %s",
&byteArrayBody(t, className(t, objectClass(stack[sp - 1])), 0), &byteArrayBody(t, className(t, objectClass(t, stack[sp - 1])), 0),
&byteArrayBody(t, className(t, class_), 0)); &byteArrayBody(t, className(t, class_), 0));
exception = makeClassCastException(t, message); exception = makeClassCastException(t, message);
goto throw_; goto throw_;
@ -3639,6 +3644,26 @@ run(Thread* t)
push(t, makeLong(t, longValue(t, a) ^ longValue(t, b))); push(t, makeLong(t, longValue(t, a) ^ longValue(t, b)));
} goto loop; } goto loop;
// case monitorenter: {
// object o = pop(t);
// if (LIKELY(o)) {
// objectMonitor(t, o)->acquire(t);
// } else {
// exception = makeNullPointerException(t);
// goto throw_;
// }
// } goto loop;
// case monitorexit: {
// object o = pop(t);
// if (LIKELY(o)) {
// objectMonitor(t, o)->release(t);
// } else {
// exception = makeNullPointerException(t);
// goto throw_;
// }
// } goto loop;
case new_: { case new_: {
uint8_t index1 = codeBody(t, code, ip++); uint8_t index1 = codeBody(t, code, ip++);
uint8_t index2 = codeBody(t, code, ip++); uint8_t index2 = codeBody(t, code, ip++);
@ -3948,7 +3973,7 @@ run(Thread* t)
arrayBody(t, codePool(t, code), exceptionHandlerCatchType(eh) - 1); arrayBody(t, codePool(t, code), exceptionHandlerCatchType(eh) - 1);
if (catchType == 0 or if (catchType == 0 or
(objectClass(catchType) (objectClass(t, catchType)
== arrayBody(t, t->vm->types, Machine::ClassType) and == arrayBody(t, t->vm->types, Machine::ClassType) and
instanceOf(t, catchType, exception))) instanceOf(t, catchType, exception)))
{ {
@ -3970,7 +3995,7 @@ run(Thread* t)
} }
fprintf(stderr, "%s", &byteArrayBody fprintf(stderr, "%s", &byteArrayBody
(t, className(t, objectClass(exception)), 0)); (t, className(t, objectClass(t, exception)), 0));
if (throwableMessage(t, exception)) { if (throwableMessage(t, exception)) {
object m = throwableMessage(t, exception); object m = throwableMessage(t, exception);
@ -4001,10 +4026,10 @@ run(Thread* t)
fprintf(stderr, "(native)\n"); fprintf(stderr, "(native)\n");
break; break;
case UnknownLine: case UnknownLine:
fprintf(stderr, "(unknown)\n"); fprintf(stderr, "(unknown line)\n");
break; break;
default: default:
fprintf(stderr, "(%d)\n", line); fprintf(stderr, "(line %d)\n", line);
} }
} }
} }