got a simple arithmetic test working

This commit is contained in:
Joel Dice 2008-09-07 14:12:11 -06:00
parent 9971eaa92a
commit af9758a6d3
4 changed files with 230 additions and 66 deletions

View File

@ -168,6 +168,13 @@ class Assembler {
virtual unsigned value() = 0; virtual unsigned value() = 0;
}; };
class Block {
public:
virtual ~Block() { }
virtual unsigned resolve(unsigned start, Block* next) = 0;
};
class Architecture { class Architecture {
public: public:
virtual ~Architecture() { } virtual ~Architecture() { }
@ -179,6 +186,8 @@ class Assembler {
virtual int returnLow() = 0; virtual int returnLow() = 0;
virtual int returnHigh() = 0; virtual int returnHigh() = 0;
virtual bool condensedAddressing() = 0;
virtual bool reserved(int register_) = 0; virtual bool reserved(int register_) = 0;
virtual unsigned argumentRegisterCount() = 0; virtual unsigned argumentRegisterCount() = 0;
@ -245,7 +254,7 @@ class Assembler {
virtual Offset* offset() = 0; virtual Offset* offset() = 0;
virtual void endBlock() = 0; virtual Block* endBlock() = 0;
virtual unsigned length() = 0; virtual unsigned length() = 0;

View File

@ -27,7 +27,7 @@ vmCall();
namespace { namespace {
const bool Verbose = false; const bool Verbose = true;
const bool DebugNatives = false; const bool DebugNatives = false;
const bool DebugCallTable = false; const bool DebugCallTable = false;
const bool DebugMethodTree = false; const bool DebugMethodTree = false;
@ -3832,11 +3832,11 @@ finish(MyThread* t, Context* context)
strcmp strcmp
(reinterpret_cast<const char*> (reinterpret_cast<const char*>
(&byteArrayBody(t, className(t, methodClass(t, context->method)), 0)), (&byteArrayBody(t, className(t, methodClass(t, context->method)), 0)),
"java/lang/String") == 0 and "Simple") == 0 and
strcmp strcmp
(reinterpret_cast<const char*> (reinterpret_cast<const char*>
(&byteArrayBody(t, methodName(t, context->method), 0)), (&byteArrayBody(t, methodName(t, context->method), 0)),
"compareTo") == 0) "main") == 0)
{ {
asm("int3"); asm("int3");
} }
@ -4959,6 +4959,8 @@ compileThunks(MyThread* t, MyProcessor* p)
Assembler::Register result(t->arch->returnLow()); Assembler::Register result(t->arch->returnLow());
a->apply(Jump, BytesPerWord, RegisterOperand, &result); a->apply(Jump, BytesPerWord, RegisterOperand, &result);
a->endBlock()->resolve(0, 0);
} }
ThunkContext nativeContext(t); ThunkContext nativeContext(t);
@ -4979,6 +4981,8 @@ compileThunks(MyThread* t, MyProcessor* p)
a->popFrame(); a->popFrame();
a->apply(Return); a->apply(Return);
a->endBlock()->resolve(0, 0);
} }
ThunkContext aioobContext(t); ThunkContext aioobContext(t);
@ -4996,6 +5000,8 @@ compileThunks(MyThread* t, MyProcessor* p)
Assembler::Constant proc(&(aioobContext.promise)); Assembler::Constant proc(&(aioobContext.promise));
a->apply(LongCall, BytesPerWord, ConstantOperand, &proc); a->apply(LongCall, BytesPerWord, ConstantOperand, &proc);
a->endBlock()->resolve(0, 0);
} }
ThunkContext tableContext(t); ThunkContext tableContext(t);
@ -5006,6 +5012,8 @@ compileThunks(MyThread* t, MyProcessor* p)
Assembler::Constant proc(&(tableContext.promise)); Assembler::Constant proc(&(tableContext.promise));
a->apply(LongJump, BytesPerWord, ConstantOperand, &proc); a->apply(LongJump, BytesPerWord, ConstantOperand, &proc);
a->endBlock()->resolve(0, 0);
} }
p->thunkSize = pad(tableContext.context.assembler->length()); p->thunkSize = pad(tableContext.context.assembler->length());

View File

