diff --git a/src/compile.cpp b/src/compile.cpp index eb6a852ab8..80979732d6 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -67,7 +67,7 @@ resolveTarget(MyThread* t, void* stack, object method) if (methodVirtual(t, method)) { unsigned parameterFootprint = methodParameterFootprint(t, method); object class_ = objectClass - (t, reinterpret_cast(stack)[parameterFootprint + 1]); + (t, reinterpret_cast(stack)[parameterFootprint]); if (classVmFlags(t, class_) & BootstrapFlag) { resolveClass(t, className(t, class_)); @@ -366,6 +366,15 @@ class Frame { assert(t, sp + 1 <= mapSize(t, method)); markBit(map, sp++); } + + void popped(unsigned count) { + assert(t, sp >= count); + assert(t, sp - count >= localSize(t, method)); + while (count) { + clearBit(map, -- sp); + -- count; + } + } void poppedInt() { assert(t, sp >= 1); @@ -587,6 +596,11 @@ class Frame { pushedObject(); } + void pushObject() { + c->push(1); + pushedObject(); + } + void pushLong(Operand* o) { c->push2(o); pushedInt(); @@ -594,12 +608,8 @@ class Frame { } void pop(unsigned count) { - assert(t, sp >= count); - assert(t, sp - count >= localSize(t, method)); - while (count) { - clearBit(map, -- sp); - -- count; - } + popped(count); + c->pop(count); } Operand* topInt() { @@ -1276,6 +1286,9 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) break; } + c->release(index); + c->release(array); + c->jmp(next); c->mark(outOfBounds); @@ -1345,6 +1358,10 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) break; } + c->release(value); + c->release(index); + c->release(array); + c->jmp(next); c->mark(outOfBounds); @@ -1397,18 +1414,24 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) (c->constant(reinterpret_cast(makeBlankObjectArray)), 3, c->thread(), frame->append(class_), length); + c->release(length); + frame->trace(); frame->pushObject(r); } break; - case areturn: - c->return_(frame->popObject()); - return; + case areturn: { + Operand* result = frame->popObject(); + c->return_(result); + c->release(result); + } return; - case arraylength: - frame->pushInt(c->memory(frame->popObject(), ArrayLength)); - break; + case arraylength: { + Operand* array = frame->popObject(); + frame->pushInt(c->memory(array, ArrayLength)); + c->release(array); + } break; case astore: frame->storeObject(codeBody(t, code, ip++)); @@ -1430,13 +1453,15 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) frame->storeObject(3); break; - case athrow: + case athrow: { + Operand* e = frame->popObject(); c->indirectCallNoReturn (c->constant(reinterpret_cast(throw_)), - 2, c->thread(), frame->popObject()); + 2, c->thread(), e); + c->release(e); frame->trace(); - break; + } return; case bipush: frame->pushInt @@ -1486,6 +1511,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) frame->pushInt (c->directCall (c->constant(reinterpret_cast(doubleToFloat)), 1, a)); + c->release(a); } break; case d2i: { @@ -1493,6 +1519,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) frame->pushInt (c->directCall (c->constant(reinterpret_cast(doubleToInt)), 1, a)); + c->release(a); } break; case d2l: { @@ -1500,6 +1527,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) frame->pushLong (c->directCall (c->constant(reinterpret_cast(doubleToLong)), 1, a)); + c->release(a); } break; case dadd: { @@ -1508,6 +1536,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) frame->pushLong (c->directCall (c->constant(reinterpret_cast(addDouble)), 2, a, b)); + c->release(a); + c->release(b); } break; case dcmpg: { @@ -1516,6 +1546,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) frame->pushInt (c->directCall (c->constant(reinterpret_cast(compareDoublesG)), 2, a, b)); + c->release(a); + c->release(b); } break; case dcmpl: { @@ -1524,6 +1556,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) frame->pushInt (c->directCall (c->constant(reinterpret_cast(compareDoublesL)), 2, a, b)); + c->release(a); + c->release(b); } break; case dconst_0: @@ -1540,6 +1574,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) frame->pushLong (c->directCall (c->constant(reinterpret_cast(divideDouble)), 2, a, b)); + c->release(a); + c->release(b); } break; case dmul: { @@ -1548,6 +1584,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) frame->pushLong (c->directCall (c->constant(reinterpret_cast(multiplyDouble)), 2, a, b)); + c->release(a); + c->release(b); } break; case dneg: { @@ -1555,6 +1593,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) frame->pushLong (c->directCall (c->constant(reinterpret_cast(negateDouble)), 1, a)); + c->release(a); } break; case vm::drem: { @@ -1563,6 +1602,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) frame->pushLong (c->directCall (c->constant(reinterpret_cast(moduloDouble)), 2, a, b)); + c->release(a); + c->release(b); } break; case dsub: { @@ -1571,6 +1612,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) frame->pushLong (c->directCall (c->constant(reinterpret_cast(subtractDouble)), 2, a, b)); + c->release(a); + c->release(b); } break; case dup: @@ -1602,6 +1645,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) frame->pushLong (c->directCall (c->constant(reinterpret_cast(floatToDouble)), 1, a)); + c->release(a); } break; case f2i: { @@ -1609,6 +1653,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) frame->pushInt (c->directCall (c->constant(reinterpret_cast(floatToInt)), 1, a)); + c->release(a); } break; case f2l: { @@ -1616,6 +1661,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) frame->pushLong (c->directCall (c->constant(reinterpret_cast(floatToLong)), 1, a)); + c->release(a); } break; case fadd: { @@ -1624,6 +1670,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) frame->pushInt (c->directCall (c->constant(reinterpret_cast(addFloat)), 2, a, b)); + c->release(a); + c->release(b); } break; case fcmpg: { @@ -1632,6 +1680,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) frame->pushInt (c->directCall (c->constant(reinterpret_cast(compareFloatsG)), 2, a, b)); + c->release(a); + c->release(b); } break; case fcmpl: { @@ -1640,6 +1690,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) frame->pushInt (c->directCall (c->constant(reinterpret_cast(compareFloatsL)), 2, a, b)); + c->release(a); + c->release(b); } break; case fconst_0: @@ -1660,6 +1712,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) frame->pushInt (c->directCall (c->constant(reinterpret_cast(divideFloat)), 2, a, b)); + c->release(a); + c->release(b); } break; case fmul: { @@ -1668,6 +1722,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) frame->pushInt (c->directCall (c->constant(reinterpret_cast(multiplyFloat)), 2, a, b)); + c->release(a); + c->release(b); } break; case fneg: { @@ -1675,6 +1731,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) frame->pushLong (c->directCall (c->constant(reinterpret_cast(negateFloat)), 1, a)); + c->release(a); } break; case vm::frem: { @@ -1683,6 +1740,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) frame->pushInt (c->directCall (c->constant(reinterpret_cast(moduloFloat)), 2, a, b)); + c->release(a); + c->release(b); } break; case fsub: { @@ -1691,6 +1750,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) frame->pushInt (c->directCall (c->constant(reinterpret_cast(subtractFloat)), 2, a, b)); + c->release(a); + c->release(b); } break; case getfield: @@ -1742,6 +1803,10 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) default: abort(t); } + + if (instruction != getstatic) { + c->release(table); + } } break; case goto_: { @@ -1775,6 +1840,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) frame->pushLong (c->directCall (c->constant(reinterpret_cast(intToDouble)), 1, a)); + c->release(a); } break; case i2f: { @@ -1782,11 +1848,14 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) frame->pushInt (c->directCall (c->constant(reinterpret_cast(intToFloat)), 1, a)); + c->release(a); } break; - case i2l: - frame->pushLong(frame->popInt()); - break; + case i2l: { + Operand* a = frame->popInt(); + frame->pushLong(a); + c->release(a); + } break; case i2s: { Operand* top = frame->topInt(); @@ -1796,11 +1865,13 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) case iadd: { Operand* a = frame->popInt(); c->add(a, frame->topInt()); + c->release(a); } break; case iand: { Operand* a = frame->popInt(); c->and_(a, frame->topInt()); + c->release(a); } break; case iconst_m1: @@ -1834,6 +1905,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) case idiv: { Operand* a = frame->popInt(); c->div(a, frame->topInt()); + c->release(a); } break; case if_acmpeq: @@ -1844,6 +1916,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) Operand* a = frame->popObject(); Operand* b = frame->popObject(); c->cmp(a, b); + c->release(a); + c->release(b); Operand* target = c->logicalIp(newIp); if (instruction == if_acmpeq) { @@ -1868,6 +1942,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) Operand* a = frame->popInt(); Operand* b = frame->popInt(); c->cmp(a, b); + c->release(a); + c->release(b); Operand* target = c->logicalIp(newIp); switch (instruction) { @@ -1904,7 +1980,9 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) uint32_t newIp = (ip - 3) + codeReadInt16(t, code, ip); assert(t, newIp < codeLength(t, code)); - c->cmp(0, frame->popInt()); + Operand* a = frame->popInt(); + c->cmp(c->constant(0), a); + c->release(a); Operand* target = c->logicalIp(newIp); switch (instruction) { @@ -1937,7 +2015,9 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) uint32_t newIp = (ip - 3) + codeReadInt16(t, code, ip); assert(t, newIp < codeLength(t, code)); - c->cmp(0, frame->popObject()); + Operand* a = frame->popInt(); + c->cmp(c->constant(0), a); + c->release(a); Operand* target = c->logicalIp(newIp); if (instruction == ifnull) { @@ -1985,6 +2065,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) case imul: { Operand* a = frame->popInt(); c->mul(a, frame->topInt()); + c->release(a); } break; case instanceof: { @@ -2120,11 +2201,13 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) case ior: { Operand* a = frame->popInt(); c->or_(a, frame->topInt()); + c->release(a); } break; case irem: { Operand* a = frame->popInt(); c->rem(a, frame->topInt()); + c->release(a); } break; case ireturn: @@ -2135,11 +2218,13 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) case ishl: { Operand* a = frame->popInt(); c->shl(a, frame->topInt()); + c->release(a); } break; case ishr: { Operand* a = frame->popInt(); c->shr(a, frame->topInt()); + c->release(a); } break; case istore: @@ -2170,16 +2255,19 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) case isub: { Operand* a = frame->popInt(); c->sub(a, frame->topInt()); + c->release(a); } break; case iushr: { Operand* a = frame->popInt(); c->ushr(a, frame->topInt()); + c->release(a); } break; case ixor: { Operand* a = frame->popInt(); c->xor_(a, frame->topInt()); + c->release(a); } break; case jsr: @@ -2195,6 +2283,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) case ladd: { Operand* a = frame->popLong(); c->sub(a, frame->topLong()); + c->release(a); } break; case lcmp: { @@ -2207,6 +2296,9 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) Operand* result = c->temporary(); c->cmp(a, b); + c->release(a); + c->release(b); + c->jl(less); c->jg(greater); @@ -2276,6 +2368,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) case ldiv_: { Operand* a = frame->popLong(); c->div(a, frame->topLong()); + c->release(a); } break; case lload: @@ -2306,6 +2399,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) case lmul: { Operand* a = frame->popLong(); c->mul(a, frame->topLong()); + c->release(a); } break; case lneg: @@ -2351,31 +2445,39 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) (c->directCall (c->constant(reinterpret_cast(lookUpAddress)), 4, key, start, c->constant(pairCount), default_)); + + c->release(key); } return; case lor: { Operand* a = frame->popLong(); c->or_(a, frame->topLong()); + c->release(a); } break; case lrem: { Operand* a = frame->popLong(); c->rem(a, frame->topLong()); + c->release(a); } break; case lreturn: - case dreturn: + case dreturn: { + Operand* a = frame->popLong(); c->return_(frame->popLong()); - return; + c->release(a); + } return; case lshl: { Operand* a = frame->popLong(); c->shl(a, frame->topLong()); + c->release(a); } break; case lshr: { Operand* a = frame->popLong(); c->shr(a, frame->topLong()); + c->release(a); } break; case lstore: @@ -2406,30 +2508,37 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) case lsub: { Operand* a = frame->popLong(); c->sub(a, frame->topLong()); + c->release(a); } break; case lushr: { Operand* a = frame->popLong(); c->ushr(a, frame->topLong()); + c->release(a); } break; case lxor: { Operand* a = frame->popLong(); c->xor_(a, frame->topLong()); + c->release(a); } break; case monitorenter: { + Operand* a = frame->popObject(); c->indirectCall (c->constant(reinterpret_cast(acquireMonitorForObject)), - 2, c->thread(), frame->popObject()); + 2, c->thread(), a); + c->release(a); frame->trace(); } break; case monitorexit: { + Operand* a = frame->popObject(); c->indirectCall (c->constant(reinterpret_cast(releaseMonitorForObject)), - 2, c->thread(), frame->popObject()); + 2, c->thread(), a); + c->release(a); frame->trace(); } break; @@ -2486,6 +2595,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) Operand* size = frame->popInt(); c->cmp(0, size); + c->release(size); + c->jge(nonnegative); compileThrowNew(t, frame, Machine::NegativeArraySizeExceptionType); @@ -2582,7 +2693,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) } break; case ObjectField: { - value = frame->popLong(); + value = frame->popObject(); } break; default: abort(t); @@ -2620,11 +2731,16 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) case ObjectField: c->directCall (c->constant(reinterpret_cast(set)), - 4, c->thread(), table, fieldOffset(t, field), value); + 4, c->thread(), table, c->constant(fieldOffset(t, field)), value); break; default: abort(t); } + + if (instruction != putstatic) { + c->release(table); + } + c->release(value); } break; case return_: @@ -2687,6 +2803,8 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) c->mark(defaultCase); c->jmp(default_); + + c->release(key); } return; case wide: { @@ -2884,7 +3002,7 @@ compile(MyThread* t, Compiler* c, object method) uintptr_t map[Frame::mapSizeInWords(t, method)]; Frame frame2(&frame, map); - frame2.pushedObject(); + frame2.pushObject(); compile(t, &frame2, exceptionHandlerIp(eh)); if (UNLIKELY(t->exception)) return 0; @@ -3169,17 +3287,12 @@ compileDefault(MyThread* t, Compiler* c) object compileNative(MyThread* t, Compiler* c) { - c->prologue(); - c->mov(c->base(), c->memory(c->thread(), difference(&(t->base), t))); c->mov(c->stack(), c->memory(c->thread(), difference(&(t->stack), t))); - c->call - (c->directCall - (c->constant(reinterpret_cast(invokeNative)), - 1, c->thread())); + c->directCall + (c->constant(reinterpret_cast(invokeNative)), 1, c->thread()); - c->epilogue(); c->ret(); return finish(t, c); @@ -3698,7 +3811,7 @@ findTraceNode(MyThread* t, void* address) & (arrayLength(t, p->addressTable) - 1); for (object n = arrayBody(t, p->addressTable, index); - n; n = tripleThird(t, n)) + n; n = traceNodeNext(t, n)) { intptr_t k = traceNodeAddress(t, n); diff --git a/src/compiler.cpp b/src/compiler.cpp index b8c1aa3e7f..fd1a2f5de5 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -64,7 +64,7 @@ class IpTask { virtual ~IpTask() { } virtual void run(Context* c, unsigned ip, unsigned start, unsigned end, - uint8_t* code, unsigned offset) = 0; + unsigned offset) = 0; virtual Priority priority() { return LowPriority; @@ -96,32 +96,53 @@ class MyPromise: public Promise { public: MyPromise(intptr_t key): key(key) { } - virtual unsigned value(Compiler*); + virtual intptr_t value(Compiler*); - virtual unsigned value(Context*) = 0; + virtual intptr_t value(Context*) = 0; + + virtual bool resolved(Context*) = 0; intptr_t key; }; +class ResolvedPromise: public MyPromise { + public: + ResolvedPromise(intptr_t key): MyPromise(key) { } + + virtual intptr_t value(Context*) { + return key; + } + + virtual bool resolved(Context*) { + return true; + } +}; + class PoolPromise: public MyPromise { public: PoolPromise(intptr_t key): MyPromise(key) { } - virtual unsigned value(Context*); + virtual intptr_t value(Context*); + virtual bool resolved(Context*); }; class CodePromise: public MyPromise { public: - CodePromise(intptr_t key): MyPromise(key) { } + CodePromise(intptr_t key, bool absolute): + MyPromise(key), absolute(absolute) + { } - virtual unsigned value(Context*); + virtual intptr_t value(Context*); + virtual bool resolved(Context*); + + bool absolute; }; class CodePromiseTask: public IpTask { public: CodePromiseTask(CodePromise* p, IpTask* next): IpTask(next), p(p) { } - virtual void run(Context*, unsigned, unsigned start, unsigned, uint8_t*, + virtual void run(Context*, unsigned, unsigned start, unsigned, unsigned offset) { p->key = offset + (p->key - start); @@ -136,9 +157,14 @@ class CodePromiseTask: public IpTask { class IpPromise: public MyPromise { public: - IpPromise(intptr_t key): MyPromise(key) { } + IpPromise(intptr_t key, bool absolute): + MyPromise(key), absolute(absolute) + { } - virtual unsigned value(Context*); + virtual intptr_t value(Context*); + virtual bool resolved(Context*); + + bool absolute; }; class MyOperand: public Operand { @@ -182,7 +208,7 @@ class MyOperand: public Operand { virtual void release(Context*) { /* ignore */ } - virtual void setAbsolute(Context* c, intptr_t) { abort(c); } + virtual void setImmediate(Context* c, intptr_t) { abort(c); } virtual void apply(Context* c, Operation) { abort(c); } @@ -229,17 +255,21 @@ class RegisterOperand: public MyOperand { class ImmediateOperand: public MyOperand { public: - ImmediateOperand(intptr_t value): + ImmediateOperand(MyPromise* value): value(value) { } + virtual void setImmediate(Context*, intptr_t v) { + value->key = v; + } + virtual void apply(Context* c, Operation operation); virtual void apply(Context* c, Operation operation, MyOperand* operand) { operand->accept(c, operation, this); } - intptr_t value; + MyPromise* value; }; class AbsoluteOperand: public MyOperand { @@ -254,10 +284,6 @@ class AbsoluteOperand: public MyOperand { operand->accept(c, operation, this); } - virtual void setAbsolute(Context*, intptr_t v) { - value->key = v; - } - MyPromise* value; }; @@ -358,7 +384,8 @@ class Context { indirectCaller(reinterpret_cast(indirectCaller)), stack(0), ipTable(0), - reserved(0) + reserved(0), + output(0) { ipMappings.appendAddress (new (zone.allocate(sizeof(IpMapping))) IpMapping(-1, 0)); @@ -390,6 +417,7 @@ class Context { StackOperand* stack; IpMapping** ipTable; unsigned reserved; + uint8_t* output; RegisterOperand* registers[RegisterCount]; }; @@ -413,10 +441,17 @@ expect(Context* c, bool v) expect(c->s, v); } +ImmediateOperand* +immediate(Context* c, MyPromise* p) +{ + return new (c->zone.allocate(sizeof(ImmediateOperand))) ImmediateOperand(p); +} + ImmediateOperand* immediate(Context* c, intptr_t v) { - return new (c->zone.allocate(sizeof(ImmediateOperand))) ImmediateOperand(v); + return immediate(c, new (c->zone.allocate(sizeof(ResolvedPromise))) + ResolvedPromise(v)); } AbsoluteOperand* @@ -463,10 +498,8 @@ temporary(Context* c) } StackOperand* -push(Context* c, MyOperand* v) +pushed(Context* c) { - v->apply(c, MyOperand::push); - int index = (c->stack ? c->stack->index + (c->stack->footprint() / BytesPerWord) : 0); @@ -478,6 +511,36 @@ push(Context* c, MyOperand* v) StackOperand(base, index, c->stack); } +void +push(Context* c, int count) +{ + while (count) { + -- count; + pushed(c); + } + immediate(c, count * BytesPerWord)->apply + (c, MyOperand::sub, register_(c, rsp)); +} + +StackOperand* +push(Context* c, MyOperand* v) +{ + v->apply(c, MyOperand::push); + return pushed(c); +} + +void +pop(Context* c, int count) +{ + while (count) { + count -= (c->stack->footprint() / BytesPerWord); + assert(c, count >= 0); + c->stack = c->stack->next; + } + immediate(c, count * BytesPerWord)->apply + (c, MyOperand::add, register_(c, rsp)); +} + void pop(Context* c, MyOperand* dst) { @@ -641,6 +704,12 @@ RegisterOperand::accept(Context* c, Operation operation, c->code.append(0xc0 | (operand->value << 3) | value); break; + case cmp: + rex(c); + c->code.append(0x39); + c->code.append(0xc0 | (operand->value << 3) | value); + break; + case mov: if (value != operand->value) { rex(c); @@ -658,50 +727,66 @@ RegisterOperand::accept(Context* c, Operation operation, ImmediateOperand* operand) { switch (operation) { - case add: - if (operand->value) { - assert(c, isInt8(operand->value)); // todo + case add: { + intptr_t v = operand->value->value(c); + if (v) { + assert(c, isInt8(v)); // todo rex(c); c->code.append(0x83); c->code.append(0xc0 | value); - c->code.append(operand->value); + c->code.append(v); } - break; + } break; - case and_: - if (operand->value) { + case and_: { + intptr_t v = operand->value->value(c); + if (v) { rex(c); - if (isInt8(operand->value)) { + if (isInt8(v)) { c->code.append(0x83); c->code.append(0xe0 | value); - c->code.append(operand->value); + c->code.append(v); } else { - assert(c, isInt32(operand->value)); + assert(c, isInt32(v)); c->code.append(0x81); c->code.append(0xe0 | value); - c->code.append(operand->value); + c->code.append(v); } } - break; + } break; - case mov: + case cmp: { + intptr_t v = operand->value->value(c); + if (v) { + assert(c, isInt8(v)); // todo + + rex(c); + c->code.append(0x83); + c->code.append(0xf8 | value); + c->code.append(v); + } + } break; + + case mov: { + intptr_t v = operand->value->value(c); rex(c); c->code.append(0xb8 | value); - c->code.appendAddress(operand->value); - break; + c->code.appendAddress(v); + } break; - case sub: - if (operand->value) { - assert(c, isInt8(operand->value)); // todo + case sub: { + intptr_t v = operand->value->value(c); + if (v) { + assert(c, isInt8(v)); // todo rex(c); c->code.append(0x83); c->code.append(0xe8 | value); - c->code.append(operand->value); + c->code.append(v); } - break; + } break; default: abort(c); } @@ -729,10 +814,10 @@ class AbsoluteMovTask: public IpTask { { } virtual void run(Context* c UNUSED, unsigned, unsigned start, unsigned, - uint8_t* code, unsigned offset) + unsigned offset) { - uint8_t* instruction = code + offset + (this->start - start); - intptr_t v = reinterpret_cast(code + promise->value(c)); + uint8_t* instruction = c->output + offset + (this->start - start); + intptr_t v = reinterpret_cast(c->output + promise->value(c)); memcpy(instruction + (BytesPerWord / 8) + 1, &v, BytesPerWord); } @@ -764,36 +849,47 @@ RegisterOperand::accept(Context* c, Operation operation, } } -class DirectCallTask: public IpTask { +class DirectJumpTask: public IpTask { public: - DirectCallTask(unsigned start, uint8_t* address, IpTask* next): - IpTask(next), start(start), address(address) + DirectJumpTask(unsigned start, unsigned offset, MyPromise* address, + IpTask* next): + IpTask(next), start(start), offset(offset), address(address) { } virtual void run(Context* c UNUSED, unsigned, unsigned start, unsigned, - uint8_t* code, unsigned offset) + unsigned offset) { - uint8_t* instruction = code + offset + (this->start - start); - assert(c, *instruction == 0xe8); - - intptr_t v = address - instruction - 5; + uint8_t* instruction = c->output + offset + (this->start - start); + intptr_t v = reinterpret_cast(address->value(c)) + - instruction - 4 - this->offset; assert(c, isInt32(v)); int32_t v32 = v; - memcpy(instruction + 1, &v32, 4); + memcpy(instruction + this->offset, &v32, 4); } unsigned start; - uint8_t* address; + unsigned offset; + MyPromise* address; }; void -addDirectCallTask(Context* c, intptr_t v) +addDirectJumpTask(Context* c, unsigned offset, MyPromise* p) { IpMapping* mapping = currentMapping(c); - mapping->task = new (c->zone.allocate(sizeof(DirectCallTask))) - DirectCallTask - (c->code.length(), reinterpret_cast(v), mapping->task); + mapping->task = new (c->zone.allocate(sizeof(DirectJumpTask))) + DirectJumpTask(c->code.length(), offset, p, mapping->task); +} + +void +immediateConditional(Context* c, unsigned condition, + ImmediateOperand* operand) +{ + addDirectJumpTask(c, 2, operand->value); + + c->code.append(0x0f); + c->code.append(condition); + c->code.append4(0); } void @@ -807,44 +903,83 @@ ImmediateOperand::apply(Context* c, Operation operation) apply(c, call); } break; - case call: { - addDirectCallTask(c, value); + case call: + addDirectJumpTask(c, 1, value); - c->code.append(0xE8); + c->code.append(0xe8); c->code.append4(0); - } break; + break; - case push: - if (isInt8(value)) { + case jmp: + addDirectJumpTask(c, 1, value); + + c->code.append(0xe9); + c->code.append4(0); + break; + + case je: + immediateConditional(c, 0x84, this); + break; + + case jne: + immediateConditional(c, 0x85, this); + break; + + case jg: + immediateConditional(c, 0x8f, this); + break; + + case jge: + immediateConditional(c, 0x8d, this); + break; + + case jl: + immediateConditional(c, 0x8c, this); + break; + + case jle: + immediateConditional(c, 0x8e, this); + break; + + case push: { + intptr_t v = value->value(c); + if (isInt8(v)) { c->code.append(0x6a); - c->code.append(value); - } else if (isInt32(value)) { + c->code.append(v); + } else if (isInt32(v)) { c->code.append(0x68); - c->code.append4(value); + c->code.append4(v); } else { RegisterOperand* tmp = temporary(c); tmp->accept(c, mov, this); tmp->apply(c, push); tmp->release(c); } - break; + } break; default: abort(c); } } +void +absoluteApply(Context* c, MyOperand::Operation operation, + AbsoluteOperand* operand) +{ + addAbsoluteMovTask(c, operand->value); + + RegisterOperand* tmp = temporary(c); + tmp->accept(c, MyOperand::mov, immediate(c, 0)); + memory(c, tmp, 0, 0, 1)->apply(c, operation); + tmp->release(c); +} + void AbsoluteOperand::apply(Context* c, Operation operation) { switch (operation) { - case push: { - addAbsoluteMovTask(c, value); - - RegisterOperand* tmp = temporary(c); - tmp->accept(c, mov, immediate(c, 0)); - memory(c, tmp, 0, 0, 1)->apply(c, push); - tmp->release(c); - } break; + case push: + absoluteApply(c, operation, this); + break; default: abort(c); } @@ -884,15 +1019,21 @@ MemoryOperand::accept(Context* c, Operation operation, RegisterOperand* operand) { switch (operation) { + case add: + rex(c); + encode(c, 0x01, 0, 0x40, 0x80, operand->value, base->asRegister(c), + displacement); + break; + case mov: rex(c); encode(c, 0x89, 0, 0x40, 0x80, operand->value, base->asRegister(c), displacement); break; - case add: + case sub: rex(c); - encode(c, 0x01, 0, 0x40, 0x80, operand->value, base->asRegister(c), + encode(c, 0x29, 0, 0x40, 0x80, operand->value, base->asRegister(c), displacement); break; @@ -905,13 +1046,28 @@ MemoryOperand::accept(Context* c, Operation operation, ImmediateOperand* operand) { switch (operation) { - case mov: - assert(c, isInt32(operand->value)); // todo + case add: { + rex(c); + intptr_t v = operand->value->value(c); + unsigned i = (isInt8(v) ? 0x83 : 0x81); + encode(c, i, 0, 0x40, 0x80, rax, base->asRegister(c), displacement); + if (isInt8(v)) { + c->code.append(v); + } else if (isInt32(v)) { + c->code.append4(v); + } else { + abort(c); + } + } break; + + case mov: { + intptr_t v = operand->value->value(c); + assert(c, isInt32(v)); // todo rex(c); encode(c, 0xc7, 0, 0x40, 0x80, rax, base->asRegister(c), displacement); - c->code.append4(operand->value); - break; + c->code.append4(v); + } break; default: abort(c); } @@ -935,30 +1091,46 @@ MemoryOperand::accept(Context* c, Operation operation, } } -unsigned +intptr_t PoolPromise::value(Context* c) { - if (c->ipTable) { + if (resolved(c)) { return c->code.length() + key; } abort(c); } -unsigned +bool +PoolPromise::resolved(Context* c) +{ + return c->output != 0; +} + +intptr_t CodePromise::value(Context* c) { - if (c->ipTable) { - return key; + if (resolved(c)) { + if (absolute) { + return reinterpret_cast(c->output + key); + } else { + return key; + } } abort(c); } -unsigned +bool +CodePromise::resolved(Context* c) +{ + return c->output != 0; +} + +intptr_t IpPromise::value(Context* c) { - if (c->ipTable) { + if (resolved(c)) { unsigned bottom = 0; unsigned top = c->ipMappings.length() / BytesPerWord; for (unsigned span = top - bottom; span; span = top - bottom) { @@ -966,7 +1138,11 @@ IpPromise::value(Context* c) IpMapping* mapping = c->ipTable[middle]; if (key == mapping->ip) { - return mapping->start; + if (absolute) { + return reinterpret_cast(c->output + mapping->start); + } else { + return mapping->start; + } } else if (key < mapping->ip) { top = middle; } else if (key > mapping->ip) { @@ -978,17 +1154,23 @@ IpPromise::value(Context* c) abort(c); } -void -runTasks(Context* c, uint8_t* out, IpTask::Priority priority) +bool +IpPromise::resolved(Context* c) { - uint8_t* p = out; + return c->output != 0; +} + +void +runTasks(Context* c, IpTask::Priority priority) +{ + uint8_t* p = c->output; for (unsigned i = 0; i < c->ipMappings.length() / BytesPerWord; ++i) { IpMapping* mapping = c->ipTable[i]; int length = mapping->end - mapping->start; for (IpTask* t = mapping->task; t; t = t->next) { if (t->priority() == priority) { - t->run(c, mapping->ip, mapping->start, mapping->end, out, p - out); + t->run(c, mapping->ip, mapping->start, mapping->end, p - c->output); } } @@ -1009,10 +1191,10 @@ class MyCompiler: public Compiler { virtual Promise* codeOffset() { if (c.code.length() == 0) { - return new (c.zone.allocate(sizeof(CodePromise))) CodePromise(0); + return new (c.zone.allocate(sizeof(CodePromise))) CodePromise(0, false); } else { CodePromise* p = new (c.zone.allocate(sizeof(CodePromise))) - CodePromise(c.code.length()); + CodePromise(c.code.length(), false); IpMapping* mapping = currentMapping(&c); mapping->task = new (c.zone.allocate(sizeof(CodePromiseTask))) @@ -1032,6 +1214,10 @@ class MyCompiler: public Compiler { return immediate(&c, v); } + virtual void push(unsigned count) { + ::push(&c, count); + } + virtual void push(Operand* v) { ::push(&c, static_cast(v)); } @@ -1054,6 +1240,10 @@ class MyCompiler: public Compiler { return s; } + virtual void pop(unsigned count) { + ::pop(&c, count); + } + virtual Operand* pop() { return ::pop(&c); } @@ -1097,12 +1287,12 @@ class MyCompiler: public Compiler { } virtual Operand* label() { - return absolute - (&c, new (c.zone.allocate(sizeof(CodePromise))) CodePromise(0)); + return immediate + (&c, new (c.zone.allocate(sizeof(CodePromise))) CodePromise(0, true)); } virtual void mark(Operand* label) { - static_cast(label)->setAbsolute(&c, c.code.length()); + static_cast(label)->setImmediate(&c, c.code.length()); } virtual Operand* indirectCall @@ -1304,7 +1494,8 @@ class MyCompiler: public Compiler { } virtual void reserve(unsigned size) { - sub(constant(size * BytesPerWord), stack()); + immediate(&c, size * BytesPerWord)->apply + (&c, MyOperand::sub, register_(&c, rsp)); c.reserved = size; } @@ -1320,11 +1511,12 @@ class MyCompiler: public Compiler { } virtual Operand* logicalIp(unsigned ip) { - return absolute(&c, static_cast(logicalIpToOffset(ip))); + return immediate + (&c, new (c.zone.allocate(sizeof(IpPromise))) IpPromise(ip, true)); } virtual Promise* logicalIpToOffset(unsigned ip) { - return new (c.zone.allocate(sizeof(IpPromise))) IpPromise(ip); + return new (c.zone.allocate(sizeof(IpPromise))) IpPromise(ip, false); } virtual unsigned codeSize() { @@ -1336,6 +1528,8 @@ class MyCompiler: public Compiler { } virtual void writeTo(uint8_t* out) { + c.output = out; + unsigned tableSize = (c.ipMappings.length() / BytesPerWord); c.ipTable = static_cast @@ -1371,8 +1565,8 @@ class MyCompiler: public Compiler { memcpy(p, c.constantPool.data, c.constantPool.length()); - runTasks(&c, out, IpTask::HighPriority); - runTasks(&c, out, IpTask::LowPriority); + runTasks(&c, IpTask::HighPriority); + runTasks(&c, IpTask::LowPriority); } virtual void updateCall(void* returnAddress, void* newTarget) { @@ -1394,7 +1588,7 @@ class MyCompiler: public Compiler { Context c; }; -unsigned +intptr_t MyPromise::value(Compiler* compiler) { return value(&(static_cast(compiler)->c)); diff --git a/src/compiler.h b/src/compiler.h index b3f98ef865..b1ccef5db9 100644 --- a/src/compiler.h +++ b/src/compiler.h @@ -13,7 +13,7 @@ class Promise { public: virtual ~Promise() { } - virtual unsigned value(Compiler*) = 0; + virtual intptr_t value(Compiler*) = 0; }; class Compiler { @@ -49,8 +49,10 @@ class Compiler { virtual void return_(Operand*) = 0; virtual void ret() = 0; + virtual void push(unsigned count) = 0; virtual void push(Operand*) = 0; virtual void push2(Operand*) = 0; + virtual void pop(unsigned count) = 0; virtual Operand* pop() = 0; virtual Operand* pop2() = 0; virtual void pop(Operand*) = 0; diff --git a/test/Misc.java b/test/Misc.java index ae2e84d5da..956c220b16 100644 --- a/test/Misc.java +++ b/test/Misc.java @@ -15,7 +15,7 @@ public class Misc { } public static void main(String[] args) { -// boolean v = Boolean.valueOf("true"); + boolean v = Boolean.valueOf("true"); // ClassLoader.getSystemClassLoader().toString();