diff --git a/src/compile.cpp b/src/compile.cpp index 423fc0d0f5..7c1f16ea04 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -948,6 +948,8 @@ class Frame { (context->zone.allocate(sizeof(TraceElement) + (mapSize * BytesPerWord))) TraceElement(context, target, virtualCall, context->traceLog); + fprintf(stderr, "make element %p at ip %d\n", e, ip); + context->eventLog.append(TraceEvent); context->eventLog.appendAddress(e); @@ -1573,6 +1575,10 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) frame->startLogicalIp(ip); + if (ip == 0) { + handleEntrance(t, frame); + } + // fprintf(stderr, "ip: %d map: %ld\n", ip, *(frame->map)); unsigned instruction = codeBody(t, code, ip++); @@ -1591,17 +1597,24 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) if (CheckArrayBounds) { Compiler::Operand* load = c->label(); - Compiler::Operand* throw_ = c->label(); + Compiler::Operand* throw_ = 0; - c->cmp(4, c->constant(0), index); - c->jl(throw_); + if (c->isConstant(index)) { + expect(t, c->constantValue(index) >= 0); + } else { + throw_ = c->label(); + c->cmp(4, c->constant(0), index); + c->jl(throw_); + } c->cmp(BytesPerWord, - c->memory(array, ArrayLength, 0, 1, frame->trace(0, false)), - index); - c->jl(load); + index, + c->memory(array, ArrayLength, 0, 1, frame->trace(0, false))); + c->jge(load); - c->mark(throw_); + if (not c->isConstant(index)) { + c->mark(throw_); + } c->call (c->constant(reinterpret_cast(throwArrayIndexOutOfBounds)), @@ -1614,34 +1627,67 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) c->mark(load); } - switch (instruction) { - case aaload: - frame->pushObject - (c->load - (BytesPerWord, c->memory(array, ArrayBody, index, BytesPerWord))); - break; + if (c->isConstant(index)) { + unsigned i = c->constantValue(index); + switch (instruction) { + case aaload: + frame->pushObject + (c->load + (BytesPerWord, c->memory(array, ArrayBody + (i * BytesPerWord)))); + break; - case faload: - case iaload: - frame->pushInt(c->load(4, c->memory(array, ArrayBody, index, 4))); - break; + case faload: + case iaload: + frame->pushInt(c->load(4, c->memory(array, ArrayBody + (i * 4)))); + break; - case baload: - frame->pushInt(c->load(1, c->memory(array, ArrayBody, index, 1))); - break; + case baload: + frame->pushInt(c->load(1, c->memory(array, ArrayBody + i))); + break; - case caload: - frame->pushInt(c->loadz(2, c->memory(array, ArrayBody, index, 2))); - break; + case caload: + frame->pushInt(c->loadz(2, c->memory(array, ArrayBody + (i * 2)))); + break; - case daload: - case laload: - frame->pushLong(c->load(8, c->memory(array, ArrayBody, index, 8))); - break; + case daload: + case laload: + frame->pushInt(c->load(8, c->memory(array, ArrayBody + (i * 8)))); + break; - case saload: - frame->pushInt(c->load(2, c->memory(array, ArrayBody, index, 2))); - break; + case saload: + frame->pushInt(c->load(2, c->memory(array, ArrayBody + (i * 2)))); + break; + } + } else { + switch (instruction) { + case aaload: + frame->pushObject + (c->load + (BytesPerWord, c->memory(array, ArrayBody, index, BytesPerWord))); + break; + + case faload: + case iaload: + frame->pushInt(c->load(4, c->memory(array, ArrayBody, index, 4))); + break; + + case baload: + frame->pushInt(c->load(1, c->memory(array, ArrayBody, index, 1))); + break; + + case caload: + frame->pushInt(c->loadz(2, c->memory(array, ArrayBody, index, 2))); + break; + + case daload: + case laload: + frame->pushLong(c->load(8, c->memory(array, ArrayBody, index, 8))); + break; + + case saload: + frame->pushInt(c->load(2, c->memory(array, ArrayBody, index, 2))); + break; + } } } break; @@ -1667,17 +1713,24 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) if (CheckArrayBounds) { Compiler::Operand* store = c->label(); - Compiler::Operand* throw_ = c->label(); + Compiler::Operand* throw_ = 0; - c->cmp(4, c->constant(0), index); - c->jl(throw_); + if (c->isConstant(index)) { + expect(t, c->constantValue(index) >= 0); + } else { + throw_ = c->label(); + c->cmp(4, c->constant(0), index); + c->jl(throw_); + } c->cmp(BytesPerWord, - c->memory(array, ArrayLength, 0, 1, frame->trace(0, false)), - index); - c->jl(store); + index, + c->memory(array, ArrayLength, 0, 1, frame->trace(0, false))); + c->jge(store); - c->mark(throw_); + if (not c->isConstant(index)) { + c->mark(throw_); + } c->call (c->constant(reinterpret_cast(throwArrayIndexOutOfBounds)), @@ -1690,38 +1743,74 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) c->mark(store); } - switch (instruction) { - case aastore: { - c->call - (c->constant(reinterpret_cast(setMaybeNull)), - context->indirection, - 0, - frame->trace(0, false), - 0, - 4, c->thread(), array, - c->add(4, c->constant(ArrayBody), - c->shl(4, c->constant(log(BytesPerWord)), index)), - value); - } break; + if (c->isConstant(index)) { + unsigned i = c->constantValue(index); + switch (instruction) { + case aastore: { + c->call + (c->constant(reinterpret_cast(setMaybeNull)), + context->indirection, + 0, + frame->trace(0, false), + 0, + 4, c->thread(), array, + c->constant(ArrayBody + (i * BytesPerWord)), + value); + } break; - case fastore: - case iastore: - c->store(4, value, c->memory(array, ArrayBody, index, 4)); - break; + case fastore: + case iastore: + c->store(4, value, c->memory(array, ArrayBody + (i * 4))); + break; - case bastore: - c->store(1, value, c->memory(array, ArrayBody, index, 1)); - break; + case bastore: + c->store(1, value, c->memory(array, ArrayBody + i)); + break; - case castore: - case sastore: - c->store(2, value, c->memory(array, ArrayBody, index, 2)); - break; + case castore: + case sastore: + c->store(2, value, c->memory(array, ArrayBody + (i * 2))); + break; - case dastore: - case lastore: - c->store(8, value, c->memory(array, ArrayBody, index, 8)); - break; + case dastore: + case lastore: + c->store(8, value, c->memory(array, ArrayBody + (i * 8))); + break; + } + } else { + switch (instruction) { + case aastore: { + c->call + (c->constant(reinterpret_cast(setMaybeNull)), + context->indirection, + 0, + frame->trace(0, false), + 0, + 4, c->thread(), array, + c->add(4, c->constant(ArrayBody), + c->shl(4, c->constant(log(BytesPerWord)), index)), + value); + } break; + + case fastore: + case iastore: + c->store(4, value, c->memory(array, ArrayBody, index, 4)); + break; + + case bastore: + c->store(1, value, c->memory(array, ArrayBody, index, 1)); + break; + + case castore: + case sastore: + c->store(2, value, c->memory(array, ArrayBody, index, 2)); + break; + + case dastore: + case lastore: + c->store(8, value, c->memory(array, ArrayBody, index, 8)); + break; + } } } break; @@ -1755,21 +1844,26 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) object class_ = resolveClassInPool(t, codePool(t, code), index - 1); if (UNLIKELY(t->exception)) return; - Compiler::Operand* nonnegative = c->label(); - Compiler::Operand* length = frame->popInt(); - c->cmp(4, c->constant(0), length); - c->jge(nonnegative); - c->call - (c->constant(reinterpret_cast(throwNegativeArraySize)), - context->indirection, - Compiler::NoReturn, - frame->trace(0, false), - 0, - 2, c->thread(), length); + if (c->isConstant(length)) { + expect(t, c->constantValue(length) >= 0); + } else{ + Compiler::Operand* nonnegative = c->label(); - c->mark(nonnegative); + c->cmp(4, c->constant(0), length); + c->jge(nonnegative); + + c->call + (c->constant(reinterpret_cast(throwNegativeArraySize)), + context->indirection, + Compiler::NoReturn, + frame->trace(0, false), + 0, + 2, c->thread(), length); + + c->mark(nonnegative); + } frame->pushObject (c->call @@ -2924,22 +3018,26 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) case newarray: { uint8_t type = codeBody(t, code, ip++); - Compiler::Operand* nonnegative = c->label(); - Compiler::Operand* length = frame->popInt(); - c->cmp(4, c->constant(0), length); - c->jge(nonnegative); + if (c->isConstant(length)) { + expect(t, c->constantValue(length) >= 0); + } else{ + Compiler::Operand* nonnegative = c->label(); - c->call - (c->constant(reinterpret_cast(throwNegativeArraySize)), - context->indirection, - Compiler::NoReturn, - frame->trace(0, false), - 0, - 2, c->thread(), length); + c->cmp(4, c->constant(0), length); + c->jge(nonnegative); - c->mark(nonnegative); + c->call + (c->constant(reinterpret_cast(throwNegativeArraySize)), + context->indirection, + Compiler::NoReturn, + frame->trace(0, false), + 0, + 2, c->thread(), length); + + c->mark(nonnegative); + } object (*constructor)(Thread*, uintptr_t, bool); switch (type) { @@ -2985,7 +3083,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip) 0, frame->trace(0, false), BytesPerWord, - 2, c->thread(), c->constant(reinterpret_cast(constructor)), + 3, c->thread(), c->constant(reinterpret_cast(constructor)), length)); } break; @@ -3463,6 +3561,7 @@ finish(MyThread* t, Context* context) unsigned mapSize = frameMapSizeInWords(t, context->method); for (TraceElement* p = context->traceLog; p; p = p->next) { + fprintf(stderr, "make node for %p\n", p); object node = makeTraceNode (t, p->address->value(), 0, context->method, p->target, p->virtualCall, mapSize, false); @@ -3562,8 +3661,6 @@ compile(MyThread* t, Context* context) } } - handleEntrance(t, &frame); - compile(t, &frame, 0); if (UNLIKELY(t->exception)) return 0; diff --git a/src/compiler.cpp b/src/compiler.cpp index 094623ddd4..9a2f7cede6 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -43,6 +43,8 @@ class Value { virtual void asAssemblerOperand(Context*, OperandType* type, Assembler::Operand** operand) = 0; + + virtual int64_t constantValue(Context*) = 0; }; class MyOperand: public Compiler::Operand { @@ -291,6 +293,10 @@ class ConstantValue: public Value { *operand = &value; } + virtual int64_t constantValue(Context*) { + return value.value->value(); + } + Assembler::Constant value; }; @@ -300,11 +306,17 @@ constant(Context* c, Promise* value) return new (c->zone->allocate(sizeof(ConstantValue))) ConstantValue(value); } +ResolvedPromise* +resolved(Context* c, int64_t value) +{ + return new (c->zone->allocate(sizeof(ResolvedPromise))) + ResolvedPromise(value); +} + ConstantValue* constant(Context* c, int64_t value) { - return constant(c, new (c->zone->allocate(sizeof(ResolvedPromise))) - ResolvedPromise(value)); + return constant(c, resolved(c, value)); } class AddressValue: public Value { @@ -323,6 +335,10 @@ class AddressValue: public Value { *operand = &address; } + virtual int64_t constantValue(Context* c) { + abort(c); + } + Assembler::Address address; }; @@ -385,6 +401,10 @@ class RegisterValue: public Value { *operand = ®ister_; } + virtual int64_t constantValue(Context* c) { + abort(c); + } + Assembler::Register register_; }; @@ -437,6 +457,10 @@ class MemoryValue: public Value { *operand = &value; } + virtual int64_t constantValue(Context* c) { + abort(c); + } + Assembler::Memory value; }; @@ -467,7 +491,7 @@ class AbstractMemoryValue: public MemoryValue { } virtual int index(Context* c) { - return index_ ? ::toRegister(c, base_) : NoRegister; + return index_ ? ::toRegister(c, index_) : NoRegister; } MyOperand* base_; @@ -502,6 +526,10 @@ class StackValue: public Value { abort(c); } + virtual int64_t constantValue(Context* c) { + abort(c); + } + Stack* stack; }; @@ -514,6 +542,8 @@ stackValue(Context* c, Stack* stack) class Event { public: Event(Context* c): next(0), stack(c->state->stack), promises(0) { + assert(c, c->logicalIp >= 0); + if (c->event) { c->event->next = this; } @@ -538,13 +568,37 @@ class Event { CodePromise* promises; }; +class NullEvent: public Event { + public: + NullEvent(Context* c): + Event(c) + { } + + virtual Value* target(Context*, MyOperand*) { + return 0; + } + + virtual void compile(Context*) { + // ignore + } +}; + +void +setEvent(Context* c, MyOperand* a, Event* e) +{ + if (a->event) { + a->event = new (c->zone->allocate(sizeof(NullEvent))) NullEvent(c); + } else{ + a->event = e; + } +} + class ArgumentEvent: public Event { public: ArgumentEvent(Context* c, unsigned size, MyOperand* a, unsigned index): Event(c), size(size), a(a), index(index) { - assert(c, a->event == 0); - a->event = this; + setEvent(c, a, this); } virtual Value* target(Context* c, MyOperand* v UNUSED) { @@ -590,8 +644,7 @@ class ReturnEvent: public Event { Event(c), size(size), a(a) { if (a) { - assert(c, a->event == 0); - a->event = this; + setEvent(c, a, this); } } @@ -643,8 +696,7 @@ class CallEvent: public Event { traceHandler(traceHandler), result(result) { - assert(c, address->event == 0); - address->event = this; + setEvent(c, address, this); } virtual Value* target(Context* c, MyOperand* v UNUSED) { @@ -855,8 +907,7 @@ class MoveEvent: public Event { MyOperand* dst): Event(c), type(type), size(size), src(src), dst(dst) { - assert(c, src->event == 0); - src->event = this; + setEvent(c, src, this); } virtual Value* target(Context* c, MyOperand* v UNUSED) { @@ -983,10 +1034,8 @@ class CompareEvent: public Event { CompareEvent(Context* c, unsigned size, MyOperand* a, MyOperand* b): Event(c), size(size), a(a), b(b) { - assert(c, a->event == 0); - a->event = this; - assert(c, b->event == 0); - b->event = this; + setEvent(c, a, this); + setEvent(c, b, this); } virtual Value* target(Context* c UNUSED, MyOperand* v UNUSED) { @@ -1020,8 +1069,7 @@ class BranchEvent: public Event { BranchEvent(Context* c, UnaryOperation type, MyOperand* address): Event(c), type(type), address(address) { - assert(c, address->event == 0); - address->event = this; + setEvent(c, address, this); } virtual Value* target(Context* c UNUSED, MyOperand* v UNUSED) { @@ -1054,8 +1102,7 @@ class JumpEvent: public Event { Event(c), address(address) { - assert(c, address->event == 0); - address->event = this; + setEvent(c, address, this); } virtual Value* target(Context* c UNUSED, MyOperand* v UNUSED) { @@ -1087,10 +1134,8 @@ class CombineEvent: public Event { MyOperand* b, MyOperand* result): Event(c), type(type), size(size), a(a), b(b), result(result) { - assert(c, a->event == 0); - a->event = this; - assert(c, b->event == 0); - b->event = this; + setEvent(c, a, this); + setEvent(c, b, this); } virtual Value* target(Context* c, MyOperand* v) { @@ -1174,8 +1219,7 @@ class TranslateEvent: public Event { MyOperand* result): Event(c), type(type), size(size), a(a), result(result) { - assert(c, a->event == 0); - a->event = this; + setEvent(c, a, this); } virtual Value* target(Context* c, MyOperand* v UNUSED) { @@ -1356,12 +1400,21 @@ compile(Context* c) a->apply(Push, BytesPerWord, Register, &base); a->apply(Move, BytesPerWord, Register, &stack, Register, &base); + if (c->stackOffset) { + Assembler::Constant offset(resolved(c, c->stackOffset * BytesPerWord)); + a->apply(Subtract, BytesPerWord, Constant, &offset, Register, &stack); + } + for (unsigned i = 0; i < c->logicalCodeLength; ++ i) { fprintf(stderr, "compile ip %d\n", i); for (Event* e = c->logicalCode[i].firstEvent; e; e = e->next) { e->compile(c); if (e == c->logicalCode[i].lastEvent) break; + + for (CodePromise* p = e->promises; p; p = p->next) { + p->offset = a->length(); + } } } } @@ -1408,8 +1461,7 @@ class MyCompiler: public Compiler { } virtual Promise* poolAppend(intptr_t value) { - return poolAppendPromise(new (c.zone->allocate(sizeof(ResolvedPromise))) - ResolvedPromise(value)); + return poolAppendPromise(resolved(&c, value)); } virtual Promise* poolAppendPromise(Promise* value) { @@ -1432,8 +1484,7 @@ class MyCompiler: public Compiler { } virtual Operand* constant(int64_t value) { - return promiseConstant(new (c.zone->allocate(sizeof(ResolvedPromise))) - ResolvedPromise(value)); + return promiseConstant(resolved(&c, value)); } virtual Operand* promiseConstant(Promise* value) { @@ -1468,6 +1519,16 @@ class MyCompiler: public Compiler { return operand(&c, register_(&c, c.assembler->thread())); } + virtual bool isConstant(Operand* a) { + return static_cast(a)->value + and static_cast(a)->value->type(&c) == Constant; + } + + virtual int64_t constantValue(Operand* a) { + assert(&c, isConstant(a)); + return static_cast(a)->value->constantValue(&c); + } + virtual Operand* label() { return operand(&c, ::constant(&c, static_cast(0))); } diff --git a/src/compiler.h b/src/compiler.h index 725838c062..8136db3586 100644 --- a/src/compiler.h +++ b/src/compiler.h @@ -51,6 +51,9 @@ class Compiler { virtual Operand* base() = 0; virtual Operand* thread() = 0; + virtual bool isConstant(Operand* value) = 0; + virtual int64_t constantValue(Operand* value) = 0; + virtual Operand* label() = 0; virtual void mark(Operand* label) = 0; diff --git a/src/x86.cpp b/src/x86.cpp index 68ea6d4a55..79f4178359 100644 --- a/src/x86.cpp +++ b/src/x86.cpp @@ -224,6 +224,7 @@ void encode(Context* c, uint8_t instruction, int a, Assembler::Memory* b, bool rex) { if (b->traceHandler) { + fprintf(stderr, "handle trace %p\n", b->traceHandler); b->traceHandler->handleTrace(codePromise(c, c->code.length())); } @@ -239,6 +240,7 @@ encode2(Context* c, uint16_t instruction, int a, Assembler::Memory* b, bool rex) { if (b->traceHandler) { + fprintf(stderr, "handle trace %p\n", b->traceHandler); b->traceHandler->handleTrace(codePromise(c, c->code.length())); } @@ -331,6 +333,14 @@ jumpR(Context* c, unsigned size UNUSED, Assembler::Register* a) c->code.append(0xe0 | a->low); } +void +jumpIfGreaterOrEqualC(Context* c, unsigned size UNUSED, Assembler::Constant* a) +{ + assert(c, size == BytesPerWord); + + conditional(c, 0x8d, a); +} + void pushR(Context* c, unsigned size, Assembler::Register* a) { @@ -552,6 +562,29 @@ addCR(Context* c, unsigned size UNUSED, Assembler::Constant* a, } } +void +subtractCR(Context* c, unsigned size UNUSED, Assembler::Constant* a, + Assembler::Register* b) +{ + assert(c, BytesPerWord == 8 or size == 4); // todo + + int64_t v = a->value->value(); + if (v) { + rex(c); + if (isInt8(v)) { + c->code.append(0x83); + c->code.append(0xe8 | b->low); + c->code.append(v); + } else if (isInt32(v)) { + c->code.append(0x81); + c->code.append(0xe8 | b->low); + c->code.append4(v); + } else { + abort(c); + } + } +} + void addRR(Context* c, unsigned size UNUSED, Assembler::Register* a, Assembler::Register* b) @@ -598,7 +631,23 @@ andCM(Context* c, unsigned size UNUSED, Assembler::Constant* a, { assert(c, BytesPerWord == 8 or size == 4); - encode(c, isInt8(a->value->value()) ? 0x83 : 0x81, 4, b, true); + encode(c, isInt8(a->value->value()) ? 0x83 : 0x81, 5, b, true); + if (isInt8(a->value->value())) { + c->code.append(a->value->value()); + } else if (isInt32(a->value->value())) { + c->code.append4(a->value->value()); + } else { + abort(c); + } +} + +void +compareCM(Context* c, unsigned size UNUSED, Assembler::Constant* a, + Assembler::Memory* b) +{ + assert(c, BytesPerWord == 8 or size == 4); + + encode(c, isInt8(a->value->value()) ? 0x83 : 0x81, 7, b, true); if (isInt8(a->value->value())) { c->code.append(a->value->value()); } else if (isInt32(a->value->value())) { @@ -614,29 +663,44 @@ populateTables() Operations[Return] = return_; UnaryOperations[INDEX1(Call, Constant)] = CAST1(callC); - UnaryOperations[INDEX1(AlignedCall, Constant)] = CAST1(alignedCallC); UnaryOperations[INDEX1(Call, Register)] = CAST1(callR); UnaryOperations[INDEX1(Call, Memory)] = CAST1(callM); + + UnaryOperations[INDEX1(AlignedCall, Constant)] = CAST1(alignedCallC); + UnaryOperations[INDEX1(Jump, Register)] = CAST1(jumpR); + + UnaryOperations[INDEX1(JumpIfGreaterOrEqual, Constant)] + = CAST1(jumpIfGreaterOrEqualC); + UnaryOperations[INDEX1(Push, Register)] = CAST1(pushR); UnaryOperations[INDEX1(Push, Memory)] = CAST1(pushM); + UnaryOperations[INDEX1(Pop, Register)] = CAST1(popR); UnaryOperations[INDEX1(Pop, Memory)] = CAST1(popM); BinaryOperations[INDEX2(LoadAddress, Memory, Register)] = CAST2(leaMR); + BinaryOperations[INDEX2(Move, Constant, Register)] = CAST2(moveCR); BinaryOperations[INDEX2(Move, Constant, Memory)] = CAST2(moveCM); BinaryOperations[INDEX2(Move, Register, Memory)] = CAST2(moveRM); BinaryOperations[INDEX2(Move, Register, Register)] = CAST2(moveRR); - BinaryOperations[INDEX2(Move4To8, Register, Register)] = CAST2(move4To8RR); BinaryOperations[INDEX2(Move, Memory, Register)] = CAST2(moveMR); BinaryOperations[INDEX2(Move, Address, Register)] = CAST2(moveAR); + + BinaryOperations[INDEX2(Move4To8, Register, Register)] = CAST2(move4To8RR); BinaryOperations[INDEX2(Move4To8, Memory, Register)] = CAST2(move4To8MR); + BinaryOperations[INDEX2(Add, Constant, Register)] = CAST2(addCR); BinaryOperations[INDEX2(Add, Register, Register)] = CAST2(addRR); BinaryOperations[INDEX2(Add, Register, Memory)] = CAST2(addRM); + BinaryOperations[INDEX2(And, Constant, Register)] = CAST2(andCR); BinaryOperations[INDEX2(And, Constant, Memory)] = CAST2(andCM); + + BinaryOperations[INDEX2(Subtract, Constant, Register)] = CAST2(subtractCR); + + BinaryOperations[INDEX2(Compare, Constant, Memory)] = CAST2(compareCM); } class MyAssembler: public Assembler {