From f151d85f4e6dbba28d79361d7e39df1fb66c67d8 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Mon, 31 Dec 2007 15:40:56 -0700 Subject: [PATCH] intercept SIGSEGV and throw NullPointerExceptions --- makefile | 4 +- src/compile.cpp | 650 ++++++++++++++++++++++-------------------- src/compiler.cpp | 541 +++++++++++++++++------------------ src/compiler.h | 28 +- src/posix.cpp | 10 +- test/NullPointer.java | 92 ++++++ 6 files changed, 724 insertions(+), 601 deletions(-) create mode 100644 test/NullPointer.java diff --git a/makefile b/makefile index 5e84d216d8..9801a3511e 100644 --- a/makefile +++ b/makefile @@ -28,7 +28,7 @@ src = src classpath = classpath test = test -input = $(test-build)/Misc.class +input = List build-cxx = g++ build-cc = gcc @@ -215,7 +215,7 @@ else flags = -cp $(test-build) endif -args = $(flags) $(call class-name,$(test-build),$(input)) +args = $(flags) $(input) .PHONY: build build: $(interpreter) $(archive) $(classpath-dep) $(test-dep) diff --git a/src/compile.cpp b/src/compile.cpp index af70885b42..aba84fc611 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -74,21 +74,24 @@ resolveTarget(MyThread* t, void* stack, object method) { if (method and methodVirtual(t, method)) { unsigned parameterFootprint = methodParameterFootprint(t, method); - object class_ = objectClass - (t, reinterpret_cast(stack)[parameterFootprint]); - if (classVmFlags(t, class_) & BootstrapFlag) { - PROTECT(t, method); - PROTECT(t, class_); + if (reinterpret_cast(stack)[parameterFootprint]) { + object class_ = objectClass + (t, reinterpret_cast(stack)[parameterFootprint]); - resolveClass(t, className(t, class_)); - if (UNLIKELY(t->exception)) return 0; - } + if (classVmFlags(t, class_) & BootstrapFlag) { + PROTECT(t, method); + PROTECT(t, class_); - if (classFlags(t, methodClass(t, method)) & ACC_INTERFACE) { - return findInterfaceMethod(t, method, class_); - } else { - return findMethod(t, method, class_); + resolveClass(t, className(t, class_)); + if (UNLIKELY(t->exception)) return 0; + } + + if (classFlags(t, methodClass(t, method)) & ACC_INTERFACE) { + return findInterfaceMethod(t, method, class_); + } else { + return findMethod(t, method, class_); + } } } @@ -235,10 +238,10 @@ class MyStackWalker: public Processor::StackWalker { }; uintptr_t* -makeCodeMask(MyThread* t, unsigned length) +makeCodeMask(Zone* zone, unsigned length) { unsigned size = ceiling(length, BytesPerWord) * BytesPerWord; - uintptr_t* mask = static_cast(t->m->system->allocate(size)); + uintptr_t* mask = static_cast(zone->allocate(size)); memset(mask, 0, size); return mask; } @@ -265,23 +268,40 @@ localObject(MyThread* t, void* base, object method, unsigned index) class PoolElement { public: - PoolElement(object value, Promise* address): - value(value), address(address) + PoolElement(object value, Promise* address, PoolElement* next): + value(value), address(address), next(next) { } object value; Promise* address; + PoolElement* next; }; -class TraceElement { - public: - TraceElement(object target, Promise* machineIp, bool virtualCall): - target(target), machineIp(machineIp), virtualCall(virtualCall) { } +class Context; +class TraceElement: public Compiler::TraceHandler { + public: + TraceElement(Context* context, object target, + bool virtualCall, TraceElement* next): + context(context), + address(0), + target(target), + virtualCall(virtualCall), + next(next) + { } + + virtual void handleTrace(Promise* address) { + if (this->address == 0) { + this->address = address; + } + } + + Context* context; + Promise* address; object target; - Promise* machineIp; bool virtualCall; - uint8_t map[0]; + TraceElement* next; + uintptr_t map[0]; }; inline Stack* @@ -354,76 +374,94 @@ and_(Compiler* c, Operand* src, Operand* dst) } } -class Frame { +class Context { public: class MyProtector: public Thread::Protector { public: - MyProtector(Frame* frame): Protector(frame->t), frame(frame) { } + MyProtector(Context* c): Protector(c->t), c(c) { } virtual void visit(Heap::Visitor* v) { - v->visit(&(frame->method)); + v->visit(&(c->method)); - if (frame->next == 0) { - Vector* pool = frame->objectPool; - for (unsigned i = 0; i < pool->length(); i += sizeof(PoolElement)) { - v->visit(&(pool->peek(i)->value)); - } + for (PoolElement* p = c->objectPool; p; p = p->next) { + v->visit(&(p->value)); + } - Vector* log = frame->traceLog; - unsigned traceSize = traceSizeInBytes(t, frame->method); - for (unsigned i = 0; i < log->length(); i += traceSize) { - v->visit(&(log->peek(i)->target)); - } + for (TraceElement* p = c->traceLog; p; p = p->next) { + v->visit(&(p->target)); } } - Frame* frame; + Context* c; }; - Frame(MyThread* t, Compiler* c, object method, uintptr_t* map, - Vector* objectPool, Vector* traceLog): - next(0), + Context(MyThread* t, object method, uint8_t* indirectCaller): t(t), - c(c), - stack(0), + zone(t->m->system, 8 * 1024), + c(makeCompiler(t->m->system, &zone, indirectCaller)), method(method), - map(map), - objectPool(objectPool), - traceLog(traceLog), - codeMask(makeCodeMask(t, codeLength(t, methodCode(t, method)))), - ip(0), - sp(localSize(t, method)), + objectPool(0), + traceLog(0), + codeMask(makeCodeMask(&zone, codeLength(t, methodCode(t, method)))), protector(this) + { } + + Context(MyThread* t): + t(t), + zone(t->m->system, 256), + c(makeCompiler(t->m->system, &zone, 0)), + method(0), + objectPool(0), + traceLog(0), + codeMask(0), + protector(this) + { } + + ~Context() { + c->dispose(); + } + + MyThread* t; + Zone zone; + Compiler* c; + object method; + PoolElement* objectPool; + TraceElement* traceLog; + uintptr_t* codeMask; + MyProtector protector; +}; + +class Frame { + public: + Frame(Context* context, uintptr_t* map): + context(context), + t(context->t), + c(context->c), + stack(0), + map(map), + ip(0), + sp(localSize(t, context->method)) { - memset(map, 0, mapSizeInBytes(t, method)); + memset(map, 0, mapSizeInBytes(t, context->method)); } Frame(Frame* f, uintptr_t* map): - next(f), - t(f->t), - c(f->c), + context(f->context), + t(context->t), + c(context->c), stack(f->stack), - method(f->method), map(map), - objectPool(f->objectPool), - traceLog(f->traceLog), - codeMask(f->codeMask), ip(f->ip), - sp(f->sp), - protector(this) + sp(f->sp) { - memcpy(map, f->map, mapSizeInBytes(t, method)); - } - - ~Frame() { - if (next == 0) { - t->m->system->free(codeMask); - } + memcpy(map, f->map, mapSizeInBytes(context->t, context->method)); } Operand* append(object o) { Promise* p = c->poolAppend(0); - new (objectPool->allocate(sizeof(PoolElement))) PoolElement(o, p); + context->objectPool = new + (context->zone.allocate(sizeof(PoolElement))) + PoolElement(o, p, context->objectPool); return c->absolute(p); } @@ -457,19 +495,19 @@ class Frame { } void pushedInt() { - assert(t, sp + 1 <= mapSize(t, method)); + assert(t, sp + 1 <= mapSize(t, context->method)); assert(t, getBit(map, sp) == 0); ++ sp; } void pushedObject() { - assert(t, sp + 1 <= mapSize(t, method)); + assert(t, sp + 1 <= mapSize(t, context->method)); markBit(map, sp++); } void popped(unsigned count) { assert(t, sp >= count); - assert(t, sp - count >= localSize(t, method)); + assert(t, sp - count >= localSize(t, context->method)); while (count) { clearBit(map, -- sp); -- count; @@ -478,35 +516,37 @@ class Frame { void poppedInt() { assert(t, sp >= 1); - assert(t, sp - 1 >= localSize(t, method)); + assert(t, sp - 1 >= localSize(t, context->method)); assert(t, getBit(map, sp - 1) == 0); -- sp; } void poppedObject() { assert(t, sp >= 1); - assert(t, sp - 1 >= localSize(t, method)); + assert(t, sp - 1 >= localSize(t, context->method)); assert(t, getBit(map, sp - 1) != 0); clearBit(map, -- sp); } void storedInt(unsigned index) { - if (index >= parameterFootprint(t, method)) { - assert(t, index - parameterFootprint(t, method) < localSize(t, method)); - clearBit(map, index - parameterFootprint(t, method)); + if (index >= parameterFootprint(t, context->method)) { + assert(t, index - parameterFootprint(t, context->method) + < localSize(t, context->method)); + clearBit(map, index - parameterFootprint(t, context->method)); } } void storedObject(unsigned index) { - if (index >= parameterFootprint(t, method)) { - assert(t, index - parameterFootprint(t, method) < localSize(t, method)); - markBit(map, index - parameterFootprint(t, method)); + if (index >= parameterFootprint(t, context->method)) { + assert(t, index - parameterFootprint(t, context->method) + < localSize(t, context->method)); + markBit(map, index - parameterFootprint(t, context->method)); } } void dupped() { - assert(t, sp + 1 <= mapSize(t, method)); - assert(t, sp - 1 >= localSize(t, method)); + assert(t, sp + 1 <= mapSize(t, context->method)); + assert(t, sp - 1 >= localSize(t, context->method)); if (getBit(map, sp - 1)) { markBit(map, sp); } @@ -514,8 +554,8 @@ class Frame { } void duppedX1() { - assert(t, sp + 1 <= mapSize(t, method)); - assert(t, sp - 2 >= localSize(t, method)); + assert(t, sp + 1 <= mapSize(t, context->method)); + assert(t, sp - 2 >= localSize(t, context->method)); unsigned b2 = getBit(map, sp - 2); unsigned b1 = getBit(map, sp - 1); @@ -537,8 +577,8 @@ class Frame { } void duppedX2() { - assert(t, sp + 1 <= mapSize(t, method)); - assert(t, sp - 3 >= localSize(t, method)); + assert(t, sp + 1 <= mapSize(t, context->method)); + assert(t, sp - 3 >= localSize(t, context->method)); unsigned b3 = getBit(map, sp - 3); unsigned b2 = getBit(map, sp - 2); @@ -567,8 +607,8 @@ class Frame { } void dupped2() { - assert(t, sp + 2 <= mapSize(t, method)); - assert(t, sp - 2 >= localSize(t, method)); + assert(t, sp + 2 <= mapSize(t, context->method)); + assert(t, sp - 2 >= localSize(t, context->method)); unsigned b2 = getBit(map, sp - 2); unsigned b1 = getBit(map, sp - 1); @@ -585,8 +625,8 @@ class Frame { } void dupped2X1() { - assert(t, sp + 2 <= mapSize(t, method)); - assert(t, sp - 3 >= localSize(t, method)); + assert(t, sp + 2 <= mapSize(t, context->method)); + assert(t, sp - 3 >= localSize(t, context->method)); unsigned b3 = getBit(map, sp - 3); unsigned b2 = getBit(map, sp - 2); @@ -616,8 +656,8 @@ class Frame { } void dupped2X2() { - assert(t, sp + 2 <= mapSize(t, method)); - assert(t, sp - 4 >= localSize(t, method)); + assert(t, sp + 2 <= mapSize(t, context->method)); + assert(t, sp - 4 >= localSize(t, context->method)); unsigned b4 = getBit(map, sp - 4); unsigned b3 = getBit(map, sp - 3); @@ -654,8 +694,8 @@ class Frame { } void swapped() { - assert(t, sp - 1 >= localSize(t, method)); - assert(t, sp - 2 >= localSize(t, method)); + assert(t, sp - 1 >= localSize(t, context->method)); + assert(t, sp - 2 >= localSize(t, context->method)); bool savedBit = getBit(map, sp - 1); if (getBit(map, sp - 2)) { @@ -671,12 +711,6 @@ class Frame { } } - void trace(Promise* address, object target, bool virtualCall) { - TraceElement* e = new (traceLog->allocate(traceSizeInBytes(t, method))) - TraceElement(target, address, virtualCall); - memcpy(e->map, map, mapSizeInWords(t, method) * BytesPerWord); - } - Operand* machineIp(unsigned logicalIp) { return c->promiseConstant(c->machineIp(logicalIp)); } @@ -756,14 +790,14 @@ class Frame { Operand* topInt() { assert(t, sp >= 1); - assert(t, sp - 1 >= localSize(t, method)); + assert(t, sp - 1 >= localSize(t, context->method)); assert(t, getBit(map, sp - 1) == 0); return c->stack(stack, 0); } Operand* topLong() { assert(t, sp >= 2); - assert(t, sp - 2 >= localSize(t, method)); + assert(t, sp - 2 >= localSize(t, context->method)); assert(t, getBit(map, sp - 1) == 0); assert(t, getBit(map, sp - 2) == 0); return c->stack(stack, 0); @@ -771,7 +805,7 @@ class Frame { Operand* topObject() { assert(t, sp >= 1); - assert(t, sp - 1 >= localSize(t, method)); + assert(t, sp - 1 >= localSize(t, context->method)); assert(t, getBit(map, sp - 1) != 0); return c->stack(stack, 0); } @@ -815,51 +849,52 @@ class Frame { } void loadInt(unsigned index) { - assert(t, index < codeMaxLocals(t, methodCode(t, method))); - assert(t, index < parameterFootprint(t, method) - or getBit(map, index - parameterFootprint(t, method)) == 0); - pushInt(c->memory(c->base(), localOffset(t, index, method))); + assert(t, index < codeMaxLocals(t, methodCode(t, context->method))); + assert(t, index < parameterFootprint(t, context->method) + or getBit(map, index - parameterFootprint(t, context->method)) + == 0); + pushInt(c->memory(c->base(), localOffset(t, index, context->method))); } void loadLong(unsigned index) { assert(t, index < static_cast - (codeMaxLocals(t, methodCode(t, method)) - 1)); - assert(t, index < parameterFootprint(t, method) - or getBit(map, index - parameterFootprint(t, method)) == 0); - assert(t, index < parameterFootprint(t, method) - or getBit(map, index + 1 - parameterFootprint(t, method)) == 0); - pushLong(c->memory(c->base(), localOffset(t, index + 1, method))); + (codeMaxLocals(t, methodCode(t, context->method)) - 1)); + assert(t, index < parameterFootprint(t, context->method) + or getBit(map, index - parameterFootprint(t, context->method)) + == 0); + assert(t, index < parameterFootprint(t, context->method) + or getBit(map, index + 1 - parameterFootprint(t, context->method)) + == 0); + pushLong(c->memory(c->base(), localOffset(t, index + 1, context->method))); } void loadObject(unsigned index) { - assert(t, index < codeMaxLocals(t, methodCode(t, method))); -// assert(t, index < parameterFootprint(t, method) -// or getBit(map, index - parameterFootprint(t, method)) != 0); - pushObject(c->memory(c->base(), localOffset(t, index, method))); + assert(t, index < codeMaxLocals(t, methodCode(t, context->method))); + pushObject(c->memory(c->base(), localOffset(t, index, context->method))); } void storeInt(unsigned index) { - popInt(c->memory(c->base(), localOffset(t, index, method))); + popInt(c->memory(c->base(), localOffset(t, index, context->method))); storedInt(index); } void storeLong(unsigned index) { - popLong(c->memory(c->base(), localOffset(t, index + 1, method))); + popLong(c->memory(c->base(), localOffset(t, index + 1, context->method))); storedInt(index); storedInt(index + 1); } void storeObject(unsigned index) { - popObject(c->memory(c->base(), localOffset(t, index, method))); + popObject(c->memory(c->base(), localOffset(t, index, context->method))); storedObject(index); } void storeObjectOrAddress(unsigned index) { stack = ::pop - (c, stack, c->memory(c->base(), localOffset(t, index, method))); + (c, stack, c->memory(c->base(), localOffset(t, index, context->method))); assert(t, sp >= 1); - assert(t, sp - 1 >= localSize(t, method)); + assert(t, sp - 1 >= localSize(t, context->method)); if (getBit(map, sp - 1)) { storedObject(index); } else { @@ -870,11 +905,12 @@ class Frame { } void increment(unsigned index, int count) { - assert(t, index < codeMaxLocals(t, methodCode(t, method))); - assert(t, index < parameterFootprint(t, method) - or getBit(map, index - parameterFootprint(t, method)) == 0); + assert(t, index < codeMaxLocals(t, methodCode(t, context->method))); + assert(t, index < parameterFootprint(t, context->method) + or getBit(map, index - parameterFootprint(t, context->method)) + == 0); c->add4(c->constant(count), - c->memory(c->base(), localOffset(t, index, method))); + c->memory(c->base(), localOffset(t, index, context->method))); } void dup() { @@ -940,32 +976,26 @@ class Frame { swapped(); } + + TraceElement* trace(object target, bool virtualCall) { + unsigned mapSize = mapSizeInWords(t, context->method); + + TraceElement* e = context->traceLog = new + (context->zone.allocate(sizeof(TraceElement) + (mapSize * BytesPerWord))) + TraceElement(context, target, virtualCall, context->traceLog); + + memcpy(e->map, map, mapSizeInWords(t, context->method) * BytesPerWord); + + return e; + } - Frame* next; + Context* context; MyThread* t; Compiler* c; Stack* stack; - object method; uintptr_t* map; - Vector* objectPool; - Vector* traceLog; - uintptr_t* codeMask; unsigned ip; unsigned sp; - MyProtector protector; -}; - -class MyNullHandler: public Compiler::NullHandler { - public: - MyNullHandler(Frame* frame): frame(frame) { - frame->c->setNullHandler(this); - } - - virtual void handleMaybeNull(Promise* address) { - frame->trace(address, 0, false); - } - - Frame* frame; }; void NO_RETURN @@ -974,7 +1004,9 @@ unwind(MyThread* t) void* ip = t->ip; void* base = t->base; void** stack = static_cast(t->stack); - if (ip == 0) { + if (ip) { + t->ip = 0; + } else { ip = *stack; } @@ -1021,6 +1053,29 @@ unwind(MyThread* t) } } +void +insertTraceNode(MyThread* t, object method, object target, bool virtualCall, + uintptr_t* map, void* address) +{ + unsigned mapSize = Frame::mapSizeInWords(t, method); + + object node = makeTraceNode + (t, + reinterpret_cast(address), + 0, + method, + target, + virtualCall, + mapSize, + false); + + if (mapSize) { + memcpy(&traceNodeMap(t, node, 0), map, mapSize * BytesPerWord); + } + + insertTraceNode(t, node); +} + void* findInterfaceMethodFromInstance(MyThread* t, object method, object instance) { @@ -1273,7 +1328,7 @@ lookUpAddress(int32_t key, uintptr_t* start, int32_t count, void setMaybeNull(MyThread* t, object o, unsigned offset, object value) { - if (o) { + if (LIKELY(o)) { set(t, o, offset, value); } else { t->exception = makeNullPointerException(t); @@ -1284,7 +1339,7 @@ setMaybeNull(MyThread* t, object o, unsigned offset, object value) void acquireMonitorForObject(MyThread* t, object o) { - if (o) { + if (LIKELY(o)) { acquire(t, o); } else { t->exception = makeNullPointerException(t); @@ -1295,7 +1350,7 @@ acquireMonitorForObject(MyThread* t, object o) void releaseMonitorForObject(MyThread* t, object o) { - if (o) { + if (LIKELY(o)) { release(t, o); } else { t->exception = makeNullPointerException(t); @@ -1352,7 +1407,7 @@ throwNew(MyThread* t, object class_) void NO_RETURN throw_(MyThread* t, object o) { - if (o) { + if (LIKELY(o)) { t->exception = o; } else { t->exception = makeNullPointerException(t); @@ -1368,9 +1423,8 @@ compileThrowNew(MyThread* t, Frame* frame, Machine::Type type) c->indirectCallNoReturn (c->constant(reinterpret_cast(throwNew)), + frame->trace(0, false), 2, c->thread(), class_); - - frame->trace(c->machineIp(), 0, false); } void @@ -1427,9 +1481,8 @@ compileDirectInvoke(MyThread* t, Frame* frame, object target) c->alignedCall (c->constant (reinterpret_cast - (&singletonBody(t, methodCompiled(t, target), 0)))); - - frame->trace(c->machineIp(), target, false); + (&singletonBody(t, methodCompiled(t, target), 0))), + frame->trace(target, false)); frame->pop(methodParameterFootprint(t, target)); @@ -1440,7 +1493,7 @@ void handleMonitorEvent(MyThread* t, Frame* frame, intptr_t function) { Compiler* c = frame->c; - object method = frame->method; + object method = frame->context->method; if (methodFlags(t, method) & ACC_SYNCHRONIZED) { Operand* lock; @@ -1450,10 +1503,10 @@ handleMonitorEvent(MyThread* t, Frame* frame, intptr_t function) lock = c->memory(c->base(), localOffset(t, 0, method)); } - Promise* returnAddress = c->indirectCall - (c->constant(function), 2, c->thread(), lock); - - frame->trace(returnAddress, 0, false); + c->indirectCall + (c->constant(function), + frame->trace(0, false), + 2, c->thread(), lock); } } @@ -1474,21 +1527,22 @@ handleExit(MyThread* t, Frame* frame) void compile(MyThread* t, Frame* initialFrame, unsigned ip) { - uintptr_t map[Frame::mapSizeInWords(t, initialFrame->method)]; + uintptr_t map[Frame::mapSizeInWords(t, initialFrame->context->method)]; Frame myFrame(initialFrame, map); Frame* frame = &myFrame; Compiler* c = frame->c; + Context* context = frame->context; - object code = methodCode(t, frame->method); + object code = methodCode(t, context->method); PROTECT(t, code); while (ip < codeLength(t, code)) { - if (getBit(frame->codeMask, ip)) { + if (getBit(context->codeMask, ip)) { // we've already visited this part of the code return; } - markBit(frame->codeMask, ip); + markBit(context->codeMask, ip); frame->startLogicalIp(ip); @@ -1512,35 +1566,36 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) c->cmp4(c->constant(0), index); c->jl(outOfBounds); - c->cmp4(c->memory(array, ArrayLength), index); + c->cmp4(c->memory(array, ArrayLength, 0, 1, frame->trace(0, false)), + index); c->jge(outOfBounds); switch (instruction) { case aaload: frame->pushObject - (c->memory(array, ArrayBody, index, BytesPerWord, true)); + (c->memory(array, ArrayBody, index, BytesPerWord)); break; case faload: case iaload: - frame->pushInt4(c->memory(array, ArrayBody, index, 4, true)); + frame->pushInt4(c->memory(array, ArrayBody, index, 4)); break; case baload: - frame->pushInt1(c->memory(array, ArrayBody, index, 1, true)); + frame->pushInt1(c->memory(array, ArrayBody, index, 1)); break; case caload: - frame->pushInt2z(c->memory(array, ArrayBody, index, 2, true)); + frame->pushInt2z(c->memory(array, ArrayBody, index, 2)); break; case daload: case laload: - frame->pushLong(c->memory(array, ArrayBody, index, 8, true)); + frame->pushLong(c->memory(array, ArrayBody, index, 8)); break; case saload: - frame->pushInt2(c->memory(array, ArrayBody, index, 2, true)); + frame->pushInt2(c->memory(array, ArrayBody, index, 2)); break; } @@ -1581,7 +1636,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) c->cmp4(c->constant(0), index); c->jl(outOfBounds); - c->cmp4(c->memory(array, BytesPerWord), index); + c->cmp4(c->memory(array, BytesPerWord, 0, 1, frame->trace(0, false)), + index); c->jge(outOfBounds); switch (instruction) { @@ -1589,30 +1645,29 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) c->shl4(c->constant(log(BytesPerWord)), index); c->add4(c->constant(ArrayBody), index); - Promise* returnAddress = c->indirectCall + c->indirectCall (c->constant(reinterpret_cast(setMaybeNull)), + frame->trace(0, false), 4, c->thread(), array, index, value); - - frame->trace(returnAddress, 0, false); } break; case fastore: case iastore: - c->mov4(value, c->memory(array, ArrayBody, index, 4, true)); + c->mov4(value, c->memory(array, ArrayBody, index, 4)); break; case bastore: - c->mov1(value, c->memory(array, ArrayBody, index, 1, true)); + c->mov1(value, c->memory(array, ArrayBody, index, 1)); break; case castore: case sastore: - c->mov2(value, c->memory(array, ArrayBody, index, 2, true)); + c->mov2(value, c->memory(array, ArrayBody, index, 2)); break; case dastore: case lastore: - c->mov8(value, c->memory(array, ArrayBody, index, 8, true)); + c->mov8(value, c->memory(array, ArrayBody, index, 8)); break; } @@ -1668,16 +1723,15 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) c->mark(nonnegative); - Promise* returnAddress = c->indirectCall - (c->constant(reinterpret_cast(makeBlankObjectArray)), - 3, c->thread(), frame->append(class_), length); + c->indirectCall + (c->constant(reinterpret_cast(makeBlankObjectArray)), + frame->trace(0, false), + 3, c->thread(), frame->append(class_), length); Operand* result = ::result(c); c->release(length); - frame->trace(returnAddress, 0, false); - frame->pushObject(result); c->release(result); } break; @@ -1691,7 +1745,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) case arraylength: { Operand* array = frame->popObject(); - frame->pushInt4(c->memory(array, ArrayLength, 0, 1, true)); + frame->pushInt4 + (c->memory(array, ArrayLength, 0, 1, frame->trace(0, false))); c->release(array); } break; @@ -1719,10 +1774,9 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) Operand* e = frame->popObject(); c->indirectCallNoReturn (c->constant(reinterpret_cast(throw_)), + frame->trace(0, false), 2, c->thread(), e); c->release(e); - - frame->trace(c->machineIp(), 0, false); } return; case bipush: @@ -1740,11 +1794,10 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) Operand* classOperand = frame->append(class_); - Promise* returnAddress = c->indirectCall - (c->constant(reinterpret_cast(checkCast)), - 3, c->thread(), classOperand, instance); - - frame->trace(returnAddress, 0, false); + c->indirectCall + (c->constant(reinterpret_cast(checkCast)), + frame->trace(0, false), + 3, c->thread(), classOperand, instance); } break; case d2f: { @@ -2108,47 +2161,50 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) table = frame->popObject(); } - bool maybeNull = (instruction == getfield); + TraceElement* trace = 0; + if (instruction == getfield) { + trace = frame->trace(0, false); + } switch (fieldCode(t, field)) { case ByteField: case BooleanField: frame->pushInt1 - (c->memory(table, fieldOffset(t, field), 0, 1, maybeNull)); + (c->memory(table, fieldOffset(t, field), 0, 1, trace)); break; case CharField: frame->pushInt2z - (c->memory(table, fieldOffset(t, field), 0, 1, maybeNull)); + (c->memory(table, fieldOffset(t, field), 0, 1, trace)); break; case ShortField: frame->pushInt2 - (c->memory(table, fieldOffset(t, field), 0, 1, maybeNull)); + (c->memory(table, fieldOffset(t, field), 0, 1, trace)); break; case FloatField: case IntField: frame->pushInt4 - (c->memory(table, fieldOffset(t, field), 0, 1, maybeNull)); + (c->memory(table, fieldOffset(t, field), 0, 1, trace)); break; case DoubleField: case LongField: frame->pushLong - (c->memory(table, fieldOffset(t, field), 0, 1, maybeNull)); + (c->memory(table, fieldOffset(t, field), 0, 1, trace)); break; case ObjectField: frame->pushObject - (c->memory(table, fieldOffset(t, field), 0, 1, maybeNull)); + (c->memory(table, fieldOffset(t, field), 0, 1, trace)); break; default: abort(t); } - if (instruction != getstatic) { + if (instruction == getfield) { c->release(table); } } break; @@ -2456,14 +2512,13 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) c->indirectCall (c->constant (reinterpret_cast(findInterfaceMethodFromInstance)), + frame->trace(target, true), 3, c->thread(), frame->append(target), c->stack(frame->stack, instance)); Operand* result = ::result(c); - c->call(result); + c->call(result, frame->trace(target, true)); c->release(result); - - frame->trace(c->machineIp(), target, true); frame->pop(parameterFootprint); @@ -2513,12 +2568,10 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) Operand* instance = c->stack(frame->stack, parameterFootprint - 1); Operand* class_ = c->temporary(); - mov(c, c->memory(instance), class_); + mov(c, c->memory(instance, 0, 0, 1, frame->trace(0, false)), class_); and_(c, c->constant(PointerMask), class_); - c->call(c->memory(class_, offset, 0, 1, true)); - - frame->trace(c->machineIp(), target, true); + c->call(c->memory(class_, offset, 0, 1), frame->trace(target, true)); c->release(class_); @@ -2890,22 +2943,20 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) case monitorenter: { Operand* a = frame->popObject(); - Promise* returnAddress = c->indirectCall + c->indirectCall (c->constant(reinterpret_cast(acquireMonitorForObject)), + frame->trace(0, false), 2, c->thread(), a); c->release(a); - - frame->trace(returnAddress, 0, false); } break; case monitorexit: { Operand* a = frame->popObject(); - Promise* returnAddress = c->indirectCall + c->indirectCall (c->constant(reinterpret_cast(releaseMonitorForObject)), + frame->trace(0, false), 2, c->thread(), a); c->release(a); - - frame->trace(returnAddress, 0, false); } break; case multianewarray: { @@ -2916,15 +2967,14 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) if (UNLIKELY(t->exception)) return; PROTECT(t, class_); - Promise* returnAddress = c->indirectCall + c->indirectCall (c->constant(reinterpret_cast(makeMultidimensionalArray)), + frame->trace(0, false), 4, c->thread(), frame->append(class_), c->stack(), c->constant(dimensions)); Operand* result = ::result(c); - frame->trace(returnAddress, 0, false); - frame->pop(dimensions); frame->pushObject(result); c->release(result); @@ -2940,19 +2990,18 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) initClass(t, class_); if (UNLIKELY(t->exception)) return; - Promise* returnAddress; if (classVmFlags(t, class_) & WeakReferenceFlag) { - returnAddress = c->indirectCall + c->indirectCall (c->constant(reinterpret_cast(makeNewWeakReference)), + frame->trace(0, false), 2, c->thread(), frame->append(class_)); } else { - returnAddress = c->indirectCall + c->indirectCall (c->constant(reinterpret_cast(makeNew)), + frame->trace(0, false), 2, c->thread(), frame->append(class_)); } - frame->trace(returnAddress, 0, false); - Operand* result = ::result(c); frame->pushObject(result); c->release(result); @@ -3009,8 +3058,9 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) default: abort(t); } - Promise* returnAddress = c->indirectCall + c->indirectCall (c->constant(reinterpret_cast(makeBlankArray)), + frame->trace(0, false), 3, c->thread(), c->constant(reinterpret_cast(constructor)), size); @@ -3018,8 +3068,6 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) c->release(size); - frame->trace(returnAddress, 0, false); - frame->pushObject(result); c->release(result); } break; @@ -3083,37 +3131,37 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) table = frame->popObject(); } - bool maybeNull = (instruction == getstatic); + TraceElement* trace = 0; + if (instruction == putfield and fieldCode(t, field) != ObjectField) { + trace = frame->trace(0, false); + } switch (fieldCode(t, field)) { case ByteField: case BooleanField: - c->mov1(value, c->memory - (table, fieldOffset(t, field), 0, 1, maybeNull)); + c->mov1(value, c->memory(table, fieldOffset(t, field), 0, 1, trace)); break; case CharField: case ShortField: - c->mov2(value, c->memory - (table, fieldOffset(t, field), 0, 1, maybeNull)); + c->mov2(value, c->memory(table, fieldOffset(t, field), 0, 1, trace)); break; case FloatField: case IntField: - c->mov4(value, c->memory - (table, fieldOffset(t, field), 0, 1, maybeNull)); + c->mov4(value, c->memory(table, fieldOffset(t, field), 0, 1, trace)); break; case DoubleField: case LongField: - c->mov8(value, c->memory - (table, fieldOffset(t, field), 0, 1, maybeNull)); + c->mov8(value, c->memory(table, fieldOffset(t, field), 0, 1, trace)); break; case ObjectField: - if (maybeNull) { + if (instruction == putfield) { c->indirectCall (c->constant(reinterpret_cast(setMaybeNull)), + frame->trace(0, false), 4, c->thread(), table, c->constant(fieldOffset(t, field)), value); } else { c->directCall @@ -3125,7 +3173,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) default: abort(t); } - if (instruction != putstatic) { + if (instruction == putfield) { c->release(table); } c->release(value); @@ -3134,7 +3182,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) case ret: c->jmp (c->memory - (c->base(), localOffset(t, codeBody(t, code, ip), frame->method))); + (c->base(), localOffset + (t, codeBody(t, code, ip), context->method))); return; case return_: @@ -3243,7 +3292,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) c->jmp (c->memory (c->base(), localOffset - (t, codeReadInt16(t, code, ip), frame->method))); + (t, codeReadInt16(t, code, ip), context->method))); return; default: abort(t); @@ -3266,10 +3315,9 @@ logCompile(const void* code, unsigned size, const char* class_, } object -finish(MyThread* t, Compiler* c, object method, Vector* objectPool, - Vector* traceLog, const char* name) +finish(MyThread* t, Context* context, const char* name) { - PROTECT(t, method); + Compiler* c = context->c; unsigned count = ceiling(c->codeSize() + c->poolSize(), BytesPerWord); unsigned size = count + singletonMaskSize(count); @@ -3282,36 +3330,33 @@ finish(MyThread* t, Compiler* c, object method, Vector* objectPool, c->writeTo(start); - if (method) { + if (context->method) { PROTECT(t, result); - for (unsigned i = 0; i < objectPool->length(); i += sizeof(PoolElement)) { - PoolElement* e = objectPool->peek(i); - intptr_t offset = e->address->value(c) - - reinterpret_cast(start); - - singletonMarkObject(t, result, offset / BytesPerWord); - - set(t, result, SingletonBody + offset, e->value); - } - - unsigned traceSize = Frame::traceSizeInBytes(t, method); - unsigned mapSize = Frame::mapSizeInBytes(t, method); - for (unsigned i = 0; i < traceLog->length(); i += traceSize) { - TraceElement* e = traceLog->peek(i); + unsigned mapSize = Frame::mapSizeInWords(t, context->method); + for (TraceElement* p = context->traceLog; p; p = p->next) { object node = makeTraceNode - (t, e->machineIp->value(c), 0, method, e->target, e->virtualCall, - mapSize / BytesPerWord, false); + (t, p->address->value(c), 0, context->method, p->target, + p->virtualCall, mapSize, false); if (mapSize) { - memcpy(&traceNodeMap(t, node, 0), e->map, mapSize); + memcpy(&traceNodeMap(t, node, 0), p->map, mapSize * BytesPerWord); } insertTraceNode(t, node); } - object code = methodCode(t, method); + for (PoolElement* p = context->objectPool; p; p = p->next) { + intptr_t offset = p->address->value(c) + - reinterpret_cast(start); + + singletonMarkObject(t, result, offset / BytesPerWord); + + set(t, result, SingletonBody + offset, p->value); + } + + object code = methodCode(t, context->method); PROTECT(t, code); { @@ -3370,21 +3415,24 @@ finish(MyThread* t, Compiler* c, object method, Vector* objectPool, } if (Verbose) { - logCompile(start, c->codeSize(), - reinterpret_cast - (&byteArrayBody(t, className(t, methodClass(t, method)), 0)), - reinterpret_cast - (&byteArrayBody(t, methodName(t, method), 0))); + logCompile + (start, c->codeSize(), + reinterpret_cast + (&byteArrayBody(t, className(t, methodClass(t, context->method)), 0)), + reinterpret_cast + (&byteArrayBody(t, methodName(t, context->method), 0))); } // for debugging: if (false and - strcmp(reinterpret_cast - (&byteArrayBody(t, className(t, methodClass(t, method)), 0)), - "Misc") == 0 and - strcmp(reinterpret_cast - (&byteArrayBody(t, methodName(t, method), 0)), - "syncStatic") == 0) + strcmp + (reinterpret_cast + (&byteArrayBody(t, className(t, methodClass(t, context->method)), 0)), + "Misc") == 0 and + strcmp + (reinterpret_cast + (&byteArrayBody(t, methodName(t, context->method), 0)), + "syncStatic") == 0) { asm("int3"); } @@ -3398,46 +3446,37 @@ finish(MyThread* t, Compiler* c, object method, Vector* objectPool, } object -finish(MyThread* t, Compiler* c, const char* name) +compile(MyThread* t, Context* context) { - return finish(t, c, 0, 0, 0, name); -} + Compiler* c = context->c; -object -compile(MyThread* t, Compiler* c, object method) -{ - PROTECT(t, method); - c->prologue(); - object code = methodCode(t, method); + object code = methodCode(t, context->method); PROTECT(t, code); - unsigned footprint = methodParameterFootprint(t, method); + unsigned footprint = methodParameterFootprint(t, context->method); unsigned locals = codeMaxLocals(t, code); c->reserve(locals - footprint); - Vector objectPool(t->m->system, 256); - Vector traceLog(t->m->system, 1024); - uintptr_t map[Frame::mapSizeInWords(t, method)]; - Frame frame(t, c, method, map, &objectPool, &traceLog); - MyNullHandler nullHandler(&frame); + uintptr_t map[Frame::mapSizeInWords(t, context->method)]; + Frame frame(context, map); handleEntrance(t, &frame); compile(t, &frame, 0); if (UNLIKELY(t->exception)) return 0; - object eht = codeExceptionHandlerTable(t, methodCode(t, method)); + object eht = codeExceptionHandlerTable(t, methodCode(t, context->method)); if (eht) { PROTECT(t, eht); for (unsigned i = 0; i < exceptionHandlerTableLength(t, eht); ++i) { ExceptionHandler* eh = exceptionHandlerTableBody(t, eht, i); - assert(t, getBit(frame.codeMask, exceptionHandlerStart(eh))); + assert(t, getBit(context->codeMask, exceptionHandlerStart(eh))); - uintptr_t map[Frame::mapSizeInWords(t, method)]; + uintptr_t map[Frame::mapSizeInWords(t, context->method)]; Frame frame2(&frame, map); frame2.pushObject(); @@ -3446,7 +3485,7 @@ compile(MyThread* t, Compiler* c, object method) } } - return finish(t, c, method, &objectPool, &traceLog, 0); + return finish(t, context, 0); } void @@ -3473,10 +3512,10 @@ compileMethod2(MyThread* t) return 0; } else { if (not traceNodeVirtualCall(t, node)) { - Compiler* c = makeCompiler(t->m->system, 0); - c->updateCall(reinterpret_cast(traceNodeAddress(t, node)), - &singletonValue(t, methodCompiled(t, target), 0)); - c->dispose(); + Context context(t); + context.c->updateCall + (reinterpret_cast(traceNodeAddress(t, node)), + &singletonValue(t, methodCompiled(t, target), 0)); } return &singletonValue(t, methodCompiled(t, target), 0); } @@ -3753,8 +3792,10 @@ visitStack(MyThread* t, Heap::Visitor* v) } object -compileDefault(MyThread* t, Compiler* c) +compileDefault(MyThread* t, Context* context) { + Compiler* c = context->c; + mov(c, c->base(), c->memory(c->thread(), difference(&(t->base), t))); mov(c, c->stack(), c->memory(c->thread(), difference(&(t->stack), t))); @@ -3766,12 +3807,14 @@ compileDefault(MyThread* t, Compiler* c) c->jmp(result); c->release(result); - return finish(t, c, "default"); + return finish(t, context, "default"); } object -compileNative(MyThread* t, Compiler* c) +compileNative(MyThread* t, Context* context) { + Compiler* c = context->c; + mov(c, c->base(), c->memory(c->thread(), difference(&(t->base), t))); mov(c, c->stack(), c->memory(c->thread(), difference(&(t->stack), t))); @@ -3780,7 +3823,7 @@ compileNative(MyThread* t, Compiler* c) c->ret(); - return finish(t, c, "native"); + return finish(t, context, "native"); } class ArgumentList { @@ -3995,18 +4038,16 @@ class MyProcessor: public Processor { object getDefaultCompiled(MyThread* t) { if (defaultCompiled == 0) { - Compiler* c = makeCompiler(t->m->system, 0); - defaultCompiled = compileDefault(t, c); - c->dispose(); + Context context(t); + defaultCompiled = compileDefault(t, &context); } return defaultCompiled; } object getNativeCompiled(MyThread* t) { if (nativeCompiled == 0) { - Compiler* c = makeCompiler(t->m->system, 0); - nativeCompiled = compileNative(t, c); - c->dispose(); + Context context(t); + nativeCompiled = compileNative(t, &context); } return nativeCompiled; } @@ -4267,7 +4308,8 @@ processor(MyThread* t) if (p->addressTable == 0) { p->addressTable = makeArray(t, 128, true); - Compiler* c = makeCompiler(t->m->system, 0); + Context context(t); + Compiler* c = context.c; mov(c, c->base(), c->memory(c->thread(), difference(&(t->base), t))); mov(c, c->stack(), c->memory(c->thread(), difference(&(t->stack), t))); @@ -4281,8 +4323,6 @@ processor(MyThread* t) if (Verbose) { logCompile(p->indirectCaller, c->codeSize(), 0, "indirect caller"); } - - c->dispose(); } p->segFaultHandler.m = t->m; @@ -4303,17 +4343,15 @@ compile(MyThread* t, object method) ACQUIRE(t, t->m->classLock); if (methodCompiled(t, method) == p->getDefaultCompiled(t)) { - Compiler* c = makeCompiler(t->m->system, p->indirectCaller); + Context context(t, method, p->indirectCaller); - object compiled = compile(t, c, method); + object compiled = compile(t, &context); set(t, method, MethodCompiled, compiled); if (methodVirtual(t, method)) { classVtable(t, methodClass(t, method), methodOffset(t, method)) = &singletonValue(t, compiled, 0); } - - c->dispose(); } } } diff --git a/src/compiler.cpp b/src/compiler.cpp index 182f7dd5d3..c56d383489 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -137,20 +137,19 @@ class RegisterData { class Context { public: - Context(System* s, void* indirectCaller): + Context(System* s, Zone* zone, void* indirectCaller): s(s), constantPool(s, BytesPerWord * 32), plan(s, 1024), code(s, 1024), - zone(s, 8 * 1024), + zone(zone), indirectCaller(reinterpret_cast(indirectCaller)), segmentTable(0), reserved(0), - codeLength(-1), - nullHandler(0) + codeLength(-1) { - plan.appendAddress(new (zone.allocate(sizeof(Segment))) Segment - (-1, new (zone.allocate(sizeof(Event))) Event(0))); + plan.appendAddress(new (zone->allocate(sizeof(Segment))) Segment + (-1, new (zone->allocate(sizeof(Event))) Event(0))); registers[rsp].reserved = true; registers[rbp].reserved = true; @@ -158,7 +157,6 @@ class Context { } void dispose() { - zone.dispose(); plan.dispose(); code.dispose(); constantPool.dispose(); @@ -169,12 +167,11 @@ class Context { Vector constantPool; Vector plan; Vector code; - Zone zone; + Zone* zone; intptr_t indirectCaller; Segment** segmentTable; unsigned reserved; int codeLength; - Compiler::NullHandler* nullHandler; RegisterData registers[RegisterCount]; }; @@ -222,6 +219,13 @@ class ResolvedPromise: public MyPromise { intptr_t value_; }; +ResolvedPromise* +resolved(Context* c, intptr_t value) +{ + return new (c->zone->allocate(sizeof(ResolvedPromise))) + ResolvedPromise(value); +} + class PoolPromise: public MyPromise { public: PoolPromise(intptr_t key): key(key) { } @@ -313,7 +317,7 @@ register_(Context* c, Register = NoRegister, Register = NoRegister); MemoryOperand* memory(Context* c, MyOperand* base, int displacement, - MyOperand* index, unsigned scale, bool maybeNull); + MyOperand* index, unsigned scale, Compiler::TraceHandler* traceHandler); class MyOperand: public Operand { public: @@ -523,7 +527,7 @@ class RegisterOperand: public MyOperand { } virtual RegisterNode* dependencies(Context* c, RegisterNode* next) { - return new (c->zone.allocate(sizeof(RegisterNode))) + return new (c->zone->allocate(sizeof(RegisterNode))) RegisterNode(value(c), next); } @@ -533,8 +537,8 @@ class RegisterOperand: public MyOperand { virtual void apply(Context*, Operation); - virtual void apply(Context* c, Operation operation, MyOperand* operand) { - operand->accept(c, operation, this); + virtual void apply(Context* c, Operation op, MyOperand* operand) { + operand->accept(c, op, this); } virtual void accept(Context*, Operation, RegisterOperand*); @@ -552,10 +556,10 @@ class ImmediateOperand: public MyOperand { value(value) { } - virtual void apply(Context* c, Operation operation); + virtual void apply(Context* c, Operation op); - virtual void apply(Context* c, Operation operation, MyOperand* operand) { - operand->accept(c, operation, this); + virtual void apply(Context* c, Operation op, MyOperand* operand) { + operand->accept(c, op, this); } virtual void accept(Context* c, Operation, RegisterOperand*) { abort(c); } @@ -578,8 +582,8 @@ class AddressOperand: public MyOperand { virtual void setLabelValue(Context*, MyPromise*); virtual void apply(Context*, Operation); - virtual void apply(Context* c, Operation operation, MyOperand* operand) { - operand->accept(c, operation, this); + virtual void apply(Context* c, Operation op, MyOperand* operand) { + operand->accept(c, op, this); } virtual void accept(Context* c, Operation, RegisterOperand*) { abort(c); } @@ -601,8 +605,8 @@ class AbsoluteOperand: public MyOperand { virtual void apply(Context*, Operation); - virtual void apply(Context* c, Operation operation, MyOperand* operand) { - operand->accept(c, operation, this); + virtual void apply(Context* c, Operation op, MyOperand* operand) { + operand->accept(c, op, this); } virtual void accept(Context* c, Operation, RegisterOperand*) { abort(c); } @@ -617,14 +621,19 @@ class AbsoluteOperand: public MyOperand { class MemoryOperand: public MyOperand { public: MemoryOperand(MyOperand* base, int displacement, MyOperand* index, - unsigned scale, bool maybeNull): + unsigned scale, Compiler::TraceHandler* traceHandler): base(base), displacement(displacement), index(index), scale(scale), - maybeNull(maybeNull) + traceHandler(traceHandler) { } + MemoryOperand* high(Context* c) { + return memory + (c, base, displacement + BytesPerWord, index, scale, traceHandler); + } + virtual Register asRegister(Context*); virtual RegisterNode* dependencies(Context* c, RegisterNode* next) { @@ -638,8 +647,8 @@ class MemoryOperand: public MyOperand { virtual void apply(Context*, Operation); - virtual void apply(Context* c, Operation operation, MyOperand* operand) { - operand->accept(c, operation, this); + virtual void apply(Context* c, Operation op, MyOperand* operand) { + operand->accept(c, op, this); } virtual void accept(Context*, Operation, RegisterOperand*); @@ -652,7 +661,7 @@ class MemoryOperand: public MyOperand { int displacement; MyOperand* index; unsigned scale; - bool maybeNull; + Compiler::TraceHandler* traceHandler; }; class CodePromiseTask: public Task { @@ -671,43 +680,43 @@ class CodePromiseTask: public Task { AddressOperand* address(Context* c, MyPromise* p) { - return new (c->zone.allocate(sizeof(AddressOperand))) AddressOperand(p); + return new (c->zone->allocate(sizeof(AddressOperand))) AddressOperand(p); } ImmediateOperand* immediate(Context* c, int64_t v) { - return new (c->zone.allocate(sizeof(ImmediateOperand))) + return new (c->zone->allocate(sizeof(ImmediateOperand))) ImmediateOperand(v); } AbsoluteOperand* absolute(Context* c, MyPromise* v) { - return new (c->zone.allocate(sizeof(AbsoluteOperand))) AbsoluteOperand(v); + return new (c->zone->allocate(sizeof(AbsoluteOperand))) AbsoluteOperand(v); } RegisterOperand* register_(Context* c, RegisterReference* r) { - return new (c->zone.allocate(sizeof(RegisterOperand))) + return new (c->zone->allocate(sizeof(RegisterOperand))) RegisterOperand(r); } RegisterOperand* register_(Context* c, Register v, Register h) { - RegisterReference* r = new (c->zone.allocate(sizeof(RegisterReference))) + RegisterReference* r = new (c->zone->allocate(sizeof(RegisterReference))) RegisterReference(v, h); return register_(c, r); } MemoryOperand* memory(Context* c, MyOperand* base, int displacement, - MyOperand* index, unsigned scale, bool maybeNull) + MyOperand* index, unsigned scale, Compiler::TraceHandler* traceHandler) { - return new (c->zone.allocate(sizeof(MemoryOperand))) - MemoryOperand(base, displacement, index, scale, maybeNull); + return new (c->zone->allocate(sizeof(MemoryOperand))) + MemoryOperand(base, displacement, index, scale, traceHandler); } RegisterOperand* @@ -741,26 +750,15 @@ currentSegment(Context* c) Promise* machineIp(Context* c) { - CodePromise* p = new (c->zone.allocate(sizeof(CodePromise))) CodePromise(); + CodePromise* p = new (c->zone->allocate(sizeof(CodePromise))) CodePromise(); Segment* s = currentSegment(c); - s->event->task = new (c->zone.allocate(sizeof(CodePromiseTask))) + s->event->task = new (c->zone->allocate(sizeof(CodePromiseTask))) CodePromiseTask(p, s->event->task); return p; } -void -handleMaybeNull(Context* c) -{ - if (c->codeLength >= 0) { - c->nullHandler->handleMaybeNull - (new (c->zone.allocate(sizeof(ResolvedPromise))) - ResolvedPromise - (reinterpret_cast(c->code.data + c->code.length))); - } -} - void apply(Context* c, MyOperand::Operation op) { @@ -775,54 +773,54 @@ apply(Context* c, MyOperand::Operation op) class OpEvent: public Event { public: - OpEvent(MyOperand::Operation operation, Event* next): - Event(next), operation(operation) + OpEvent(MyOperand::Operation op, Event* next): + Event(next), op(op) { } virtual void run(Context* c) { - apply(c, operation); + apply(c, op); } - MyOperand::Operation operation; + MyOperand::Operation op; }; class UnaryOpEvent: public Event { public: - UnaryOpEvent(MyOperand::Operation operation, Operand* operand, Event* next): + UnaryOpEvent(MyOperand::Operation op, Operand* operand, Event* next): Event(next), - operation(operation), + op(op), operand(static_cast(operand)) { } virtual void run(Context* c) { if (Verbose) { - fprintf(stderr, "unary %d\n", operation); + fprintf(stderr, "unary %d\n", op); } - operand->apply(c, operation); + operand->apply(c, op); } - MyOperand::Operation operation; + MyOperand::Operation op; MyOperand* operand; }; class BinaryOpEvent: public Event { public: - BinaryOpEvent(MyOperand::Operation operation, Operand* a, Operand* b, + BinaryOpEvent(MyOperand::Operation op, Operand* a, Operand* b, Event* next): Event(next), - operation(operation), + op(op), a(static_cast(a)), b(static_cast(b)) { } virtual void run(Context* c) { if (Verbose) { - fprintf(stderr, "binary %d\n", operation); + fprintf(stderr, "binary %d\n", op); } - a->apply(c, operation, b); + a->apply(c, op, b); } - MyOperand::Operation operation; + MyOperand::Operation op; MyOperand* a; MyOperand* b; }; @@ -887,7 +885,8 @@ push(Context* c, Movement* table, unsigned size) } } - mi->source->apply(c, MyOperand::mov, register_(c, mi->destination)); + mi->source->apply + (c, MyOperand::mov, register_(c, mi->destination)); loop:; } @@ -960,34 +959,34 @@ class ArgumentEvent: public Event { }; void -appendOperation(Context* c, MyOperand::Operation operation) +appendOperation(Context* c, MyOperand::Operation op) { Segment* s = currentSegment(c); - s->event = new (c->zone.allocate(sizeof(OpEvent))) - OpEvent(operation, s->event); + s->event = new (c->zone->allocate(sizeof(OpEvent))) + OpEvent(op, s->event); } void -appendOperation(Context* c, MyOperand::Operation operation, Operand* operand) +appendOperation(Context* c, MyOperand::Operation op, Operand* operand) { Segment* s = currentSegment(c); - s->event = new (c->zone.allocate(sizeof(UnaryOpEvent))) - UnaryOpEvent(operation, operand, s->event); + s->event = new (c->zone->allocate(sizeof(UnaryOpEvent))) + UnaryOpEvent(op, operand, s->event); } void -appendOperation(Context* c, MyOperand::Operation operation, Operand* a, Operand* b) +appendOperation(Context* c, MyOperand::Operation op, Operand* a, Operand* b) { Segment* s = currentSegment(c); - s->event = new (c->zone.allocate(sizeof(BinaryOpEvent))) - BinaryOpEvent(operation, a, b, s->event); + s->event = new (c->zone->allocate(sizeof(BinaryOpEvent))) + BinaryOpEvent(op, a, b, s->event); } void appendAcquire(Context* c, RegisterOperand* operand) { Segment* s = currentSegment(c); - s->event = new (c->zone.allocate(sizeof(AcquireEvent))) + s->event = new (c->zone->allocate(sizeof(AcquireEvent))) AcquireEvent(operand, s->event); } @@ -995,7 +994,7 @@ void appendRelease(Context* c, Operand* operand) { Segment* s = currentSegment(c); - s->event = new (c->zone.allocate(sizeof(ReleaseEvent))) + s->event = new (c->zone->allocate(sizeof(ReleaseEvent))) ReleaseEvent(operand, s->event); } @@ -1003,7 +1002,7 @@ void appendArgumentEvent(Context* c, MyOperand** arguments, unsigned count) { Segment* s = currentSegment(c); - s->event = new (c->zone.allocate(sizeof(ArgumentEvent))) + s->event = new (c->zone->allocate(sizeof(ArgumentEvent))) ArgumentEvent(arguments, count, s->event); } @@ -1031,9 +1030,10 @@ pushed(Context* c, MyStack* stack) MyOperand* value = memory (c, register_(c, rbp), - (c->reserved + index + 1) * BytesPerWord, 0, 1, - false); + 0); - stack = new (c->zone.allocate(sizeof(MyStack))) MyStack(value, index, stack); + stack = new (c->zone->allocate(sizeof(MyStack))) + MyStack(value, index, stack); if (Verbose) { logStack(c, stack); @@ -1043,11 +1043,11 @@ pushed(Context* c, MyStack* stack) } MyStack* -push(Context* c, MyStack* stack, MyOperand::Operation operation, MyOperand* v) +push(Context* c, MyStack* stack, MyOperand::Operation op, MyOperand* v) { - appendOperation(c, operation, v); + appendOperation(c, op, v); - if (BytesPerWord == 4 and operation == MyOperand::push8) { + if (BytesPerWord == 4 and op == MyOperand::push8) { stack = pushed(c, stack); } return pushed(c, stack); @@ -1057,7 +1057,9 @@ MyStack* pop(Context* c, MyStack* stack, int count) { appendOperation - (c, MyOperand::add, immediate(c, count * BytesPerWord), register_(c, rsp)); + (c, MyOperand::add, + immediate(c, count * BytesPerWord), + register_(c, rsp)); while (count) { -- count; @@ -1073,11 +1075,11 @@ pop(Context* c, MyStack* stack, int count) } MyStack* -pop(Context* c, MyStack* stack, MyOperand::Operation operation, MyOperand* dst) +pop(Context* c, MyStack* stack, MyOperand::Operation op, MyOperand* dst) { - appendOperation(c, operation, dst); + appendOperation(c, op, dst); - if (BytesPerWord == 4 and operation == MyOperand::pop8) { + if (BytesPerWord == 4 and op == MyOperand::pop8) { stack = stack->next; } @@ -1092,7 +1094,7 @@ void pushArguments(Context* c, unsigned count, va_list list) { MyOperand** arguments = static_cast - (c->zone.allocate(count * BytesPerWord)); + (c->zone->allocate(count * BytesPerWord)); unsigned index = 0; for (unsigned i = 0; i < count; ++i) { @@ -1171,6 +1173,13 @@ encode(Context* c, uint8_t instruction, int a, MemoryOperand* b, bool rex) { Register r = b->base->asRegister(c); int index = b->index ? b->index->asRegister(c) : -1; + + if (b->traceHandler and c->codeLength >= 0) { + b->traceHandler->handleTrace + (resolved(c, reinterpret_cast + (c->code.data + c->code.length()))); + } + if (rex) { ::rex(c); } @@ -1182,6 +1191,13 @@ encode2(Context* c, uint16_t instruction, int a, MemoryOperand* b, bool rex) { Register r = b->base->asRegister(c); int index = b->index ? b->index->asRegister(c) : -1; + + if (b->traceHandler and c->codeLength >= 0) { + b->traceHandler->handleTrace + (resolved(c, reinterpret_cast + (c->code.data + c->code.length()))); + } + if (rex) { ::rex(c); } @@ -1190,13 +1206,13 @@ encode2(Context* c, uint16_t instruction, int a, MemoryOperand* b, bool rex) } void -RegisterOperand::apply(Context* c, Operation operation) +RegisterOperand::apply(Context* c, Operation op) { - switch (operation) { - case call: + switch (op) { + case call: { c->code.append(0xff); c->code.append(0xd0 | value(c)); - break; + } break; case jmp: c->code.append(0xff); @@ -1205,7 +1221,7 @@ RegisterOperand::apply(Context* c, Operation operation) case pop4: case pop8: - if (BytesPerWord == 4 and operation == pop8) { + if (BytesPerWord == 4 and op == pop8) { apply(c, pop); register_(c, high(c))->apply(c, pop); } else { @@ -1215,7 +1231,7 @@ RegisterOperand::apply(Context* c, Operation operation) case push4: case push8: - if (BytesPerWord == 4 and operation == push8) { + if (BytesPerWord == 4 and op == push8) { register_(c, high(c))->apply(c, push); apply(c, push); } else { @@ -1225,7 +1241,7 @@ RegisterOperand::apply(Context* c, Operation operation) case neg4: case neg8: - assert(c, BytesPerWord == 8 or operation == neg4); // todo + assert(c, BytesPerWord == 8 or op == neg4); // todo rex(c); c->code.append(0xf7); @@ -1237,10 +1253,10 @@ RegisterOperand::apply(Context* c, Operation operation) } void -RegisterOperand::accept(Context* c, Operation operation, +RegisterOperand::accept(Context* c, Operation op, RegisterOperand* operand) { - switch (operation) { + switch (op) { case add: rex(c); c->code.append(0x01); @@ -1249,7 +1265,7 @@ RegisterOperand::accept(Context* c, Operation operation, case cmp4: case cmp8: - if (BytesPerWord == 4 and operation == cmp8) { + if (BytesPerWord == 4 and op == cmp8) { register_(c, high(c))->accept (c, cmp, register_(c, operand->high(c))); @@ -1261,7 +1277,7 @@ RegisterOperand::accept(Context* c, Operation operation, accept(c, cmp, operand); } else { - if (operation == cmp8) rex(c); + if (op == cmp8) rex(c); c->code.append(0x39); c->code.append(0xc0 | (operand->value(c) << 3) | value(c)); } @@ -1269,7 +1285,7 @@ RegisterOperand::accept(Context* c, Operation operation, case mov4: case mov8: - if (BytesPerWord == 4 and operation == mov8) { + if (BytesPerWord == 4 and op == mov8) { accept(c, mov, operand); register_(c, high(c))->accept @@ -1305,7 +1321,7 @@ RegisterOperand::accept(Context* c, Operation operation, case mul4: case mul8: - assert(c, BytesPerWord == 8 or operation == mul4); // todo + assert(c, BytesPerWord == 8 or op == mul4); // todo rex(c); c->code.append(0x0f); @@ -1318,13 +1334,13 @@ RegisterOperand::accept(Context* c, Operation operation, } void -RegisterOperand::accept(Context* c, Operation operation, +RegisterOperand::accept(Context* c, Operation op, ImmediateOperand* operand) { - switch (operation) { + switch (op) { case add4: case add8: - assert(c, BytesPerWord == 8 or operation == add4); // todo + assert(c, BytesPerWord == 8 or op == add4); // todo if (operand->value) { rex(c); @@ -1354,7 +1370,7 @@ RegisterOperand::accept(Context* c, Operation operation, case and4: case and8: - assert(c, BytesPerWord == 8 or operation == and4); // todo + assert(c, BytesPerWord == 8 or op == and4); // todo rex(c); if (isInt8(operand->value)) { @@ -1372,7 +1388,7 @@ RegisterOperand::accept(Context* c, Operation operation, case cmp4: case cmp8: { - assert(c, BytesPerWord == 8 or operation == cmp4); // todo + assert(c, BytesPerWord == 8 or op == cmp4); // todo rex(c); if (isInt8(operand->value)) { @@ -1390,7 +1406,7 @@ RegisterOperand::accept(Context* c, Operation operation, case mov4: case mov8: { - assert(c, BytesPerWord == 8 or operation == mov4); // todo + assert(c, BytesPerWord == 8 or op == mov4); // todo rex(c); c->code.append(0xb8 | value(c)); @@ -1399,7 +1415,7 @@ RegisterOperand::accept(Context* c, Operation operation, case shl4: case shl8: { - assert(c, BytesPerWord == 8 or operation == shl4); // todo + assert(c, BytesPerWord == 8 or op == shl4); // todo if (operand->value) { rex(c); @@ -1418,7 +1434,7 @@ RegisterOperand::accept(Context* c, Operation operation, case sub4: case sub8: { - assert(c, BytesPerWord == 8 or operation == sub4); // todo + assert(c, BytesPerWord == 8 or op == sub4); // todo if (operand->value) { rex(c); @@ -1451,12 +1467,12 @@ value(Context* c, AddressOperand* operand) } void -RegisterOperand::accept(Context* c, Operation operation, +RegisterOperand::accept(Context* c, Operation op, AddressOperand* operand) { - switch (operation) { + switch (op) { case mov: { - accept(c, operation, ::value(c, operand)); + accept(c, op, ::value(c, operand)); } break; default: abort(c); @@ -1464,29 +1480,24 @@ RegisterOperand::accept(Context* c, Operation operation, } void -RegisterOperand::accept(Context* c, Operation operation, +RegisterOperand::accept(Context* c, Operation op, MemoryOperand* operand) { - assert(c, not operand->maybeNull); - - switch (operation) { + switch (op) { case cmp4: case cmp8: - assert(c, BytesPerWord == 8 or operation == cmp4); // todo + assert(c, BytesPerWord == 8 or op == cmp4); // todo encode(c, 0x3b, value(c), operand, true); break; case mov4: case mov8: - if (BytesPerWord == 4 and operation == mov8) { + if (BytesPerWord == 4 and op == mov8) { accept(c, mov, operand); - register_(c, high(c))->accept - (c, mov, memory - (c, operand->base, operand->displacement + BytesPerWord, - operand->index, operand->scale, false)); - } else if (BytesPerWord == 8 and operation == mov4) { + register_(c, high(c))->accept(c, mov, operand->high(c)); + } else if (BytesPerWord == 8 and op == mov4) { encode(c, 0x63, value(c), operand, true); } else { encode(c, 0x8b, value(c), operand, true); @@ -1494,16 +1505,16 @@ RegisterOperand::accept(Context* c, Operation operation, break; case mov1ToW: - encode2(c, 0x0fbe, value(c), operand, true); + encode2(c, 0x0fbe, value(c), operand, true); break; case mov2ToW: - encode2(c, 0x0fbf, value(c), operand, true); - break; + encode2(c, 0x0fbf, value(c), operand, true); + break; case mov2zToW: - encode2(c, 0x0fb7, value(c), operand, true); - break; + encode2(c, 0x0fb7, value(c), operand, true); + break; case mov4To8: assert(c, BytesPerWord == 8); // todo @@ -1513,7 +1524,7 @@ RegisterOperand::accept(Context* c, Operation operation, case mul4: case mul8: - assert(c, BytesPerWord == 8 or operation == mul4); // todo + assert(c, BytesPerWord == 8 or op == mul4); // todo encode2(c, 0x0faf, value(c), operand, true); break; @@ -1533,26 +1544,26 @@ value(Context* c, AbsoluteOperand* operand) } void -RegisterOperand::accept(Context* c, Operation operation, +RegisterOperand::accept(Context* c, Operation op, AbsoluteOperand* operand) { - switch (operation) { + switch (op) { case cmp4: case cmp8: { - assert(c, BytesPerWord == 8 or operation == cmp4); // todo + assert(c, BytesPerWord == 8 or op == cmp4); // todo RegisterOperand* tmp = temporary(c); tmp->accept(c, mov, ::value(c, operand)); - accept(c, cmp, memory(c, tmp, 0, 0, 1, false)); + accept(c, cmp, memory(c, tmp, 0, 0, 1, 0)); tmp->release(c); } break; case mov4: case mov8: { - assert(c, BytesPerWord == 8 or operation == mov4); // todo + assert(c, BytesPerWord == 8 or op == mov4); // todo accept(c, mov, ::value(c, operand)); - accept(c, mov, memory(c, this, 0, 0, 1, false)); + accept(c, mov, memory(c, this, 0, 0, 1, 0)); } break; default: abort(c); @@ -1599,9 +1610,9 @@ AddressOperand::setLabelValue(Context*, MyPromise* p) } void -AddressOperand::apply(Context* c, Operation operation) +AddressOperand::apply(Context* c, Operation op) { - switch (operation) { + switch (op) { case alignedCall: { while ((c->code.length() + 1) % 4) { c->code.append(0x90); @@ -1609,9 +1620,9 @@ AddressOperand::apply(Context* c, Operation operation) apply(c, call); } break; - case call: + case call: { unconditional(c, 0xe8, this); - break; + } break; case jmp: unconditional(c, 0xe9, this); @@ -1644,7 +1655,7 @@ AddressOperand::apply(Context* c, Operation operation) case push4: case push8: { - assert(c, BytesPerWord == 8 or operation == push4); // todo + assert(c, BytesPerWord == 8 or op == push4); // todo RegisterOperand* tmp = temporary(c); tmp->accept(c, mov, this); @@ -1674,21 +1685,22 @@ AddressOperand::asRegister(Context* c) } void -ImmediateOperand::apply(Context* c, Operation operation) +ImmediateOperand::apply(Context* c, Operation op) { - switch (operation) { + switch (op) { case alignedCall: case call: case jmp: - address(c, new (c->zone.allocate(sizeof(ResolvedPromise))) - ResolvedPromise(value))->apply(c, operation); + address(c, resolved(c, value))->apply(c, op); break; case push4: case push8: - if (BytesPerWord == 4 and operation == push8) { - immediate(c, (value >> 32) & 0xFFFFFFFF)->apply(c, push); - immediate(c, (value ) & 0xFFFFFFFF)->apply(c, push); + if (BytesPerWord == 4 and op == push8) { + immediate(c, (value >> 32) & 0xFFFFFFFF)->apply + (c, push); + immediate(c, (value ) & 0xFFFFFFFF)->apply + (c, push); } else { if (isInt8(value)) { c->code.append(0x6a); @@ -1713,28 +1725,28 @@ Register AbsoluteOperand::asRegister(Context* c) { RegisterOperand* tmp = temporary(c); - tmp->accept(c, mov, this); + tmp->accept(c, MyOperand::mov, this); Register v = tmp->value(c); tmp->release(c); return v; } void -absoluteApply(Context* c, MyOperand::Operation operation, +absoluteApply(Context* c, MyOperand::Operation op, AbsoluteOperand* operand) { RegisterOperand* tmp = temporary(c); tmp->accept(c, MyOperand::mov, value(c, operand)); - memory(c, tmp, 0, 0, 1, false)->apply(c, operation); + memory(c, tmp, 0, 0, 1, 0)->apply(c, op); tmp->release(c); } void -AbsoluteOperand::apply(Context* c, Operation operation) +AbsoluteOperand::apply(Context* c, Operation op) { - switch (operation) { + switch (op) { case push: - absoluteApply(c, operation, this); + absoluteApply(c, op, this); break; default: abort(c); @@ -1752,32 +1764,25 @@ MemoryOperand::asRegister(Context* c) } void -MemoryOperand::apply(Context* c, Operation operation) +MemoryOperand::apply(Context* c, Operation op) { - switch (operation) { + switch (op) { case call: - if (maybeNull) handleMaybeNull(c); - encode(c, 0xff, 2, this, false); break; case jmp: - if (maybeNull) handleMaybeNull(c); - encode(c, 0xff, 4, this, false); break; case neg4: case neg8: - assert(c, not maybeNull); - - if (BytesPerWord == 4 and operation == neg8) { + if (BytesPerWord == 4 and op == neg8) { RegisterOperand* ax = temporary(c, rax); RegisterOperand* dx = temporary(c, rdx); MemoryOperand* low = this; - MemoryOperand* high = memory - (c, base, displacement + BytesPerWord, index, scale, false); + MemoryOperand* high = this->high(c); ax->accept(c, mov, low); dx->accept(c, mov, high); @@ -1798,16 +1803,13 @@ MemoryOperand::apply(Context* c, Operation operation) case pop4: case pop8: - assert(c, not maybeNull); - - if (BytesPerWord == 4 and operation == pop8) { + if (BytesPerWord == 4 and op == pop8) { MemoryOperand* low = this; - MemoryOperand* high = memory - (c, base, displacement + BytesPerWord, index, scale, false); + MemoryOperand* high = this->high(c); low->apply(c, pop); high->apply(c, pop); - } else if (BytesPerWord == 8 and operation == pop4) { + } else if (BytesPerWord == 8 and op == pop4) { abort(c); } else { encode(c, 0x8f, 0, this, false); @@ -1816,20 +1818,16 @@ MemoryOperand::apply(Context* c, Operation operation) case push4: case push8: - assert(c, not maybeNull); - - if (BytesPerWord == 4 and operation == push8) { - MemoryOperand* low = memory - (c, base, displacement, index, scale, false); - MemoryOperand* high = memory - (c, base, displacement + BytesPerWord, index, scale, maybeNull); + if (BytesPerWord == 4 and op == push8) { + MemoryOperand* low = this; + MemoryOperand* high = this->high(c); high->apply(c, push); low->apply(c, push); - } else if (BytesPerWord == 8 and operation == push4) { + } else if (BytesPerWord == 8 and op == push4) { RegisterOperand* tmp = temporary(c); tmp->accept(c, mov4, this); - tmp->apply(c, operation); + tmp->apply(c, op); tmp->release(c); } else { encode(c, 0xff, 6, this, false); @@ -1839,10 +1837,8 @@ MemoryOperand::apply(Context* c, Operation operation) case push1: case push2: case push2z: { - assert(c, not maybeNull); - RegisterOperand* tmp = temporary(c); - switch (operation) { + switch (op) { case push1: tmp->accept(c, mov1ToW, this); break; @@ -1866,22 +1862,19 @@ MemoryOperand::apply(Context* c, Operation operation) } void -MemoryOperand::accept(Context* c, Operation operation, - RegisterOperand* operand) +MemoryOperand::accept(Context* c, Operation op, RegisterOperand* operand) { - assert(c, not maybeNull); - - switch (operation) { + switch (op) { case and4: case and8: - assert(c, BytesPerWord == 8 or operation == and4); // todo + assert(c, BytesPerWord == 8 or op == and4); // todo encode(c, 0x21, operand->value(c), this, true); break; case add4: case add8: - if (BytesPerWord == 4 and operation == add8) { + if (BytesPerWord == 4 and op == add8) { RegisterOperand* ax = temporary(c, rax); RegisterOperand* dx = temporary(c, rdx); @@ -1889,8 +1882,7 @@ MemoryOperand::accept(Context* c, Operation operation, dx->accept(c, mov, register_(c, operand->high(c))); accept(c, add, ax); - memory(c, base, displacement + BytesPerWord, index, scale, false)->accept - (c, addc, dx); + high(c)->accept(c, addc, dx); ax->release(c); dx->release(c); @@ -1905,13 +1897,15 @@ MemoryOperand::accept(Context* c, Operation operation, case div4: case div8: - if (BytesPerWord == 4 and operation == div8) { + if (BytesPerWord == 4 and op == div8) { RegisterOperand* axdx = temporary(c, rax, rdx); operand->apply(c, push8); apply(c, push8); - immediate(c, reinterpret_cast(divideLong))->apply(c, call); - register_(c, rsp)->accept(c, add, immediate(c, 16)); + immediate(c, reinterpret_cast(divideLong))->apply + (c, call); + register_(c, rsp)->accept + (c, add, immediate(c, 16)); accept(c, mov8, axdx); axdx->release(c); @@ -1935,12 +1929,12 @@ MemoryOperand::accept(Context* c, Operation operation, case mov4: case mov8: - if (BytesPerWord == 4 and operation == mov8) { + if (BytesPerWord == 4 and op == mov8) { accept(c, mov, operand); - memory(c, base, displacement + BytesPerWord, index, scale, false)->accept + high(c)->accept (c, mov, register_(c, operand->high(c))); - } else if (BytesPerWord == 8 and operation == mov4) { + } else if (BytesPerWord == 8 and op == mov4) { encode(c, 0x89, operand->value(c), this, false); } else { encode(c, 0x89, operand->value(c), this, true); @@ -1977,7 +1971,7 @@ MemoryOperand::accept(Context* c, Operation operation, case mul4: case mul8: - if (BytesPerWord == 4 and operation == mul8) { + if (BytesPerWord == 4 and op == mul8) { RegisterOperand* tmp = temporary(c, rcx); RegisterOperand* ax = temporary(c, rax); RegisterOperand* dx = temporary(c, rdx); @@ -1986,8 +1980,7 @@ MemoryOperand::accept(Context* c, Operation operation, RegisterOperand* highSrc = register_(c, operand->high(c)); MemoryOperand* lowDst = this; - MemoryOperand* highDst = memory - (c, base, displacement + BytesPerWord, index, scale, false); + MemoryOperand* highDst = this->high(c); tmp->accept(c, mov, highSrc); tmp->accept(c, mul, lowDst); @@ -2021,20 +2014,22 @@ MemoryOperand::accept(Context* c, Operation operation, case or4: case or8: - assert(c, BytesPerWord == 8 or operation == or4); // todo + assert(c, BytesPerWord == 8 or op == or4); // todo encode(c, 0x09, operand->value(c), this, true); break; case rem4: case rem8: - if (BytesPerWord == 4 and operation == rem8) { + if (BytesPerWord == 4 and op == rem8) { RegisterOperand* axdx = temporary(c, rax, rdx); operand->apply(c, push8); apply(c, push8); - immediate(c, reinterpret_cast(moduloLong))->apply(c, call); - register_(c, rsp)->accept(c, add, immediate(c, 16)); + immediate(c, reinterpret_cast(moduloLong))->apply + (c, call); + register_(c, rsp)->accept + (c, add, immediate(c, 16)); accept(c, mov8, axdx); axdx->release(c); @@ -2058,19 +2053,16 @@ MemoryOperand::accept(Context* c, Operation operation, case shl4: case shl8: { - if (BytesPerWord == 4 and operation == shl8) { + if (BytesPerWord == 4 and op == shl8) { RegisterOperand* cx = temporary(c, rcx); RegisterOperand* tmp = temporary(c); cx->accept(c, mov, operand); tmp->accept(c, mov, this); // shld - encode2(c, 0x0fa5, tmp->value(c), memory - (c, base, displacement + BytesPerWord, index, scale, maybeNull), - false); + encode2(c, 0x0fa5, tmp->value(c), high(c), false); // shl - encode(c, 0xd3, 4, memory(c, base, displacement, index, scale, false), - false); + encode(c, 0xd3, 4, this, false); tmp->release(c); cx->release(c); @@ -2084,7 +2076,7 @@ MemoryOperand::accept(Context* c, Operation operation, case shr4: case shr8: { - if (BytesPerWord == 4 and operation == shr8) { + if (BytesPerWord == 4 and op == shr8) { RegisterOperand* cx = temporary(c, rcx); RegisterOperand* tmp = temporary(c); @@ -2093,9 +2085,7 @@ MemoryOperand::accept(Context* c, Operation operation, // shrd encode2(c, 0x0fad, tmp->value(c), this, false); // sar - encode(c, 0xd3, 5, memory - (c, base, displacement + BytesPerWord, index, scale, false), - false); + encode(c, 0xd3, 5, high(c), false); tmp->release(c); cx->release(c); @@ -2109,7 +2099,7 @@ MemoryOperand::accept(Context* c, Operation operation, case ushr4: case ushr8: { - if (BytesPerWord == 4 and operation == ushr8) { + if (BytesPerWord == 4 and op == ushr8) { RegisterOperand* cx = temporary(c, rcx); RegisterOperand* tmp = temporary(c); @@ -2118,9 +2108,7 @@ MemoryOperand::accept(Context* c, Operation operation, // shrd encode2(c, 0x0fad, tmp->value(c), this, false); // shr - encode(c, 0xd3, 7, memory - (c, base, displacement + BytesPerWord, index, scale, false), - false); + encode(c, 0xd3, 7, high(c), false); tmp->release(c); cx->release(c); @@ -2134,7 +2122,7 @@ MemoryOperand::accept(Context* c, Operation operation, case sub4: case sub8: - if (BytesPerWord == 4 and operation == sub8) { + if (BytesPerWord == 4 and op == sub8) { RegisterOperand* ax = temporary(c, rax); RegisterOperand* dx = temporary(c, rdx); @@ -2142,8 +2130,7 @@ MemoryOperand::accept(Context* c, Operation operation, dx->accept(c, mov, register_(c, operand->high(c))); accept(c, sub, ax); - memory(c, base, displacement + BytesPerWord, index, scale, false)->accept - (c, subb, dx); + high(c)->accept(c, subb, dx); ax->release(c); dx->release(c); @@ -2158,7 +2145,7 @@ MemoryOperand::accept(Context* c, Operation operation, case xor4: case xor8: { - assert(c, BytesPerWord == 8 or operation == xor4); // todo + assert(c, BytesPerWord == 8 or op == xor4); // todo encode(c, 0x31, operand->value(c), this, true); } break; @@ -2168,15 +2155,13 @@ MemoryOperand::accept(Context* c, Operation operation, } void -MemoryOperand::accept(Context* c, Operation operation, +MemoryOperand::accept(Context* c, Operation op, ImmediateOperand* operand) { - assert(c, not maybeNull); - - switch (operation) { + switch (op) { case add4: case add8: { - assert(c, BytesPerWord == 8 or operation == add4); // todo + assert(c, BytesPerWord == 8 or op == add4); // todo unsigned i = (isInt8(operand->value) ? 0x83 : 0x81); @@ -2193,7 +2178,7 @@ MemoryOperand::accept(Context* c, Operation operation, case mov4: case mov8: { assert(c, isInt32(operand->value)); // todo - assert(c, BytesPerWord == 8 or operation == mov4); // todo + assert(c, BytesPerWord == 8 or op == mov4); // todo encode(c, 0xc7, 0, this, true); c->code.append4(operand->value); @@ -2204,32 +2189,27 @@ MemoryOperand::accept(Context* c, Operation operation, } void -MemoryOperand::accept(Context* c, Operation operation, +MemoryOperand::accept(Context* c, Operation op, AbsoluteOperand* operand) { - assert(c, not maybeNull); - RegisterOperand* tmp = temporary(c); tmp->accept(c, mov, operand); - accept(c, operation, tmp); + accept(c, op, tmp); tmp->release(c); } void -MemoryOperand::accept(Context* c, Operation operation, +MemoryOperand::accept(Context* c, Operation op, MemoryOperand* operand) { - assert(c, not maybeNull); - assert(c, not operand->maybeNull); - - switch (operation) { + switch (op) { case mov1ToW: case mov2ToW: case mov2zToW: case mov4To8: { - if (BytesPerWord == 4 and operation == mov4To8) { + if (BytesPerWord == 4 and op == mov4To8) { RegisterOperand* ax = temporary(c, rax); RegisterOperand* dx = temporary(c, rdx); @@ -2241,7 +2221,7 @@ MemoryOperand::accept(Context* c, Operation operation, dx->release(c); } else { RegisterOperand* tmp = temporary(c); - tmp->accept(c, operation, operand); + tmp->accept(c, op, operand); accept(c, mov, tmp); tmp->release(c); } @@ -2252,7 +2232,7 @@ MemoryOperand::accept(Context* c, Operation operation, case and4: { RegisterOperand* tmp = temporary(c); tmp->accept(c, mov, operand); - accept(c, operation, tmp); + accept(c, op, tmp); tmp->release(c); } break; @@ -2320,30 +2300,20 @@ writeCode(Context* c) class MyCompiler: public Compiler { public: - MyCompiler(System* s, void* indirectCaller): - c(s, indirectCaller) + MyCompiler(System* s, Zone* zone, void* indirectCaller): + c(s, zone, indirectCaller) { } - virtual void setNullHandler(NullHandler* nullHandler) { - assert(&c, c.nullHandler == 0); - c.nullHandler = nullHandler; - } - - virtual Promise* machineIp() { - return ::machineIp(&c); - } - virtual Promise* machineIp(unsigned logicalIp) { - return new (c.zone.allocate(sizeof(IpPromise))) IpPromise(logicalIp); + return new (c.zone->allocate(sizeof(IpPromise))) IpPromise(logicalIp); } virtual Promise* poolAppend(intptr_t v) { - return poolAppendPromise - (new (c.zone.allocate(sizeof(ResolvedPromise))) ResolvedPromise(v)); + return poolAppendPromise(resolved(&c, v)); } virtual Promise* poolAppendPromise(Promise* v) { - Promise* p = new (c.zone.allocate(sizeof(PoolPromise))) + Promise* p = new (c.zone->allocate(sizeof(PoolPromise))) PoolPromise(c.constantPool.length()); c.constantPool.appendAddress(v); return p; @@ -2363,7 +2333,8 @@ class MyCompiler: public Compiler { virtual Stack* push(Stack* s, unsigned count) { appendOperation - (&c, MyOperand::sub, immediate(&c, count * BytesPerWord), + (&c, MyOperand::sub, + immediate(&c, count * BytesPerWord), register_(&c, rsp)); return pushed(s, count); @@ -2458,54 +2429,64 @@ class MyCompiler: public Compiler { return address(&c, 0); } + Promise* machineIp() { + CodePromise* p = new (c.zone->allocate(sizeof(CodePromise))) CodePromise(); + + Segment* s = currentSegment(&c); + s->event->task = new (c.zone->allocate(sizeof(CodePromiseTask))) + CodePromiseTask(p, s->event->task); + + return p; + } + virtual void mark(Operand* label) { static_cast(label)->setLabelValue (&c, static_cast(machineIp())); } - virtual Promise* indirectCall - (Operand* address, unsigned argumentCount, ...) + virtual void indirectCall + (Operand* address, TraceHandler* traceHandler, unsigned argumentCount, ...) { va_list a; va_start(a, argumentCount); pushArguments(&c, argumentCount, a); va_end(a); - appendOperation(&c, MyOperand::mov, address, register_(&c, rax)); - call(immediate(&c, c.indirectCaller)); - Promise* p = machineIp(); + appendOperation + (&c, MyOperand::mov, address, register_(&c, rax)); + call(immediate(&c, c.indirectCaller), traceHandler); appendOperation - (&c, MyOperand::add, immediate(&c, argumentFootprint(argumentCount)), + (&c, MyOperand::add, + immediate(&c, argumentFootprint(argumentCount)), register_(&c, rsp)); - return p; } virtual void indirectCallNoReturn - (Operand* address, unsigned argumentCount, ...) + (Operand* address, TraceHandler* traceHandler, unsigned argumentCount, ...) { va_list a; va_start(a, argumentCount); pushArguments(&c, argumentCount, a); va_end(a); - appendOperation(&c, MyOperand::mov, address, register_(&c, rax)); + appendOperation + (&c, MyOperand::mov, address, register_(&c, rax)); - call(immediate(&c, c.indirectCaller)); + call(immediate(&c, c.indirectCaller), traceHandler); } - virtual Promise* directCall + virtual void directCall (Operand* address, unsigned argumentCount, ...) { va_list a; va_start(a, argumentCount); pushArguments(&c, argumentCount, a); va_end(a); - call(address); - Promise* p = machineIp(); + call(address, 0); appendOperation - (&c, MyOperand::add, immediate(&c, argumentFootprint(argumentCount)), + (&c, MyOperand::add, + immediate(&c, argumentFootprint(argumentCount)), register_(&c, rsp)); - return p; } virtual Operand* result4() { @@ -2540,12 +2521,18 @@ class MyCompiler: public Compiler { } } - virtual void call(Operand* v) { + virtual void call(Operand* v, TraceHandler* traceHandler) { appendOperation(&c, MyOperand::call, v); + if (traceHandler) { + traceHandler->handleTrace(machineIp()); + } } - virtual void alignedCall(Operand* v) { + virtual void alignedCall(Operand* v, TraceHandler* traceHandler) { appendOperation(&c, MyOperand::alignedCall, v); + if (traceHandler) { + traceHandler->handleTrace(machineIp()); + } } virtual void ret() { @@ -2718,16 +2705,16 @@ class MyCompiler: public Compiler { virtual Operand* memory(Operand* base, int displacement, Operand* index, unsigned scale, - bool maybeNull) + TraceHandler* trace) { return ::memory(&c, static_cast(base), displacement, - static_cast(index), scale, maybeNull); + static_cast(index), scale, trace); } virtual void prologue() { appendOperation(&c, MyOperand::push, register_(&c, rbp)); appendOperation - (&c, MyOperand::mov, register_(&c, rsp), register_(&c, rbp)); + (&c, MyOperand::mov, register_(&c, rsp), register_(&c, rbp)); } virtual void reserve(unsigned size) { @@ -2746,8 +2733,8 @@ class MyCompiler: public Compiler { virtual void startLogicalIp(unsigned ip) { c.plan.appendAddress - (new (c.zone.allocate(sizeof(Segment))) - Segment(ip, new (c.zone.allocate(sizeof(Event))) Event(0))); + (new (c.zone->allocate(sizeof(Segment))) + Segment(ip, new (c.zone->allocate(sizeof(Event))) Event(0))); } virtual unsigned codeSize() { @@ -2784,8 +2771,6 @@ class MyCompiler: public Compiler { virtual void dispose() { c.dispose(); - - c.s->free(this); } Context c; @@ -2802,10 +2787,10 @@ MyPromise::value(Compiler* compiler) namespace vm { Compiler* -makeCompiler(System* system, void* indirectCaller) +makeCompiler(System* system, Zone* zone, void* indirectCaller) { - return new (system->allocate(sizeof(MyCompiler))) - MyCompiler(system, indirectCaller); + return new (zone->allocate(sizeof(MyCompiler))) + MyCompiler(system, zone, indirectCaller); } } // namespace v diff --git a/src/compiler.h b/src/compiler.h index 6fce772738..059e09043d 100644 --- a/src/compiler.h +++ b/src/compiler.h @@ -2,6 +2,7 @@ #define COMPILER_H #include "system.h" +#include "zone.h" namespace vm { @@ -20,18 +21,15 @@ class Promise { class Compiler { public: - class NullHandler { + class TraceHandler { public: - virtual ~NullHandler() { } + virtual ~TraceHandler() { } - virtual void handleMaybeNull(Promise* address) = 0; + virtual void handleTrace(Promise* address) = 0; }; virtual ~Compiler() { } - virtual void setNullHandler(NullHandler*) = 0; - - virtual Promise* machineIp() = 0; virtual Promise* machineIp(unsigned logicalIp) = 0; virtual Promise* poolAppend(intptr_t) = 0; @@ -44,7 +42,7 @@ class Compiler { int displacement = 0, Operand* index = 0, unsigned scale = 1, - bool maybeNull = false) = 0; + TraceHandler* traceHandler = 0) = 0; virtual Operand* stack() = 0; virtual Operand* base() = 0; @@ -58,15 +56,17 @@ class Compiler { virtual Operand* label() = 0; virtual void mark(Operand*) = 0; - virtual Promise* indirectCall - (Operand* address, unsigned argumentCount, ...) = 0; + virtual void indirectCall + (Operand* address, TraceHandler* traceHandler, + unsigned argumentCount, ...) = 0; virtual void indirectCallNoReturn - (Operand* address, unsigned argumentCount, ...) = 0; - virtual Promise* directCall + (Operand* address, TraceHandler* traceHandler, + unsigned argumentCount, ...) = 0; + virtual void directCall (Operand* address, unsigned argumentCount, ...) = 0; - virtual void call(Operand*) = 0; - virtual void alignedCall(Operand*) = 0; + virtual void call(Operand*, TraceHandler*) = 0; + virtual void alignedCall(Operand*, TraceHandler*) = 0; virtual void return4(Operand*) = 0; virtual void return8(Operand*) = 0; virtual void ret() = 0; @@ -141,7 +141,7 @@ class Compiler { }; Compiler* -makeCompiler(System* system, void* indirectCaller); +makeCompiler(System* system, Zone* zone, void* indirectCaller); } // namespace vm diff --git a/src/posix.cpp b/src/posix.cpp index 9463f17a21..4873cf2b25 100644 --- a/src/posix.cpp +++ b/src/posix.cpp @@ -55,6 +55,12 @@ void handleSignal(int signal, siginfo_t* info, void* context) { if (signal == SIGSEGV) { + sigset_t set; + + sigemptyset(&set); + sigaddset(&set, SIGSEGV); + sigprocmask(SIG_UNBLOCK, &set, 0); + greg_t* registers = static_cast(context)->uc_mcontext.gregs; @@ -66,8 +72,10 @@ handleSignal(int signal, siginfo_t* info, void* context) if (not handled) { if (oldSegFaultHandler.sa_flags & SA_SIGINFO) { oldSegFaultHandler.sa_sigaction(signal, info, context); - } else { + } else if (oldSegFaultHandler.sa_handler) { oldSegFaultHandler.sa_handler(signal); + } else { + abort(); } } } diff --git a/test/NullPointer.java b/test/NullPointer.java new file mode 100644 index 0000000000..c09dc83340 --- /dev/null +++ b/test/NullPointer.java @@ -0,0 +1,92 @@ +public class NullPointer { + private int x; + private Object y; + + public static void main(String[] args) { + // invokeinterface + try { + ((Runnable) null).run(); + } catch (NullPointerException e) { + e.printStackTrace(); + } + + // invokevirtual + try { + ((Object) null).toString(); + } catch (NullPointerException e) { + e.printStackTrace(); + } + + // arraylength + try { + int a = ((byte[]) null).length; + } catch (NullPointerException e) { + e.printStackTrace(); + } + + // iaload + try { + int a = ((byte[]) null)[42]; + } catch (NullPointerException e) { + e.printStackTrace(); + } + + // aaload + try { + Object a = ((Object[]) null)[42]; + } catch (NullPointerException e) { + e.printStackTrace(); + } + + // getfield (int) + try { + int a = ((NullPointer) null).x; + } catch (NullPointerException e) { + e.printStackTrace(); + } + + // getfield (Object) + try { + Object a = ((NullPointer) null).y; + } catch (NullPointerException e) { + e.printStackTrace(); + } + + // iastore + try { + ((byte[]) null)[42] = 42; + } catch (NullPointerException e) { + e.printStackTrace(); + } + + // aastore + try { + ((Object[]) null)[42] = null; + } catch (NullPointerException e) { + e.printStackTrace(); + } + + // putfield (int) + try { + ((NullPointer) null).x = 42; + } catch (NullPointerException e) { + e.printStackTrace(); + } + + // putfield (Object) + try { + ((NullPointer) null).y = null; + } catch (NullPointerException e) { + e.printStackTrace(); + } + + // monitorenter + try { + synchronized ((Object) null) { + int a = 42; + } + } catch (NullPointerException e) { + e.printStackTrace(); + } + } +}