diff --git a/src/assembler.h b/src/assembler.h index e97ee597db..1a8a1f6fba 100644 --- a/src/assembler.h +++ b/src/assembler.h @@ -136,6 +136,9 @@ class Assembler { virtual int acquireTemporary(int r = NoRegister) = 0; virtual void releaseTemporary(int r) = 0; + + virtual void save(int r) = 0; + virtual void restore(int r) = 0; }; virtual ~Assembler() { } diff --git a/src/compile.cpp b/src/compile.cpp index 9bd513b945..0712548195 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -3828,11 +3828,11 @@ finish(MyThread* t, Context* context) strcmp (reinterpret_cast (&byteArrayBody(t, className(t, methodClass(t, context->method)), 0)), - "java/lang/StringBuilder") == 0 and + "java/lang/Class") == 0 and strcmp (reinterpret_cast (&byteArrayBody(t, methodName(t, context->method), 0)), - "") == 0) + "replace") == 0) { asm("int3"); } diff --git a/src/compiler.cpp b/src/compiler.cpp index 9370f9d565..d24d98aca6 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -15,10 +15,10 @@ using namespace vm; namespace { -const bool DebugAppend = true; -const bool DebugCompile = true; -const bool DebugStack = true; -const bool DebugRegisters = true; +const bool DebugAppend = false; +const bool DebugCompile = false; +const bool DebugStack = false; +const bool DebugRegisters = false; class Context; class Value; @@ -101,6 +101,7 @@ class Register { unsigned size; unsigned refCount; bool reserved; + bool pushed; }; class ConstantPoolNode { @@ -826,6 +827,42 @@ pushNow(Context* c, Stack* start) pushNow(c, start, count); } +bool +trySteal(Context* c, int r, Stack* stack) +{ + Value* v = c->registers[r].value; + + assert(c, c->registers[r].refCount == 0); + + if (DebugRegisters) { + fprintf(stderr, "try steal %d from %p: next: %p\n", + r, v, v->sites->next); + } + + if (v->sites->next == 0) { + unsigned count = 0; + Stack* start = 0; + for (Stack* s = stack; s and (not s->pushed); s = s->next) { + if (s->value == v) { + start = s; + } + if (start) { + ++ count; + } + } + + if (start) { + pushNow(c, start, count); + } else { + return false; + } + } + + removeSite(c, v, c->registers[r].site); + + return true; +} + bool tryAcquire(Context* c, int r, Stack* stack, unsigned newSize, Value* newValue, Site* newSite) @@ -842,33 +879,9 @@ tryAcquire(Context* c, int r, Stack* stack, unsigned newSize, Value* newValue, and oldValue != newValue and findSite(c, oldValue, c->registers[r].site)) { - assert(c, c->registers[r].refCount == 0); - - if (DebugRegisters) { - fprintf(stderr, "try steal %d from %p: next: %p\n", - r, oldValue, oldValue->sites->next); + if (not trySteal(c, r, stack)) { + return false; } - - if (oldValue->sites->next == 0) { - unsigned count = 0; - Stack* start = 0; - for (Stack* s = stack; s and (not s->pushed); s = s->next) { - if (s->value == oldValue) { - start = s; - } - if (start) { - ++ count; - } - } - - if (start) { - pushNow(c, start, count); - } else { - return false; - } - } - - removeSite(c, oldValue, c->registers[r].site); } c->registers[r].size = newSize; @@ -1182,15 +1195,15 @@ class MoveEvent: public Event { nextRead(c, src); + if (cost) { + apply(c, type, size, src->source, target); + } + if (dst->reads) { addSite(c, stack, size, dst, target); } else { removeSite(c, dst, target); } - - if (cost) { - apply(c, type, size, src->source, target); - } } BinaryOperation type; @@ -1730,7 +1743,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); @@ -1863,16 +1876,16 @@ 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; - } - } - if (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) @@ -1924,8 +1937,9 @@ class Client: public Assembler::Client { if (r == NoRegister) { r = freeRegisterExcept(c, NoRegister, false); } else { - expect(c, c->registers[r].refCount == 0); - expect(c, c->registers[r].value == 0); + expect(c, (c->registers[r].refCount == 0 + and c->registers[r].value == 0) + or c->registers[r].pushed); } increment(c, r); return r; @@ -1935,6 +1949,22 @@ class Client: public Assembler::Client { decrement(c, r); } + virtual void save(int r) { + if (c->registers[r].refCount or c->registers[r].value) { + Assembler::Register operand(r); + c->assembler->apply(Push, BytesPerWord, RegisterOperand, &operand); + c->registers[r].pushed = true; + } + } + + virtual void restore(int r) { + if (c->registers[r].pushed) { + Assembler::Register operand(r); + c->assembler->apply(Pop, BytesPerWord, RegisterOperand, &operand); + c->registers[r].pushed = false; + } + } + Context* c; }; @@ -2092,7 +2122,10 @@ class MyCompiler: public Compiler { } virtual void push(unsigned size) { - ::push(&c, size, value(&c)); + assert(&c, ceiling(size, BytesPerWord)); + + c.state->stack = ::stack + (&c, value(&c), ceiling(size, BytesPerWord), c.state->stack); } virtual void push(unsigned size, Operand* value) { diff --git a/src/x86.cpp b/src/x86.cpp index 25827bde41..9e1f796a10 100644 --- a/src/x86.cpp +++ b/src/x86.cpp @@ -598,6 +598,7 @@ moveRR(Context* c, unsigned size, Assembler::Register* a, } else { switch (size) { case 1: + rex(c); if (BytesPerWord == 8) { c->code.append(0x0f); } @@ -606,6 +607,7 @@ moveRR(Context* c, unsigned size, Assembler::Register* a, break; case 2: + rex(c); if (BytesPerWord == 8) { c->code.append(0x0f); } @@ -675,7 +677,7 @@ move4To8RR(Context* c, unsigned size UNUSED, Assembler::Register* a, if (BytesPerWord == 8) { rex(c); c->code.append(0x63); - c->code.append(0xc0 | (a->low << 3) | b->low); + c->code.append(0xc0 | (b->low << 3) | a->low); } else { if (a->low == rax and b->low == rax and b->high == rdx) { c->code.append(0x99); // cdq @@ -897,6 +899,8 @@ divideRR(Context* c, unsigned size, Assembler::Register* a, Assembler::Register* b) { if (BytesPerWord == 4 and size == 8) { + abort(c); // todo: sync stack first + Assembler::Register axdx(c->client->acquireTemporary(rax), c->client->acquireTemporary(rdx)); @@ -918,10 +922,18 @@ divideRR(Context* c, unsigned size, Assembler::Register* a, c->client->releaseTemporary(axdx.high); } else { Assembler::Register ax(rax); - Assembler::Register dx(c->client->acquireTemporary(rdx)); + Assembler::Register divisor(a->low); + + if (a->low == rdx) { + divisor.low = c->client->acquireTemporary(); + moveRR(c, BytesPerWord, a, &divisor); + } else if (b->low != rdx) { + c->client->save(rdx); + } if (b->low != rax) { - c->client->acquireTemporary(ax.low); + c->client->save(rax); + c->client->acquireTemporary(rax); moveRR(c, BytesPerWord, b, &ax); } @@ -929,14 +941,85 @@ divideRR(Context* c, unsigned size, Assembler::Register* a, c->code.append(0x99); rex(c); c->code.append(0xf7); - c->code.append(0xf8 | a->low); + c->code.append(0xf8 | divisor.low); if (b->low != rax) { moveRR(c, BytesPerWord, &ax, b); - c->client->releaseTemporary(ax.low); + c->client->releaseTemporary(rax); + c->client->restore(rax); } - c->client->releaseTemporary(dx.low); + if (a->low == rdx) { + moveRR(c, BytesPerWord, &divisor, a); + c->client->releaseTemporary(divisor.low); + } else if (b->low != rdx) { + c->client->restore(rdx); + } + } +} + +void +remainderRR(Context* c, unsigned size, Assembler::Register* a, + Assembler::Register* b) +{ + if (BytesPerWord == 4 and size == 8) { + abort(c); // todo: sync stack first + + Assembler::Register axdx(c->client->acquireTemporary(rax), + c->client->acquireTemporary(rdx)); + + pushR(c, size, a); + pushR(c, size, b); + + ResolvedPromise addressPromise(reinterpret_cast(moduloLong)); + 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(rdx); + Assembler::Register divisor(a->low); + + if (a->low == rdx) { + divisor.low = c->client->acquireTemporary(); + moveRR(c, BytesPerWord, a, &divisor); + } else if (b->low != rdx) { + c->client->save(rdx); + } + + if (b->low != rax) { + c->client->save(rax); + c->client->acquireTemporary(rax); + moveRR(c, BytesPerWord, b, &ax); + } + + rex(c); + c->code.append(0x99); + rex(c); + c->code.append(0xf7); + c->code.append(0xf8 | divisor.low); + + if (b->low != rdx) { + moveRR(c, BytesPerWord, &dx, b); + c->client->releaseTemporary(rax); + c->client->restore(rax); + } + + if (a->low == rdx) { + moveRR(c, BytesPerWord, &divisor, a); + c->client->releaseTemporary(divisor.low); + } else if (b->low != rdx) { + c->client->restore(rdx); + } } } @@ -1167,6 +1250,8 @@ populateTables() BinaryOperations[INDEX2(Divide, Register, Register)] = CAST2(divideRR); + BinaryOperations[INDEX2(Remainder, Register, Register)] = CAST2(remainderRR); + BinaryOperations[INDEX2(And, Constant, Register)] = CAST2(andCR); BinaryOperations[INDEX2(And, Constant, Memory)] = CAST2(andCM);