From af9758a6d37a2263f8fdedf4536386a2325798c4 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sun, 7 Sep 2008 14:12:11 -0600 Subject: [PATCH] got a simple arithmetic test working --- src/assembler.h | 11 +++- src/compile.cpp | 14 +++- src/compiler.cpp | 107 +++++++++++++++++++++---------- src/x86.cpp | 164 +++++++++++++++++++++++++++++++++++++++-------- 4 files changed, 230 insertions(+), 66 deletions(-) diff --git a/src/assembler.h b/src/assembler.h index 87bf9110df..f970fc908c 100644 --- a/src/assembler.h +++ b/src/assembler.h @@ -168,6 +168,13 @@ class Assembler { virtual unsigned value() = 0; }; + class Block { + public: + virtual ~Block() { } + + virtual unsigned resolve(unsigned start, Block* next) = 0; + }; + class Architecture { public: virtual ~Architecture() { } @@ -179,6 +186,8 @@ class Assembler { virtual int returnLow() = 0; virtual int returnHigh() = 0; + virtual bool condensedAddressing() = 0; + virtual bool reserved(int register_) = 0; virtual unsigned argumentRegisterCount() = 0; @@ -245,7 +254,7 @@ class Assembler { virtual Offset* offset() = 0; - virtual void endBlock() = 0; + virtual Block* endBlock() = 0; virtual unsigned length() = 0; diff --git a/src/compile.cpp b/src/compile.cpp index b5be3763b9..e7b656a4b7 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -27,7 +27,7 @@ vmCall(); namespace { -const bool Verbose = false; +const bool Verbose = true; const bool DebugNatives = false; const bool DebugCallTable = false; const bool DebugMethodTree = false; @@ -3832,11 +3832,11 @@ finish(MyThread* t, Context* context) strcmp (reinterpret_cast (&byteArrayBody(t, className(t, methodClass(t, context->method)), 0)), - "java/lang/String") == 0 and + "Simple") == 0 and strcmp (reinterpret_cast (&byteArrayBody(t, methodName(t, context->method), 0)), - "compareTo") == 0) + "main") == 0) { asm("int3"); } @@ -4959,6 +4959,8 @@ compileThunks(MyThread* t, MyProcessor* p) Assembler::Register result(t->arch->returnLow()); a->apply(Jump, BytesPerWord, RegisterOperand, &result); + + a->endBlock()->resolve(0, 0); } ThunkContext nativeContext(t); @@ -4979,6 +4981,8 @@ compileThunks(MyThread* t, MyProcessor* p) a->popFrame(); a->apply(Return); + + a->endBlock()->resolve(0, 0); } ThunkContext aioobContext(t); @@ -4996,6 +5000,8 @@ compileThunks(MyThread* t, MyProcessor* p) Assembler::Constant proc(&(aioobContext.promise)); a->apply(LongCall, BytesPerWord, ConstantOperand, &proc); + + a->endBlock()->resolve(0, 0); } ThunkContext tableContext(t); @@ -5006,6 +5012,8 @@ compileThunks(MyThread* t, MyProcessor* p) Assembler::Constant proc(&(tableContext.promise)); a->apply(LongJump, BytesPerWord, ConstantOperand, &proc); + + a->endBlock()->resolve(0, 0); } p->thunkSize = pad(tableContext.context.assembler->length()); diff --git a/src/compiler.cpp b/src/compiler.cpp index 6d6d63810a..30ee87bf8d 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -15,8 +15,8 @@ using namespace vm; namespace { -const bool DebugAppend = false; -const bool DebugCompile = false; +const bool DebugAppend = true; +const bool DebugCompile = true; const bool DebugStack = false; const bool DebugRegisters = false; @@ -120,9 +120,10 @@ class State { class LogicalInstruction { public: - LogicalInstruction() { - memset(this, 0, sizeof(LogicalInstruction)); - } + LogicalInstruction(int index): + firstEvent(0), lastEvent(0), immediatePredecessor(0), stack(0), locals(0), + machineOffset(0), index(index), stackSaved(false) + { } Event* firstEvent; Event* lastEvent; @@ -321,6 +322,17 @@ class CodePromise: public Promise { CodePromise* next; }; +unsigned +machineOffset(Context* c, int logicalIp) +{ + for (unsigned n = logicalIp; n < c->logicalCodeLength; ++n) { + LogicalInstruction* i = c->logicalCode[n]; + if (i and i->machineOffset) return i->machineOffset->value(); + } + + abort(c); +} + class IpPromise: public Promise { public: IpPromise(Context* c, int logicalIp): @@ -331,7 +343,7 @@ class IpPromise: public Promise { virtual int64_t value() { if (resolved()) { return reinterpret_cast - (c->machineCode + c->logicalCode[logicalIp]->machineOffset->value()); + (c->machineCode + machineOffset(c, logicalIp)); } abort(c); @@ -365,6 +377,12 @@ expect(Context* c, bool v) expect(c->system, v); } +Cell* +cons(Context* c, void* value, Cell* next) +{ + return new (c->zone->allocate(sizeof(Cell))) Cell(next, value); +} + class Event { public: Event(Context* c): @@ -377,6 +395,8 @@ class Event { if (c->lastEvent) { c->lastEvent->next = this; + predecessors = cons(c, c->lastEvent, 0); + c->lastEvent->successors = cons(c, this, c->lastEvent->successors); } else { c->firstEvent = this; } @@ -1367,6 +1387,7 @@ insertRead(Context*, Event* event, int sequence, Value* v, Read* r) { r->value = v; r->event = event; + r->eventNext = event->reads; event->reads = r; ++ event->readCount; @@ -1791,10 +1812,12 @@ class CombineEvent: public Event { unsigned firstSize, Value* first, unsigned secondSize, Value* second, unsigned resultSize, Value* result, - Read* firstRead, Read* secondRead): + Read* firstRead, + Read* secondRead, + Read* resultRead): Event(c), type(type), firstSize(firstSize), first(first), secondSize(secondSize), second(second), resultSize(resultSize), - result(result) + result(result), resultRead(resultRead) { addRead(c, first, firstRead); addRead(c, second, secondRead); @@ -1805,18 +1828,20 @@ class CombineEvent: public Event { fprintf(stderr, "CombineEvent.compile\n"); } - maybePreserve(c, stack, locals, secondSize, second, second->source); + Site* target; + if (c->arch->condensedAddressing()) { + maybePreserve(c, stack, locals, secondSize, second, second->source); + target = second->source; + } else { + target = resultRead->allocateSite(c); + addSite(c, stack, locals, resultSize, result, target); + } - Site* target = targetOrRegister(c, result); apply(c, type, firstSize, first->source, secondSize, second->source, resultSize, target); nextRead(c, first); nextRead(c, second); - - if (live(result)) { - addSite(c, 0, 0, resultSize, result, target); - } } TernaryOperation type; @@ -1826,6 +1851,7 @@ class CombineEvent: public Event { Value* second; unsigned resultSize; Value* result; + Read* resultRead; }; Value* @@ -1902,7 +1928,15 @@ appendCombine(Context* c, TernaryOperation type, fprintf(stderr, "appendCombine\n"); } - // todo: respect resultTypeMask and resultRegisterMask + Read* resultRead = read + (c, resultSize, resultTypeMask, resultRegisterMask, AnyFrameIndex); + Read* secondRead; + if (c->arch->condensedAddressing()) { + secondRead = resultRead; + } else { + secondRead = read + (c, secondSize, secondTypeMask, secondRegisterMask, AnyFrameIndex); + } new (c->zone->allocate(sizeof(CombineEvent))) CombineEvent @@ -1911,7 +1945,8 @@ appendCombine(Context* c, TernaryOperation type, secondSize, second, resultSize, result, read(c, firstSize, firstTypeMask, firstRegisterMask, AnyFrameIndex), - read(c, secondSize, secondTypeMask, secondRegisterMask, AnyFrameIndex)); + secondRead, + resultRead); } } @@ -2331,7 +2366,7 @@ propagateJunctionSites(Context* c, Event* e, Site** sites) unsigned frameFootprint(Context* c, Stack* s) { - return c->localFootprint + s->index + s->size; + return c->localFootprint + (s ? (s->index + s->size) : 0); } void @@ -2448,7 +2483,7 @@ next(Context* c, LogicalInstruction* i) { for (unsigned n = i->index + 1; n < c->logicalCodeLength; ++n) { i = c->logicalCode[n]; - if (i) return i; + if (i and i->firstEvent) return i; } return 0; } @@ -2456,12 +2491,12 @@ next(Context* c, LogicalInstruction* i) class Block { public: Block(Event* head): - head(head), nextInstruction(0), offset(0), start(0) + head(head), nextInstruction(0), assemblerBlock(0), start(0) { } Event* head; LogicalInstruction* nextInstruction; - Assembler::Offset* offset; + Assembler::Block* assemblerBlock; unsigned start; }; @@ -2490,11 +2525,13 @@ compile(Context* c) e->logicalInstruction->machineOffset = a->offset(); } - Event* predecessor = static_cast(e->predecessors->value); - if (e->predecessors->next) { - setSites(c, e, predecessor->junctionSites); - } else if (predecessor->successors->next) { - setSites(c, e, predecessor->savedSites); + if (e->predecessors) { + Event* predecessor = static_cast(e->predecessors->value); + if (e->predecessors->next) { + setSites(c, e, predecessor->junctionSites); + } else if (predecessor->successors->next) { + setSites(c, e, predecessor->savedSites); + } } populateSources(c, e); @@ -2514,28 +2551,25 @@ compile(Context* c) if (e->next and e->logicalInstruction->lastEvent == e) { LogicalInstruction* nextInstruction = next(c, e->logicalInstruction); if (nextInstruction != e->next->logicalInstruction) { - a->endBlock(); - block->nextInstruction = nextInstruction; - block->offset = a->offset(); + block->assemblerBlock = a->endBlock(); block = ::block(c, e->next); } } } - a->endBlock(); - block->nextInstruction = 0; - block->offset = a->offset(); + block->assemblerBlock = a->endBlock(); block = firstBlock; while (block->nextInstruction) { Block* next = block->nextInstruction->firstEvent->block; - next->start = block->offset->resolve(block->start); + next->start = block->assemblerBlock->resolve + (block->start, next->assemblerBlock); block = next; } - return block->offset->resolve(block->start); + return block->assemblerBlock->resolve(block->start, 0); } unsigned @@ -2599,8 +2633,11 @@ visit(Context* c, unsigned logicalIp) { assert(c, logicalIp < c->logicalCodeLength); - c->logicalCode[logicalIp] = new - (c->zone->allocate(sizeof(LogicalInstruction))) LogicalInstruction; + if (c->logicalCode[logicalIp] == 0) { + c->logicalCode[logicalIp] = new + (c->zone->allocate(sizeof(LogicalInstruction))) + LogicalInstruction(logicalIp); + } } class Client: public Assembler::Client { diff --git a/src/x86.cpp b/src/x86.cpp index 07737c3287..4d91ddbfa0 100644 --- a/src/x86.cpp +++ b/src/x86.cpp @@ -34,6 +34,8 @@ enum { r15 = 15, }; +const unsigned FrameHeaderSize = 2; + inline bool isInt8(intptr_t v) { @@ -48,19 +50,28 @@ isInt32(intptr_t v) class Task; -class Block { +class MyBlock: public Assembler::Block { public: - Block(unsigned offset): offset(offset), start(~0) { } + MyBlock(unsigned offset): offset(offset), start(~0), size(0), next(0) { } + + virtual unsigned resolve(unsigned start, Assembler::Block* next) { + this->start = start; + this->next = static_cast(next); + return start + size; + } unsigned offset; unsigned start; + unsigned size; + MyBlock* next; }; class Context { public: Context(System* s, Allocator* a, Zone* zone): s(s), zone(zone), client(0), code(s, a, 1024), tasks(0), result(0), - block(0) + firstBlock(new (zone->allocate(sizeof(MyBlock))) MyBlock(0)), + lastBlock(firstBlock) { } System* s; @@ -69,7 +80,8 @@ class Context { Vector code; Task* tasks; uint8_t* result; - Block* block; + MyBlock* firstBlock; + MyBlock* lastBlock; }; typedef void (*OperationType)(Context*); @@ -623,11 +635,95 @@ moveCR(Context* c, unsigned aSize, Assembler::Constant* a, } void -subtractBorrowCR(Context* c, unsigned aSize UNUSED, Assembler::Constant* a, - unsigned bSize UNUSED, Assembler::Register* b) +addCarryRR(Context* c, unsigned size, Assembler::Register* a, + Assembler::Register* b) +{ + assert(c, BytesPerWord == 8 or size == 4); + + if (size == 8) rex(c); + c->code.append(0x11); + c->code.append(0xc0 | (a->low << 3) | b->low); +} + +void +addRR(Context* c, unsigned aSize, Assembler::Register* a, + unsigned bSize UNUSED, Assembler::Register* b) { assert(c, aSize == bSize); - assert(c, BytesPerWord == 8 or aSize == 4); + + if (BytesPerWord == 4 and aSize == 8) { + Assembler::Register ah(a->high); + Assembler::Register bh(b->high); + + addRR(c, 4, a, 4, b); + addCarryRR(c, 4, &ah, &bh); + } else { + if (aSize == 8) rex(c); + c->code.append(0x01); + c->code.append(0xc0 | (a->low << 3) | b->low); + } +} + +void +addCarryCR(Context* c, unsigned size UNUSED, Assembler::Constant* a, + Assembler::Register* b) +{ + assert(c, BytesPerWord == 8 or size == 4); + + int64_t v = a->value->value(); + if (isInt8(v)) { + c->code.append(0x83); + c->code.append(0xd0 | b->low); + c->code.append(v); + } else { + abort(c); + } +} + +void +addCR(Context* c, unsigned aSize, Assembler::Constant* a, + unsigned bSize, Assembler::Register* b) +{ + assert(c, aSize == bSize); + + int64_t v = a->value->value(); + if (v) { + if (BytesPerWord == 4 and aSize == 8) { + ResolvedPromise high((v >> 32) & 0xFFFFFFFF); + Assembler::Constant ah(&high); + + ResolvedPromise low(v & 0xFFFFFFFF); + Assembler::Constant al(&low); + + Assembler::Register bh(b->high); + + addCR(c, 4, &al, 4, b); + addCarryCR(c, 4, &ah, &bh); + } else { + if (aSize == 8) rex(c); + if (isInt8(v)) { + c->code.append(0x83); + c->code.append(0xc0 | b->low); + c->code.append(v); + } else if (isInt32(v)) { + c->code.append(0x81); + c->code.append(0xc0 | b->low); + c->code.append4(v); + } else { + Assembler::Register tmp(c->client->acquireTemporary()); + moveCR(c, aSize, a, aSize, &tmp); + addRR(c, aSize, &tmp, bSize, b); + c->client->releaseTemporary(tmp.low); + } + } + } +} + +void +subtractBorrowCR(Context* c, unsigned size UNUSED, Assembler::Constant* a, + Assembler::Register* b) +{ + assert(c, BytesPerWord == 8 or size == 4); int64_t v = a->value->value(); if (isInt8(v)) { @@ -661,7 +757,7 @@ subtractCR(Context* c, unsigned aSize, Assembler::Constant* a, Assembler::Register bh(b->high); subtractCR(c, 4, &al, 4, b); - subtractBorrowCR(c, 4, &ah, 4, &bh); + subtractBorrowCR(c, 4, &ah, &bh); } else { if (aSize == 8) rex(c); if (isInt8(v)) { @@ -683,13 +779,12 @@ subtractCR(Context* c, unsigned aSize, Assembler::Constant* a, } void -subtractBorrowRR(Context* c, unsigned aSize UNUSED, Assembler::Register* a, - unsigned bSize UNUSED, Assembler::Register* b) +subtractBorrowRR(Context* c, unsigned size, Assembler::Register* a, + Assembler::Register* b) { - assert(c, aSize == bSize); - assert(c, BytesPerWord == 8 or aSize == 4); + assert(c, BytesPerWord == 8 or size == 4); - if (aSize == 8) rex(c); + if (size == 8) rex(c); c->code.append(0x19); c->code.append(0xc0 | (a->low << 3) | b->low); } @@ -705,7 +800,7 @@ subtractRR(Context* c, unsigned aSize, Assembler::Register* a, Assembler::Register bh(b->high); subtractRR(c, 4, a, 4, b); - subtractBorrowRR(c, 4, &ah, 4, &bh); + subtractBorrowRR(c, 4, &ah, &bh); } else { if (aSize == 8) rex(c); c->code.append(0x29); @@ -741,9 +836,12 @@ populateTables(ArchitectureContext* c) uo[index(LongJump, C)] = CAST1(longJumpC); bo[index(Move, R, R)] = CAST2(moveRR); + bo[index(Move, C, R)] = CAST2(moveCR); bo[index(Move, M, R)] = CAST2(moveMR); bo[index(Move, R, M)] = CAST2(moveRM); + bo[index(Add, C, R)] = CAST2(addCR); + bo[index(Subtract, C, R)] = CAST2(subtractCR); } @@ -769,6 +867,10 @@ class MyArchitecture: public Assembler::Architecture { return rax; } + virtual bool condensedAddressing() { + return true; + } + virtual bool reserved(int register_) { switch (register_) { case rbp: @@ -822,7 +924,8 @@ class MyArchitecture: public Assembler::Architecture { virtual unsigned alignFrameSize(unsigned sizeInWords) { const unsigned alignment = 16 / BytesPerWord; - return (ceiling(sizeInWords + 2, alignment) * alignment); + return (ceiling(sizeInWords + FrameHeaderSize, alignment) * alignment) + - FrameHeaderSize; } virtual void* frameIp(void* stack) { @@ -830,7 +933,7 @@ class MyArchitecture: public Assembler::Architecture { } virtual unsigned frameHeaderSize() { - return 2; + return FrameHeaderSize; } virtual unsigned frameFooterSize() { @@ -936,7 +1039,7 @@ class MyArchitecture: public Assembler::Architecture { class MyOffset: public Assembler::Offset { public: - MyOffset(Context* c, Block* block, unsigned offset): + MyOffset(Context* c, MyBlock* block, unsigned offset): c(c), block(block), offset(offset) { } @@ -955,7 +1058,7 @@ class MyOffset: public Assembler::Offset { } Context* c; - Block* block; + MyBlock* block; unsigned offset; }; @@ -1002,14 +1105,15 @@ class MyAssembler: public Assembler { } va_end(a); - allocateFrame(footprint); + allocateFrame(arch_->alignFrameSize(footprint)); + unsigned offset = 0; for (unsigned i = 0; i < argumentCount; ++i) { - Memory dst(rsp, footprint); + Memory dst(rsp, offset * BytesPerWord); apply(Move, arguments[i].size, arguments[i].type, arguments[i].operand, pad(arguments[i].size), MemoryOperand, &dst); - footprint -= ceiling(arguments[i].size, BytesPerWord); + offset += ceiling(arguments[i].size, BytesPerWord); } } @@ -1021,8 +1125,7 @@ class MyAssembler: public Assembler { apply(Move, BytesPerWord, RegisterOperand, &stack, BytesPerWord, RegisterOperand, &base); - Constant footprintConstant - (resolved(&c, arch_->alignFrameSize(footprint) * BytesPerWord)); + Constant footprintConstant(resolved(&c, footprint * BytesPerWord)); apply(Subtract, BytesPerWord, ConstantOperand, &footprintConstant, BytesPerWord, RegisterOperand, &stack, BytesPerWord, RegisterOperand, &stack); @@ -1070,7 +1173,10 @@ class MyAssembler: public Assembler { virtual void writeTo(uint8_t* dst) { c.result = dst; - memcpy(dst, c.code.data, c.code.length()); + + for (MyBlock* b = c.firstBlock; b; b = b->next) { + memcpy(dst + b->start, c.code.data + b->offset, b->size); + } for (Task* t = c.tasks; t; t = t->next) { t->run(&c); @@ -1079,11 +1185,15 @@ class MyAssembler: public Assembler { virtual Offset* offset() { return new (c.zone->allocate(sizeof(MyOffset))) - MyOffset(&c, c.block, c.code.length()); + MyOffset(&c, c.lastBlock, c.code.length()); } - virtual void endBlock() { - c.block = new (c.zone->allocate(sizeof(Block))) Block(c.code.length()); + virtual Block* endBlock() { + MyBlock* b = c.lastBlock; + b->size = c.code.length() - b->offset; + c.lastBlock = new (c.zone->allocate(sizeof(MyBlock))) + MyBlock(c.code.length()); + return b; } virtual unsigned length() {