@ -15,8 +15,8 @@ using namespace vm;
namespace { namespace {
const bool DebugAppend = false; const bool DebugAppend = true;
const bool DebugCompile = false; const bool DebugCompile = true;
const bool DebugStack = false; const bool DebugStack = false;
const bool DebugRegisters = false; const bool DebugRegisters = false;
@ -120,9 +120,10 @@ class State {
class LogicalInstruction { class LogicalInstruction {
public: public:
LogicalInstruction() { LogicalInstruction(int index):
memset(this, 0, sizeof(LogicalInstruction)); firstEvent(0), lastEvent(0), immediatePredecessor(0), stack(0), locals(0),
} machineOffset(0), index(index), stackSaved(false)
{ }
Event* firstEvent; Event* firstEvent;
Event* lastEvent; Event* lastEvent;
@ -321,6 +322,17 @@ class CodePromise: public Promise {
CodePromise* next; 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 { class IpPromise: public Promise {
public: public:
IpPromise(Context* c, int logicalIp): IpPromise(Context* c, int logicalIp):
@ -331,7 +343,7 @@ class IpPromise: public Promise {
virtual int64_t value() { virtual int64_t value() {
if (resolved()) { if (resolved()) {
return reinterpret_cast<intptr_t> return reinterpret_cast<intptr_t>
(c->machineCode + c->logicalCode[logicalIp]->machineOffset->value()); (c->machineCode + machineOffset(c, logicalIp));
} }
abort(c); abort(c);
@ -365,6 +377,12 @@ expect(Context* c, bool v)
expect(c->system, 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 { class Event {
public: public:
Event(Context* c): Event(Context* c):
@ -377,6 +395,8 @@ class Event {
if (c->lastEvent) { if (c->lastEvent) {
c->lastEvent->next = this; c->lastEvent->next = this;
predecessors = cons(c, c->lastEvent, 0);
c->lastEvent->successors = cons(c, this, c->lastEvent->successors);
} else { } else {
c->firstEvent = this; c->firstEvent = this;
} }
@ -1367,6 +1387,7 @@ insertRead(Context*, Event* event, int sequence, Value* v, Read* r)
{ {
r->value = v; r->value = v;
r->event = event; r->event = event;
r->eventNext = event->reads;
event->reads = r; event->reads = r;
++ event->readCount; ++ event->readCount;
@ -1791,10 +1812,12 @@ class CombineEvent: public Event {
unsigned firstSize, Value* first, unsigned firstSize, Value* first,
unsigned secondSize, Value* second, unsigned secondSize, Value* second,
unsigned resultSize, Value* result, unsigned resultSize, Value* result,
Read* firstRead, Read* secondRead): Read* firstRead,
Read* secondRead,
Read* resultRead):
Event(c), type(type), firstSize(firstSize), first(first), Event(c), type(type), firstSize(firstSize), first(first),
secondSize(secondSize), second(second), resultSize(resultSize), secondSize(secondSize), second(second), resultSize(resultSize),
result(result) result(result), resultRead(resultRead)
{ {
addRead(c, first, firstRead); addRead(c, first, firstRead);
addRead(c, second, secondRead); addRead(c, second, secondRead);
@ -1805,18 +1828,20 @@ class CombineEvent: public Event {
fprintf(stderr, "CombineEvent.compile\n"); fprintf(stderr, "CombineEvent.compile\n");
} }
Site* target;
if (c->arch->condensedAddressing()) {
maybePreserve(c, stack, locals, secondSize, second, second->source); 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, apply(c, type, firstSize, first->source, secondSize, second->source,
resultSize, target); resultSize, target);
nextRead(c, first); nextRead(c, first);
nextRead(c, second); nextRead(c, second);
if (live(result)) {
addSite(c, 0, 0, resultSize, result, target);
}
} }
TernaryOperation type; TernaryOperation type;
@ -1826,6 +1851,7 @@ class CombineEvent: public Event {
Value* second; Value* second;
unsigned resultSize; unsigned resultSize;
Value* result; Value* result;
Read* resultRead;
}; };
Value* Value*
@ -1902,7 +1928,15 @@ appendCombine(Context* c, TernaryOperation type,
fprintf(stderr, "appendCombine\n"); 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))) new (c->zone->allocate(sizeof(CombineEvent)))
CombineEvent CombineEvent
@ -1911,7 +1945,8 @@ appendCombine(Context* c, TernaryOperation type,
secondSize, second, secondSize, second,
resultSize, result, resultSize, result,
read(c, firstSize, firstTypeMask, firstRegisterMask, AnyFrameIndex), 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 unsigned
frameFootprint(Context* c, Stack* s) frameFootprint(Context* c, Stack* s)
{ {
return c->localFootprint + s->index + s->size; return c->localFootprint + (s ? (s->index + s->size) : 0);
} }
void void
@ -2448,7 +2483,7 @@ next(Context* c, LogicalInstruction* i)
{ {
for (unsigned n = i->index + 1; n < c->logicalCodeLength; ++n) { for (unsigned n = i->index + 1; n < c->logicalCodeLength; ++n) {
i = c->logicalCode[n]; i = c->logicalCode[n];
if (i) return i; if (i and i->firstEvent) return i;
} }
return 0; return 0;
} }
@ -2456,12 +2491,12 @@ next(Context* c, LogicalInstruction* i)
class Block { class Block {
public: public:
Block(Event* head): Block(Event* head):
head(head), nextInstruction(0), offset(0), start(0) head(head), nextInstruction(0), assemblerBlock(0), start(0)
{ } { }
Event* head; Event* head;
LogicalInstruction* nextInstruction; LogicalInstruction* nextInstruction;
Assembler::Offset* offset; Assembler::Block* assemblerBlock;
unsigned start; unsigned start;
}; };
@ -2490,12 +2525,14 @@ compile(Context* c)
e->logicalInstruction->machineOffset = a->offset(); e->logicalInstruction->machineOffset = a->offset();
} }
if (e->predecessors) {
Event* predecessor = static_cast<Event*>(e->predecessors->value); Event* predecessor = static_cast<Event*>(e->predecessors->value);
if (e->predecessors->next) { if (e->predecessors->next) {
setSites(c, e, predecessor->junctionSites); setSites(c, e, predecessor->junctionSites);
} else if (predecessor->successors->next) { } else if (predecessor->successors->next) {
setSites(c, e, predecessor->savedSites); setSites(c, e, predecessor->savedSites);
} }
}
populateSources(c, e); populateSources(c, e);
@ -2514,28 +2551,25 @@ compile(Context* c)
if (e->next and e->logicalInstruction->lastEvent == e) { if (e->next and e->logicalInstruction->lastEvent == e) {
LogicalInstruction* nextInstruction = next(c, e->logicalInstruction); LogicalInstruction* nextInstruction = next(c, e->logicalInstruction);
if (nextInstruction != e->next->logicalInstruction) { if (nextInstruction != e->next->logicalInstruction) {
a->endBlock();
block->nextInstruction = nextInstruction; block->nextInstruction = nextInstruction;
block->offset = a->offset(); block->assemblerBlock = a->endBlock();
block = ::block(c, e->next); block = ::block(c, e->next);
} }
} }
} }
a->endBlock();
block->nextInstruction = 0; block->nextInstruction = 0;
block->offset = a->offset(); block->assemblerBlock = a->endBlock();
block = firstBlock; block = firstBlock;
while (block->nextInstruction) { while (block->nextInstruction) {
Block* next = block->nextInstruction->firstEvent->block; Block* next = block->nextInstruction->firstEvent->block;
next->start = block->offset->resolve(block->start); next->start = block->assemblerBlock->resolve
(block->start, next->assemblerBlock);
block = next; block = next;
} }
return block->offset->resolve(block->start); return block->assemblerBlock->resolve(block->start, 0);
} }
unsigned unsigned
@ -2599,8 +2633,11 @@ visit(Context* c, unsigned logicalIp)
{ {
assert(c, logicalIp < c->logicalCodeLength); assert(c, logicalIp < c->logicalCodeLength);
if (c->logicalCode[logicalIp] == 0) {
c->logicalCode[logicalIp] = new c->logicalCode[logicalIp] = new
(c->zone->allocate(sizeof(LogicalInstruction))) LogicalInstruction; (c->zone->allocate(sizeof(LogicalInstruction)))
LogicalInstruction(logicalIp);
}
} }
class Client: public Assembler::Client { class Client: public Assembler::Client {

View File

@ -34,6 +34,8 @@ enum {
r15 = 15, r15 = 15,
}; };
const unsigned FrameHeaderSize = 2;
inline bool inline bool
isInt8(intptr_t v) isInt8(intptr_t v)
{ {
@ -48,19 +50,28 @@ isInt32(intptr_t v)
class Task; class Task;
class Block { class MyBlock: public Assembler::Block {
public: 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<MyBlock*>(next);
return start + size;
}
unsigned offset; unsigned offset;
unsigned start; unsigned start;
unsigned size;
MyBlock* next;
}; };
class Context { class Context {
public: public:
Context(System* s, Allocator* a, Zone* zone): Context(System* s, Allocator* a, Zone* zone):
s(s), zone(zone), client(0), code(s, a, 1024), tasks(0), result(0), 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; System* s;
@ -69,7 +80,8 @@ class Context {
Vector code; Vector code;
Task* tasks; Task* tasks;
uint8_t* result; uint8_t* result;
Block* block; MyBlock* firstBlock;
MyBlock* lastBlock;
}; };
typedef void (*OperationType)(Context*); typedef void (*OperationType)(Context*);
@ -623,11 +635,95 @@ moveCR(Context* c, unsigned aSize, Assembler::Constant* a,
} }
void void
subtractBorrowCR(Context* c, unsigned aSize UNUSED, Assembler::Constant* a, 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) unsigned bSize UNUSED, Assembler::Register* b)
{ {
assert(c, aSize == bSize); 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(); int64_t v = a->value->value();
if (isInt8(v)) { if (isInt8(v)) {
@ -661,7 +757,7 @@ subtractCR(Context* c, unsigned aSize, Assembler::Constant* a,
Assembler::Register bh(b->high); Assembler::Register bh(b->high);
subtractCR(c, 4, &al, 4, b); subtractCR(c, 4, &al, 4, b);
subtractBorrowCR(c, 4, &ah, 4, &bh); subtractBorrowCR(c, 4, &ah, &bh);
} else { } else {
if (aSize == 8) rex(c); if (aSize == 8) rex(c);
if (isInt8(v)) { if (isInt8(v)) {
@ -683,13 +779,12 @@ subtractCR(Context* c, unsigned aSize, Assembler::Constant* a,
} }
void void
subtractBorrowRR(Context* c, unsigned aSize UNUSED, Assembler::Register* a, subtractBorrowRR(Context* c, unsigned size, Assembler::Register* a,
unsigned bSize UNUSED, Assembler::Register* b) Assembler::Register* b)
{ {
assert(c, aSize == bSize); assert(c, BytesPerWord == 8 or size == 4);
assert(c, BytesPerWord == 8 or aSize == 4);
if (aSize == 8) rex(c); if (size == 8) rex(c);
c->code.append(0x19); c->code.append(0x19);
c->code.append(0xc0 | (a->low << 3) | b->low); 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); Assembler::Register bh(b->high);
subtractRR(c, 4, a, 4, b); subtractRR(c, 4, a, 4, b);
subtractBorrowRR(c, 4, &ah, 4, &bh); subtractBorrowRR(c, 4, &ah, &bh);
} else { } else {
if (aSize == 8) rex(c); if (aSize == 8) rex(c);
c->code.append(0x29); c->code.append(0x29);
@ -741,9 +836,12 @@ populateTables(ArchitectureContext* c)
uo[index(LongJump, C)] = CAST1(longJumpC); uo[index(LongJump, C)] = CAST1(longJumpC);
bo[index(Move, R, R)] = CAST2(moveRR); bo[index(Move, R, R)] = CAST2(moveRR);
bo[index(Move, C, R)] = CAST2(moveCR);
bo[index(Move, M, R)] = CAST2(moveMR); bo[index(Move, M, R)] = CAST2(moveMR);
bo[index(Move, R, M)] = CAST2(moveRM); bo[index(Move, R, M)] = CAST2(moveRM);
bo[index(Add, C, R)] = CAST2(addCR);
bo[index(Subtract, C, R)] = CAST2(subtractCR); bo[index(Subtract, C, R)] = CAST2(subtractCR);
} }
@ -769,6 +867,10 @@ class MyArchitecture: public Assembler::Architecture {
return rax; return rax;
} }
virtual bool condensedAddressing() {
return true;
}
virtual bool reserved(int register_) { virtual bool reserved(int register_) {
switch (register_) { switch (register_) {
case rbp: case rbp:
@ -822,7 +924,8 @@ class MyArchitecture: public Assembler::Architecture {
virtual unsigned alignFrameSize(unsigned sizeInWords) { virtual unsigned alignFrameSize(unsigned sizeInWords) {
const unsigned alignment = 16 / BytesPerWord; const unsigned alignment = 16 / BytesPerWord;
return (ceiling(sizeInWords + 2, alignment) * alignment); return (ceiling(sizeInWords + FrameHeaderSize, alignment) * alignment)
- FrameHeaderSize;
} }
virtual void* frameIp(void* stack) { virtual void* frameIp(void* stack) {
@ -830,7 +933,7 @@ class MyArchitecture: public Assembler::Architecture {
} }
virtual unsigned frameHeaderSize() { virtual unsigned frameHeaderSize() {
return 2; return FrameHeaderSize;
} }
virtual unsigned frameFooterSize() { virtual unsigned frameFooterSize() {
@ -936,7 +1039,7 @@ class MyArchitecture: public Assembler::Architecture {
class MyOffset: public Assembler::Offset { class MyOffset: public Assembler::Offset {
public: public:
MyOffset(Context* c, Block* block, unsigned offset): MyOffset(Context* c, MyBlock* block, unsigned offset):
c(c), block(block), offset(offset) c(c), block(block), offset(offset)
{ } { }
@ -955,7 +1058,7 @@ class MyOffset: public Assembler::Offset {
} }
Context* c; Context* c;
Block* block; MyBlock* block;
unsigned offset; unsigned offset;
}; };
@ -1002,14 +1105,15 @@ class MyAssembler: public Assembler {
} }
va_end(a); va_end(a);
allocateFrame(footprint); allocateFrame(arch_->alignFrameSize(footprint));
unsigned offset = 0;
for (unsigned i = 0; i < argumentCount; ++i) { for (unsigned i = 0; i < argumentCount; ++i) {
Memory dst(rsp, footprint); Memory dst(rsp, offset * BytesPerWord);
apply(Move, apply(Move,
arguments[i].size, arguments[i].type, arguments[i].operand, arguments[i].size, arguments[i].type, arguments[i].operand,
pad(arguments[i].size), MemoryOperand, &dst); 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, apply(Move, BytesPerWord, RegisterOperand, &stack,
BytesPerWord, RegisterOperand, &base); BytesPerWord, RegisterOperand, &base);
Constant footprintConstant Constant footprintConstant(resolved(&c, footprint * BytesPerWord));
(resolved(&c, arch_->alignFrameSize(footprint) * BytesPerWord));
apply(Subtract, BytesPerWord, ConstantOperand, &footprintConstant, apply(Subtract, BytesPerWord, ConstantOperand, &footprintConstant,
BytesPerWord, RegisterOperand, &stack, BytesPerWord, RegisterOperand, &stack,
BytesPerWord, RegisterOperand, &stack); BytesPerWord, RegisterOperand, &stack);
@ -1070,7 +1173,10 @@ class MyAssembler: public Assembler {
virtual void writeTo(uint8_t* dst) { virtual void writeTo(uint8_t* dst) {
c.result = 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) { for (Task* t = c.tasks; t; t = t->next) {
t->run(&c); t->run(&c);
@ -1079,11 +1185,15 @@ class MyAssembler: public Assembler {
virtual Offset* offset() { virtual Offset* offset() {
return new (c.zone->allocate(sizeof(MyOffset))) return new (c.zone->allocate(sizeof(MyOffset)))
MyOffset(&c, c.block, c.code.length()); MyOffset(&c, c.lastBlock, c.code.length());
} }
virtual void endBlock() { virtual Block* endBlock() {
c.block = new (c.zone->allocate(sizeof(Block))) Block(c.code.length()); 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() { virtual unsigned length() {