From 0bbe9489a71289e7f762cfe2c3934f8340fcffd3 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Mon, 26 Nov 2007 16:15:53 -0700 Subject: [PATCH] flesh out call tracing in new JIT code --- makefile | 4 +- src/buffer.h | 29 ++++-- src/compile2.cpp | 256 +++++++++++++++++++++++++++++++++++++++------- src/compiler.h | 16 ++- src/interpret.cpp | 80 +-------------- src/jnienv.cpp | 1 + src/machine.cpp | 248 +------------------------------------------- src/machine.h | 68 ------------ src/process.h | 82 +++++++++++++++ src/types.def | 20 ++-- src/util.cpp | 252 +++++++++++++++++++++++++++++++++++++++++++++ src/util.h | 84 +++++++++++++++ 12 files changed, 689 insertions(+), 451 deletions(-) create mode 100644 src/util.cpp create mode 100644 src/util.h diff --git a/makefile b/makefile index 81617f85f6..2a149fda60 100644 --- a/makefile +++ b/makefile @@ -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 \ diff --git a/src/buffer.h b/src/buffer.h index b99b3c0145..84520f2b41 100644 --- a/src/buffer.h +++ b/src/buffer.h @@ -51,6 +51,23 @@ class Buffer { position += 4; } + void appendAddress(uintptr_t v) { + append4(v); + if (BytesPerWord == 8) { + // we have to use the preprocessor here to avoid a warning on + // 32-bit systems +#ifdef __x86_64__ + append4(v >> 32); +#endif + } + } + + void append(void* p, unsigned size) { + ensure(size); + memcpy(data + position, p, size); + position += size; + } + void set2(unsigned offset, uint32_t v) { assert(s, offset + 2 <= position); memcpy(data + offset, &v, 2); @@ -81,15 +98,9 @@ class Buffer { return *reinterpret_cast(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() { diff --git a/src/compile2.cpp b/src/compile2.cpp index 682e1e0867..ffb87c1e34 100644 --- a/src/compile2.cpp +++ b/src/compile2.cpp @@ -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(&(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(&(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(c->poolOffset())); Operand* result = c->poolAppend(c->constant(0)); - objectPool->appendAddress(c->poolOffset(result)); objectPool->appendAddress(reinterpret_cast(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(target)); + traceLog->appendAddress(reinterpret_cast(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 + (&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(base) + 1; base = *static_cast(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(throwNew)), - 2, c->thread(), class_); + c->indirectCallNoReturn + (c->constant(reinterpret_cast(throwNew)), + 2, c->thread(), class_); + + frame->trace(); } void @@ -1124,6 +1167,8 @@ compileDirectInvoke(MyThread* t, Frame* frame, object target) (reinterpret_cast (&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(set)), - 4, c->thread(), array, index, value); + c->directCall + (c->constant(reinterpret_cast(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(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(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(acquireMonitorForObject)), 2, c->thread(), frame->popObject()); + + frame->trace(); } break; case monitorexit: { c->indirectCall (c->constant(reinterpret_cast(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(makeBlankArray)), - 2, c->constant(reinterpret_cast(constructor)), size)); + Operand* result = c->indirectCall + (c->constant(reinterpret_cast(makeBlankArray)), + 2, c->constant(reinterpret_cast(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(&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(objectPool->getAddress(i)); - - singletonMarkObject(t, result, index); - set(t, result, SingletonBody + (index * BytesPerWord), value); + Promise* offset = reinterpret_cast + (objectPool->getAddress(i)); + + object value = reinterpret_cast + (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 + (traceLog->getAddress(i)); + + Promise* offset = reinterpret_cast + (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(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(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(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(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(vmt), method, ip); } virtual object* @@ -3459,6 +3627,20 @@ compile(MyThread* t, object method) } } +object +findTraceNode(MyThread* t, void* address) +{ + MyProcessor* p = static_cast(t->m->processor); + return treeQuery(t, p->addressTree, reinterpret_cast(address)); +} + +void +insertTraceNode(MyThread* t, object node) +{ + MyProcessor* p = static_cast(t->m->processor); + p->addressTree = treeInsert(t, p->addressTree, node); +} + } // namespace namespace vm { diff --git a/src/compiler.h b/src/compiler.h index 7f330733de..565c10b256 100644 --- a/src/compiler.h +++ b/src/compiler.h @@ -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; }; diff --git a/src/interpret.cpp b/src/interpret.cpp index f9400eb97b..c24dca9826 100644 --- a/src/interpret.cpp +++ b/src/interpret.cpp @@ -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(t), method, ip); + return findLineNumber(static_cast(t), method, ip); } virtual object* diff --git a/src/jnienv.cpp b/src/jnienv.cpp index 1a0c3101e3..9133fc89b9 100644 --- a/src/jnienv.cpp +++ b/src/jnienv.cpp @@ -1,5 +1,6 @@ #include "jnienv.h" #include "machine.h" +#include "util.h" #include "processor.h" #include "constants.h" #include "processor.h" diff --git a/src/machine.cpp b/src/machine.cpp index 7ecc7da20d..98b2cd0308 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -1,5 +1,6 @@ #include "jnienv.h" #include "machine.h" +#include "util.h" #include "stream.h" #include "constants.h" #include "processor.h" @@ -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) { diff --git a/src/machine.h b/src/machine.h index 755464a5be..0d7e4db0bd 100644 --- a/src/machine.h +++ b/src/machine.h @@ -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): diff --git a/src/process.h b/src/process.h index ab8ac65f8d..bc45f9bdc3 100644 --- a/src/process.h +++ b/src/process.h @@ -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 diff --git a/src/types.def b/src/types.def index b9df404aeb..831c5deab8 100644 --- a/src/types.def +++ b/src/types.def @@ -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 diff --git a/src/util.cpp b/src/util.cpp new file mode 100644 index 0000000000..a1d932344d --- /dev/null +++ b/src/util.cpp @@ -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 diff --git a/src/util.h b/src/util.h new file mode 100644 index 0000000000..c9a37d8911 --- /dev/null +++ b/src/util.h @@ -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