mirror of
https://github.com/corda/corda.git
synced 2025-06-02 23:50:54 +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);
|
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
|
extern "C" JNIEXPORT jdouble JNICALL
|
||||||
Java_java_lang_Math_floor(JNIEnv*, jclass, jdouble val)
|
Java_java_lang_Math_floor(JNIEnv*, jclass, jdouble val)
|
||||||
{
|
{
|
||||||
|
@ -14,6 +14,10 @@ public class ByteArrayOutputStream extends OutputStream {
|
|||||||
this(0);
|
this(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int size() {
|
||||||
|
return length;
|
||||||
|
}
|
||||||
|
|
||||||
public void write(int c) {
|
public void write(int c) {
|
||||||
if (buffer == null) {
|
if (buffer == null) {
|
||||||
buffer = new byte[BufferSize];
|
buffer = new byte[BufferSize];
|
||||||
@ -61,7 +65,6 @@ public class ByteArrayOutputStream extends OutputStream {
|
|||||||
buffer = null;
|
buffer = null;
|
||||||
position = 0;
|
position = 0;
|
||||||
chain = new Cell(b, 0, p, chain);
|
chain = new Cell(b, 0, p, chain);
|
||||||
length -= p;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,6 +3,7 @@ package java.lang;
|
|||||||
public final class Math {
|
public final class Math {
|
||||||
public static final double E = 2.718281828459045;
|
public static final double E = 2.718281828459045;
|
||||||
public static final double PI = 3.141592653589793;
|
public static final double PI = 3.141592653589793;
|
||||||
|
private static boolean randomInitialized = false;
|
||||||
|
|
||||||
private Math() { }
|
private Math() { }
|
||||||
|
|
||||||
@ -62,7 +63,17 @@ public final class Math {
|
|||||||
return (int) Math.floor(v + 0.5);
|
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);
|
public static native double floor(double v);
|
||||||
|
|
||||||
|
10
makefile
10
makefile
@ -28,7 +28,7 @@ src = src
|
|||||||
classpath = classpath
|
classpath = classpath
|
||||||
test = test
|
test = test
|
||||||
|
|
||||||
input = $(test-build)/List.class
|
input = $(test-build)/Exceptions.class
|
||||||
|
|
||||||
build-cxx = g++
|
build-cxx = g++
|
||||||
build-cc = gcc
|
build-cc = gcc
|
||||||
@ -108,10 +108,10 @@ ifeq ($(mode),debug)
|
|||||||
cflags += -O0 -g3 -DNDEBUG
|
cflags += -O0 -g3 -DNDEBUG
|
||||||
endif
|
endif
|
||||||
ifeq ($(mode),stress)
|
ifeq ($(mode),stress)
|
||||||
cflags += -O0 -g3 -DVM_STRESS
|
cflags += -O0 -g3 -DNDEBUG -DVM_STRESS
|
||||||
endif
|
endif
|
||||||
ifeq ($(mode),stress-major)
|
ifeq ($(mode),stress-major)
|
||||||
cflags += -O0 -g3 -DVM_STRESS -DVM_STRESS_MAJOR
|
cflags += -O0 -g3 -DNDEBUG -DVM_STRESS -DVM_STRESS_MAJOR
|
||||||
endif
|
endif
|
||||||
ifeq ($(mode),fast)
|
ifeq ($(mode),fast)
|
||||||
cflags += -O3 -g3 -DNDEBUG
|
cflags += -O3 -g3 -DNDEBUG
|
||||||
@ -145,12 +145,14 @@ interpreter-depends = \
|
|||||||
$(src)/stream.h \
|
$(src)/stream.h \
|
||||||
$(src)/constants.h \
|
$(src)/constants.h \
|
||||||
$(src)/jnienv.h \
|
$(src)/jnienv.h \
|
||||||
$(src)/machine.h
|
$(src)/machine.h \
|
||||||
|
$(src)/util.h
|
||||||
|
|
||||||
interpreter-sources = \
|
interpreter-sources = \
|
||||||
$(src)/$(system).cpp \
|
$(src)/$(system).cpp \
|
||||||
$(src)/finder.cpp \
|
$(src)/finder.cpp \
|
||||||
$(src)/machine.cpp \
|
$(src)/machine.cpp \
|
||||||
|
$(src)/util.cpp \
|
||||||
$(src)/heap.cpp \
|
$(src)/heap.cpp \
|
||||||
$(src)/$(process).cpp \
|
$(src)/$(process).cpp \
|
||||||
$(src)/builtin.cpp \
|
$(src)/builtin.cpp \
|
||||||
|
29
src/buffer.h
29
src/buffer.h
@ -51,6 +51,23 @@ class Buffer {
|
|||||||
position += 4;
|
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) {
|
void set2(unsigned offset, uint32_t v) {
|
||||||
assert(s, offset + 2 <= position);
|
assert(s, offset + 2 <= position);
|
||||||
memcpy(data + offset, &v, 2);
|
memcpy(data + offset, &v, 2);
|
||||||
@ -81,15 +98,9 @@ class Buffer {
|
|||||||
return *reinterpret_cast<uintptr_t*>(data + offset);
|
return *reinterpret_cast<uintptr_t*>(data + offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
void appendAddress(uintptr_t v) {
|
void get(unsigned offset, void* p, unsigned size) {
|
||||||
append4(v);
|
assert(s, offset + size <= position);
|
||||||
if (BytesPerWord == 8) {
|
memcpy(p, data + offset, size);
|
||||||
// we have to use the preprocessor here to avoid a warning on
|
|
||||||
// 32-bit systems
|
|
||||||
#ifdef __x86_64__
|
|
||||||
append4(v >> 32);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned length() {
|
unsigned length() {
|
||||||
|
@ -108,7 +108,7 @@ Java_java_lang_Object_clone(Thread* t, jclass, jobject o)
|
|||||||
// clear any object header flags:
|
// clear any object header flags:
|
||||||
setObjectClass(t, *o, objectClass(t, *o));
|
setObjectClass(t, *o, objectClass(t, *o));
|
||||||
} else {
|
} else {
|
||||||
clone = make(t, objectClass(t, *o));
|
clone = make(t, class_);
|
||||||
memcpy(reinterpret_cast<void**>(clone) + 1,
|
memcpy(reinterpret_cast<void**>(clone) + 1,
|
||||||
reinterpret_cast<void**>(*o) + 1,
|
reinterpret_cast<void**>(*o) + 1,
|
||||||
size - BytesPerWord);
|
size - BytesPerWord);
|
||||||
@ -317,12 +317,28 @@ Java_java_lang_reflect_Method_getCaller(Thread* t, jclass)
|
|||||||
{
|
{
|
||||||
ENTER(t, Thread::ActiveState);
|
ENTER(t, Thread::ActiveState);
|
||||||
|
|
||||||
Processor* p = t->m->processor;
|
class Visitor: public Processor::StackVisitor {
|
||||||
uintptr_t frame = p->frameStart(t);
|
public:
|
||||||
frame = p->frameNext(t, frame);
|
Visitor(Thread* t): t(t), method(0), count(0) { }
|
||||||
frame = p->frameNext(t, frame);
|
|
||||||
|
|
||||||
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
|
extern "C" JNIEXPORT jobject JNICALL
|
||||||
@ -567,27 +583,41 @@ Java_java_lang_Throwable_trace(Thread* t, jclass, jint skipCount)
|
|||||||
{
|
{
|
||||||
ENTER(t, Thread::ActiveState);
|
ENTER(t, Thread::ActiveState);
|
||||||
|
|
||||||
Processor* p = t->m->processor;
|
class Visitor: public Processor::StackVisitor {
|
||||||
uintptr_t frame = p->frameStart(t);
|
public:
|
||||||
|
Visitor(Thread* t, int skipCount):
|
||||||
|
t(t), trace(0), skipCount(skipCount)
|
||||||
|
{ }
|
||||||
|
|
||||||
while (skipCount-- and p->frameValid(t, frame)) {
|
virtual bool visit(Processor::StackWalker* walker) {
|
||||||
frame = p->frameNext(t, frame);
|
if (skipCount == 0) {
|
||||||
}
|
object method = walker->method();
|
||||||
|
if (isAssignableFrom
|
||||||
// skip Throwable constructors
|
(t, arrayBody(t, t->m->types, Machine::ThrowableType),
|
||||||
while (p->frameValid(t, frame)
|
methodClass(t, method))
|
||||||
and isAssignableFrom
|
and strcmp(reinterpret_cast<const int8_t*>("<init>"),
|
||||||
(t, arrayBody(t, t->m->types, Machine::ThrowableType),
|
&byteArrayBody(t, methodName(t, method), 0))
|
||||||
methodClass(t, p->frameMethod(t, frame)))
|
== 0)
|
||||||
and strcmp(reinterpret_cast<const int8_t*>("<init>"),
|
{
|
||||||
&byteArrayBody
|
return true;
|
||||||
(t, methodName(t, p->frameMethod(t, frame)), 0))
|
} else {
|
||||||
== 0)
|
trace = makeTrace(t, walker);
|
||||||
{
|
return false;
|
||||||
frame = p->frameNext(t, frame);
|
}
|
||||||
}
|
} 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
|
extern "C" JNIEXPORT jarray JNICALL
|
||||||
|
@ -239,6 +239,12 @@ bitsToFloat(uint32_t bits)
|
|||||||
return f;
|
return f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline intptr_t
|
||||||
|
difference(void* a, void* b)
|
||||||
|
{
|
||||||
|
return reinterpret_cast<intptr_t>(a) - reinterpret_cast<intptr_t>(b);
|
||||||
|
}
|
||||||
|
|
||||||
class Machine;
|
class Machine;
|
||||||
class Thread;
|
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 Operand { };
|
||||||
|
|
||||||
|
class Promise {
|
||||||
|
public:
|
||||||
|
virtual ~Promise() { }
|
||||||
|
|
||||||
|
virtual unsigned value() = 0;
|
||||||
|
};
|
||||||
|
|
||||||
class Compiler {
|
class Compiler {
|
||||||
public:
|
public:
|
||||||
virtual ~Compiler() { }
|
virtual ~Compiler() { }
|
||||||
|
|
||||||
|
virtual Promise* poolOffset() = 0;
|
||||||
|
virtual Promise* codeOffset() = 0;
|
||||||
|
|
||||||
virtual Operand* poolAppend(Operand*) = 0;
|
virtual Operand* poolAppend(Operand*) = 0;
|
||||||
virtual unsigned poolOffset() = 0;
|
|
||||||
virtual unsigned poolOffset(Operand*) = 0;
|
|
||||||
|
|
||||||
virtual Operand* constant(intptr_t) = 0;
|
virtual Operand* constant(intptr_t) = 0;
|
||||||
|
|
||||||
virtual void push(Operand*) = 0;
|
virtual void push(Operand*) = 0;
|
||||||
virtual void push2(Operand*) = 0;
|
virtual void push2(Operand*) = 0;
|
||||||
virtual Operand* stack() = 0;
|
|
||||||
virtual Operand* stack(unsigned) = 0;
|
virtual Operand* stack(unsigned) = 0;
|
||||||
virtual Operand* stack2(unsigned) = 0;
|
virtual Operand* stack2(unsigned) = 0;
|
||||||
virtual Operand* pop() = 0;
|
virtual Operand* pop() = 0;
|
||||||
@ -27,10 +34,10 @@ class Compiler {
|
|||||||
virtual void pop(Operand*) = 0;
|
virtual void pop(Operand*) = 0;
|
||||||
virtual void pop2(Operand*) = 0;
|
virtual void pop2(Operand*) = 0;
|
||||||
|
|
||||||
|
virtual Operand* stack() = 0;
|
||||||
virtual Operand* base() = 0;
|
virtual Operand* base() = 0;
|
||||||
virtual Operand* thread() = 0;
|
virtual Operand* thread() = 0;
|
||||||
virtual Operand* indirectTarget() = 0;
|
virtual Operand* indirectTarget() = 0;
|
||||||
|
|
||||||
virtual Operand* temporary() = 0;
|
virtual Operand* temporary() = 0;
|
||||||
virtual void release(Operand*) = 0;
|
virtual void release(Operand*) = 0;
|
||||||
|
|
||||||
@ -45,6 +52,7 @@ class Compiler {
|
|||||||
(Operand* address, unsigned argumentCount, ...) = 0;
|
(Operand* address, unsigned argumentCount, ...) = 0;
|
||||||
virtual Operand* directCall
|
virtual Operand* directCall
|
||||||
(Operand* address, unsigned argumentCount, ...) = 0;
|
(Operand* address, unsigned argumentCount, ...) = 0;
|
||||||
|
|
||||||
virtual void return_(Operand*) = 0;
|
virtual void return_(Operand*) = 0;
|
||||||
virtual void ret() = 0;
|
virtual void ret() = 0;
|
||||||
|
|
||||||
@ -88,10 +96,13 @@ class Compiler {
|
|||||||
|
|
||||||
virtual void startLogicalIp(unsigned) = 0;
|
virtual void startLogicalIp(unsigned) = 0;
|
||||||
virtual Operand* logicalIp(unsigned) = 0;
|
virtual Operand* logicalIp(unsigned) = 0;
|
||||||
|
virtual unsigned logicalIpToOffset(unsigned) = 0;
|
||||||
|
|
||||||
virtual unsigned size() = 0;
|
virtual unsigned size() = 0;
|
||||||
virtual void writeTo(void*) = 0;
|
virtual void writeTo(void*) = 0;
|
||||||
|
|
||||||
|
virtual void updateCall(void* returnAddress, void* newTarget);
|
||||||
|
|
||||||
virtual void dispose() = 0;
|
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
|
object
|
||||||
makeNativeMethodData(Thread* t, object method, void* function)
|
makeNativeMethodData(Thread* t, object method, void* function)
|
||||||
{
|
{
|
||||||
@ -663,43 +696,7 @@ store(Thread* t, unsigned index)
|
|||||||
ExceptionHandler*
|
ExceptionHandler*
|
||||||
findExceptionHandler(Thread* t, int frame)
|
findExceptionHandler(Thread* t, int frame)
|
||||||
{
|
{
|
||||||
object method = frameMethod(t, frame);
|
return findExceptionHandler(t, frameMethod(t, frame), frameIp(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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -768,7 +765,7 @@ interpret(Thread* t)
|
|||||||
&byteArrayBody
|
&byteArrayBody
|
||||||
(t, methodName(t, frameMethod(t, frame)), 0));
|
(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) {
|
switch (line) {
|
||||||
case NativeLine:
|
case NativeLine:
|
||||||
fprintf(stderr, "(native)\n");
|
fprintf(stderr, "(native)\n");
|
||||||
@ -1931,7 +1928,7 @@ interpret(Thread* t)
|
|||||||
uint32_t offset = codeReadInt32(t, code, ip);
|
uint32_t offset = codeReadInt32(t, code, ip);
|
||||||
|
|
||||||
pushInt(t, ip);
|
pushInt(t, ip);
|
||||||
ip = (ip - 3) + static_cast<int32_t>(offset);
|
ip = (ip - 5) + static_cast<int32_t>(offset);
|
||||||
} goto loop;
|
} goto loop;
|
||||||
|
|
||||||
case l2i: {
|
case l2i: {
|
||||||
@ -2900,74 +2897,23 @@ class MyProcessor: public Processor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual uintptr_t
|
virtual void
|
||||||
frameStart(vm::Thread* vmt)
|
walkStack(vm::Thread* vmt, StackVisitor* v)
|
||||||
{
|
{
|
||||||
Thread* t = static_cast<Thread*>(vmt);
|
Thread* t = static_cast<Thread*>(vmt);
|
||||||
|
|
||||||
if (t->frame >= 0) {
|
if (t->frame >= 0) {
|
||||||
pokeInt(t, t->frame + FrameIpOffset, t->ip);
|
pokeInt(t, t->frame + FrameIpOffset, t->ip);
|
||||||
}
|
}
|
||||||
return t->frame;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual uintptr_t
|
MyStackWalker walker(t, t->frame);
|
||||||
frameNext(vm::Thread* vmt, uintptr_t frame)
|
walker.walk(v);
|
||||||
{
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual int
|
virtual int
|
||||||
lineNumber(vm::Thread* vmt, object method, unsigned ip)
|
lineNumber(vm::Thread* t, object method, int ip)
|
||||||
{
|
{
|
||||||
Thread* t = static_cast<Thread*>(vmt);
|
return findLineNumber(static_cast<Thread*>(t), method, ip);
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual object*
|
virtual object*
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#include "jnienv.h"
|
#include "jnienv.h"
|
||||||
#include "machine.h"
|
#include "machine.h"
|
||||||
|
#include "util.h"
|
||||||
#include "processor.h"
|
#include "processor.h"
|
||||||
#include "constants.h"
|
#include "constants.h"
|
||||||
#include "processor.h"
|
#include "processor.h"
|
||||||
|
426
src/machine.cpp
426
src/machine.cpp
@ -1,5 +1,6 @@
|
|||||||
#include "jnienv.h"
|
#include "jnienv.h"
|
||||||
#include "machine.h"
|
#include "machine.h"
|
||||||
|
#include "util.h"
|
||||||
#include "stream.h"
|
#include "stream.h"
|
||||||
#include "constants.h"
|
#include "constants.h"
|
||||||
#include "processor.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
|
void
|
||||||
dispose(Thread* t, Thread* o, bool remove)
|
dispose(Thread* t, Thread* o, bool remove)
|
||||||
{
|
{
|
||||||
if (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->parent) {
|
||||||
if (o->child) {
|
Thread* previous = 0;
|
||||||
o->parent->child = o->child;
|
for (Thread* p = o->parent->child; p;) {
|
||||||
if (o->peer) {
|
if (p == o) {
|
||||||
o->peer->peer = o->child->peer;
|
if (p == o->parent->child) {
|
||||||
o->child->peer = o->peer;
|
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 {
|
for (Thread* p = o->child; p;) {
|
||||||
o->parent->child = 0;
|
Thread* next = p->peer;
|
||||||
|
p->peer = o->parent->child;
|
||||||
|
o->parent->child = p;
|
||||||
|
p->parent = o->parent;
|
||||||
|
p = next;
|
||||||
}
|
}
|
||||||
} else if (o->child) {
|
} else if (o->child) {
|
||||||
t->m->rootThread = o->child;
|
t->m->rootThread = o->child;
|
||||||
if (o->peer) {
|
|
||||||
o->peer->peer = o->child->peer;
|
for (Thread* p = o->peer; p;) {
|
||||||
o->child->peer = o->peer;
|
Thread* next = p->peer;
|
||||||
}
|
p->peer = t->m->rootThread;
|
||||||
|
t->m->rootThread = p;
|
||||||
|
p = next;
|
||||||
|
}
|
||||||
} else if (o->peer) {
|
} else if (o->peer) {
|
||||||
t->m->rootThread = o->peer;
|
t->m->rootThread = o->peer;
|
||||||
} else {
|
} else {
|
||||||
abort(t);
|
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();
|
o->dispose();
|
||||||
@ -796,7 +855,7 @@ parseInterfaceTable(Thread* t, Stream& s, object class_, object pool)
|
|||||||
if (classSuper(t, class_)) {
|
if (classSuper(t, class_)) {
|
||||||
addInterfaces(t, classSuper(t, class_), map);
|
addInterfaces(t, classSuper(t, class_), map);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned count = s.read2();
|
unsigned count = s.read2();
|
||||||
for (unsigned i = 0; i < count; ++i) {
|
for (unsigned i = 0; i < count; ++i) {
|
||||||
object name = singletonObject(t, pool, s.read2() - 1);
|
object name = singletonObject(t, pool, s.read2() - 1);
|
||||||
@ -1289,12 +1348,17 @@ parseMethodTable(Thread* t, Stream& s, object class_, object pool)
|
|||||||
if (declaredVirtualCount == 0
|
if (declaredVirtualCount == 0
|
||||||
and (classFlags(t, class_) & ACC_INTERFACE) == 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,
|
if (classInterfaceTable(t, classSuper(t, class_))
|
||||||
classInterfaceTable(t, classSuper(t, class_)));
|
and arrayLength(t, classInterfaceTable(t, class_))
|
||||||
|
== arrayLength(t, classInterfaceTable(t, classSuper(t, class_))))
|
||||||
set(t, class_, ClassVirtualTable, superVirtualTable);
|
{
|
||||||
|
// inherit interface table from superclass
|
||||||
|
set(t, class_, ClassInterfaceTable,
|
||||||
|
classInterfaceTable(t, classSuper(t, class_)));
|
||||||
|
}
|
||||||
} else if (virtualCount) {
|
} else if (virtualCount) {
|
||||||
// generate class vtable
|
// generate class vtable
|
||||||
|
|
||||||
@ -1891,6 +1955,7 @@ Thread::init()
|
|||||||
#include "type-java-initializations.cpp"
|
#include "type-java-initializations.cpp"
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
peer = parent->child;
|
||||||
parent->child = this;
|
parent->child = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2047,6 +2112,8 @@ enter(Thread* t, Thread::State s)
|
|||||||
case Thread::ExclusiveState: {
|
case Thread::ExclusiveState: {
|
||||||
assert(t, t->m->exclusive == t);
|
assert(t, t->m->exclusive == t);
|
||||||
t->m->exclusive = 0;
|
t->m->exclusive = 0;
|
||||||
|
|
||||||
|
t->m->stateLock->notifyAll(t->systemThread);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case Thread::ActiveState: break;
|
case Thread::ActiveState: break;
|
||||||
@ -2226,253 +2293,6 @@ classInitializer(Thread* t, object class_)
|
|||||||
abort(t);
|
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
|
unsigned
|
||||||
fieldCode(Thread* t, unsigned javaCode)
|
fieldCode(Thread* t, unsigned javaCode)
|
||||||
{
|
{
|
||||||
@ -2878,7 +2698,7 @@ addFinalizer(Thread* t, object target, void (*finalize)(Thread*, object))
|
|||||||
}
|
}
|
||||||
|
|
||||||
System::Monitor*
|
System::Monitor*
|
||||||
objectMonitor(Thread* t, object o)
|
objectMonitor(Thread* t, object o, bool createNew)
|
||||||
{
|
{
|
||||||
object p = hashMapFind(t, t->m->monitorMap, o, objectHash, objectEqual);
|
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));
|
return static_cast<System::Monitor*>(pointerValue(t, p));
|
||||||
} else {
|
} else if (createNew) {
|
||||||
PROTECT(t, o);
|
PROTECT(t, o);
|
||||||
|
|
||||||
ENTER(t, Thread::ExclusiveState);
|
ENTER(t, Thread::ExclusiveState);
|
||||||
@ -2911,6 +2731,8 @@ objectMonitor(Thread* t, object o)
|
|||||||
addFinalizer(t, o, removeMonitor);
|
addFinalizer(t, o, removeMonitor);
|
||||||
|
|
||||||
return m;
|
return m;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3010,33 +2832,53 @@ printTrace(Thread* t, object exception)
|
|||||||
}
|
}
|
||||||
|
|
||||||
object
|
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;
|
virtual bool visit(Processor::StackWalker* walker) {
|
||||||
for (uintptr_t frame = start;
|
if (trace == 0) {
|
||||||
p->frameValid(t, frame);
|
trace = makeArray(t, walker->count(), true);
|
||||||
frame = p->frameNext(t, frame))
|
}
|
||||||
{
|
|
||||||
++ count;
|
|
||||||
}
|
|
||||||
|
|
||||||
object trace = makeArray(t, count, true);
|
object e = makeTraceElement(t, walker->method(), walker->ip());
|
||||||
PROTECT(t, trace);
|
set(t, trace, ArrayBody + (index * BytesPerWord), e);
|
||||||
|
++ index;
|
||||||
unsigned index = 0;
|
return true;
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
void
|
||||||
|
@ -1505,13 +1505,10 @@ baseSize(Thread* t, object o, object class_)
|
|||||||
}
|
}
|
||||||
|
|
||||||
object
|
object
|
||||||
makeTrace(Thread* t, uintptr_t start);
|
makeTrace(Thread* t, Processor::StackWalker* walker);
|
||||||
|
|
||||||
inline object
|
object
|
||||||
makeTrace(Thread* t)
|
makeTrace(Thread* t);
|
||||||
{
|
|
||||||
return makeTrace(t, t->m->processor->frameStart(t));
|
|
||||||
}
|
|
||||||
|
|
||||||
inline object
|
inline object
|
||||||
makeRuntimeException(Thread* t, object message)
|
makeRuntimeException(Thread* t, object message)
|
||||||
@ -1835,74 +1832,6 @@ methodEqual(Thread* t, object a, object b)
|
|||||||
byteArrayEqual(t, methodSpec(t, a), methodSpec(t, 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 {
|
class MethodSpecIterator {
|
||||||
public:
|
public:
|
||||||
MethodSpecIterator(Thread* t, const char* s):
|
MethodSpecIterator(Thread* t, const char* s):
|
||||||
@ -2069,12 +1998,12 @@ void
|
|||||||
addFinalizer(Thread* t, object target, void (*finalize)(Thread*, object));
|
addFinalizer(Thread* t, object target, void (*finalize)(Thread*, object));
|
||||||
|
|
||||||
System::Monitor*
|
System::Monitor*
|
||||||
objectMonitor(Thread* t, object o);
|
objectMonitor(Thread* t, object o, bool createNew);
|
||||||
|
|
||||||
inline void
|
inline void
|
||||||
acquire(Thread* t, object o)
|
acquire(Thread* t, object o)
|
||||||
{
|
{
|
||||||
System::Monitor* m = objectMonitor(t, o);
|
System::Monitor* m = objectMonitor(t, o, true);
|
||||||
|
|
||||||
if (DebugMonitors) {
|
if (DebugMonitors) {
|
||||||
fprintf(stderr, "thread %p acquires %p for %x\n",
|
fprintf(stderr, "thread %p acquires %p for %x\n",
|
||||||
@ -2087,7 +2016,7 @@ acquire(Thread* t, object o)
|
|||||||
inline void
|
inline void
|
||||||
release(Thread* t, object o)
|
release(Thread* t, object o)
|
||||||
{
|
{
|
||||||
System::Monitor* m = objectMonitor(t, o);
|
System::Monitor* m = objectMonitor(t, o, false);
|
||||||
|
|
||||||
if (DebugMonitors) {
|
if (DebugMonitors) {
|
||||||
fprintf(stderr, "thread %p releases %p for %x\n",
|
fprintf(stderr, "thread %p releases %p for %x\n",
|
||||||
@ -2100,14 +2029,14 @@ release(Thread* t, object o)
|
|||||||
inline void
|
inline void
|
||||||
wait(Thread* t, object o, int64_t milliseconds)
|
wait(Thread* t, object o, int64_t milliseconds)
|
||||||
{
|
{
|
||||||
System::Monitor* m = objectMonitor(t, o);
|
System::Monitor* m = objectMonitor(t, o, false);
|
||||||
|
|
||||||
if (DebugMonitors) {
|
if (DebugMonitors) {
|
||||||
fprintf(stderr, "thread %p waits %"LLD" millis on %p for %x\n",
|
fprintf(stderr, "thread %p waits %"LLD" millis on %p for %x\n",
|
||||||
t, milliseconds, m, objectHash(t, o));
|
t, milliseconds, m, objectHash(t, o));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m->owner() == t->systemThread) {
|
if (m and m->owner() == t->systemThread) {
|
||||||
ENTER(t, Thread::IdleState);
|
ENTER(t, Thread::IdleState);
|
||||||
|
|
||||||
bool interrupted = m->wait(t->systemThread, milliseconds);
|
bool interrupted = m->wait(t->systemThread, milliseconds);
|
||||||
@ -2129,14 +2058,14 @@ wait(Thread* t, object o, int64_t milliseconds)
|
|||||||
inline void
|
inline void
|
||||||
notify(Thread* t, object o)
|
notify(Thread* t, object o)
|
||||||
{
|
{
|
||||||
System::Monitor* m = objectMonitor(t, o);
|
System::Monitor* m = objectMonitor(t, o, false);
|
||||||
|
|
||||||
if (DebugMonitors) {
|
if (DebugMonitors) {
|
||||||
fprintf(stderr, "thread %p notifies on %p for %x\n",
|
fprintf(stderr, "thread %p notifies on %p for %x\n",
|
||||||
t, m, objectHash(t, o));
|
t, m, objectHash(t, o));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m->owner() == t->systemThread) {
|
if (m and m->owner() == t->systemThread) {
|
||||||
m->notify(t->systemThread);
|
m->notify(t->systemThread);
|
||||||
} else {
|
} else {
|
||||||
t->exception = makeIllegalMonitorStateException(t);
|
t->exception = makeIllegalMonitorStateException(t);
|
||||||
@ -2146,14 +2075,14 @@ notify(Thread* t, object o)
|
|||||||
inline void
|
inline void
|
||||||
notifyAll(Thread* t, object o)
|
notifyAll(Thread* t, object o)
|
||||||
{
|
{
|
||||||
System::Monitor* m = objectMonitor(t, o);
|
System::Monitor* m = objectMonitor(t, o, false);
|
||||||
|
|
||||||
if (DebugMonitors) {
|
if (DebugMonitors) {
|
||||||
fprintf(stderr, "thread %p notifies all on %p for %x\n",
|
fprintf(stderr, "thread %p notifies all on %p for %x\n",
|
||||||
t, m, objectHash(t, o));
|
t, m, objectHash(t, o));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m->owner() == t->systemThread) {
|
if (m and m->owner() == t->systemThread) {
|
||||||
m->notifyAll(t->systemThread);
|
m->notifyAll(t->systemThread);
|
||||||
} else {
|
} else {
|
||||||
t->exception = makeIllegalMonitorStateException(t);
|
t->exception = makeIllegalMonitorStateException(t);
|
||||||
|
@ -80,7 +80,7 @@ class MySystem: public System {
|
|||||||
|
|
||||||
virtual void join() {
|
virtual void join() {
|
||||||
int rv UNUSED = pthread_join(thread, 0);
|
int rv UNUSED = pthread_join(thread, 0);
|
||||||
assert(s, rv == 0);
|
expect(s, rv == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void dispose() {
|
virtual void dispose() {
|
||||||
@ -150,21 +150,32 @@ class MySystem: public System {
|
|||||||
void append(Thread* t) {
|
void append(Thread* t) {
|
||||||
if (last) {
|
if (last) {
|
||||||
last->next = t;
|
last->next = t;
|
||||||
|
last = t;
|
||||||
} else {
|
} else {
|
||||||
first = last = t;
|
first = last = t;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void remove(Thread* t) {
|
void remove(Thread* t) {
|
||||||
for (Thread** p = &first; *p;) {
|
Thread* previous = 0;
|
||||||
if (t == *p) {
|
for (Thread* current = first; current;) {
|
||||||
*p = t->next;
|
if (t == current) {
|
||||||
if (last == t) {
|
if (current == first) {
|
||||||
last = 0;
|
first = t->next;
|
||||||
|
} else {
|
||||||
|
previous->next = t->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (current == last) {
|
||||||
|
last = previous;
|
||||||
|
}
|
||||||
|
|
||||||
|
t->next = 0;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
} else {
|
} 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 };
|
timespec ts = { then / 1000, (then % 1000) * 1000 * 1000 };
|
||||||
int rv UNUSED = pthread_cond_timedwait
|
int rv UNUSED = pthread_cond_timedwait
|
||||||
(&(t->condition), &(t->mutex), &ts);
|
(&(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 {
|
} else {
|
||||||
int rv UNUSED = pthread_cond_wait(&(t->condition), &(t->mutex));
|
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);
|
pthread_mutex_lock(&mutex);
|
||||||
@ -227,7 +238,7 @@ class MySystem: public System {
|
|||||||
|
|
||||||
t->flags |= Notified;
|
t->flags |= Notified;
|
||||||
int rv UNUSED = pthread_cond_signal(&(t->condition));
|
int rv UNUSED = pthread_cond_signal(&(t->condition));
|
||||||
assert(s, rv == 0);
|
expect(s, rv == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void notify(System::Thread* context) {
|
virtual void notify(System::Thread* context) {
|
||||||
@ -266,7 +277,7 @@ class MySystem: public System {
|
|||||||
}
|
}
|
||||||
|
|
||||||
virtual void dispose() {
|
virtual void dispose() {
|
||||||
assert(s, owner_ == 0);
|
expect(s, owner_ == 0);
|
||||||
pthread_mutex_destroy(&mutex);
|
pthread_mutex_destroy(&mutex);
|
||||||
s->free(this);
|
s->free(this);
|
||||||
}
|
}
|
||||||
@ -283,7 +294,7 @@ class MySystem: public System {
|
|||||||
public:
|
public:
|
||||||
Local(System* s): s(s) {
|
Local(System* s): s(s) {
|
||||||
int r UNUSED = pthread_key_create(&key, 0);
|
int r UNUSED = pthread_key_create(&key, 0);
|
||||||
assert(s, r == 0);
|
expect(s, r == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void* get() {
|
virtual void* get() {
|
||||||
@ -292,12 +303,12 @@ class MySystem: public System {
|
|||||||
|
|
||||||
virtual void set(void* p) {
|
virtual void set(void* p) {
|
||||||
int r UNUSED = pthread_setspecific(key, p);
|
int r UNUSED = pthread_setspecific(key, p);
|
||||||
assert(s, r == 0);
|
expect(s, r == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void dispose() {
|
virtual void dispose() {
|
||||||
int r UNUSED = pthread_key_delete(key);
|
int r UNUSED = pthread_key_delete(key);
|
||||||
assert(s, r == 0);
|
expect(s, r == 0);
|
||||||
|
|
||||||
s->free(this);
|
s->free(this);
|
||||||
}
|
}
|
||||||
@ -395,7 +406,7 @@ class MySystem: public System {
|
|||||||
sa.sa_handler = handleSignal;
|
sa.sa_handler = handleSignal;
|
||||||
|
|
||||||
int rv UNUSED = sigaction(InterruptSignal, &sa, 0);
|
int rv UNUSED = sigaction(InterruptSignal, &sa, 0);
|
||||||
assert(this, rv == 0);
|
expect(this, rv == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool success(Status s) {
|
virtual bool success(Status s) {
|
||||||
@ -455,7 +466,7 @@ class MySystem: public System {
|
|||||||
Thread* t = new (System::allocate(sizeof(Thread))) Thread(this, r);
|
Thread* t = new (System::allocate(sizeof(Thread))) Thread(this, r);
|
||||||
r->attach(t);
|
r->attach(t);
|
||||||
int rv UNUSED = pthread_create(&(t->thread), 0, run, r);
|
int rv UNUSED = pthread_create(&(t->thread), 0, run, r);
|
||||||
assert(this, rv == 0);
|
expect(this, rv == 0);
|
||||||
return 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
|
} // namespace vm
|
||||||
|
|
||||||
#endif//PROCESS_H
|
#endif//PROCESS_H
|
||||||
|
@ -9,6 +9,28 @@ namespace vm {
|
|||||||
|
|
||||||
class Processor {
|
class Processor {
|
||||||
public:
|
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 ~Processor() { }
|
||||||
|
|
||||||
virtual Thread*
|
virtual Thread*
|
||||||
@ -51,23 +73,11 @@ class Processor {
|
|||||||
virtual void
|
virtual void
|
||||||
visitObjects(Thread* t, Heap::Visitor* v) = 0;
|
visitObjects(Thread* t, Heap::Visitor* v) = 0;
|
||||||
|
|
||||||
virtual uintptr_t
|
virtual void
|
||||||
frameStart(Thread* t) = 0;
|
walkStack(Thread* t, StackVisitor* v) = 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 int
|
virtual int
|
||||||
lineNumber(Thread* t, object method, unsigned ip) = 0;
|
lineNumber(Thread* t, object method, int ip) = 0;
|
||||||
|
|
||||||
virtual object*
|
virtual object*
|
||||||
makeLocalReference(Thread* t, object o) = 0;
|
makeLocalReference(Thread* t, object o) = 0;
|
||||||
|
@ -24,17 +24,17 @@
|
|||||||
(void* value))
|
(void* value))
|
||||||
|
|
||||||
(pod exceptionHandler
|
(pod exceptionHandler
|
||||||
(uint16_t start)
|
(uint32_t start)
|
||||||
(uint16_t end)
|
(uint32_t end)
|
||||||
(uint16_t ip)
|
(uint32_t ip)
|
||||||
(uint16_t catchType))
|
(uint32_t catchType))
|
||||||
|
|
||||||
(type exceptionHandlerTable
|
(type exceptionHandlerTable
|
||||||
(array exceptionHandler body))
|
(array exceptionHandler body))
|
||||||
|
|
||||||
(pod lineNumber
|
(pod lineNumber
|
||||||
(uint16_t ip)
|
(uint32_t ip)
|
||||||
(uint16_t line))
|
(uint32_t line))
|
||||||
|
|
||||||
(type lineNumberTable
|
(type lineNumberTable
|
||||||
(array lineNumber body))
|
(array lineNumber body))
|
||||||
@ -89,8 +89,27 @@
|
|||||||
|
|
||||||
(type traceElement
|
(type traceElement
|
||||||
(object method)
|
(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
|
(type array
|
||||||
(noassert array object body))
|
(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) {
|
void append(Thread* t) {
|
||||||
if (last) {
|
if (last) {
|
||||||
last->next = t;
|
last->next = t;
|
||||||
|
last = t;
|
||||||
} else {
|
} else {
|
||||||
first = last = t;
|
first = last = t;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void remove(Thread* t) {
|
void remove(Thread* t) {
|
||||||
for (Thread** p = &first; *p;) {
|
Thread* previous = 0;
|
||||||
if (t == *p) {
|
for (Thread* current = first; current;) {
|
||||||
*p = t->next;
|
if (t == current) {
|
||||||
if (last == t) {
|
if (current == first) {
|
||||||
last = 0;
|
first = t->next;
|
||||||
|
} else {
|
||||||
|
previous->next = t->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (current == last) {
|
||||||
|
last = previous;
|
||||||
|
}
|
||||||
|
|
||||||
|
t->next = 0;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
p = &((*p)->next);
|
previous = current;
|
||||||
|
current = current->next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user