flesh out call tracing in new JIT code

This commit is contained in:
Joel Dice 2007-11-26 16:15:53 -07:00
parent 49ed41daa0
commit 0bbe9489a7
12 changed files with 689 additions and 451 deletions

View File

@ -145,12 +145,14 @@ interpreter-depends = \
$(src)/stream.h \
$(src)/constants.h \
$(src)/jnienv.h \
$(src)/machine.h
$(src)/machine.h \
$(src)/util.h
interpreter-sources = \
$(src)/$(system).cpp \
$(src)/finder.cpp \
$(src)/machine.cpp \
$(src)/util.cpp \
$(src)/heap.cpp \
$(src)/$(process).cpp \
$(src)/builtin.cpp \

View File

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

View File

@ -1,4 +1,5 @@
#include "machine.h"
#include "util.h"
#include "buffer.h"
#include "process.h"
#include "compiler.h"
@ -84,6 +85,9 @@ resolveTarget(MyThread* t, void* stack, object method)
object
findTraceNode(MyThread* t, void* address);
void
insertTraceNode(MyThread* t, object node);
class MyStackWalker: public Processor::StackWalker {
public:
class MyProtector: public Thread::Protector {
@ -175,9 +179,9 @@ class MyStackWalker: public Processor::StackWalker {
virtual int ip() {
if (nativeMethod) {
return NativeLine;
return 0;
} else {
return traceNodeLine(t, node);
return treeNodeKey(t, node);
}
}
@ -235,7 +239,7 @@ class Frame {
public:
class MyProtector: public Thread::Protector {
public:
MyProtector(MyThread* t, Frame* frame): Protector(t), frame(frame) { }
MyProtector(Frame* frame): Protector(frame->t), frame(frame) { }
virtual void visit(Heap::Visitor* v) {
v->visit(&(frame->method));
@ -245,6 +249,12 @@ class Frame {
for (unsigned i = 1; i < pool->length(); i += BytesPerWord * 2) {
v->visit(reinterpret_cast<object*>(&(pool->getAddress(i))));
}
Buffer* log = frame->traceLog;
unsigned traceSize = traceSizeInBytes(t, frame->method);
for (unsigned i = 1; i < log->length(); i += traceSize) {
v->visit(reinterpret_cast<object*>(&(log->getAddress(i))));
}
}
}
@ -252,16 +262,18 @@ class Frame {
};
Frame(MyThread* t, Compiler* c, object method, uintptr_t* map,
Buffer* objectPool):
Buffer* objectPool, Buffer* traceLog):
next(0),
t(t),
c(c),
method(method),
map(map),
objectPool(objectPool),
traceLog(traceLog),
codeMask(makeCodeMask(t, codeLength(t, methodCode(t, method)))),
ip(0),
sp(localSize(t, method)),
protector(t, this)
protector(this)
{
memset(map, 0, mapSizeInBytes(t, method));
}
@ -273,9 +285,11 @@ class Frame {
method(f->method),
map(map),
objectPool(f->objectPool),
traceLog(f->traceLog),
codeMask(f->codeMask),
ip(f->ip),
sp(f->sp),
protector(t, this)
protector(this)
{
memcpy(map, f->map, mapSizeInBytes(t, method));
}
@ -285,8 +299,8 @@ class Frame {
}
Operand* append(object o) {
objectPool->appendAddress(reinterpret_cast<uintptr_t>(c->poolOffset()));
Operand* result = c->poolAppend(c->constant(0));
objectPool->appendAddress(c->poolOffset(result));
objectPool->appendAddress(reinterpret_cast<uintptr_t>(o));
return result;
}
@ -316,6 +330,10 @@ class Frame {
return mapSizeInWords(t, method) * BytesPerWord;
}
static unsigned traceSizeInBytes(Thread* t, object method) {
return BytesPerWord + BytesPerWord + 1 + mapSizeInWords(t, method);
}
void pushedInt() {
assert(t, sp + 1 <= mapSize(t, method));
assert(t, getBit(map, sp) == 0);
@ -518,6 +536,22 @@ class Frame {
}
}
void trace(object target, bool virtualCall) {
traceLog->appendAddress(reinterpret_cast<uintptr_t>(target));
traceLog->appendAddress(reinterpret_cast<uintptr_t>(c->codeOffset()));
traceLog->append(virtualCall);
traceLog->append(map, mapSizeInWords(t, method) * BytesPerWord);
}
void trace() {
trace(0, false);
}
void startLogicalIp(unsigned ip) {
c->startLogicalIp(ip);
this->ip = ip;
}
void pushInt(Operand* o) {
c->push(o);
pushedInt();
@ -727,7 +761,9 @@ class Frame {
object method;
uintptr_t* map;
Buffer* objectPool;
Buffer* traceLog;
uintptr_t* codeMask;
unsigned ip;
unsigned sp;
MyProtector protector;
};
@ -741,10 +777,14 @@ unwind(MyThread* t)
void* returnAddress = *stack;
object node = findTraceNode(t, returnAddress);
if (node) {
void* handler = traceNodeHandler(t, node);
if (handler) {
object method = traceNodeMethod(t, node);
object method = traceNodeMethod(t, node);
uint8_t* compiled = reinterpret_cast<uint8_t*>
(&singletonValue(t, methodCompiled(t, method), 0));
ExceptionHandler* handler = findExceptionHandler
(t, method, difference(returnAddress, compiled));
if (handler) {
unsigned parameterFootprint = methodParameterFootprint(t, method);
unsigned localFootprint = codeMaxLocals(t, methodCode(t, method));
@ -755,7 +795,7 @@ unwind(MyThread* t)
*(--stack) = t->exception;
t->exception = 0;
vmJump(handler, base, stack);
vmJump(compiled + exceptionHandlerIp(handler), base, stack);
} else {
stack = static_cast<void**>(base) + 1;
base = *static_cast<void**>(base);
@ -1082,8 +1122,11 @@ compileThrowNew(MyThread* t, Frame* frame, Machine::Type type)
{
Operand* class_ = frame->append(arrayBody(t, t->m->types, type));
Compiler* c = frame->c;
c->indirectCallNoReturn(c->constant(reinterpret_cast<intptr_t>(throwNew)),
2, c->thread(), class_);
c->indirectCallNoReturn
(c->constant(reinterpret_cast<intptr_t>(throwNew)),
2, c->thread(), class_);
frame->trace();
}
void
@ -1124,6 +1167,8 @@ compileDirectInvoke(MyThread* t, Frame* frame, object target)
(reinterpret_cast<intptr_t>
(&singletonBody(t, methodCompiled(t, target), 0))));
frame->trace(target, false);
frame->pop(methodParameterFootprint(t, target));
pushReturnValue(t, frame, methodReturnCode(t, target), result);
@ -1148,7 +1193,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip)
markBit(frame->codeMask, ip);
c->startLogicalIp(ip);
frame->startLogicalIp(ip);
unsigned instruction = codeBody(t, code, ip++);
@ -1243,8 +1288,11 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip)
c->shl(c->constant(log(BytesPerWord)), index);
c->add(c->constant(ArrayBody), index);
c->directCall(c->constant(reinterpret_cast<intptr_t>(set)),
4, c->thread(), array, index, value);
c->directCall
(c->constant(reinterpret_cast<intptr_t>(set)),
4, c->thread(), array, index, value);
frame->trace();
break;
case fastore:
@ -1315,10 +1363,13 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip)
c->mark(nonnegative);
frame->pushObject
(c->indirectCall
Operand* r = c->indirectCall
(c->constant(reinterpret_cast<intptr_t>(makeBlankObjectArray)),
3, c->thread(), frame->append(class_), length));
3, c->thread(), frame->append(class_), length);
frame->trace();
frame->pushObject(r);
} break;
case areturn:
@ -1354,6 +1405,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip)
c->indirectCallNoReturn
(c->constant(reinterpret_cast<intptr_t>(throw_)),
2, c->thread(), frame->popObject());
frame->trace();
break;
case bipush:
@ -1974,6 +2027,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip)
Operand* result = c->call(c->memory(found, SingletonBody));
frame->trace(target, true);
frame->pop(parameterFootprint);
pushReturnValue(t, frame, methodReturnCode(t, target), result);
@ -2024,6 +2079,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip)
Operand* result = c->call(c->memory(class_, offset));
frame->trace(target, true);
c->release(class_);
frame->pop(parameterFootprint);
@ -2338,12 +2395,16 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip)
c->indirectCall
(c->constant(reinterpret_cast<intptr_t>(acquireMonitorForObject)),
2, c->thread(), frame->popObject());
frame->trace();
} break;
case monitorexit: {
c->indirectCall
(c->constant(reinterpret_cast<intptr_t>(releaseMonitorForObject)),
2, c->thread(), frame->popObject());
frame->trace();
} break;
case multianewarray: {
@ -2359,6 +2420,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip)
4, c->thread(), frame->append(class_), c->stack(),
c->constant(dimensions));
frame->trace();
frame->pop(dimensions);
frame->pushObject(result);
} break;
@ -2384,6 +2447,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip)
2, c->thread(), frame->append(class_));
}
frame->trace();
frame->pushObject(result);
} break;
@ -2437,10 +2502,13 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip)
default: abort(t);
}
frame->pushObject
(c->indirectCall
(c->constant(reinterpret_cast<intptr_t>(makeBlankArray)),
2, c->constant(reinterpret_cast<intptr_t>(constructor)), size));
Operand* result = c->indirectCall
(c->constant(reinterpret_cast<intptr_t>(makeBlankArray)),
2, c->constant(reinterpret_cast<intptr_t>(constructor)), size);
frame->trace();
frame->pushObject(result);
} break;
case nop: break;
@ -2639,7 +2707,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip)
}
object
finish(MyThread* t, Compiler* c, Buffer* objectPool)
finish(MyThread* t, Compiler* c, object method, Buffer* objectPool,
Buffer* traceLog)
{
unsigned count = ceiling(c->size(), BytesPerWord);
unsigned size = count + singletonMaskSize(count);
@ -2647,21 +2716,112 @@ finish(MyThread* t, Compiler* c, Buffer* objectPool)
initSingleton(t, result, size, true);
singletonMask(t, result)[0] = 1;
c->writeTo(&singletonValue(t, result, 0));
uint8_t* start = reinterpret_cast<uint8_t*>(&singletonValue(t, result, 0));
c->writeTo(start);
if (method) {
PROTECT(t, method);
if (objectPool) {
for (unsigned i = 0; i < objectPool->length(); i += BytesPerWord * 2) {
uintptr_t index = c->poolOffset() + objectPool->getAddress(i);
object value = reinterpret_cast<object>(objectPool->getAddress(i));
singletonMarkObject(t, result, index);
set(t, result, SingletonBody + (index * BytesPerWord), value);
Promise* offset = reinterpret_cast<Promise*>
(objectPool->getAddress(i));
object value = reinterpret_cast<object>
(objectPool->getAddress(i + BytesPerWord));
singletonMarkObject(t, result, offset->value() / BytesPerWord);
set(t, result, SingletonBody + offset->value(), value);
}
unsigned traceSize = Frame::traceSizeInBytes(t, method);
unsigned mapSize = Frame::mapSizeInBytes(t, method);
for (unsigned i = 0; i < traceLog->length(); i += traceSize) {
object target = reinterpret_cast<object>
(traceLog->getAddress(i));
Promise* offset = reinterpret_cast<Promise*>
(traceLog->getAddress(i + BytesPerWord));
bool virtualCall = traceLog->get(i + BytesPerWord + BytesPerWord);
uintptr_t map[mapSize / BytesPerWord];
traceLog->get(i + BytesPerWord + 2 + 1 + 4, map, mapSize);
object node = makeTraceNode
(t, reinterpret_cast<intptr_t>(start + offset->value()), 0, 0, method,
target, virtualCall, mapSize / BytesPerWord, false);
if (mapSize) {
memcpy(&traceNodeMap(t, node, 0), map, mapSize);
}
insertTraceNode(t, node);
}
object code = methodCode(t, method);
PROTECT(t, code);
{
object oldTable = codeExceptionHandlerTable(t, code);
if (oldTable) {
PROTECT(t, oldTable);
unsigned length = exceptionHandlerTableLength(t, oldTable);
object newTable = makeExceptionHandlerTable(t, length, false);
for (unsigned i = 0; i < length; ++i) {
ExceptionHandler* oldHandler = exceptionHandlerTableBody
(t, oldTable, i);
ExceptionHandler* newHandler = exceptionHandlerTableBody
(t, newTable, i);
exceptionHandlerStart(newHandler)
= c->logicalIpToOffset(exceptionHandlerStart(oldHandler));
exceptionHandlerEnd(newHandler)
= c->logicalIpToOffset(exceptionHandlerEnd(oldHandler));
exceptionHandlerIp(newHandler)
= c->logicalIpToOffset(exceptionHandlerIp(oldHandler));
exceptionHandlerCatchType(newHandler)
= exceptionHandlerCatchType(oldHandler);
}
set(t, code, CodeExceptionHandlerTable, newTable);
}
}
{
object oldTable = codeLineNumberTable(t, code);
if (oldTable) {
PROTECT(t, oldTable);
unsigned length = lineNumberTableLength(t, oldTable);
object newTable = makeLineNumberTable(t, length, false);
for (unsigned i = 0; i < length; ++i) {
LineNumber* oldLine = lineNumberTableBody(t, oldTable, i);
LineNumber* newLine = lineNumberTableBody(t, newTable, i);
lineNumberIp(newLine) = c->logicalIpToOffset(lineNumberIp(oldLine));
lineNumberLine(newLine) = lineNumberLine(oldLine);
}
set(t, code, CodeLineNumberTable, newTable);
}
}
}
return result;
}
object
finish(MyThread* t, Compiler* c)
{
return finish(t, c, 0, 0, 0);
}
object
compile(MyThread* t, Compiler* c, object method)
{
@ -2677,8 +2837,9 @@ compile(MyThread* t, Compiler* c, object method)
c->reserve(locals > footprint ? locals - footprint : 0);
Buffer objectPool(t->m->system, 256);
Buffer traceLog(t->m->system, 1024);
uintptr_t map[Frame::mapSizeInWords(t, method)];
Frame frame(t, c, method, map, &objectPool);
Frame frame(t, c, method, map, &objectPool, &traceLog);
compile(t, &frame, 0);
if (UNLIKELY(t->exception)) return 0;
@ -2701,7 +2862,7 @@ compile(MyThread* t, Compiler* c, object method)
}
}
return finish(t, c, &objectPool);
return finish(t, c, method, &objectPool, &traceLog);
}
void
@ -2720,6 +2881,12 @@ compileMethod(MyThread* t)
if (UNLIKELY(t->exception)) {
unwind(t);
} else {
if (not traceNodeVirtualCall(t, node)) {
Compiler* c = makeCompiler(t->m->system, 0);
c->updateCall(reinterpret_cast<void*>(treeNodeKey(t, node)),
&singletonValue(t, methodCompiled(t, target), 0));
c->dispose();
}
return &singletonValue(t, methodCompiled(t, target), 0);
}
}
@ -2927,6 +3094,7 @@ visitStack(MyThread* t, Heap::Visitor* v)
void* base = t->base;
void** stack = static_cast<void**>(t->stack);
MyThread::CallTrace* trace = t->trace;
while (true) {
object node = findTraceNode(t, *stack);
if (node) {
@ -2968,7 +3136,7 @@ compileDefault(MyThread* t, Compiler* c)
(c->constant(reinterpret_cast<intptr_t>(compileMethod)),
1, c->thread()));
return finish(t, c, 0);
return finish(t, c);
}
object
@ -2987,7 +3155,7 @@ compileNative(MyThread* t, Compiler* c)
c->epilogue();
c->ret();
return finish(t, c, 0);
return finish(t, c);
}
class ArgumentList {
@ -3294,9 +3462,9 @@ class MyProcessor: public Processor {
}
virtual int
lineNumber(Thread*, object, int ip)
lineNumber(Thread* vmt, object method, int ip)
{
return ip;
return findLineNumber(static_cast<MyThread*>(vmt), method, ip);
}
virtual object*
@ -3459,6 +3627,20 @@ compile(MyThread* t, object method)
}
}
object
findTraceNode(MyThread* t, void* address)
{
MyProcessor* p = static_cast<MyProcessor*>(t->m->processor);
return treeQuery(t, p->addressTree, reinterpret_cast<intptr_t>(address));
}
void
insertTraceNode(MyThread* t, object node)
{
MyProcessor* p = static_cast<MyProcessor*>(t->m->processor);
p->addressTree = treeInsert(t, p->addressTree, node);
}
} // namespace
namespace vm {

View File

@ -7,13 +7,21 @@ 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;
@ -44,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;
@ -87,10 +96,13 @@ class Compiler {
virtual void startLogicalIp(unsigned) = 0;
virtual Operand* logicalIp(unsigned) = 0;
virtual unsigned logicalIpToOffset(unsigned) = 0;
virtual unsigned size() = 0;
virtual void writeTo(void*) = 0;
virtual void updateCall(void* returnAddress, void* newTarget);
virtual void dispose() = 0;
};

View File

@ -35,44 +35,6 @@ class Thread: public vm::Thread {
uintptr_t stack[StackSizeInWords];
};
int
lineNumber(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;
}
}
inline void
pushObject(Thread* t, object o)
{
@ -734,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
@ -839,7 +765,7 @@ interpret(Thread* t)
&byteArrayBody
(t, methodName(t, frameMethod(t, frame)), 0));
int line = lineNumber(t, frameMethod(t, frame), ip);
int line = findLineNumber(t, frameMethod(t, frame), ip);
switch (line) {
case NativeLine:
fprintf(stderr, "(native)\n");
@ -2987,7 +2913,7 @@ class MyProcessor: public Processor {
virtual int
lineNumber(vm::Thread* t, object method, int ip)
{
return ::lineNumber(static_cast<Thread*>(t), method, ip);
return findLineNumber(static_cast<Thread*>(t), method, ip);
}
virtual object*

View File

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

View File

@ -1,5 +1,6 @@
#include "jnienv.h"
#include "machine.h"
#include "util.h"
#include "stream.h"
#include "constants.h"
#include "processor.h"
@ -2226,253 +2227,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)
{

View File

@ -1832,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):

View File

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

View File

@ -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))
@ -92,15 +92,15 @@
(int ip))
(type treeNode
(intptr_t key))
(intptr_t key)
(object left)
(object right))
(type traceNode
(extends treeNode)
(object method)
(void* handler)
(uint16_t line)
(uint8_t virtualCall)
(object target)
(uint8_t virtualCall)
(array uintptr_t map))
(type array

252
src/util.cpp Normal file
View File

@ -0,0 +1,252 @@
#include "util.h"
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;
}
} // namespace vm

84
src/util.h Normal file
View File

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