mirror of
https://github.com/corda/corda.git
synced 2025-01-14 16:59:52 +00:00
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:
parent
051e3bc7a8
commit
38cea04322
@ -5,7 +5,9 @@ public class TestExceptions {
|
||||
}
|
||||
|
||||
private static void moreDangerous() {
|
||||
evenMoreDangerous();
|
||||
// synchronized (TestExceptions.class) {
|
||||
evenMoreDangerous();
|
||||
// }
|
||||
}
|
||||
|
||||
private static void dangerous() {
|
||||
|
@ -1,4 +1,4 @@
|
||||
public class Test {
|
||||
public class TestGC {
|
||||
|
||||
private static void small() {
|
||||
for (int i = 0; i < 1024; ++i) {
|
2
makefile
2
makefile
@ -127,7 +127,7 @@ fast-cflags = $(fast) $(cflags)
|
||||
classpath-sources = $(shell find $(classpath)/java -name '*.java')
|
||||
classpath-classes = $(call java-classes,$(classpath-sources),$(classpath))
|
||||
|
||||
input = $(bld)/classes/TestExceptions.class
|
||||
input = $(bld)/classes/Test.class
|
||||
input-depends = \
|
||||
$(classpath-classes) \
|
||||
$(jni-library)
|
||||
|
10
src/common.h
10
src/common.h
@ -26,6 +26,9 @@ typedef void* object;
|
||||
const unsigned BytesPerWord = sizeof(uintptr_t);
|
||||
const unsigned BitsPerWord = BytesPerWord * 8;
|
||||
|
||||
const uintptr_t PointerMask
|
||||
= ((~static_cast<uintptr_t>(0)) / BytesPerWord) * BytesPerWord;
|
||||
|
||||
const unsigned LikelyPageSizeInBytes = 4 * 1024;
|
||||
|
||||
inline unsigned
|
||||
@ -109,6 +112,13 @@ cast(object p, unsigned 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
|
||||
|
95
src/heap.cpp
95
src/heap.cpp
@ -26,6 +26,32 @@ System* system(Context*);
|
||||
void NO_RETURN abort(Context*);
|
||||
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 {
|
||||
public:
|
||||
class Map {
|
||||
@ -662,7 +688,7 @@ fresh(Context* c, object o)
|
||||
inline bool
|
||||
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
|
||||
@ -779,55 +805,55 @@ copy(Context* c, object o)
|
||||
}
|
||||
|
||||
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;
|
||||
return follow(c, *p);
|
||||
return follow(c, o);
|
||||
} else {
|
||||
*needsVisit = true;
|
||||
return copy(c, *p);
|
||||
return copy(c, o);
|
||||
}
|
||||
}
|
||||
|
||||
object
|
||||
update2(Context* c, object* p, bool* needsVisit)
|
||||
update2(Context* c, object o, bool* needsVisit)
|
||||
{
|
||||
switch (c->mode) {
|
||||
case MinorCollection:
|
||||
case OverflowCollection:
|
||||
if (c->gen2.contains(*p)) {
|
||||
if (c->gen2.contains(o)) {
|
||||
*needsVisit = false;
|
||||
return *p;
|
||||
return o;
|
||||
}
|
||||
break;
|
||||
|
||||
case Gen2Collection:
|
||||
if (c->gen2.contains(*p)) {
|
||||
return update3(c, p, needsVisit);
|
||||
if (c->gen2.contains(o)) {
|
||||
return update3(c, o, needsVisit);
|
||||
} 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;
|
||||
return *p;
|
||||
return o;
|
||||
}
|
||||
break;
|
||||
|
||||
default: break;
|
||||
}
|
||||
|
||||
return update3(c, p, needsVisit);
|
||||
return update3(c, o, needsVisit);
|
||||
}
|
||||
|
||||
object
|
||||
update(Context* c, object* p, bool* needsVisit)
|
||||
{
|
||||
if (*p == 0) {
|
||||
if (mask(*p) == 0) {
|
||||
*needsVisit = false;
|
||||
return *p;
|
||||
return 0;
|
||||
}
|
||||
|
||||
object r = update2(c, p, needsVisit);
|
||||
object r = update2(c, mask(*p), needsVisit);
|
||||
|
||||
// update heap map.
|
||||
if (r) {
|
||||
@ -956,22 +982,22 @@ bitsetNext(Context* c, uintptr_t* p)
|
||||
}
|
||||
|
||||
void
|
||||
collect(Context* c, void** p)
|
||||
collect(Context* c, object* p)
|
||||
{
|
||||
object original = *p;
|
||||
object original = mask(*p);
|
||||
object parent = 0;
|
||||
|
||||
if (Debug) {
|
||||
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;
|
||||
*p = update(c, p, &needsVisit);
|
||||
set(p, update(c, mask(p), &needsVisit));
|
||||
|
||||
if (Debug) {
|
||||
fprintf(stderr, " result: %p (%s) (visit? %d)\n",
|
||||
*p, segment(c, *p), needsVisit);
|
||||
mask(*p), segment(c, *p), needsVisit);
|
||||
}
|
||||
|
||||
if (not needsVisit) return;
|
||||
@ -995,17 +1021,16 @@ collect(Context* c, void** p)
|
||||
virtual bool visit(unsigned offset) {
|
||||
if (Debug) {
|
||||
fprintf(stderr, " update %p (%s) at %p - offset %d from %p (%s)\n",
|
||||
cast<object>(copy, offset * BytesPerWord),
|
||||
segment(c, cast<object>(copy, offset * BytesPerWord)),
|
||||
&cast<object>(copy, offset * BytesPerWord),
|
||||
get(copy, offset),
|
||||
segment(c, get(copy, offset)),
|
||||
getp(copy, offset),
|
||||
offset,
|
||||
copy,
|
||||
segment(c, copy));
|
||||
}
|
||||
|
||||
bool needsVisit;
|
||||
object childCopy = update
|
||||
(c, &cast<object>(copy, offset * BytesPerWord), &needsVisit);
|
||||
object childCopy = update(c, getp(copy, offset), &needsVisit);
|
||||
|
||||
if (Debug) {
|
||||
fprintf(stderr, " result: %p (%s) (visit? %d)\n",
|
||||
@ -1027,7 +1052,7 @@ collect(Context* c, void** p)
|
||||
second = offset;
|
||||
}
|
||||
} else {
|
||||
cast<object>(copy, offset * BytesPerWord) = childCopy;
|
||||
set(copy, offset, childCopy);
|
||||
}
|
||||
|
||||
if (visits > 1 and total > 2 and (second or needsVisit)) {
|
||||
@ -1070,8 +1095,8 @@ collect(Context* c, void** p)
|
||||
parent = original;
|
||||
}
|
||||
|
||||
original = cast<object>(copy, walker.first * BytesPerWord);
|
||||
cast<object>(copy, walker.first * BytesPerWord) = follow(c, original);
|
||||
original = get(copy, walker.first);
|
||||
set(copy, walker.first, follow(c, original));
|
||||
goto visit;
|
||||
} else {
|
||||
// ascend
|
||||
@ -1131,16 +1156,16 @@ collect(Context* c, void** p)
|
||||
|
||||
if (Debug) {
|
||||
fprintf(stderr, " next is %p (%s) at %p - offset %d from %p (%s)\n",
|
||||
cast<object>(copy, walker.next * BytesPerWord),
|
||||
segment(c, cast<object>(copy, walker.next * BytesPerWord)),
|
||||
&cast<object>(copy, walker.next * BytesPerWord),
|
||||
get(copy, walker.next),
|
||||
segment(c, get(copy, walker.next)),
|
||||
getp(copy, walker.next),
|
||||
walker.next,
|
||||
copy,
|
||||
segment(c, copy));
|
||||
}
|
||||
|
||||
original = cast<object>(copy, walker.next * BytesPerWord);
|
||||
cast<object>(copy, walker.next * BytesPerWord) = follow(c, original);
|
||||
original = get(copy, walker.next);
|
||||
set(copy, walker.next, follow(c, original));
|
||||
goto visit;
|
||||
} else {
|
||||
return;
|
||||
@ -1236,7 +1261,7 @@ collect(Context* c, Segment* s, unsigned limit)
|
||||
Walker(Context* c, object p): c(c), p(p) { }
|
||||
|
||||
virtual bool visit(unsigned offset) {
|
||||
collect(c, &cast<object>(p, offset * BytesPerWord));
|
||||
collect(c, getp(p, offset));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
158
src/main.cpp
158
src/main.cpp
@ -1,8 +1,12 @@
|
||||
#include "sys/mman.h"
|
||||
#include "sys/types.h"
|
||||
#include "sys/stat.h"
|
||||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
#include "fcntl.h"
|
||||
#include "dlfcn.h"
|
||||
#include "errno.h"
|
||||
#include "pthread.h"
|
||||
#include "common.h"
|
||||
#include "system.h"
|
||||
#include "heap.h"
|
||||
@ -86,6 +90,22 @@ dynamicCall(void* function, uint64_t* arguments, uint8_t* argumentTypes,
|
||||
|
||||
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*
|
||||
append(vm::System* s, const char* a, const char* b, const char* c,
|
||||
const char* d)
|
||||
@ -108,17 +128,95 @@ class System: public vm::System {
|
||||
public:
|
||||
class Monitor: public vm::System::Monitor {
|
||||
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 void acquire(void*) { }
|
||||
virtual void release(void*) { }
|
||||
virtual void wait(void*) { }
|
||||
virtual void notify(void*) { }
|
||||
virtual void notifyAll(void*) { }
|
||||
virtual void dispose() { s->free(this); }
|
||||
virtual bool tryAcquire(void* context) {
|
||||
if (this->context == context) {
|
||||
++ depth;
|
||||
return true;
|
||||
} else {
|
||||
switch (pthread_mutex_trylock(&mutex)) {
|
||||
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;
|
||||
pthread_mutex_t mutex;
|
||||
pthread_cond_t condition;
|
||||
void* context;
|
||||
unsigned depth;
|
||||
};
|
||||
|
||||
class Library: public vm::System::Library {
|
||||
@ -149,14 +247,20 @@ class System: public vm::System {
|
||||
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) {
|
||||
return s == 0;
|
||||
}
|
||||
|
||||
virtual void* tryAllocate(unsigned size) {
|
||||
// todo: synchronize access
|
||||
pthread_mutex_lock(&mutex);
|
||||
|
||||
if (Verbose) {
|
||||
fprintf(stderr, "try %d; count: %d; limit: %d\n",
|
||||
@ -164,20 +268,26 @@ class System: public vm::System {
|
||||
}
|
||||
|
||||
if (count + size > limit) {
|
||||
pthread_mutex_unlock(&mutex);
|
||||
return 0;
|
||||
} else {
|
||||
uintptr_t* up = static_cast<uintptr_t*>
|
||||
(malloc(size + sizeof(uintptr_t)));
|
||||
if (up == 0) {
|
||||
pthread_mutex_unlock(&mutex);
|
||||
vm::abort(this);
|
||||
} else {
|
||||
*up = size;
|
||||
count += *up;
|
||||
|
||||
pthread_mutex_unlock(&mutex);
|
||||
return up + 1;
|
||||
}
|
||||
}
|
||||
|
||||
uintptr_t* up = static_cast<uintptr_t*>(malloc(size + sizeof(uintptr_t)));
|
||||
if (up == 0) abort();
|
||||
|
||||
*up = size;
|
||||
count += *up;
|
||||
|
||||
return up + 1;
|
||||
}
|
||||
|
||||
virtual void free(const void* p) {
|
||||
// todo: synchronize access
|
||||
pthread_mutex_lock(&mutex);
|
||||
|
||||
if (p) {
|
||||
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));
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&mutex);
|
||||
}
|
||||
|
||||
virtual Status start(Thread*) {
|
||||
return 1;
|
||||
virtual Status start(Thread* t) {
|
||||
pthread_t thread;
|
||||
int rv = pthread_create(&thread, 0, run, t);
|
||||
assert(this, rv == 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual Status make(vm::System::Monitor** m) {
|
||||
@ -232,6 +347,7 @@ class System: public vm::System {
|
||||
::abort();
|
||||
}
|
||||
|
||||
pthread_mutex_t mutex;
|
||||
unsigned limit;
|
||||
unsigned count;
|
||||
};
|
||||
|
@ -21,7 +21,7 @@ class System {
|
||||
virtual bool tryAcquire(void* id) = 0;
|
||||
virtual void acquire(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 notifyAll(void* id) = 0;
|
||||
virtual void dispose() = 0;
|
||||
|
@ -995,7 +995,7 @@ writeSubtypeAssertions(Output* out, Object* o)
|
||||
{
|
||||
for (Object* p = typeSubtypes(o); p; p = cdr(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(capitalize(typeName(st)));
|
||||
out->write("Type)");
|
||||
@ -1035,8 +1035,8 @@ writeAccessor(Output* out, Object* member, Object* offset, bool unsafe = false)
|
||||
if (unsafe) {
|
||||
out->write(" assert(t, true);");
|
||||
} else {
|
||||
out->write(" assert(t, t->vm->unsafe or objectClass(o) == 0 or ");
|
||||
out->write("objectClass(o) == arrayBodyUnsafe");
|
||||
out->write(" assert(t, t->vm->unsafe or ");
|
||||
out->write("objectClass(t, o) == arrayBodyUnsafe");
|
||||
out->write("(t, t->vm->types, Machine::");
|
||||
out->write(capitalize(::typeName(memberOwner(member))));
|
||||
out->write("Type)");
|
||||
@ -1320,7 +1320,8 @@ writeConstructors(Output* out, Object* declarations)
|
||||
writeOffset(out, typeOffset(o), true);
|
||||
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("Type);\n");
|
||||
|
||||
@ -1538,7 +1539,7 @@ writeInitializations(Output* out, Object* declarations)
|
||||
out->write("t->vm->types = allocate(t, pad((");
|
||||
out->write(count);
|
||||
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(count);
|
||||
out->write(";\n");
|
||||
|
101
src/vm.cpp
101
src/vm.cpp
@ -33,12 +33,6 @@ void set(Thread*, object&, object);
|
||||
object makeString(Thread*, const char*, ...);
|
||||
object makeByteArray(Thread*, const char*, ...);
|
||||
|
||||
object&
|
||||
objectClass(object o)
|
||||
{
|
||||
return cast<object>(o, 0);
|
||||
}
|
||||
|
||||
enum FieldCode {
|
||||
VoidField,
|
||||
ByteField,
|
||||
@ -163,6 +157,12 @@ class Thread : public JNIEnv {
|
||||
object heap[HeapSizeInWords];
|
||||
};
|
||||
|
||||
inline object
|
||||
objectClass(Thread*, object o)
|
||||
{
|
||||
return mask(cast<object>(o, 0));
|
||||
}
|
||||
|
||||
#include "type-declarations.cpp"
|
||||
#include "type-constructors.cpp"
|
||||
|
||||
@ -489,8 +489,8 @@ collect(Machine* m, Heap::CollectionType type)
|
||||
virtual unsigned sizeInWords(void* p) {
|
||||
Thread* t = m->rootThread;
|
||||
|
||||
p = m->heap->follow(p);
|
||||
object class_ = m->heap->follow(objectClass(p));
|
||||
p = m->heap->follow(mask(p));
|
||||
object class_ = m->heap->follow(objectClass(t, p));
|
||||
|
||||
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) {
|
||||
Thread* t = m->rootThread;
|
||||
|
||||
p = m->heap->follow(p);
|
||||
object class_ = m->heap->follow(objectClass(p));
|
||||
p = m->heap->follow(mask(p));
|
||||
object class_ = m->heap->follow(objectClass(t, p));
|
||||
object objectMask = m->heap->follow(classObjectMask(t, class_));
|
||||
|
||||
if (objectMask) {
|
||||
@ -599,7 +599,7 @@ enter(Thread* t, Thread::State s)
|
||||
t->vm->exclusive = t;
|
||||
|
||||
while (t->vm->activeCount > 1) {
|
||||
t->vm->stateLock->wait(t);
|
||||
t->vm->stateLock->wait(t, 0);
|
||||
}
|
||||
} break;
|
||||
|
||||
@ -639,7 +639,7 @@ enter(Thread* t, Thread::State s)
|
||||
case Thread::NoState:
|
||||
case Thread::IdleState: {
|
||||
while (t->vm->exclusive) {
|
||||
t->vm->stateLock->wait(t);
|
||||
t->vm->stateLock->wait(t, 0);
|
||||
}
|
||||
|
||||
++ t->vm->activeCount;
|
||||
@ -669,7 +669,7 @@ enter(Thread* t, Thread::State s)
|
||||
t->state = s;
|
||||
|
||||
while (t->vm->liveCount > 1) {
|
||||
t->vm->stateLock->wait(t);
|
||||
t->vm->stateLock->wait(t, 0);
|
||||
}
|
||||
} break;
|
||||
|
||||
@ -762,7 +762,7 @@ make(Thread* t, object class_)
|
||||
unsigned
|
||||
objectSize(Thread* t, object o)
|
||||
{
|
||||
object class_ = objectClass(o);
|
||||
object class_ = objectClass(t, o);
|
||||
|
||||
unsigned n = divide(classFixedSize(t, class_), BytesPerWord);
|
||||
|
||||
@ -921,8 +921,8 @@ makeUnsatisfiedLinkError(Thread* t, object message)
|
||||
inline bool
|
||||
isLongOrDouble(Thread* t, object o)
|
||||
{
|
||||
return objectClass(o) == arrayBody(t, t->vm->types, Machine::LongType)
|
||||
or objectClass(o) == arrayBody(t, t->vm->types, Machine::DoubleType);
|
||||
return objectClass(t, o) == arrayBody(t, t->vm->types, Machine::LongType)
|
||||
or objectClass(t, o) == arrayBody(t, t->vm->types, Machine::DoubleType);
|
||||
}
|
||||
|
||||
unsigned
|
||||
@ -1139,10 +1139,10 @@ instanceOf(Thread* t, object class_, object o)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (objectClass(class_)
|
||||
if (objectClass(t, class_)
|
||||
== 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);
|
||||
for (unsigned i = 0; i < arrayLength(t, itable); i += 2) {
|
||||
if (arrayBody(t, itable, i) == class_) {
|
||||
@ -1151,7 +1151,7 @@ instanceOf(Thread* t, object class_, object o)
|
||||
}
|
||||
}
|
||||
} 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_) {
|
||||
return true;
|
||||
}
|
||||
@ -1165,7 +1165,7 @@ object
|
||||
findInterfaceMethod(Thread* t, object method, object o)
|
||||
{
|
||||
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) {
|
||||
if (arrayBody(t, itable, i) == interface) {
|
||||
return arrayBody(t, arrayBody(t, itable, i + 1),
|
||||
@ -1185,7 +1185,7 @@ findMethod(Thread* t, object method, object class_)
|
||||
inline object
|
||||
findVirtualMethod(Thread* t, object method, object o)
|
||||
{
|
||||
return findMethod(t, method, objectClass(o));
|
||||
return findMethod(t, method, objectClass(t, o));
|
||||
}
|
||||
|
||||
bool
|
||||
@ -1336,7 +1336,8 @@ parsePool(Thread* t, Stream& s)
|
||||
|
||||
for (unsigned i = 0; i < poolCount; ++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)) {
|
||||
case CONSTANT_Class: {
|
||||
set(t, arrayBody(t, pool, i),
|
||||
@ -1361,7 +1362,8 @@ parsePool(Thread* t, Stream& s)
|
||||
|
||||
for (unsigned i = 0; i < poolCount; ++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)) {
|
||||
case CONSTANT_Fieldref:
|
||||
case CONSTANT_Methodref:
|
||||
@ -2064,7 +2066,8 @@ inline object
|
||||
resolveClass(Thread* t, object pool, unsigned 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);
|
||||
|
||||
o = resolveClass(t, o);
|
||||
@ -2079,7 +2082,8 @@ inline object
|
||||
resolveClass(Thread* t, object container, object& (*class_)(Thread*, object))
|
||||
{
|
||||
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);
|
||||
|
||||
o = resolveClass(t, o);
|
||||
@ -2095,7 +2099,8 @@ resolve(Thread* t, object pool, unsigned index,
|
||||
object (*find)(Thread*, object, object))
|
||||
{
|
||||
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);
|
||||
|
||||
object class_ = resolveClass(t, o, referenceClass);
|
||||
@ -2179,7 +2184,7 @@ makeNativeMethodData(Thread* t, object method, void* function, bool builtin)
|
||||
inline object
|
||||
resolveNativeMethodData(Thread* t, object method)
|
||||
{
|
||||
if (objectClass(methodCode(t, method))
|
||||
if (objectClass(t, methodCode(t, method))
|
||||
== arrayBody(t, t->vm->types, Machine::ByteArrayType))
|
||||
{
|
||||
object data = 0;
|
||||
@ -2333,7 +2338,7 @@ toString(JNIEnv* e, jobject this_)
|
||||
|
||||
object s = makeString
|
||||
(t, "%s@%p",
|
||||
&byteArrayBody(t, className(t, objectClass(*this_)), 0),
|
||||
&byteArrayBody(t, className(t, objectClass(t, *this_)), 0),
|
||||
*this_);
|
||||
|
||||
pushSafe(t, s);
|
||||
@ -2493,13 +2498,13 @@ Thread::Thread(Machine* m):
|
||||
#include "type-initializations.cpp"
|
||||
|
||||
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);
|
||||
set(t, objectClass(classClass), classClass);
|
||||
set(t, cast<object>(classClass, 0), classClass);
|
||||
|
||||
object intArrayClass = arrayBody(t, m->types, Machine::IntArrayType);
|
||||
set(t, objectClass(intArrayClass), classClass);
|
||||
set(t, cast<object>(intArrayClass, 0), classClass);
|
||||
|
||||
m->unsafe = false;
|
||||
|
||||
@ -2668,7 +2673,7 @@ run(Thread* t)
|
||||
case arraylength: {
|
||||
object array = pop(t);
|
||||
if (LIKELY(array)) {
|
||||
if (objectClass(array)
|
||||
if (objectClass(t, array)
|
||||
== arrayBody(t, t->vm->types, Machine::ObjectArrayType))
|
||||
{
|
||||
push(t, makeInt(t, objectArrayLength(t, array)));
|
||||
@ -2832,7 +2837,7 @@ run(Thread* t)
|
||||
if (not instanceOf(t, class_, stack[sp - 1])) {
|
||||
object message = makeString
|
||||
(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));
|
||||
exception = makeClassCastException(t, message);
|
||||
goto throw_;
|
||||
@ -3639,6 +3644,26 @@ run(Thread* t)
|
||||
push(t, makeLong(t, longValue(t, a) ^ longValue(t, b)));
|
||||
} 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_: {
|
||||
uint8_t index1 = 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);
|
||||
|
||||
if (catchType == 0 or
|
||||
(objectClass(catchType)
|
||||
(objectClass(t, catchType)
|
||||
== arrayBody(t, t->vm->types, Machine::ClassType) and
|
||||
instanceOf(t, catchType, exception)))
|
||||
{
|
||||
@ -3970,7 +3995,7 @@ run(Thread* t)
|
||||
}
|
||||
|
||||
fprintf(stderr, "%s", &byteArrayBody
|
||||
(t, className(t, objectClass(exception)), 0));
|
||||
(t, className(t, objectClass(t, exception)), 0));
|
||||
|
||||
if (throwableMessage(t, exception)) {
|
||||
object m = throwableMessage(t, exception);
|
||||
@ -3994,17 +4019,17 @@ run(Thread* t)
|
||||
int line = lineNumber
|
||||
(t, stackTraceElementMethod(t, e), stackTraceElementIp(t, e));
|
||||
|
||||
fprintf(stderr, " at %s.%s", class_, method);
|
||||
fprintf(stderr, " at %s.%s ", class_, method);
|
||||
|
||||
switch (line) {
|
||||
case NativeLine:
|
||||
fprintf(stderr, "(native)\n");
|
||||
break;
|
||||
case UnknownLine:
|
||||
fprintf(stderr, "(unknown)\n");
|
||||
fprintf(stderr, "(unknown line)\n");
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "(%d)\n", line);
|
||||
fprintf(stderr, "(line %d)\n", line);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user