Merge branch 'master' of dice.readytalk.com:/home/dicej/git/vm

This commit is contained in:
James Sanders 2007-11-28 17:52:23 -07:00
commit b6ad93856d
20 changed files with 1817 additions and 672 deletions

View File

@ -241,6 +241,26 @@ Java_java_lang_Math_pow(JNIEnv*, jclass, jdouble val, jdouble exp)
return pow(val, exp);
}
extern "C" JNIEXPORT void JNICALL
Java_java_lang_Math_natRandomInitialize(JNIEnv*, jclass, jlong val)
{
#ifdef WIN32
srand(val);
#else
srand48(val);
#endif
}
extern "C" JNIEXPORT jdouble JNICALL
Java_java_lang_Math_natRandom(JNIEnv*, jclass)
{
#ifdef WIN32
return rand();
#else
return drand48();
#endif
}
extern "C" JNIEXPORT jdouble JNICALL
Java_java_lang_Math_floor(JNIEnv*, jclass, jdouble val)
{

View File

@ -14,6 +14,10 @@ public class ByteArrayOutputStream extends OutputStream {
this(0);
}
public int size() {
return length;
}
public void write(int c) {
if (buffer == null) {
buffer = new byte[BufferSize];
@ -61,7 +65,6 @@ public class ByteArrayOutputStream extends OutputStream {
buffer = null;
position = 0;
chain = new Cell(b, 0, p, chain);
length -= p;
}
}

View File

@ -3,6 +3,7 @@ package java.lang;
public final class Math {
public static final double E = 2.718281828459045;
public static final double PI = 3.141592653589793;
private static boolean randomInitialized = false;
private Math() { }
@ -62,7 +63,17 @@ public final class Math {
return (int) Math.floor(v + 0.5);
}
public static native double random();
public static double random() {
if (randomInitialized) {
natRandomInitialize(System.currentTimeMillis());
randomInitialized = true;
}
return natRandom();
}
public static native void natRandomInitialize(long val);
public static native double natRandom();
public static native double floor(double v);

View File

@ -28,7 +28,7 @@ src = src
classpath = classpath
test = test
input = $(test-build)/List.class
input = $(test-build)/Exceptions.class
build-cxx = g++
build-cc = gcc
@ -108,10 +108,10 @@ ifeq ($(mode),debug)
cflags += -O0 -g3 -DNDEBUG
endif
ifeq ($(mode),stress)
cflags += -O0 -g3 -DVM_STRESS
cflags += -O0 -g3 -DNDEBUG -DVM_STRESS
endif
ifeq ($(mode),stress-major)
cflags += -O0 -g3 -DVM_STRESS -DVM_STRESS_MAJOR
cflags += -O0 -g3 -DNDEBUG -DVM_STRESS -DVM_STRESS_MAJOR
endif
ifeq ($(mode),fast)
cflags += -O3 -g3 -DNDEBUG
@ -145,12 +145,14 @@ interpreter-depends = \
$(src)/stream.h \
$(src)/constants.h \
$(src)/jnienv.h \
$(src)/machine.h
$(src)/machine.h \
$(src)/util.h
interpreter-sources = \
$(src)/$(system).cpp \
$(src)/finder.cpp \
$(src)/machine.cpp \
$(src)/util.cpp \
$(src)/heap.cpp \
$(src)/$(process).cpp \
$(src)/builtin.cpp \

View File

@ -51,6 +51,23 @@ class Buffer {
position += 4;
}
void appendAddress(uintptr_t v) {
append4(v);
if (BytesPerWord == 8) {
// we have to use the preprocessor here to avoid a warning on
// 32-bit systems
#ifdef __x86_64__
append4(v >> 32);
#endif
}
}
void append(void* p, unsigned size) {
ensure(size);
memcpy(data + position, p, size);
position += size;
}
void set2(unsigned offset, uint32_t v) {
assert(s, offset + 2 <= position);
memcpy(data + offset, &v, 2);
@ -81,15 +98,9 @@ class Buffer {
return *reinterpret_cast<uintptr_t*>(data + offset);
}
void appendAddress(uintptr_t v) {
append4(v);
if (BytesPerWord == 8) {
// we have to use the preprocessor here to avoid a warning on
// 32-bit systems
#ifdef __x86_64__
append4(v >> 32);
#endif
}
void get(unsigned offset, void* p, unsigned size) {
assert(s, offset + size <= position);
memcpy(p, data + offset, size);
}
unsigned length() {

View File

@ -108,7 +108,7 @@ Java_java_lang_Object_clone(Thread* t, jclass, jobject o)
// clear any object header flags:
setObjectClass(t, *o, objectClass(t, *o));
} else {
clone = make(t, objectClass(t, *o));
clone = make(t, class_);
memcpy(reinterpret_cast<void**>(clone) + 1,
reinterpret_cast<void**>(*o) + 1,
size - BytesPerWord);
@ -317,12 +317,28 @@ Java_java_lang_reflect_Method_getCaller(Thread* t, jclass)
{
ENTER(t, Thread::ActiveState);
Processor* p = t->m->processor;
uintptr_t frame = p->frameStart(t);
frame = p->frameNext(t, frame);
frame = p->frameNext(t, frame);
class Visitor: public Processor::StackVisitor {
public:
Visitor(Thread* t): t(t), method(0), count(0) { }
return makeLocalReference(t, p->frameMethod(t, frame));
virtual bool visit(Processor::StackWalker* walker) {
if (count == 2) {
method = walker->method();
return false;
} else {
++ count;
return true;
}
}
Thread* t;
object method;
unsigned count;
} v(t);
t->m->processor->walkStack(t, &v);
return makeLocalReference(t, v.method);
}
extern "C" JNIEXPORT jobject JNICALL
@ -567,27 +583,41 @@ Java_java_lang_Throwable_trace(Thread* t, jclass, jint skipCount)
{
ENTER(t, Thread::ActiveState);
Processor* p = t->m->processor;
uintptr_t frame = p->frameStart(t);
class Visitor: public Processor::StackVisitor {
public:
Visitor(Thread* t, int skipCount):
t(t), trace(0), skipCount(skipCount)
{ }
while (skipCount-- and p->frameValid(t, frame)) {
frame = p->frameNext(t, frame);
}
// skip Throwable constructors
while (p->frameValid(t, frame)
and isAssignableFrom
(t, arrayBody(t, t->m->types, Machine::ThrowableType),
methodClass(t, p->frameMethod(t, frame)))
and strcmp(reinterpret_cast<const int8_t*>("<init>"),
&byteArrayBody
(t, methodName(t, p->frameMethod(t, frame)), 0))
== 0)
{
frame = p->frameNext(t, frame);
}
virtual bool visit(Processor::StackWalker* walker) {
if (skipCount == 0) {
object method = walker->method();
if (isAssignableFrom
(t, arrayBody(t, t->m->types, Machine::ThrowableType),
methodClass(t, method))
and strcmp(reinterpret_cast<const int8_t*>("<init>"),
&byteArrayBody(t, methodName(t, method), 0))
== 0)
{
return true;
} else {
trace = makeTrace(t, walker);
return false;
}
} else {
-- skipCount;
return true;
}
}
return makeLocalReference(t, makeTrace(t, frame));
Thread* t;
object trace;
unsigned skipCount;
} v(t, skipCount);
t->m->processor->walkStack(t, &v);
return makeLocalReference(t, v.trace);
}
extern "C" JNIEXPORT jarray JNICALL

View File

@ -239,6 +239,12 @@ bitsToFloat(uint32_t bits)
return f;
}
inline intptr_t
difference(void* a, void* b)
{
return reinterpret_cast<intptr_t>(a) - reinterpret_cast<intptr_t>(b);
}
class Machine;
class Thread;

File diff suppressed because it is too large Load Diff

View File

@ -7,19 +7,26 @@ namespace vm {
class Operand { };
class Promise {
public:
virtual ~Promise() { }
virtual unsigned value() = 0;
};
class Compiler {
public:
virtual ~Compiler() { }
virtual Promise* poolOffset() = 0;
virtual Promise* codeOffset() = 0;
virtual Operand* poolAppend(Operand*) = 0;
virtual unsigned poolOffset() = 0;
virtual unsigned poolOffset(Operand*) = 0;
virtual Operand* constant(intptr_t) = 0;
virtual void push(Operand*) = 0;
virtual void push2(Operand*) = 0;
virtual Operand* stack() = 0;
virtual Operand* stack(unsigned) = 0;
virtual Operand* stack2(unsigned) = 0;
virtual Operand* pop() = 0;
@ -27,10 +34,10 @@ class Compiler {
virtual void pop(Operand*) = 0;
virtual void pop2(Operand*) = 0;
virtual Operand* stack() = 0;
virtual Operand* base() = 0;
virtual Operand* thread() = 0;
virtual Operand* indirectTarget() = 0;
virtual Operand* temporary() = 0;
virtual void release(Operand*) = 0;
@ -45,6 +52,7 @@ class Compiler {
(Operand* address, unsigned argumentCount, ...) = 0;
virtual Operand* directCall
(Operand* address, unsigned argumentCount, ...) = 0;
virtual void return_(Operand*) = 0;
virtual void ret() = 0;
@ -88,10 +96,13 @@ class Compiler {
virtual void startLogicalIp(unsigned) = 0;
virtual Operand* logicalIp(unsigned) = 0;
virtual unsigned logicalIpToOffset(unsigned) = 0;
virtual unsigned size() = 0;
virtual void writeTo(void*) = 0;
virtual void updateCall(void* returnAddress, void* newTarget);
virtual void dispose() = 0;
};

View File

@ -356,6 +356,39 @@ popFrame(Thread* t)
}
}
class MyStackWalker: public Processor::StackWalker {
public:
MyStackWalker(Thread* t, int frame): t(t), frame(frame) { }
virtual void walk(Processor::StackVisitor* v) {
for (int frame = this->frame; frame >= 0; frame = frameNext(t, frame)) {
MyStackWalker walker(t, frame);
if (not v->visit(&walker)) {
break;
}
}
}
virtual object method() {
return frameMethod(t, frame);
}
virtual int ip() {
return frameIp(t, frame);
}
virtual unsigned count() {
unsigned count = 0;
for (int frame = this->frame; frame >= 0; frame = frameNext(t, frame)) {
++ count;
}
return count;
}
Thread* t;
int frame;
};
object
makeNativeMethodData(Thread* t, object method, void* function)
{
@ -663,43 +696,7 @@ store(Thread* t, unsigned index)
ExceptionHandler*
findExceptionHandler(Thread* t, int frame)
{
object method = frameMethod(t, frame);
object eht = codeExceptionHandlerTable(t, methodCode(t, method));
if (eht) {
for (unsigned i = 0; i < exceptionHandlerTableLength(t, eht); ++i) {
ExceptionHandler* eh = exceptionHandlerTableBody(t, eht, i);
if (frameIp(t, frame) - 1 >= exceptionHandlerStart(eh)
and frameIp(t, frame) - 1 < exceptionHandlerEnd(eh))
{
object catchType = 0;
if (exceptionHandlerCatchType(eh)) {
object e = t->exception;
t->exception = 0;
PROTECT(t, e);
PROTECT(t, eht);
catchType = resolveClassInPool
(t, codePool(t, t->code), exceptionHandlerCatchType(eh) - 1);
if (catchType) {
eh = exceptionHandlerTableBody(t, eht, i);
t->exception = e;
} else {
// can't find what we're supposed to catch - move on.
continue;
}
}
if (catchType == 0 or instanceOf(t, catchType, t->exception)) {
return eh;
}
}
}
}
return 0;
return findExceptionHandler(t, frameMethod(t, frame), frameIp(t, frame));
}
void
@ -768,7 +765,7 @@ interpret(Thread* t)
&byteArrayBody
(t, methodName(t, frameMethod(t, frame)), 0));
int line = t->m->processor->lineNumber(t, frameMethod(t, frame), ip);
int line = findLineNumber(t, frameMethod(t, frame), ip);
switch (line) {
case NativeLine:
fprintf(stderr, "(native)\n");
@ -1931,7 +1928,7 @@ interpret(Thread* t)
uint32_t offset = codeReadInt32(t, code, ip);
pushInt(t, ip);
ip = (ip - 3) + static_cast<int32_t>(offset);
ip = (ip - 5) + static_cast<int32_t>(offset);
} goto loop;
case l2i: {
@ -2900,74 +2897,23 @@ class MyProcessor: public Processor {
}
}
virtual uintptr_t
frameStart(vm::Thread* vmt)
virtual void
walkStack(vm::Thread* vmt, StackVisitor* v)
{
Thread* t = static_cast<Thread*>(vmt);
if (t->frame >= 0) {
pokeInt(t, t->frame + FrameIpOffset, t->ip);
}
return t->frame;
}
virtual uintptr_t
frameNext(vm::Thread* vmt, uintptr_t frame)
{
Thread* t = static_cast<Thread*>(vmt);
assert(t, static_cast<intptr_t>(frame) >= 0);
return ::frameNext(t, frame);
}
virtual bool
frameValid(vm::Thread*, uintptr_t frame)
{
return static_cast<intptr_t>(frame) >= 0;
}
virtual object
frameMethod(vm::Thread* vmt, uintptr_t frame)
{
Thread* t = static_cast<Thread*>(vmt);
assert(t, static_cast<intptr_t>(frame) >= 0);
return ::frameMethod(t, frame);
}
virtual unsigned
frameIp(vm::Thread* vmt, uintptr_t frame)
{
Thread* t = static_cast<Thread*>(vmt);
assert(t, static_cast<intptr_t>(frame) >= 0);
return ::frameIp(t, frame);
MyStackWalker walker(t, t->frame);
walker.walk(v);
}
virtual int
lineNumber(vm::Thread* vmt, object method, unsigned ip)
lineNumber(vm::Thread* t, object method, int ip)
{
Thread* t = static_cast<Thread*>(vmt);
if (methodFlags(t, method) & ACC_NATIVE) {
return NativeLine;
}
object table = codeLineNumberTable(t, methodCode(t, method));
if (table) {
// todo: do a binary search:
int last = UnknownLine;
for (unsigned i = 0; i < lineNumberTableLength(t, table); ++i) {
if (ip <= lineNumberIp(lineNumberTableBody(t, table, i))) {
return last;
} else {
last = lineNumberLine(lineNumberTableBody(t, table, i));
}
}
return last;
} else {
return UnknownLine;
}
return findLineNumber(static_cast<Thread*>(t), method, ip);
}
virtual object*

View File

@ -1,5 +1,6 @@
#include "jnienv.h"
#include "machine.h"
#include "util.h"
#include "processor.h"
#include "constants.h"
#include "processor.h"

View File

@ -1,5 +1,6 @@
#include "jnienv.h"
#include "machine.h"
#include "util.h"
#include "stream.h"
#include "constants.h"
#include "processor.h"
@ -31,35 +32,93 @@ join(Thread* t, Thread* o)
}
}
unsigned
count(Thread* t, Thread* o)
{
unsigned c = 0;
if (t != o) ++ c;
for (Thread* p = t->peer; p; p = p->peer) {
c += count(p, o);
}
if (t->child) c += count(t->child, o);
return c;
}
Thread**
fill(Thread* t, Thread* o, Thread** array)
{
if (t != o) *(array++) = t;
for (Thread* p = t->peer; p; p = p->peer) {
array = fill(p, o, array);
}
if (t->child) array = fill(t->child, o, array);
return array;
}
void
dispose(Thread* t, Thread* o, bool remove)
{
if (remove) {
// debug
expect(t, find(t->m->rootThread, o));
unsigned c = count(t->m->rootThread, o);
Thread* threads[c];
fill(t->m->rootThread, o, threads);
// end debug
if (o->parent) {
if (o->child) {
o->parent->child = o->child;
if (o->peer) {
o->peer->peer = o->child->peer;
o->child->peer = o->peer;
Thread* previous = 0;
for (Thread* p = o->parent->child; p;) {
if (p == o) {
if (p == o->parent->child) {
o->parent->child = p->peer;
} else {
previous->peer = p->peer;
}
break;
} else {
previous = p;
p = p->peer;
}
} else if (o->peer) {
o->parent->child = o->peer;
} else {
o->parent->child = 0;
}
for (Thread* p = o->child; p;) {
Thread* next = p->peer;
p->peer = o->parent->child;
o->parent->child = p;
p->parent = o->parent;
p = next;
}
} else if (o->child) {
t->m->rootThread = o->child;
if (o->peer) {
o->peer->peer = o->child->peer;
o->child->peer = o->peer;
}
for (Thread* p = o->peer; p;) {
Thread* next = p->peer;
p->peer = t->m->rootThread;
t->m->rootThread = p;
p = next;
}
} else if (o->peer) {
t->m->rootThread = o->peer;
} else {
abort(t);
}
assert(t, not find(t->m->rootThread, o));
// debug
expect(t, not find(t->m->rootThread, o));
for (unsigned i = 0; i < c; ++i) {
expect(t, find(t->m->rootThread, threads[i]));
}
// end debug
}
o->dispose();
@ -796,7 +855,7 @@ parseInterfaceTable(Thread* t, Stream& s, object class_, object pool)
if (classSuper(t, class_)) {
addInterfaces(t, classSuper(t, class_), map);
}
unsigned count = s.read2();
for (unsigned i = 0; i < count; ++i) {
object name = singletonObject(t, pool, s.read2() - 1);
@ -1289,12 +1348,17 @@ parseMethodTable(Thread* t, Stream& s, object class_, object pool)
if (declaredVirtualCount == 0
and (classFlags(t, class_) & ACC_INTERFACE) == 0)
{
// inherit interface table and virtual table from superclass
// inherit virtual table from superclass
set(t, class_, ClassVirtualTable, superVirtualTable);
set(t, class_, ClassInterfaceTable,
classInterfaceTable(t, classSuper(t, class_)));
set(t, class_, ClassVirtualTable, superVirtualTable);
if (classInterfaceTable(t, classSuper(t, class_))
and arrayLength(t, classInterfaceTable(t, class_))
== arrayLength(t, classInterfaceTable(t, classSuper(t, class_))))
{
// inherit interface table from superclass
set(t, class_, ClassInterfaceTable,
classInterfaceTable(t, classSuper(t, class_)));
}
} else if (virtualCount) {
// generate class vtable
@ -1891,6 +1955,7 @@ Thread::init()
#include "type-java-initializations.cpp"
}
} else {
peer = parent->child;
parent->child = this;
}
@ -2047,6 +2112,8 @@ enter(Thread* t, Thread::State s)
case Thread::ExclusiveState: {
assert(t, t->m->exclusive == t);
t->m->exclusive = 0;
t->m->stateLock->notifyAll(t->systemThread);
} break;
case Thread::ActiveState: break;
@ -2226,253 +2293,6 @@ classInitializer(Thread* t, object class_)
abort(t);
}
object
hashMapFindNode(Thread* t, object map, object key,
uint32_t (*hash)(Thread*, object),
bool (*equal)(Thread*, object, object))
{
bool weak = objectClass(t, map)
== arrayBody(t, t->m->types, Machine::WeakHashMapType);
object array = hashMapArray(t, map);
if (array) {
unsigned index = hash(t, key) & (arrayLength(t, array) - 1);
for (object n = arrayBody(t, array, index); n; n = tripleThird(t, n)) {
object k = tripleFirst(t, n);
if (weak) {
k = jreferenceTarget(t, k);
if (k == 0) {
continue;
}
}
if (equal(t, key, k)) {
return n;
}
}
}
return 0;
}
void
hashMapResize(Thread* t, object map, uint32_t (*hash)(Thread*, object),
unsigned size)
{
PROTECT(t, map);
object newArray = 0;
if (size) {
object oldArray = hashMapArray(t, map);
PROTECT(t, oldArray);
unsigned newLength = nextPowerOfTwo(size);
if (oldArray and arrayLength(t, oldArray) == newLength) {
return;
}
newArray = makeArray(t, newLength, true);
if (oldArray) {
bool weak = objectClass(t, map)
== arrayBody(t, t->m->types, Machine::WeakHashMapType);
for (unsigned i = 0; i < arrayLength(t, oldArray); ++i) {
object next;
for (object p = arrayBody(t, oldArray, i); p; p = next) {
next = tripleThird(t, p);
object k = tripleFirst(t, p);
if (weak) {
k = jreferenceTarget(t, k);
if (k == 0) {
continue;
}
}
unsigned index = hash(t, k) & (newLength - 1);
set(t, p, TripleThird, arrayBody(t, newArray, index));
set(t, newArray, ArrayBody + (index * BytesPerWord), p);
}
}
}
}
set(t, map, HashMapArray, newArray);
}
void
hashMapInsert(Thread* t, object map, object key, object value,
uint32_t (*hash)(Thread*, object))
{
bool weak = objectClass(t, map)
== arrayBody(t, t->m->types, Machine::WeakHashMapType);
object array = hashMapArray(t, map);
PROTECT(t, array);
++ hashMapSize(t, map);
if (array == 0 or hashMapSize(t, map) >= arrayLength(t, array) * 2) {
PROTECT(t, map);
PROTECT(t, key);
PROTECT(t, value);
hashMapResize(t, map, hash, array ? arrayLength(t, array) * 2 : 16);
array = hashMapArray(t, map);
}
unsigned index = hash(t, key) & (arrayLength(t, array) - 1);
if (weak) {
PROTECT(t, key);
PROTECT(t, value);
object r = makeWeakReference(t, 0, 0, 0, 0);
jreferenceTarget(t, r) = key;
jreferenceVmNext(t, r) = t->m->weakReferences;
key = t->m->weakReferences = r;
}
object n = makeTriple(t, key, value, arrayBody(t, array, index));
set(t, array, ArrayBody + (index * BytesPerWord), n);
}
object
hashMapRemoveNode(Thread* t, object map, unsigned index, object p, object n)
{
if (p) {
set(t, p, TripleThird, tripleThird(t, n));
} else {
set(t, hashMapArray(t, map), ArrayBody + (index * BytesPerWord),
tripleThird(t, n));
}
-- hashMapSize(t, map);
return n;
}
object
hashMapRemove(Thread* t, object map, object key,
uint32_t (*hash)(Thread*, object),
bool (*equal)(Thread*, object, object))
{
bool weak = objectClass(t, map)
== arrayBody(t, t->m->types, Machine::WeakHashMapType);
object array = hashMapArray(t, map);
object o = 0;
if (array) {
unsigned index = hash(t, key) & (arrayLength(t, array) - 1);
object p = 0;
for (object n = arrayBody(t, array, index); n;) {
object k = tripleFirst(t, n);
if (weak) {
k = jreferenceTarget(t, k);
if (k == 0) {
n = tripleThird(t, hashMapRemoveNode(t, map, index, p, n));
continue;
}
}
if (equal(t, key, k)) {
o = tripleSecond(t, hashMapRemoveNode(t, map, index, p, n));
break;
} else {
p = n;
n = tripleThird(t, n);
}
}
if (hashMapSize(t, map) <= arrayLength(t, array) / 3) {
PROTECT(t, o);
hashMapResize(t, map, hash, arrayLength(t, array) / 2);
}
}
return o;
}
object
hashMapIterator(Thread* t, object map)
{
object array = hashMapArray(t, map);
if (array) {
for (unsigned i = 0; i < arrayLength(t, array); ++i) {
if (arrayBody(t, array, i)) {
return makeHashMapIterator(t, map, arrayBody(t, array, i), i + 1);
}
}
}
return 0;
}
object
hashMapIteratorNext(Thread* t, object it)
{
object map = hashMapIteratorMap(t, it);
object node = hashMapIteratorNode(t, it);
unsigned index = hashMapIteratorIndex(t, it);
if (tripleThird(t, node)) {
return makeHashMapIterator(t, map, tripleThird(t, node), index);
} else {
object array = hashMapArray(t, map);
for (unsigned i = index; i < arrayLength(t, array); ++i) {
if (arrayBody(t, array, i)) {
return makeHashMapIterator(t, map, arrayBody(t, array, i), i + 1);
}
}
return 0;
}
}
void
listAppend(Thread* t, object list, object value)
{
PROTECT(t, list);
++ listSize(t, list);
object p = makePair(t, value, 0);
if (listFront(t, list)) {
set(t, listRear(t, list), PairSecond, p);
} else {
set(t, list, ListFront, p);
}
set(t, list, ListRear, 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, vector, VectorBody + (vectorSize(t, vector) * BytesPerWord), value);
++ vectorSize(t, vector);
return vector;
}
unsigned
fieldCode(Thread* t, unsigned javaCode)
{
@ -2878,7 +2698,7 @@ addFinalizer(Thread* t, object target, void (*finalize)(Thread*, object))
}
System::Monitor*
objectMonitor(Thread* t, object o)
objectMonitor(Thread* t, object o, bool createNew)
{
object p = hashMapFind(t, t->m->monitorMap, o, objectHash, objectEqual);
@ -2890,7 +2710,7 @@ objectMonitor(Thread* t, object o)
}
return static_cast<System::Monitor*>(pointerValue(t, p));
} else {
} else if (createNew) {
PROTECT(t, o);
ENTER(t, Thread::ExclusiveState);
@ -2911,6 +2731,8 @@ objectMonitor(Thread* t, object o)
addFinalizer(t, o, removeMonitor);
return m;
} else {
return 0;
}
}
@ -3010,33 +2832,53 @@ printTrace(Thread* t, object exception)
}
object
makeTrace(Thread* t, uintptr_t start)
makeTrace(Thread* t, Processor::StackWalker* walker)
{
Processor* p = t->m->processor;
class Visitor: public Processor::StackVisitor {
public:
Visitor(Thread* t): t(t), trace(0), index(0), protector(t, &trace) { }
unsigned count = 0;
for (uintptr_t frame = start;
p->frameValid(t, frame);
frame = p->frameNext(t, frame))
{
++ count;
}
virtual bool visit(Processor::StackWalker* walker) {
if (trace == 0) {
trace = makeArray(t, walker->count(), true);
}
object trace = makeArray(t, count, true);
PROTECT(t, trace);
unsigned index = 0;
for (uintptr_t frame = start;
p->frameValid(t, frame);
frame = p->frameNext(t, frame))
{
object e = makeTraceElement
(t, p->frameMethod(t, frame), p->frameIp(t, frame));
set(t, trace, ArrayBody + (index * BytesPerWord), e);
++ index;
}
object e = makeTraceElement(t, walker->method(), walker->ip());
set(t, trace, ArrayBody + (index * BytesPerWord), e);
++ index;
return true;
}
return trace;
Thread* t;
object trace;
unsigned index;
Thread::SingleProtector protector;
} v(t);
walker->walk(&v);
return v.trace;
}
object
makeTrace(Thread* t)
{
class Visitor: public Processor::StackVisitor {
public:
Visitor(Thread* t): t(t), trace(0) { }
virtual bool visit(Processor::StackWalker* walker) {
trace = makeTrace(t, walker);
return false;
}
Thread* t;
object trace;
} v(t);
t->m->processor->walkStack(t, &v);
return v.trace;
}
void

View File

@ -1505,13 +1505,10 @@ baseSize(Thread* t, object o, object class_)
}
object
makeTrace(Thread* t, uintptr_t start);
makeTrace(Thread* t, Processor::StackWalker* walker);
inline object
makeTrace(Thread* t)
{
return makeTrace(t, t->m->processor->frameStart(t));
}
object
makeTrace(Thread* t);
inline object
makeRuntimeException(Thread* t, object message)
@ -1835,74 +1832,6 @@ methodEqual(Thread* t, object a, object b)
byteArrayEqual(t, methodSpec(t, a), methodSpec(t, b)));
}
object
hashMapFindNode(Thread* t, object map, object key,
uint32_t (*hash)(Thread*, object),
bool (*equal)(Thread*, object, object));
inline object
hashMapFind(Thread* t, object map, object key,
uint32_t (*hash)(Thread*, object),
bool (*equal)(Thread*, object, object))
{
object n = hashMapFindNode(t, map, key, hash, equal);
return (n ? tripleSecond(t, n) : 0);
}
void
hashMapResize(Thread* t, object map, uint32_t (*hash)(Thread*, object),
unsigned size);
void
hashMapInsert(Thread* t, object map, object key, object value,
uint32_t (*hash)(Thread*, object));
inline bool
hashMapInsertOrReplace(Thread* t, object map, object key, object value,
uint32_t (*hash)(Thread*, object),
bool (*equal)(Thread*, object, object))
{
object n = hashMapFindNode(t, map, key, hash, equal);
if (n == 0) {
hashMapInsert(t, map, key, value, hash);
return true;
} else {
set(t, n, TripleSecond, value);
return false;
}
}
inline bool
hashMapInsertMaybe(Thread* t, object map, object key, object value,
uint32_t (*hash)(Thread*, object),
bool (*equal)(Thread*, object, object))
{
object n = hashMapFindNode(t, map, key, hash, equal);
if (n == 0) {
hashMapInsert(t, map, key, value, hash);
return true;
} else {
return false;
}
}
object
hashMapRemove(Thread* t, object map, object key,
uint32_t (*hash)(Thread*, object),
bool (*equal)(Thread*, object, object));
object
hashMapIterator(Thread* t, object map);
object
hashMapIteratorNext(Thread* t, object it);
void
listAppend(Thread* t, object list, object value);
object
vectorAppend(Thread* t, object vector, object value);
class MethodSpecIterator {
public:
MethodSpecIterator(Thread* t, const char* s):
@ -2069,12 +1998,12 @@ void
addFinalizer(Thread* t, object target, void (*finalize)(Thread*, object));
System::Monitor*
objectMonitor(Thread* t, object o);
objectMonitor(Thread* t, object o, bool createNew);
inline void
acquire(Thread* t, object o)
{
System::Monitor* m = objectMonitor(t, o);
System::Monitor* m = objectMonitor(t, o, true);
if (DebugMonitors) {
fprintf(stderr, "thread %p acquires %p for %x\n",
@ -2087,7 +2016,7 @@ acquire(Thread* t, object o)
inline void
release(Thread* t, object o)
{
System::Monitor* m = objectMonitor(t, o);
System::Monitor* m = objectMonitor(t, o, false);
if (DebugMonitors) {
fprintf(stderr, "thread %p releases %p for %x\n",
@ -2100,14 +2029,14 @@ release(Thread* t, object o)
inline void
wait(Thread* t, object o, int64_t milliseconds)
{
System::Monitor* m = objectMonitor(t, o);
System::Monitor* m = objectMonitor(t, o, false);
if (DebugMonitors) {
fprintf(stderr, "thread %p waits %"LLD" millis on %p for %x\n",
t, milliseconds, m, objectHash(t, o));
}
if (m->owner() == t->systemThread) {
if (m and m->owner() == t->systemThread) {
ENTER(t, Thread::IdleState);
bool interrupted = m->wait(t->systemThread, milliseconds);
@ -2129,14 +2058,14 @@ wait(Thread* t, object o, int64_t milliseconds)
inline void
notify(Thread* t, object o)
{
System::Monitor* m = objectMonitor(t, o);
System::Monitor* m = objectMonitor(t, o, false);
if (DebugMonitors) {
fprintf(stderr, "thread %p notifies on %p for %x\n",
t, m, objectHash(t, o));
}
if (m->owner() == t->systemThread) {
if (m and m->owner() == t->systemThread) {
m->notify(t->systemThread);
} else {
t->exception = makeIllegalMonitorStateException(t);
@ -2146,14 +2075,14 @@ notify(Thread* t, object o)
inline void
notifyAll(Thread* t, object o)
{
System::Monitor* m = objectMonitor(t, o);
System::Monitor* m = objectMonitor(t, o, false);
if (DebugMonitors) {
fprintf(stderr, "thread %p notifies all on %p for %x\n",
t, m, objectHash(t, o));
}
if (m->owner() == t->systemThread) {
if (m and m->owner() == t->systemThread) {
m->notifyAll(t->systemThread);
} else {
t->exception = makeIllegalMonitorStateException(t);

View File

@ -80,7 +80,7 @@ class MySystem: public System {
virtual void join() {
int rv UNUSED = pthread_join(thread, 0);
assert(s, rv == 0);
expect(s, rv == 0);
}
virtual void dispose() {
@ -150,21 +150,32 @@ class MySystem: public System {
void append(Thread* t) {
if (last) {
last->next = t;
last = t;
} else {
first = last = t;
}
}
void remove(Thread* t) {
for (Thread** p = &first; *p;) {
if (t == *p) {
*p = t->next;
if (last == t) {
last = 0;
Thread* previous = 0;
for (Thread* current = first; current;) {
if (t == current) {
if (current == first) {
first = t->next;
} else {
previous->next = t->next;
}
if (current == last) {
last = previous;
}
t->next = 0;
break;
} else {
p = &((*p)->next);
previous = current;
current = current->next;
}
}
}
@ -194,10 +205,10 @@ class MySystem: public System {
timespec ts = { then / 1000, (then % 1000) * 1000 * 1000 };
int rv UNUSED = pthread_cond_timedwait
(&(t->condition), &(t->mutex), &ts);
assert(s, rv == 0 or rv == ETIMEDOUT or rv == EINTR);
expect(s, rv == 0 or rv == ETIMEDOUT or rv == EINTR);
} else {
int rv UNUSED = pthread_cond_wait(&(t->condition), &(t->mutex));
assert(s, rv == 0 or rv == EINTR);
expect(s, rv == 0 or rv == EINTR);
}
pthread_mutex_lock(&mutex);
@ -227,7 +238,7 @@ class MySystem: public System {
t->flags |= Notified;
int rv UNUSED = pthread_cond_signal(&(t->condition));
assert(s, rv == 0);
expect(s, rv == 0);
}
virtual void notify(System::Thread* context) {
@ -266,7 +277,7 @@ class MySystem: public System {
}
virtual void dispose() {
assert(s, owner_ == 0);
expect(s, owner_ == 0);
pthread_mutex_destroy(&mutex);
s->free(this);
}
@ -283,7 +294,7 @@ class MySystem: public System {
public:
Local(System* s): s(s) {
int r UNUSED = pthread_key_create(&key, 0);
assert(s, r == 0);
expect(s, r == 0);
}
virtual void* get() {
@ -292,12 +303,12 @@ class MySystem: public System {
virtual void set(void* p) {
int r UNUSED = pthread_setspecific(key, p);
assert(s, r == 0);
expect(s, r == 0);
}
virtual void dispose() {
int r UNUSED = pthread_key_delete(key);
assert(s, r == 0);
expect(s, r == 0);
s->free(this);
}
@ -395,7 +406,7 @@ class MySystem: public System {
sa.sa_handler = handleSignal;
int rv UNUSED = sigaction(InterruptSignal, &sa, 0);
assert(this, rv == 0);
expect(this, rv == 0);
}
virtual bool success(Status s) {
@ -455,7 +466,7 @@ class MySystem: public System {
Thread* t = new (System::allocate(sizeof(Thread))) Thread(this, r);
r->attach(t);
int rv UNUSED = pthread_create(&(t->thread), 0, run, r);
assert(this, rv == 0);
expect(this, rv == 0);
return 0;
}

View File

@ -206,6 +206,88 @@ populateMultiArray(Thread* t, object array, int32_t* counts,
}
}
inline ExceptionHandler*
findExceptionHandler(Thread* t, object method, unsigned ip)
{
PROTECT(t, method);
object eht = codeExceptionHandlerTable(t, methodCode(t, method));
if (eht) {
for (unsigned i = 0; i < exceptionHandlerTableLength(t, eht); ++i) {
ExceptionHandler* eh = exceptionHandlerTableBody(t, eht, i);
if (ip - 1 >= exceptionHandlerStart(eh)
and ip - 1 < exceptionHandlerEnd(eh))
{
object catchType = 0;
if (exceptionHandlerCatchType(eh)) {
object e = t->exception;
t->exception = 0;
PROTECT(t, e);
PROTECT(t, eht);
catchType = resolveClassInPool
(t, codePool(t, methodCode(t, method)),
exceptionHandlerCatchType(eh) - 1);
if (catchType) {
eh = exceptionHandlerTableBody(t, eht, i);
t->exception = e;
} else {
// can't find what we're supposed to catch - move on.
continue;
}
}
if (catchType == 0 or instanceOf(t, catchType, t->exception)) {
return eh;
}
}
}
}
return 0;
}
inline int
findLineNumber(Thread* t, object method, unsigned ip)
{
if (methodFlags(t, method) & ACC_NATIVE) {
return NativeLine;
}
// our parameter indicates the instruction following the one we care
// about, so we back up first:
-- ip;
object code = methodCode(t, method);
object lnt = codeLineNumberTable(t, code);
if (lnt) {
unsigned bottom = 0;
unsigned top = lineNumberTableLength(t, lnt);
for (unsigned span = top - bottom; span; span = top - bottom) {
unsigned middle = bottom + (span / 2);
LineNumber* ln = lineNumberTableBody(t, lnt, middle);
if (ip >= lineNumberIp(ln)
and (middle + 1 == lineNumberTableLength(t, lnt)
or ip < lineNumberIp(lineNumberTableBody(t, lnt, middle + 1))))
{
return lineNumberLine(ln);
} else if (ip < lineNumberIp(ln)) {
top = middle;
} else if (ip > lineNumberIp(ln)) {
bottom = middle + 1;
}
}
abort(t);
} else {
return UnknownLine;
}
}
} // namespace vm
#endif//PROCESS_H

View File

@ -9,6 +9,28 @@ namespace vm {
class Processor {
public:
class StackWalker;
class StackVisitor {
public:
virtual ~StackVisitor() { }
virtual bool visit(StackWalker* walker) = 0;
};
class StackWalker {
public:
virtual ~StackWalker() { }
virtual void walk(StackVisitor* v) = 0;
virtual object method() = 0;
virtual int ip() = 0;
virtual unsigned count() = 0;
};
virtual ~Processor() { }
virtual Thread*
@ -51,23 +73,11 @@ class Processor {
virtual void
visitObjects(Thread* t, Heap::Visitor* v) = 0;
virtual uintptr_t
frameStart(Thread* t) = 0;
virtual uintptr_t
frameNext(Thread* t, uintptr_t frame) = 0;
virtual bool
frameValid(Thread* t, uintptr_t frame) = 0;
virtual object
frameMethod(Thread* t, uintptr_t frame) = 0;
virtual unsigned
frameIp(Thread* t, uintptr_t frame) = 0;
virtual void
walkStack(Thread* t, StackVisitor* v) = 0;
virtual int
lineNumber(Thread* t, object method, unsigned ip) = 0;
lineNumber(Thread* t, object method, int ip) = 0;
virtual object*
makeLocalReference(Thread* t, object o) = 0;

View File

@ -24,17 +24,17 @@
(void* value))
(pod exceptionHandler
(uint16_t start)
(uint16_t end)
(uint16_t ip)
(uint16_t catchType))
(uint32_t start)
(uint32_t end)
(uint32_t ip)
(uint32_t catchType))
(type exceptionHandlerTable
(array exceptionHandler body))
(pod lineNumber
(uint16_t ip)
(uint16_t line))
(uint32_t ip)
(uint32_t line))
(type lineNumberTable
(array lineNumber body))
@ -89,8 +89,27 @@
(type traceElement
(object method)
(int32_t ip))
(int ip))
(type treeNode
(intptr_t key)
(uintptr_t red)
(object left)
(object right))
(type treePath
(uintptr_t fresh)
(object node)
(object root)
(object ancestors))
(type traceNode
(extends treeNode)
(object method)
(object target)
(uintptr_t virtualCall)
(array uintptr_t map))
(type array
(noassert array object body))

497
src/util.cpp Normal file
View File

@ -0,0 +1,497 @@
#include "util.h"
using namespace vm;
namespace {
object
clone(Thread* t, object o)
{
object class_ = objectClass(t, o);
unsigned size = baseSize(t, o, class_) * BytesPerWord;
object clone = make(t, class_);
memcpy(reinterpret_cast<void**>(clone) + 1,
reinterpret_cast<void**>(o) + 1,
size - BytesPerWord);
return clone;
}
object
treeFind(Thread* t, object old, object node, object sentinal)
{
PROTECT(t, old);
PROTECT(t, node);
PROTECT(t, sentinal);
object newRoot = clone(t, old);
PROTECT(t, newRoot);
object new_ = newRoot;
PROTECT(t, new_);
object ancestors = 0;
PROTECT(t, ancestors);
while (old != sentinal) {
ancestors = makePair(t, new_, ancestors);
intptr_t difference = treeNodeKey(t, node) - treeNodeKey(t, old);
if (difference < 0) {
old = treeNodeLeft(t, old);
object n = clone(t, old);
set(t, new_, TreeNodeLeft, n);
new_ = n;
} else if (difference > 0) {
old = treeNodeRight(t, old);
object n = clone(t, old);
set(t, new_, TreeNodeRight, n);
new_ = n;
} else {
return makeTreePath(t, false, new_, newRoot, pairSecond(t, ancestors));
}
}
object class_ = objectClass(t, node);
unsigned size = baseSize(t, node, class_) * BytesPerWord;
unsigned treeNodeSize = classFixedSize
(t, arrayBody(t, t->m->types, Machine::TreeNodeType)) * BytesPerWord;
unsigned diff = treeNodeSize - size;
if (diff) {
memcpy(reinterpret_cast<uint8_t*>(new_) + treeNodeSize,
reinterpret_cast<uint8_t*>(node) + treeNodeSize,
diff);
}
return makeTreePath(t, true, new_, newRoot, ancestors);
}
object
leftRotate(Thread* t, object n)
{
object child = clone(t, treeNodeRight(t, n));
set(t, n, TreeNodeRight, treeNodeLeft(t, child));
set(t, child, TreeNodeLeft, n);
return child;
}
object
rightRotate(Thread* t, object n)
{
object child = clone(t, treeNodeLeft(t, n));
set(t, n, TreeNodeLeft, treeNodeRight(t, child));
set(t, child, TreeNodeRight, n);
return child;
}
object
treeAdd(Thread* t, object path)
{
object new_ = treePathNode(t, path);
PROTECT(t, new_);
object newRoot = treePathRoot(t, path);
PROTECT(t, newRoot);
object ancestors = treePathAncestors(t, path);
PROTECT(t, ancestors);
// rebalance
treeNodeRed(t, new_) = true;
while (ancestors != 0 and treeNodeRed(t, pairFirst(t, ancestors))) {
if (pairFirst(t, ancestors)
== treeNodeLeft(t, pairFirst(t, pairSecond(t, ancestors))))
{
if (treeNodeRed
(t, treeNodeRight(t, pairFirst(t, pairSecond(t, ancestors)))))
{
treeNodeRed(t, pairFirst(t, ancestors)) = true;
object n = clone
(t, treeNodeRight(t, pairFirst(t, pairSecond(t, ancestors))));
set(t, pairFirst(t, pairSecond(t, ancestors)), TreeNodeRight, n);
treeNodeRed
(t, treeNodeRight
(t, pairFirst(t, pairSecond(t, ancestors)))) = false;
treeNodeRed(t, pairFirst(t, pairSecond(t, ancestors))) = false;
new_ = pairFirst(t, pairSecond(t, ancestors));
ancestors = pairSecond(t, pairSecond(t, ancestors));
} else {
if (new_ == treeNodeRight(t, pairFirst(t, ancestors))) {
new_ = pairFirst(t, ancestors);
ancestors = pairSecond(t, ancestors);
object n = leftRotate(t, new_);
if (new_ == treeNodeRight(t, pairFirst(t, ancestors))) {
set(t, pairFirst(t, ancestors), TreeNodeRight, n);
} else {
set(t, pairFirst(t, ancestors), TreeNodeLeft, n);
}
ancestors = makePair(t, n, ancestors);
}
treeNodeRed(t, pairFirst(t, ancestors)) = false;
treeNodeRed(t, pairFirst(t, pairSecond(t, ancestors))) = true;
object n = rightRotate(t, pairFirst(t, pairSecond(t, ancestors)));
if (pairSecond(t, pairSecond(t, ancestors)) == 0) {
newRoot = n;
} else if (treeNodeRight
(t, pairFirst(t, pairSecond(t, pairSecond(t, ancestors))))
== pairFirst(t, pairSecond(t, ancestors)))
{
set(t, pairFirst(t, pairSecond(t, pairSecond(t, ancestors))),
TreeNodeRight, n);
} else {
set(t, pairFirst(t, pairSecond(t, pairSecond(t, ancestors))),
TreeNodeLeft, n);
}
// done
}
} else { // this is just the reverse of the code above (right and
// left swapped):
if (treeNodeRed
(t, treeNodeLeft(t, pairFirst(t, pairSecond(t, ancestors)))))
{
treeNodeRed(t, pairFirst(t, ancestors)) = true;
object n = clone
(t, treeNodeLeft(t, pairFirst(t, pairSecond(t, ancestors))));
set(t, pairFirst(t, pairSecond(t, ancestors)), TreeNodeLeft, n);
treeNodeRed
(t, treeNodeLeft
(t, pairFirst(t, pairSecond(t, ancestors)))) = false;
treeNodeRed(t, pairFirst(t, pairSecond(t, ancestors))) = false;
new_ = pairFirst(t, pairSecond(t, ancestors));
ancestors = pairSecond(t, pairSecond(t, ancestors));
} else {
if (new_ == treeNodeLeft(t, pairFirst(t, ancestors))) {
new_ = pairFirst(t, ancestors);
ancestors = pairSecond(t, ancestors);
object n = rightRotate(t, new_);
if (new_ == treeNodeLeft(t, pairFirst(t, ancestors))) {
set(t, pairFirst(t, ancestors), TreeNodeLeft, n);
} else {
set(t, pairFirst(t, ancestors), TreeNodeRight, n);
}
ancestors = makePair(t, n, ancestors);
}
treeNodeRed(t, pairFirst(t, ancestors)) = false;
treeNodeRed(t, pairFirst(t, pairSecond(t, ancestors))) = true;
object n = leftRotate(t, pairFirst(t, pairSecond(t, ancestors)));
if (pairSecond(t, pairSecond(t, ancestors)) == 0) {
newRoot = n;
} else if (treeNodeLeft
(t, pairFirst(t, pairSecond(t, pairSecond(t, ancestors))))
== pairFirst(t, pairSecond(t, ancestors)))
{
set(t, pairFirst(t, pairSecond(t, pairSecond(t, ancestors))),
TreeNodeLeft, n);
} else {
set(t, pairFirst(t, pairSecond(t, pairSecond(t, ancestors))),
TreeNodeRight, n);
}
// done
}
}
}
treeNodeRed(t, newRoot) = false;
return newRoot;
}
} // namespace
namespace vm {
object
hashMapFindNode(Thread* t, object map, object key,
uint32_t (*hash)(Thread*, object),
bool (*equal)(Thread*, object, object))
{
bool weak = objectClass(t, map)
== arrayBody(t, t->m->types, Machine::WeakHashMapType);
object array = hashMapArray(t, map);
if (array) {
unsigned index = hash(t, key) & (arrayLength(t, array) - 1);
for (object n = arrayBody(t, array, index); n; n = tripleThird(t, n)) {
object k = tripleFirst(t, n);
if (weak) {
k = jreferenceTarget(t, k);
if (k == 0) {
continue;
}
}
if (equal(t, key, k)) {
return n;
}
}
}
return 0;
}
void
hashMapResize(Thread* t, object map, uint32_t (*hash)(Thread*, object),
unsigned size)
{
PROTECT(t, map);
object newArray = 0;
if (size) {
object oldArray = hashMapArray(t, map);
PROTECT(t, oldArray);
unsigned newLength = nextPowerOfTwo(size);
if (oldArray and arrayLength(t, oldArray) == newLength) {
return;
}
newArray = makeArray(t, newLength, true);
if (oldArray) {
bool weak = objectClass(t, map)
== arrayBody(t, t->m->types, Machine::WeakHashMapType);
for (unsigned i = 0; i < arrayLength(t, oldArray); ++i) {
object next;
for (object p = arrayBody(t, oldArray, i); p; p = next) {
next = tripleThird(t, p);
object k = tripleFirst(t, p);
if (weak) {
k = jreferenceTarget(t, k);
if (k == 0) {
continue;
}
}
unsigned index = hash(t, k) & (newLength - 1);
set(t, p, TripleThird, arrayBody(t, newArray, index));
set(t, newArray, ArrayBody + (index * BytesPerWord), p);
}
}
}
}
set(t, map, HashMapArray, newArray);
}
void
hashMapInsert(Thread* t, object map, object key, object value,
uint32_t (*hash)(Thread*, object))
{
bool weak = objectClass(t, map)
== arrayBody(t, t->m->types, Machine::WeakHashMapType);
object array = hashMapArray(t, map);
PROTECT(t, array);
++ hashMapSize(t, map);
if (array == 0 or hashMapSize(t, map) >= arrayLength(t, array) * 2) {
PROTECT(t, map);
PROTECT(t, key);
PROTECT(t, value);
hashMapResize(t, map, hash, array ? arrayLength(t, array) * 2 : 16);
array = hashMapArray(t, map);
}
unsigned index = hash(t, key) & (arrayLength(t, array) - 1);
if (weak) {
PROTECT(t, key);
PROTECT(t, value);
object r = makeWeakReference(t, 0, 0, 0, 0);
jreferenceTarget(t, r) = key;
jreferenceVmNext(t, r) = t->m->weakReferences;
key = t->m->weakReferences = r;
}
object n = makeTriple(t, key, value, arrayBody(t, array, index));
set(t, array, ArrayBody + (index * BytesPerWord), n);
}
object
hashMapRemoveNode(Thread* t, object map, unsigned index, object p, object n)
{
if (p) {
set(t, p, TripleThird, tripleThird(t, n));
} else {
set(t, hashMapArray(t, map), ArrayBody + (index * BytesPerWord),
tripleThird(t, n));
}
-- hashMapSize(t, map);
return n;
}
object
hashMapRemove(Thread* t, object map, object key,
uint32_t (*hash)(Thread*, object),
bool (*equal)(Thread*, object, object))
{
bool weak = objectClass(t, map)
== arrayBody(t, t->m->types, Machine::WeakHashMapType);
object array = hashMapArray(t, map);
object o = 0;
if (array) {
unsigned index = hash(t, key) & (arrayLength(t, array) - 1);
object p = 0;
for (object n = arrayBody(t, array, index); n;) {
object k = tripleFirst(t, n);
if (weak) {
k = jreferenceTarget(t, k);
if (k == 0) {
n = tripleThird(t, hashMapRemoveNode(t, map, index, p, n));
continue;
}
}
if (equal(t, key, k)) {
o = tripleSecond(t, hashMapRemoveNode(t, map, index, p, n));
break;
} else {
p = n;
n = tripleThird(t, n);
}
}
if (hashMapSize(t, map) <= arrayLength(t, array) / 3) {
PROTECT(t, o);
hashMapResize(t, map, hash, arrayLength(t, array) / 2);
}
}
return o;
}
object
hashMapIterator(Thread* t, object map)
{
object array = hashMapArray(t, map);
if (array) {
for (unsigned i = 0; i < arrayLength(t, array); ++i) {
if (arrayBody(t, array, i)) {
return makeHashMapIterator(t, map, arrayBody(t, array, i), i + 1);
}
}
}
return 0;
}
object
hashMapIteratorNext(Thread* t, object it)
{
object map = hashMapIteratorMap(t, it);
object node = hashMapIteratorNode(t, it);
unsigned index = hashMapIteratorIndex(t, it);
if (tripleThird(t, node)) {
return makeHashMapIterator(t, map, tripleThird(t, node), index);
} else {
object array = hashMapArray(t, map);
for (unsigned i = index; i < arrayLength(t, array); ++i) {
if (arrayBody(t, array, i)) {
return makeHashMapIterator(t, map, arrayBody(t, array, i), i + 1);
}
}
return 0;
}
}
void
listAppend(Thread* t, object list, object value)
{
PROTECT(t, list);
++ listSize(t, list);
object p = makePair(t, value, 0);
if (listFront(t, list)) {
set(t, listRear(t, list), PairSecond, p);
} else {
set(t, list, ListFront, p);
}
set(t, list, ListRear, 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, vector, VectorBody + (vectorSize(t, vector) * BytesPerWord), value);
++ vectorSize(t, vector);
return vector;
}
object
treeQuery(Thread* t, object tree, intptr_t key, object sentinal)
{
object node = tree;
while (node != sentinal) {
intptr_t difference = key - treeNodeKey(t, node);
if (difference < 0) {
node = treeNodeLeft(t, node);
} else if (difference > 0) {
node = treeNodeRight(t, node);
} else {
return node;
}
}
return 0;
}
object
treeInsert(Thread* t, object tree, object node, object sentinal)
{
object path = treeFind(t, tree, node, sentinal);
if (treePathFresh(t, path)) {
return treeAdd(t, path);
} else {
return tree;
}
}
} // namespace vm

84
src/util.h Normal file
View File

@ -0,0 +1,84 @@
#ifndef UTIL_H
#define UTIL_H
#include "machine.h"
namespace vm {
object
hashMapFindNode(Thread* t, object map, object key,
uint32_t (*hash)(Thread*, object),
bool (*equal)(Thread*, object, object));
inline object
hashMapFind(Thread* t, object map, object key,
uint32_t (*hash)(Thread*, object),
bool (*equal)(Thread*, object, object))
{
object n = hashMapFindNode(t, map, key, hash, equal);
return (n ? tripleSecond(t, n) : 0);
}
void
hashMapResize(Thread* t, object map, uint32_t (*hash)(Thread*, object),
unsigned size);
void
hashMapInsert(Thread* t, object map, object key, object value,
uint32_t (*hash)(Thread*, object));
inline bool
hashMapInsertOrReplace(Thread* t, object map, object key, object value,
uint32_t (*hash)(Thread*, object),
bool (*equal)(Thread*, object, object))
{
object n = hashMapFindNode(t, map, key, hash, equal);
if (n == 0) {
hashMapInsert(t, map, key, value, hash);
return true;
} else {
set(t, n, TripleSecond, value);
return false;
}
}
inline bool
hashMapInsertMaybe(Thread* t, object map, object key, object value,
uint32_t (*hash)(Thread*, object),
bool (*equal)(Thread*, object, object))
{
object n = hashMapFindNode(t, map, key, hash, equal);
if (n == 0) {
hashMapInsert(t, map, key, value, hash);
return true;
} else {
return false;
}
}
object
hashMapRemove(Thread* t, object map, object key,
uint32_t (*hash)(Thread*, object),
bool (*equal)(Thread*, object, object));
object
hashMapIterator(Thread* t, object map);
object
hashMapIteratorNext(Thread* t, object it);
void
listAppend(Thread* t, object list, object value);
object
vectorAppend(Thread* t, object vector, object value);
object
treeQuery(Thread* t, object tree, intptr_t key, object sentinal);
object
treeInsert(Thread* t, object tree, object node, object sentinal);
} // vm
#endif//UTIL_H

View File

@ -151,21 +151,32 @@ class MySystem: public System {
void append(Thread* t) {
if (last) {
last->next = t;
last = t;
} else {
first = last = t;
}
}
void remove(Thread* t) {
for (Thread** p = &first; *p;) {
if (t == *p) {
*p = t->next;
if (last == t) {
last = 0;
Thread* previous = 0;
for (Thread* current = first; current;) {
if (t == current) {
if (current == first) {
first = t->next;
} else {
previous->next = t->next;
}
if (current == last) {
last = previous;
}
t->next = 0;
break;
} else {
p = &((*p)->next);
previous = current;
current = current->next;
}
}
}