From d5137a7cdf4044b9a061b0c2e7efa17a7a08f330 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sat, 26 Apr 2008 14:56:03 -0600 Subject: [PATCH] use stack instead of registers to save data across jumps and branches; bugfixes --- src/compile.cpp | 86 ++++++-------------- src/compiler.cpp | 199 +++++++++++++++++++++++------------------------ src/compiler.h | 1 + src/x86.cpp | 85 +++++++++++++++++++- 4 files changed, 204 insertions(+), 167 deletions(-) diff --git a/src/compile.cpp b/src/compile.cpp index db067d2c02..9bd513b945 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -751,7 +751,7 @@ class Frame { void pushLongQuiet(Compiler::Operand* o) { if (BytesPerWord == 8) { - c->pushed(1); + c->push(8); } c->push(8, o); } @@ -774,7 +774,7 @@ class Frame { Compiler::Operand* popLongQuiet() { Compiler::Operand* r = c->pop(8); if (BytesPerWord == 8) { - c->popped(1); + c->pop(8); } return r; } @@ -1364,16 +1364,28 @@ longToFloat(int64_t a) } object FORCE_ALIGN -makeBlankObjectArray(Thread* t, object class_, int32_t length) +makeBlankObjectArray(MyThread* t, object class_, int32_t length) { - return makeObjectArray(t, class_, length, true); + if (length >= 0) { + return makeObjectArray(t, class_, length, true); + } else { + object message = makeString(t, "%d", length); + t->exception = makeNegativeArraySizeException(t, message); + unwind(t); + } } object FORCE_ALIGN -makeBlankArray(Thread* t, object (*constructor)(Thread*, uintptr_t, bool), +makeBlankArray(MyThread* t, object (*constructor)(Thread*, uintptr_t, bool), int32_t length) { - return constructor(t, length, true); + if (length >= 0) { + return constructor(t, length, true); + } else { + object message = makeString(t, "%d", length); + t->exception = makeNegativeArraySizeException(t, message); + unwind(t); + } } uintptr_t @@ -1478,14 +1490,6 @@ throwArrayIndexOutOfBounds(MyThread* t, object array, int32_t index) unwind(t); } -void NO_RETURN FORCE_ALIGN -throwNegativeArraySize(MyThread* t, int32_t length) -{ - object message = makeString(t, "%d", length); - t->exception = makeArrayIndexOutOfBoundsException(t, message); - unwind(t); -} - void NO_RETURN FORCE_ALIGN throw_(MyThread* t, object o) { @@ -2008,30 +2012,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, object class_ = resolveClassInPool(t, codePool(t, code), index - 1); if (UNLIKELY(t->exception)) return; - Compiler::Operand* length = c->peek(4, 0); - - if (c->isConstant(length)) { - expect(t, c->constantValue(length) >= 0); - } else{ - Compiler::Operand* nonnegative = c->label(); - - c->cmp(4, c->constant(0), length); - c->jge(nonnegative); - - length = c->peek(4, 0); - - c->call - (c->constant(reinterpret_cast(throwNegativeArraySize)), - context->indirection, - Compiler::NoReturn, - frame->trace(0, false), - 0, - 2, c->thread(), length); - - c->mark(nonnegative); - } - - length = frame->popInt(); + Compiler::Operand* length = frame->popInt(); frame->pushObject (c->call @@ -3197,30 +3178,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, case newarray: { uint8_t type = codeBody(t, code, ip++); - Compiler::Operand* length = c->peek(4, 0); - - if (c->isConstant(length)) { - expect(t, c->constantValue(length) >= 0); - } else{ - Compiler::Operand* nonnegative = c->label(); - - c->cmp(4, c->constant(0), length); - c->jge(nonnegative); - - length = c->peek(4, 0); - - c->call - (c->constant(reinterpret_cast(throwNegativeArraySize)), - context->indirection, - Compiler::NoReturn, - frame->trace(0, false), - 0, - 2, c->thread(), length); - - c->mark(nonnegative); - } - - length = frame->popInt(); + Compiler::Operand* length = frame->popInt(); object (*constructor)(Thread*, uintptr_t, bool); switch (type) { @@ -3870,11 +3828,11 @@ finish(MyThread* t, Context* context) strcmp (reinterpret_cast (&byteArrayBody(t, className(t, methodClass(t, context->method)), 0)), - "Enums") == 0 and + "java/lang/StringBuilder") == 0 and strcmp (reinterpret_cast (&byteArrayBody(t, methodName(t, context->method), 0)), - "main") == 0) + "") == 0) { asm("int3"); } diff --git a/src/compiler.cpp b/src/compiler.cpp index a12ebebab2..9370f9d565 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -17,8 +17,8 @@ namespace { const bool DebugAppend = true; const bool DebugCompile = true; -const bool DebugStack = false; -const bool DebugRegisters = false; +const bool DebugStack = true; +const bool DebugRegisters = true; class Context; class Value; @@ -61,7 +61,7 @@ class Stack { public: Stack(Value* value, unsigned size, unsigned index, Stack* next): value(value), size(size), index(index), next(next), pushEvent(0), - pushSite(0), syncSite(0), pushed(false) + pushSite(0), pushed(false) { } Value* value; @@ -70,7 +70,6 @@ class Stack { Stack* next; PushEvent* pushEvent; Site* pushSite; - Site* syncSite; bool pushed; }; @@ -141,8 +140,8 @@ class Read { class Value: public Compiler::Operand { public: - Value(Site* site): - reads(0), lastRead(0), sites(site), source(0), target(site) + Value(Site* site, Site* target): + reads(0), lastRead(0), sites(site), source(0), target(target) { } Read* reads; @@ -330,8 +329,6 @@ class Event { virtual ~Event() { } - virtual void prepare(Context*) { } - virtual void compile(Context* c) = 0; virtual bool isBranch() { return false; }; @@ -773,6 +770,14 @@ pick(Context* c, Site* sites, Site* target = 0, unsigned* cost = 0) return site; } +Site* +pushSite(Context* c, unsigned index) +{ + return memorySite + (c, c->assembler->base(), + - (c->stackOffset + index + 1) * BytesPerWord, NoRegister, 1); +} + void pushNow(Context* c, Stack* start, unsigned count) { @@ -787,11 +792,12 @@ pushNow(Context* c, Stack* start, unsigned count) assert(c, not s->pushed); if (s->value and s->value->sites) { - apply(c, Push, s->size * BytesPerWord, pick(c, s->value->sites)); - s->pushSite = memorySite - (c, c->assembler->base(), - - (c->stackOffset + s->index + 1) * BytesPerWord, NoRegister, 1); + Site* source = pick(c, s->value->sites); + + s->pushSite = pushSite(c, s->index); addSite(c, 0, s->size * BytesPerWord, s->value, s->pushSite); + + apply(c, Push, s->size * BytesPerWord, source); } else { Assembler::Register stack(c->assembler->stack()); Assembler::Constant offset(resolved(c, s->size * BytesPerWord)); @@ -959,7 +965,7 @@ class PushEvent: public Event { virtual void compile(Context* c) { if (DebugCompile) { - fprintf(stderr, "PushEvent.compile\n"); + fprintf(stderr, "PushEvent.compile active: %d\n", active); } if (active) { @@ -1161,17 +1167,17 @@ class MoveEvent: public Event { } Site* target; + unsigned cost; if (type == Move and size >= BytesPerWord and dst->reads and next == dst->reads->event) { target = src->source; + cost = 0; } else { target = targetOrRegister(c, size, dst, this); - if (src->source->copyCost(c, target)) { - apply(c, type, size, src->source, target); - } + cost = src->source->copyCost(c, target); } nextRead(c, src); @@ -1181,6 +1187,10 @@ class MoveEvent: public Event { } else { removeSite(c, dst, target); } + + if (cost) { + apply(c, type, size, src->source, target); + } } BinaryOperation type; @@ -1390,16 +1400,6 @@ appendMemory(Context* c, Value* base, int displacement, Value* index, MemoryEvent(c, base, displacement, index, scale, result); } -Site* -stackSyncSite(Context* c, unsigned index, unsigned size) -{ - assert(c, index + size <= c->freeRegisterCount); - - return registerSite - (c, c->freeRegisters[index], - size == 2 ? c->freeRegisters[index + 1] : NoRegister); -} - Stack* stack(Context* c, Value* value, unsigned size, unsigned index, Stack* next) { @@ -1408,9 +1408,9 @@ stack(Context* c, Value* value, unsigned size, unsigned index, Stack* next) } Value* -value(Context* c, Site* site = 0) +value(Context* c, Site* site = 0, Site* target = 0) { - return new (c->zone->allocate(sizeof(Value))) Value(site); + return new (c->zone->allocate(sizeof(Value))) Value(site, target); } void @@ -1419,8 +1419,9 @@ resetStack(Context* c) unsigned i = 0; Stack* p = 0; for (Stack* s = c->state->stack; s; s = s->next) { - Stack* n = stack - (c, value(c, stackSyncSite(c, i, s->size)), s->size, s->index, 0); + Stack* n = stack(c, value(c), s->size, s->index, 0); + n->value->sites = n->pushSite = pushSite(c, s->index); + n->pushed = true; if (p) { p->next = n; @@ -1453,9 +1454,9 @@ popNow(Context* c, Event* event, Stack* stack, unsigned count, bool ignore) s, s->value, target); } - apply(c, Pop, BytesPerWord * s->size, target); - addSite(c, stack, s->size * BytesPerWord, s->value, target); + + apply(c, Pop, BytesPerWord * s->size, target); } else { if (DebugStack) { fprintf(stderr, "ignore %p value: %p\n", s, s->value); @@ -1485,31 +1486,21 @@ class StackSyncEvent: public Event { StackSyncEvent(Context* c): Event(c) { - unsigned i = 0; for (Stack* s = stack; s; s = s->next) { - s->syncSite = stackSyncSite(c, i, s->size); - addRead(c, s->value, s->size * BytesPerWord, s->syncSite); - i += s->size; - } + if (s->pushEvent) s->pushEvent->active = true; + addRead(c, s->value, s->size * BytesPerWord, 0); + } } StackSyncEvent(Context* c, unsigned sequence, Stack* stack): Event(c, sequence, stack) { - unsigned i = 0; for (Stack* s = stack; s; s = s->next) { - s->syncSite = stackSyncSite(c, i, s->size); - insertRead(c, this, sequence, s->value, s->size * BytesPerWord, - s->syncSite); - if (s->pushEvent) s->pushEvent->active = false; - i += s->size; + if (s->pushEvent) s->pushEvent->active = true; + insertRead(c, this, sequence, s->value, s->size * BytesPerWord, 0); } } - virtual void prepare(Context* c) { - popNow(c, this, stack, 0xFFFFFFFF, false); - } - virtual void compile(Context* c) { if (DebugCompile) { fprintf(stderr, "StackSyncEvent.compile\n"); @@ -1520,7 +1511,9 @@ class StackSyncEvent: public Event { } for (Stack* s = stack; s; s = s->next) { - addSite(c, 0, s->size * BytesPerWord, s->value, s->syncSite); + if (s->pushSite) { + addSite(c, 0, s->size * BytesPerWord, s->value, s->pushSite); + } } for (Read* r = reads; r; r = r->eventNext) { @@ -1642,23 +1635,23 @@ appendPop(Context* c, unsigned count, bool ignore) new (c->zone->allocate(sizeof(PopEvent))) PopEvent(c, count, ignore); } -void -swapRegisters(Context* c, int* ap, int* bp) -{ - Assembler::Register a(*ap); - Assembler::Register b(*bp); +// void +// swapRegisters(Context* c, int* ap, int* bp) +// { +// Assembler::Register a(*ap); +// Assembler::Register b(*bp); - c->assembler->apply - (Xor, BytesPerWord, RegisterOperand, &a, RegisterOperand, &b); - c->assembler->apply - (Xor, BytesPerWord, RegisterOperand, &b, RegisterOperand, &a); - c->assembler->apply - (Xor, BytesPerWord, RegisterOperand, &a, RegisterOperand, &b); +// c->assembler->apply +// (Xor, BytesPerWord, RegisterOperand, &a, RegisterOperand, &b); +// c->assembler->apply +// (Xor, BytesPerWord, RegisterOperand, &b, RegisterOperand, &a); +// c->assembler->apply +// (Xor, BytesPerWord, RegisterOperand, &a, RegisterOperand, &b); - int t = *ap; - *ap = *bp; - *bp = t; -} +// int t = *ap; +// *ap = *bp; +// *bp = t; +// } Site* readSource(Context* c, Stack* stack, Read* r, Event* e) @@ -1674,29 +1667,30 @@ readSource(Context* c, Stack* stack, Read* r, Event* e) apply(c, Move, r->size, site, target); return target; } else { - // this is a filthy hack, but I think the core idea is right: + abort(c); +// // this is a filthy hack, but I think the core idea is right: - assert(c, target->type(c) == RegisterOperand); +// assert(c, target->type(c) == RegisterOperand); - RegisterSite* ts = static_cast(target); +// RegisterSite* ts = static_cast(target); - for (Site* s = r->value->sites; s; s = s->next) { - if (s->type(c) == RegisterOperand) { - RegisterSite* rs = static_cast(s); +// for (Site* s = r->value->sites; s; s = s->next) { +// if (s->type(c) == RegisterOperand) { +// RegisterSite* rs = static_cast(s); - RegisterSite* os = static_cast - (c->registers[ts->register_.low].site); +// RegisterSite* os = static_cast +// (c->registers[ts->register_.low].site); - assert(c, os->register_.low == ts->register_.low); - assert(c, os->register_.high == NoRegister); - assert(c, ts->register_.high == NoRegister); - assert(c, rs->register_.high == NoRegister); +// assert(c, os->register_.low == ts->register_.low); +// assert(c, os->register_.high == NoRegister); +// assert(c, ts->register_.high == NoRegister); +// assert(c, rs->register_.high == NoRegister); - swapRegisters(c, &(os->register_.low), &(rs->register_.low)); +// swapRegisters(c, &(os->register_.low), &(rs->register_.low)); - return rs; - } - } +// return rs; +// } +// } } abort(c); @@ -1736,7 +1730,7 @@ compile(Context* c) for (Event* e = li->firstEvent; e; e = e->next) { if (e->stackReset) { -// fprintf(stderr, "stack reset\n"); + fprintf(stderr, "stack reset\n"); for (Stack* s = e->stack; s; s = s->next) { if (s->value->sites) { assert(c, s->value->sites->next == 0); @@ -1748,8 +1742,6 @@ compile(Context* c) } } - e->prepare(c); - for (Read* r = e->reads; r; r = r->eventNext) { r->value->source = readSource(c, e->stack, r, e); } @@ -1852,14 +1844,12 @@ used(Context* c, int r) return v and findSite(c, v, c->registers[r].site); } -// bool -// usedExclusively(Context* c, int r) -// { -// Value* v = c->registers[r].value; -// return used(c, r) -// and v->pushCount == 0 -// and v->sites->next == 0; -// } +bool +usedExclusively(Context* c, int r) +{ + Value* v = c->registers[r].value; + return used(c, r) and v->sites->next == 0; +} int freeRegisterExcept(Context* c, int except, bool allowAcquired) @@ -1873,14 +1863,14 @@ freeRegisterExcept(Context* c, int except, bool allowAcquired) } } -// for (int i = c->assembler->registerCount() - 1; i >= 0; --i) { -// if (i != except -// and c->registers[i].refCount == 0 -// and (not usedExclusively(c, i))) -// { -// return i; -// } -// } + for (int i = c->assembler->registerCount() - 1; i >= 0; --i) { + if (i != except + and c->registers[i].refCount == 0 + and (not usedExclusively(c, i))) + { + return i; + } + } if (allowAcquired) { for (int i = c->assembler->registerCount() - 1; i >= 0; --i) { @@ -2048,15 +2038,18 @@ class MyCompiler: public Compiler { } virtual Operand* stack() { - return value(&c, registerSite(&c, c.assembler->stack())); + Site* s = registerSite(&c, c.assembler->stack()); + return value(&c, s, s); } virtual Operand* base() { - return value(&c, registerSite(&c, c.assembler->base())); + Site* s = registerSite(&c, c.assembler->base()); + return value(&c, s, s); } virtual Operand* thread() { - return value(&c, registerSite(&c, c.assembler->thread())); + Site* s = registerSite(&c, c.assembler->thread()); + return value(&c, s, s); } virtual bool isConstant(Operand* a) { @@ -2098,6 +2091,10 @@ class MyCompiler: public Compiler { abort(&c); } + virtual void push(unsigned size) { + ::push(&c, size, value(&c)); + } + virtual void push(unsigned size, Operand* value) { ::push(&c, size, static_cast(value)); } diff --git a/src/compiler.h b/src/compiler.h index 5019968e37..62f4387be5 100644 --- a/src/compiler.h +++ b/src/compiler.h @@ -57,6 +57,7 @@ class Compiler { virtual Operand* label() = 0; virtual void mark(Operand* label) = 0; + virtual void push(unsigned size) = 0; virtual void push(unsigned size, Operand* value) = 0; virtual Operand* pop(unsigned size) = 0; virtual void pushed(unsigned count) = 0; diff --git a/src/x86.cpp b/src/x86.cpp index ad12475da5..25827bde41 100644 --- a/src/x86.cpp +++ b/src/x86.cpp @@ -35,6 +35,18 @@ enum { r15 = 15, }; +int64_t FORCE_ALIGN +divideLong(int64_t a, int64_t b) +{ + return a / b; +} + +int64_t FORCE_ALIGN +moduloLong(int64_t a, int64_t b) +{ + return a % b; +} + inline bool isInt8(intptr_t v) { @@ -523,6 +535,17 @@ popM(Context* c, unsigned size, Assembler::Memory* a) } } +void +negateR(Context* c, unsigned size, Assembler::Register* a) +{ + assert(c, BytesPerWord == 8 or size == 4); // todo + + rex(c); + c->code.append(0xf7); + c->code.append(0xd8 | a->low); +} + + void leaMR(Context* c, unsigned size, Assembler::Memory* b, Assembler::Register* a) { @@ -575,13 +598,19 @@ moveRR(Context* c, unsigned size, Assembler::Register* a, } else { switch (size) { case 1: + if (BytesPerWord == 8) { + c->code.append(0x0f); + } c->code.append(0xbe); - c->code.append(0xc0 | (a->low << 3) | b->low); + c->code.append(0xc0 | (b->low << 3) | a->low); break; case 2: + if (BytesPerWord == 8) { + c->code.append(0x0f); + } c->code.append(0xbf); - c->code.append(0xc0 | (a->low << 3) | b->low); + c->code.append(0xc0 | (b->low << 3) | a->low); break; case 8: @@ -863,6 +892,54 @@ addRM(Context* c, unsigned size UNUSED, Assembler::Register* a, encode(c, 0x01, a->low, b, true); } +void +divideRR(Context* c, unsigned size, Assembler::Register* a, + Assembler::Register* b) +{ + if (BytesPerWord == 4 and size == 8) { + Assembler::Register axdx(c->client->acquireTemporary(rax), + c->client->acquireTemporary(rdx)); + + pushR(c, size, a); + pushR(c, size, b); + + ResolvedPromise addressPromise(reinterpret_cast(divideLong)); + Assembler::Constant address(&addressPromise); + callC(c, BytesPerWord, &address); + + ResolvedPromise offsetPromise(16); + Assembler::Constant offset(&offsetPromise); + Assembler::Register stack(rsp); + addCR(c, BytesPerWord, &offset, &stack); + + moveRR(c, size, &axdx, b); + + c->client->releaseTemporary(axdx.low); + c->client->releaseTemporary(axdx.high); + } else { + Assembler::Register ax(rax); + Assembler::Register dx(c->client->acquireTemporary(rdx)); + + if (b->low != rax) { + c->client->acquireTemporary(ax.low); + moveRR(c, BytesPerWord, b, &ax); + } + + rex(c); + c->code.append(0x99); + rex(c); + c->code.append(0xf7); + c->code.append(0xf8 | a->low); + + if (b->low != rax) { + moveRR(c, BytesPerWord, &ax, b); + c->client->releaseTemporary(ax.low); + } + + c->client->releaseTemporary(dx.low); + } +} + void andCR(Context* c, unsigned size UNUSED, Assembler::Constant* a, Assembler::Register* b) @@ -1065,6 +1142,8 @@ populateTables() UnaryOperations[INDEX1(Pop, Register)] = CAST1(popR); UnaryOperations[INDEX1(Pop, Memory)] = CAST1(popM); + UnaryOperations[INDEX1(Negate, Register)] = CAST1(negateR); + BinaryOperations[INDEX2(LoadAddress, Memory, Register)] = CAST2(leaMR); BinaryOperations[INDEX2(Move, Constant, Register)] = CAST2(moveCR); @@ -1086,6 +1165,8 @@ populateTables() BinaryOperations[INDEX2(Add, Register, Register)] = CAST2(addRR); BinaryOperations[INDEX2(Add, Register, Memory)] = CAST2(addRM); + BinaryOperations[INDEX2(Divide, Register, Register)] = CAST2(divideRR); + BinaryOperations[INDEX2(And, Constant, Register)] = CAST2(andCR); BinaryOperations[INDEX2(And, Constant, Memory)] = CAST2(andCM);