mirror of
https://github.com/corda/corda.git
synced 2025-01-22 04:18:31 +00:00
Merge branch 'master' of dice.readytalk.com:/home/dicej/git/vm
This commit is contained in:
commit
b6ad93856d
@ -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)
|
||||
{
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
10
makefile
10
makefile
@ -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 \
|
||||
|
29
src/buffer.h
29
src/buffer.h
@ -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() {
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
||||
|
845
src/compile2.cpp
845
src/compile2.cpp
File diff suppressed because it is too large
Load Diff
@ -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;
|
||||
};
|
||||
|
||||
|
@ -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*
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include "jnienv.h"
|
||||
#include "machine.h"
|
||||
#include "util.h"
|
||||
#include "processor.h"
|
||||
#include "constants.h"
|
||||
#include "processor.h"
|
||||
|
426
src/machine.cpp
426
src/machine.cpp
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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
497
src/util.cpp
Normal 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
84
src/util.h
Normal 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
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user