mirror of
https://github.com/corda/corda.git
synced 2025-01-05 20:54:13 +00:00
snapshot
This commit is contained in:
parent
4299063be9
commit
9efe6f1f05
@ -17,14 +17,14 @@
|
||||
namespace vm {
|
||||
|
||||
enum Operation {
|
||||
PopFrame,
|
||||
Return
|
||||
};
|
||||
|
||||
const unsigned OperationCount = Return + 1;
|
||||
|
||||
enum UnaryOperation {
|
||||
Push,
|
||||
Pop,
|
||||
PushFrame,
|
||||
Call,
|
||||
LongCall,
|
||||
AlignedCall,
|
||||
@ -42,13 +42,16 @@ enum UnaryOperation {
|
||||
const unsigned UnaryOperationCount = Negate + 1;
|
||||
|
||||
enum BinaryOperation {
|
||||
LoadAddress,
|
||||
Move,
|
||||
MoveZ,
|
||||
Move4To8,
|
||||
Swap,
|
||||
Compare
|
||||
};
|
||||
|
||||
const unsigned BinaryOperationCount = Compare + 1;
|
||||
|
||||
enum TernaryOperation {
|
||||
LongCompare,
|
||||
Compare,
|
||||
Add,
|
||||
Subtract,
|
||||
Multiply,
|
||||
@ -62,7 +65,7 @@ enum BinaryOperation {
|
||||
Xor
|
||||
};
|
||||
|
||||
const unsigned BinaryOperationCount = Xor + 1;
|
||||
const unsigned TernaryOperationCount = Xor + 1;
|
||||
|
||||
enum OperandType {
|
||||
ConstantOperand,
|
||||
@ -156,14 +159,20 @@ class Assembler {
|
||||
virtual void restore(int r) = 0;
|
||||
};
|
||||
|
||||
class Offset {
|
||||
public:
|
||||
virtual ~Offset() { }
|
||||
|
||||
virtual unsigned calculate(unsigned start) = 0;
|
||||
};
|
||||
|
||||
virtual ~Assembler() { }
|
||||
|
||||
virtual void setClient(Client* client) = 0;
|
||||
|
||||
virtual unsigned registerCount() = 0;
|
||||
|
||||
virtual int base() = 0;
|
||||
virtual int stack() = 0;
|
||||
virtual int frame() = 0;
|
||||
virtual int thread() = 0;
|
||||
virtual int returnLow() = 0;
|
||||
virtual int returnHigh() = 0;
|
||||
@ -171,22 +180,37 @@ class Assembler {
|
||||
virtual unsigned argumentRegisterCount() = 0;
|
||||
virtual int argumentRegister(unsigned index) = 0;
|
||||
|
||||
virtual unsigned stackAlignment() = 0;
|
||||
virtual void plan
|
||||
(UnaryOperation op,
|
||||
unsigned aSize, uint8_t* aTypeMask, uint64_t* aRegisterMask,
|
||||
bool* thunk) = 0;
|
||||
|
||||
virtual void plan(UnaryOperation op, unsigned size, uint8_t* typeMask,
|
||||
uint64_t* registerMask, bool* thunk) = 0;
|
||||
virtual void plan
|
||||
(BinaryOperation op,
|
||||
unsigned aSize, uint8_t* aTypeMask, uint64_t* aRegisterMask,
|
||||
unsigned bSize, uint8_t* bTypeMask, uint64_t* bRegisterMask,
|
||||
bool* thunk) = 0;
|
||||
|
||||
virtual void plan(BinaryOperation op, unsigned size, uint8_t* aTypeMask,
|
||||
uint64_t* aRegisterMask, uint8_t* bTypeMask,
|
||||
uint64_t* bRegisterMask, bool* thunk) = 0;
|
||||
virtual void plan
|
||||
(TernaryOperation op,
|
||||
unsigned aSize, uint8_t* aTypeMask, uint64_t* aRegisterMask,
|
||||
unsigned bSize, uint8_t* bTypeMask, uint64_t* bRegisterMask,
|
||||
unsigned cSize, uint8_t* cTypeMask, uint64_t* cRegisterMask,
|
||||
bool* thunk) = 0;
|
||||
|
||||
virtual void apply(Operation op) = 0;
|
||||
|
||||
virtual void apply(UnaryOperation op, unsigned size, OperandType type,
|
||||
Operand* operand) = 0;
|
||||
virtual void apply(UnaryOperation op,
|
||||
unsigned aSize, OperandType aType, Operand* aOperand) = 0;
|
||||
|
||||
virtual void apply(BinaryOperation op, unsigned size, OperandType aType,
|
||||
Operand* a, OperandType bType, Operand* b) = 0;
|
||||
virtual void apply(BinaryOperation op,
|
||||
unsigned aSize, OperandType aType, Operand* aOperand,
|
||||
unsigned bSize, OperandType bType, Operand* bOperand) = 0;
|
||||
|
||||
virtual void apply(TernaryOperation op,
|
||||
unsigned aSize, OperandType aType, Operand* aOperand,
|
||||
unsigned bSize, OperandType bType, Operand* bOperand,
|
||||
unsigned cSize, OperandType cType, Operand* cOperand) = 0;
|
||||
|
||||
virtual void writeTo(uint8_t* dst) = 0;
|
||||
|
||||
@ -195,6 +219,8 @@ class Assembler {
|
||||
virtual void updateCall(void* returnAddress, void* newTarget) = 0;
|
||||
|
||||
virtual void dispose() = 0;
|
||||
|
||||
static unsigned alignFrameSize(unsigned sizeInWords);
|
||||
};
|
||||
|
||||
Assembler*
|
||||
|
@ -41,26 +41,22 @@ class MyThread: public Thread {
|
||||
public:
|
||||
CallTrace(MyThread* t):
|
||||
t(t),
|
||||
base(t->base),
|
||||
stack(t->stack),
|
||||
frame(t->frame),
|
||||
nativeMethod(0),
|
||||
next(t->trace)
|
||||
{
|
||||
t->trace = this;
|
||||
t->base = 0;
|
||||
t->stack = 0;
|
||||
t->frame = 0;
|
||||
}
|
||||
|
||||
~CallTrace() {
|
||||
t->stack = stack;
|
||||
t->base = base;
|
||||
t->frame = frame;
|
||||
t->trace = next;
|
||||
}
|
||||
|
||||
MyThread* t;
|
||||
void* ip;
|
||||
void* base;
|
||||
void* stack;
|
||||
void* frame;
|
||||
object nativeMethod;
|
||||
CallTrace* next;
|
||||
};
|
||||
@ -68,15 +64,13 @@ class MyThread: public Thread {
|
||||
MyThread(Machine* m, object javaThread, Thread* parent):
|
||||
Thread(m, javaThread, parent),
|
||||
ip(0),
|
||||
base(0),
|
||||
stack(0),
|
||||
frame(0),
|
||||
trace(0),
|
||||
reference(0)
|
||||
{ }
|
||||
|
||||
void* ip;
|
||||
void* base;
|
||||
void* stack;
|
||||
void* frame;
|
||||
CallTrace* trace;
|
||||
Reference* reference;
|
||||
};
|
||||
@ -4311,42 +4305,34 @@ visitStack(MyThread* t, Heap::Visitor* v)
|
||||
}
|
||||
|
||||
void
|
||||
saveStackAndBase(MyThread* t, Assembler* a)
|
||||
saveFrame(MyThread* t, Assembler* a)
|
||||
{
|
||||
Assembler::Register base(a->base());
|
||||
Assembler::Memory baseDst(a->thread(), difference(&(t->base), t));
|
||||
a->apply(Move, BytesPerWord, RegisterOperand, &base,
|
||||
MemoryOperand, &baseDst);
|
||||
|
||||
Assembler::Register stack(a->stack());
|
||||
Assembler::Memory stackDst(a->thread(), difference(&(t->stack), t));
|
||||
a->apply(Move, BytesPerWord, RegisterOperand, &stack,
|
||||
MemoryOperand, &stackDst);
|
||||
Assembler::Register frame(a->frame());
|
||||
Assembler::Memory frameDst(a->thread(), difference(&(t->frame), t));
|
||||
a->apply(Move, BytesPerWord, RegisterOperand, &frame,
|
||||
BytesPerWord, MemoryOperand, &frameDst);
|
||||
}
|
||||
|
||||
void
|
||||
pushThread(MyThread*, Assembler* a)
|
||||
pushFrame(MyThread* t, Assembler* a, unsigned size)
|
||||
{
|
||||
Assembler::Constant offset(resolved(c, Assembler::alignFrameSize(size)));
|
||||
a->apply(PushFrame, BytesPerWord, ConstantOperand, &offset);
|
||||
}
|
||||
|
||||
void
|
||||
setThreadArgument(MyThread*, Assembler* a)
|
||||
{
|
||||
Assembler::Register thread(a->thread());
|
||||
|
||||
if (a->argumentRegisterCount()) {
|
||||
Assembler::Register arg(a->argumentRegister(0));
|
||||
a->apply(Move, BytesPerWord, RegisterOperand, &thread,
|
||||
RegisterOperand, &arg);
|
||||
BytesPerWord, RegisterOperand, &arg);
|
||||
} else {
|
||||
a->apply(Push, BytesPerWord, RegisterOperand, &thread);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
popThread(MyThread*, Assembler* a)
|
||||
{
|
||||
if (a->argumentRegisterCount() == 0) {
|
||||
ResolvedPromise bpwPromise(BytesPerWord);
|
||||
Assembler::Constant bpw(&bpwPromise);
|
||||
Assembler::Register stack(a->stack());
|
||||
a->apply(Add, BytesPerWord, ConstantOperand, &bpw,
|
||||
RegisterOperand, &stack);
|
||||
Assembler::Memory arg(a->frame(), a->argumentPosition(0));
|
||||
a->apply(Move, BytesPerWord, RegisterOperand, &thread,
|
||||
BytesPerWord, MemoryOperand, &arg);
|
||||
}
|
||||
}
|
||||
|
||||
@ -4984,8 +4970,9 @@ compileThunks(MyThread* t, MyProcessor* p)
|
||||
|
||||
{ Assembler* a = defaultContext.context.assembler;
|
||||
|
||||
saveStackAndBase(t, a);
|
||||
pushThread(t, a);
|
||||
saveFrame(t, a);
|
||||
pushFrame(t, a, 1);
|
||||
setThreadArgument(t, a);
|
||||
|
||||
defaultContext.promise.resolved_ = true;
|
||||
defaultContext.promise.value_ = reinterpret_cast<intptr_t>(compileMethod);
|
||||
@ -4993,7 +4980,7 @@ compileThunks(MyThread* t, MyProcessor* p)
|
||||
Assembler::Constant proc(&(defaultContext.promise));
|
||||
a->apply(LongCall, BytesPerWord, ConstantOperand, &proc);
|
||||
|
||||
popThread(t, a);
|
||||
a->apply(PopFrame);
|
||||
|
||||
Assembler::Register result(a->returnLow());
|
||||
a->apply(Jump, BytesPerWord, RegisterOperand, &result);
|
||||
@ -5003,8 +4990,9 @@ compileThunks(MyThread* t, MyProcessor* p)
|
||||
|
||||
{ Assembler* a = nativeContext.context.assembler;
|
||||
|
||||
saveStackAndBase(t, a);
|
||||
pushThread(t, a);
|
||||
saveFrame(t, a);
|
||||
pushFrame(t, a, 1);
|
||||
setThreadArgument(t, a);
|
||||
|
||||
nativeContext.promise.resolved_ = true;
|
||||
nativeContext.promise.value_ = reinterpret_cast<intptr_t>(invokeNative);
|
||||
@ -5012,7 +5000,7 @@ compileThunks(MyThread* t, MyProcessor* p)
|
||||
Assembler::Constant proc(&(nativeContext.promise));
|
||||
a->apply(LongCall, BytesPerWord, ConstantOperand, &proc);
|
||||
|
||||
popThread(t, a);
|
||||
a->apply(PopFrame);
|
||||
|
||||
a->apply(Return);
|
||||
}
|
||||
@ -5021,8 +5009,9 @@ compileThunks(MyThread* t, MyProcessor* p)
|
||||
|
||||
{ Assembler* a = aioobContext.context.assembler;
|
||||
|
||||
saveStackAndBase(t, a);
|
||||
pushThread(t, a);
|
||||
saveFrame(t, a);
|
||||
pushFrame(t, a, 1);
|
||||
setThreadArgument(t, a);
|
||||
|
||||
aioobContext.promise.resolved_ = true;
|
||||
aioobContext.promise.value_ = reinterpret_cast<intptr_t>
|
||||
@ -5036,7 +5025,7 @@ compileThunks(MyThread* t, MyProcessor* p)
|
||||
|
||||
{ Assembler* a = tableContext.context.assembler;
|
||||
|
||||
saveStackAndBase(t, a);
|
||||
saveFrame(t, a);
|
||||
|
||||
Assembler::Constant proc(&(tableContext.promise));
|
||||
a->apply(LongJump, BytesPerWord, ConstantOperand, &proc);
|
||||
|
474
src/compiler.cpp
474
src/compiler.cpp
@ -32,10 +32,19 @@ class Read;
|
||||
void NO_RETURN abort(Context*);
|
||||
|
||||
void
|
||||
apply(Context* c, UnaryOperation op, unsigned size, Site* a);
|
||||
apply(Context* c, UnaryOperation op,
|
||||
unsigned s1Size, Site* s1);
|
||||
|
||||
void
|
||||
apply(Context* c, BinaryOperation op, unsigned size, Site* a, Site* b);
|
||||
apply(Context* c, BinaryOperation op,
|
||||
unsigned s1Size, Site* s1,
|
||||
unsigned s2Size, Site* s2);
|
||||
|
||||
void
|
||||
apply(Context* c, TernaryOperation op,
|
||||
unsigned s1Size, Site* s1,
|
||||
unsigned s2Size, Site* s2,
|
||||
unsigned s3Size, Site* s3);
|
||||
|
||||
enum ConstantCompare {
|
||||
CompareNone,
|
||||
@ -221,7 +230,7 @@ class Context {
|
||||
Compiler::Client* client;
|
||||
int logicalIp;
|
||||
State* state;
|
||||
LogicalInstruction* logicalCode;
|
||||
LogicalInstruction** logicalCode;
|
||||
unsigned logicalCodeLength;
|
||||
unsigned parameterFootprint;
|
||||
unsigned localFootprint;
|
||||
@ -292,7 +301,7 @@ class IpPromise: public Promise {
|
||||
virtual int64_t value() {
|
||||
if (resolved()) {
|
||||
return reinterpret_cast<intptr_t>
|
||||
(c->machineCode + c->logicalCode[logicalIp].machineOffset);
|
||||
(c->machineCode + c->logicalCode[logicalIp]->machineOffset->value());
|
||||
}
|
||||
|
||||
abort(c);
|
||||
@ -334,7 +343,7 @@ class Event {
|
||||
{
|
||||
assert(c, c->logicalIp >= 0);
|
||||
|
||||
LogicalInstruction* i = c->logicalCode + c->logicalIp;
|
||||
LogicalInstruction* i = c->logicalCode[c->logicalIp];
|
||||
if (i->lastEvent) {
|
||||
i->lastEvent->next = this;
|
||||
} else {
|
||||
@ -1021,7 +1030,7 @@ trySteal(Context* c, Register* r, Stack* stack, Value** locals)
|
||||
}
|
||||
|
||||
if (saveSite) {
|
||||
apply(c, Move, r->size, r->site, saveSite);
|
||||
apply(c, Move, r->size, r->site, r->size, saveSite);
|
||||
addSite(c, 0, 0, r->size, v, saveSite);
|
||||
} else {
|
||||
if (DebugRegisters) {
|
||||
@ -1106,7 +1115,8 @@ swap(Context* c, Register* a, Register* b)
|
||||
Assembler::Register ar(a->number);
|
||||
Assembler::Register br(b->number);
|
||||
c->assembler->apply
|
||||
(Swap, BytesPerWord, RegisterOperand, &ar, RegisterOperand, &br);
|
||||
(Swap, BytesPerWord, RegisterOperand, &ar,
|
||||
BytesPerWord, RegisterOperand, &br);
|
||||
|
||||
c->registers[a->number] = b;
|
||||
c->registers[b->number] = a;
|
||||
@ -1209,31 +1219,56 @@ validate(Context* c, uint32_t mask, Stack* stack, Value** locals,
|
||||
Assembler::Register rr(r->number);
|
||||
Assembler::Register cr(current->number);
|
||||
c->assembler->apply
|
||||
(Move, BytesPerWord, RegisterOperand, &cr, RegisterOperand, &rr);
|
||||
(Move, BytesPerWord, RegisterOperand, &cr,
|
||||
BytesPerWord, RegisterOperand, &rr);
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
void
|
||||
apply(Context* c, UnaryOperation op, unsigned size, Site* a)
|
||||
apply(Context* c, UnaryOperation op,
|
||||
unsigned s1Size, Site* s1)
|
||||
{
|
||||
OperandType type = a->type(c);
|
||||
Assembler::Operand* operand = a->asAssemblerOperand(c);
|
||||
OperandType s1Type = s1->type(c);
|
||||
Assembler::Operand* s1Operand = s1->asAssemblerOperand(c);
|
||||
|
||||
c->assembler->apply(op, size, type, operand);
|
||||
c->assembler->apply(op, s1Size, s1Type, s1Operand);
|
||||
}
|
||||
|
||||
void
|
||||
apply(Context* c, BinaryOperation op, unsigned size, Site* a, Site* b)
|
||||
apply(Context* c, BinaryOperation op,
|
||||
unsigned s1Size, Site* s1,
|
||||
unsigned s2Size, Site* s2)
|
||||
{
|
||||
OperandType aType = a->type(c);
|
||||
Assembler::Operand* aOperand = a->asAssemblerOperand(c);
|
||||
OperandType s1Type = s1->type(c);
|
||||
Assembler::Operand* s1Operand = s1->asAssemblerOperand(c);
|
||||
|
||||
OperandType bType = b->type(c);
|
||||
Assembler::Operand* bOperand = b->asAssemblerOperand(c);
|
||||
OperandType s2Type = s2->type(c);
|
||||
Assembler::Operand* s2Operand = s2->asAssemblerOperand(c);
|
||||
|
||||
c->assembler->apply(op, size, aType, aOperand, bType, bOperand);
|
||||
c->assembler->apply(op, s1Size, s1Type, s1Operand,
|
||||
s2Size, s2Type, s2Operand);
|
||||
}
|
||||
|
||||
void
|
||||
apply(Context* c, TernaryOperation op,
|
||||
unsigned s1Size, Site* s1,
|
||||
unsigned s2Size, Site* s2,
|
||||
unsigned s3Size, Site* s3)
|
||||
{
|
||||
OperandType s1Type = s1->type(c);
|
||||
Assembler::Operand* s1Operand = s1->asAssemblerOperand(c);
|
||||
|
||||
OperandType s2Type = s2->type(c);
|
||||
Assembler::Operand* s2Operand = s2->asAssemblerOperand(c);
|
||||
|
||||
OperandType s3Type = s3->type(c);
|
||||
Assembler::Operand* s3Operand = s3->asAssemblerOperand(c);
|
||||
|
||||
c->assembler->apply(op, s1Size, s1Type, s1Operand,
|
||||
s2Size, s2Type, s2Operand,
|
||||
s3Size, s3Type, s3Operand);
|
||||
}
|
||||
|
||||
void
|
||||
@ -1269,7 +1304,7 @@ insertRead(Context* c, Event* event, int sequence, Value* v, Read* r)
|
||||
void
|
||||
addRead(Context* c, Value* v, Read* r)
|
||||
{
|
||||
insertRead(c, c->logicalCode[c->logicalIp].lastEvent, -1, v, r);
|
||||
insertRead(c, c->logicalCode[c->logicalIp]->lastEvent, -1, v, r);
|
||||
}
|
||||
|
||||
Site*
|
||||
@ -1355,17 +1390,6 @@ appendPushed(Context* c, Stack* s)
|
||||
void
|
||||
push(Context* c, unsigned size, Value* v);
|
||||
|
||||
void
|
||||
ignore(Context* c, unsigned count)
|
||||
{
|
||||
if (count) {
|
||||
Assembler::Register stack(c->assembler->stack());
|
||||
Assembler::Constant offset(resolved(c, count * BytesPerWord));
|
||||
c->assembler->apply
|
||||
(Add, BytesPerWord, ConstantOperand, &offset, RegisterOperand, &stack);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
cleanStack(Context* c, Stack* stack, Local* locals, Read* reads)
|
||||
{
|
||||
@ -1531,12 +1555,11 @@ class ReturnEvent: public Event {
|
||||
nextRead(c, value);
|
||||
}
|
||||
|
||||
Assembler::Register base(c->assembler->base());
|
||||
Assembler::Register stack(c->assembler->stack());
|
||||
Assembler::Register frame(c->assembler->frame());
|
||||
Assembler::Memory oldFrame(c->assembler->frame(), 0);
|
||||
|
||||
c->assembler->apply(Move, BytesPerWord, RegisterOperand, &base,
|
||||
RegisterOperand, &stack);
|
||||
c->assembler->apply(Pop, BytesPerWord, RegisterOperand, &base);
|
||||
c->assembler->apply(Move, BytesPerWord, MemoryOperand, &oldFrame,
|
||||
BytesPerWord, RegisterOperand, &frame);
|
||||
c->assembler->apply(Return);
|
||||
}
|
||||
|
||||
@ -1555,9 +1578,11 @@ appendReturn(Context* c, unsigned size, Value* value)
|
||||
|
||||
class MoveEvent: public Event {
|
||||
public:
|
||||
MoveEvent(Context* c, BinaryOperation type, unsigned size, Value* src,
|
||||
Value* dst, Site* srcTarget, VirtualSite* dstTarget):
|
||||
Event(c), type(type), size(size), src(src), dst(dst), dstTarget(dstTarget)
|
||||
MoveEvent(Context* c, BinaryOperation type, unsigned srcSize, Value* src,
|
||||
unsigned dstSize, Value* dst, Site* srcTarget,
|
||||
VirtualSite* dstTarget):
|
||||
Event(c), type(type), srcSize(srcSize), src(src), dstSize(dstSize),
|
||||
dst(dst), dstTarget(dstTarget)
|
||||
{
|
||||
addRead(c, src, size, srcTarget);
|
||||
}
|
||||
@ -1583,25 +1608,25 @@ class MoveEvent: public Event {
|
||||
}
|
||||
|
||||
if (not isStore) {
|
||||
addSite(c, stack, locals, size, dst, target);
|
||||
addSite(c, stack, locals, dstSize, dst, target);
|
||||
}
|
||||
|
||||
if (cost or type != Move) {
|
||||
if (match(c, target, dstTarget->typeMask, dstTarget->registerMask)) {
|
||||
apply(c, type, size, src->source, target);
|
||||
apply(c, type, srcSize, src->source, dstSize, target);
|
||||
} else {
|
||||
assert(c, dstTarget->typeMask & (1 << RegisterOperand));
|
||||
|
||||
Site* tmpTarget = freeRegisterSite(c, dstTarget->registerMask);
|
||||
|
||||
addSite(c, stack, locals, size, dst, tmpTarget);
|
||||
addSite(c, stack, locals, dstSize, dst, tmpTarget);
|
||||
|
||||
apply(c, type, size, src->source, tmpTarget);
|
||||
apply(c, type, srcSize, src->source, dstSize, tmpTarget);
|
||||
|
||||
if (isStore) {
|
||||
removeSite(c, dst, tmpTarget);
|
||||
|
||||
apply(c, Move, size, tmpTarget, target);
|
||||
apply(c, Move, dstSize, tmpTarget, dstSize, target);
|
||||
} else {
|
||||
removeSite(c, dst, target);
|
||||
}
|
||||
@ -1616,8 +1641,9 @@ class MoveEvent: public Event {
|
||||
}
|
||||
|
||||
BinaryOperation type;
|
||||
unsigned size;
|
||||
unsigned srcSize;
|
||||
Value* src;
|
||||
unsigned dstSize;
|
||||
Value* dst;
|
||||
VirtualSite* dstTarget;
|
||||
};
|
||||
@ -1688,7 +1714,7 @@ class CompareEvent: public Event {
|
||||
} else {
|
||||
c->constantCompare = CompareNone;
|
||||
|
||||
apply(c, Compare, size, first->source, second->source);
|
||||
apply(c, Compare, size, first->source, size, second->source);
|
||||
}
|
||||
|
||||
nextRead(c, first);
|
||||
@ -1730,7 +1756,7 @@ preserve(Context* c, Stack* stack, unsigned size, Value* v, Site* s,
|
||||
Site* r = targetOrNull(c, read);
|
||||
if (r == 0 or r == s) r = freeRegisterSite(c);
|
||||
addSite(c, stack, locals, size, v, r);
|
||||
apply(c, Move, size, s, r);
|
||||
apply(c, Move, size, s, size, r);
|
||||
}
|
||||
|
||||
void
|
||||
@ -1743,30 +1769,17 @@ maybePreserve(Context* c, Stack* stack, unsigned size, Value* v, Site* s)
|
||||
|
||||
class CombineEvent: public Event {
|
||||
public:
|
||||
CombineEvent(Context* c, BinaryOperation type, unsigned size, Value* first,
|
||||
Value* second, Value* result, Site* firstTarget,
|
||||
Site* secondTarget):
|
||||
Event(c), type(type), size(size), first(first), second(second),
|
||||
CombineEvent(Context* c, TernaryOperation type,
|
||||
unsigned firstSize, Value* first,
|
||||
unsigned secondSize, Value* second,
|
||||
unsigned resultSize, Value* result,
|
||||
Site* firstTarget, Site* secondTarget):
|
||||
Event(c), type(type), firstSize(firstSize), first(first),
|
||||
secondSize(secondSize), second(second), resultSize(resultSize),
|
||||
result(result)
|
||||
{
|
||||
// todo: we should really specify the sizes of each operand
|
||||
// seperately for binary operations. The following is a hack
|
||||
// until then.
|
||||
unsigned firstSize;
|
||||
switch (type) {
|
||||
case ShiftLeft:
|
||||
case ShiftRight:
|
||||
case UnsignedShiftRight:
|
||||
firstSize = 4;
|
||||
break;
|
||||
|
||||
default:
|
||||
firstSize = size;
|
||||
break;
|
||||
}
|
||||
|
||||
addRead(c, first, firstSize, firstTarget);
|
||||
addRead(c, second, size, secondTarget);
|
||||
addRead(c, second, secondSize, secondTarget);
|
||||
}
|
||||
|
||||
virtual void compile(Context* c) {
|
||||
@ -1774,23 +1787,26 @@ class CombineEvent: public Event {
|
||||
fprintf(stderr, "CombineEvent.compile\n");
|
||||
}
|
||||
|
||||
maybePreserve(c, stack, size, second, second->source);
|
||||
maybePreserve(c, stack, secondSize, second, second->source);
|
||||
|
||||
apply(c, type, size, first->source, second->source);
|
||||
Site* target = targetOrRegister(c, result);
|
||||
apply(c, type, firstSize, first->source, secondSize, second->source,
|
||||
resultSize, target);
|
||||
|
||||
nextRead(c, first);
|
||||
nextRead(c, second);
|
||||
|
||||
removeSite(c, second, second->source);
|
||||
if (live(result)) {
|
||||
addSite(c, 0, 0, size, result, second->source);
|
||||
if (live(target)) {
|
||||
addSite(c, 0, 0, resultSize, result, target);
|
||||
}
|
||||
}
|
||||
|
||||
BinaryOperation type;
|
||||
unsigned size;
|
||||
unsigned firstSize;
|
||||
Value* first;
|
||||
unsigned secondSize;
|
||||
Value* second;
|
||||
unsigned resultSize;
|
||||
Value* result;
|
||||
};
|
||||
|
||||
@ -2340,122 +2356,210 @@ propagateJunctionSites(Context* c, Event* e, Site** sites)
|
||||
}
|
||||
|
||||
void
|
||||
frameCount(Context* c, Stack* s)
|
||||
{
|
||||
return c->localCount + s->index + footprint(s);
|
||||
}
|
||||
|
||||
void
|
||||
populateSiteTables(Context* c, Event* e)
|
||||
{
|
||||
Event* successor = static_cast<Event*>(e->successors->value);
|
||||
|
||||
unsigned frameCount = ::frameCount(c, successor->stack);
|
||||
|
||||
{ Site* frozenSites[frameCount];
|
||||
unsigned frozenSiteIndex = 0;
|
||||
|
||||
if (e->junctionSites) {
|
||||
for (unsigned i = 0; i < frameCount; ++i) {
|
||||
Site* site = e->junctionSites[i];
|
||||
if (site) {
|
||||
frozenSites[frozenSiteIndex++] = site;
|
||||
site->freeze(c);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (Cell* sc = e->successors; sc; sc = sc->next) {
|
||||
Event* s = static_cast<Event*>(sc->value);
|
||||
if (s->predecessors->next) {
|
||||
unsigned size = sizeof(Site*) * frameCount;
|
||||
Site** junctionSites = static_cast<Site**>
|
||||
(c->zone->allocate(size));
|
||||
memset(junctionSites, 0, size);
|
||||
|
||||
propagateJunctionSites(c, s, junctionSites);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (e->junctionSites) {
|
||||
Event* s = e->next;
|
||||
for (unsigned i = 0; i < c->localCount; ++i) {
|
||||
frozenSiteIndex = resolveJunctionSite
|
||||
(c, e, s, s->locals[i], i, frozenSites, frozenSiteIndex);
|
||||
}
|
||||
|
||||
unsigned i = s->stack->index + c->localCount;
|
||||
for (Stack* stack = s->stack; stack; stack = stack->next) {
|
||||
frozenSiteIndex = resolveJunctionSite
|
||||
(c, e, s, stack->value, i, frozenSites, frozenSiteIndex);
|
||||
|
||||
i -= footprint(stack);
|
||||
}
|
||||
}
|
||||
|
||||
while (frozenSiteIndex) {
|
||||
frozenSites[--frozenSiteIndex]->thaw(c);
|
||||
}
|
||||
}
|
||||
|
||||
if (e->successors->next) {
|
||||
unsigned size = sizeof(Site*) * frameCount;
|
||||
Site** savedSites = static_cast<Site**>(c->zone->allocate(size));
|
||||
|
||||
for (unsigned i = 0; i < c->localCount; ++i) {
|
||||
savedSites = successor->locals[i]->sites;
|
||||
}
|
||||
|
||||
unsigned i = successor->stack->index + c->localCount;
|
||||
for (Stack* stack = successor->stack; stack; stack = stack->next) {
|
||||
savedSites = stack->value->sites;
|
||||
|
||||
i -= footprint(stack);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
setSites(Context* c, Event* e, Site** sites)
|
||||
{
|
||||
for (unsigned i = 0; i < c->localCount; ++i) {
|
||||
Value* v = e->locals[i];
|
||||
clearSites(c, v);
|
||||
addSites(c, v, sites);
|
||||
}
|
||||
|
||||
unsigned i = e->stack->index + c->localCount;
|
||||
for (Stack* stack = e->stack; stack; stack = stack->next) {
|
||||
Value* v = stack->value;
|
||||
clearSites(c, v);
|
||||
addSites(c, v, sites);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
populateSources(Context* c, Event* e)
|
||||
{
|
||||
Site* frozenSites[e->readCount];
|
||||
unsigned frozenSiteIndex = 0;
|
||||
for (Read* r = e->reads; r; r = r->eventNext) {
|
||||
r->value->source = readSource(c, e->stack, e->locals, r);
|
||||
|
||||
if (r->value->source) {
|
||||
assert(c, frozenSiteIndex < e->readCount);
|
||||
frozenSites[frozenSiteIndex++] = r->value->source;
|
||||
r->value->source->freeze(c);
|
||||
}
|
||||
}
|
||||
|
||||
while (frozenSiteIndex) {
|
||||
frozenSites[--frozenSiteIndex]->thaw(c);
|
||||
}
|
||||
}
|
||||
|
||||
LogicalInstruction*
|
||||
next(Context* c, LogicalInstruction* i)
|
||||
{
|
||||
for (unsigned n = i->index + 1; n < c->logicalCodeLength; ++n) {
|
||||
i = c->logicalCode[n];
|
||||
if (i) return i;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
class Block {
|
||||
public:
|
||||
Block(Event* head):
|
||||
head(head), nextInstruction(0), offset(0), start(0)
|
||||
{ }
|
||||
|
||||
Event* head;
|
||||
LogicalInstruction* nextInstruction;
|
||||
Assembler::Offset* offset;
|
||||
unsigned start;
|
||||
};
|
||||
|
||||
Block*
|
||||
block(Context* c, Event* head)
|
||||
{
|
||||
return new (c->zone->allocate(sizeof(Block))) Block(head);
|
||||
}
|
||||
|
||||
unsigned
|
||||
compile(Context* c)
|
||||
{
|
||||
Assembler* a = c->assembler;
|
||||
|
||||
c->pass = CompilePass;
|
||||
|
||||
Assembler::Register base(a->base());
|
||||
Assembler::Register stack(a->stack());
|
||||
a->apply(Push, BytesPerWord, RegisterOperand, &base);
|
||||
a->apply(Move, BytesPerWord, RegisterOperand, &stack,
|
||||
RegisterOperand, &base);
|
||||
Block* firstBlock = block(c, c->firstEvent);
|
||||
Block* block = firstBlock;
|
||||
|
||||
if (stackOffset(c)) {
|
||||
Assembler::Constant offset(resolved(c, stackOffset(c) * BytesPerWord));
|
||||
a->apply(Subtract, BytesPerWord, ConstantOperand, &offset,
|
||||
RegisterOperand, &stack);
|
||||
}
|
||||
Assembler::Constant offset(resolved(c, alignedFrameSize(c)));
|
||||
a->apply(PushFrame, BytesPerWord, ConstantOperand, &offset);
|
||||
|
||||
for (Event* e = c->firstEvent; e; e = e->next) {
|
||||
e->block = block;
|
||||
|
||||
if (e->predecessors->next) {
|
||||
setSites(e, static_cast<Event*>(e->predecessors->value)->junctionSites);
|
||||
setSites
|
||||
(c, e, static_cast<Event*>(e->predecessors->value)->junctionSites);
|
||||
} else if (e->predecessors->successors->next) {
|
||||
setSites(e, static_cast<Event*>(e->predecessors->value)->savedSites);
|
||||
setSites
|
||||
(c, e, static_cast<Event*>(e->predecessors->value)->savedSites);
|
||||
}
|
||||
|
||||
{ Site* frozenSites[e->readCount];
|
||||
unsigned frozenSiteIndex = 0;
|
||||
for (Read* r = e->reads; r; r = r->eventNext) {
|
||||
r->value->source = readSource(c, e->stack, e->locals, r);
|
||||
populateSources(c, e);
|
||||
|
||||
if (r->value->source) {
|
||||
assert(c, frozenSiteIndex < e->readCount);
|
||||
frozenSites[frozenSiteIndex++] = r->value->source;
|
||||
r->value->source->freeze(c);
|
||||
}
|
||||
}
|
||||
e->compile(c);
|
||||
|
||||
while (frozenSiteIndex) {
|
||||
frozenSites[--frozenSiteIndex]->thaw(c);
|
||||
}
|
||||
}
|
||||
|
||||
e->compilePresync(c);
|
||||
|
||||
unsigned frameCount
|
||||
= c->localCount + s->stack->index + footprint(s->stack);
|
||||
|
||||
{ Site* frozenSites[frameCount];
|
||||
unsigned frozenSiteIndex = 0;
|
||||
|
||||
if (e->junctionSites) {
|
||||
for (unsigned i = 0; i < frameCount; ++i) {
|
||||
Site* site = e->junctionSites[i];
|
||||
if (site) {
|
||||
frozenSites[frozenSiteIndex++] = site;
|
||||
site->freeze(c);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (Cell* sc = e->successors; sc; sc = sc->next) {
|
||||
Event* s = static_cast<Event*>(sc->value);
|
||||
if (s->predecessors->next) {
|
||||
unsigned size = sizeof(Site*) * frameCount;
|
||||
Site** junctionSites = static_cast<Site**>
|
||||
(c->zone->allocate(size));
|
||||
memset(junctionSites, 0, size);
|
||||
|
||||
propagateJunctionSites(c, s, junctionSites);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (e->junctionSites) {
|
||||
Event* s = e->next;
|
||||
for (unsigned i = 0; i < c->localCount; ++i) {
|
||||
frozenSiteIndex = resolveJunctionSite
|
||||
(c, e, s, s->locals[i], i, frozenSites, frozenSiteIndex);
|
||||
}
|
||||
|
||||
unsigned i = s->stack->index + c->localCount;
|
||||
for (Stack* stack = s->stack; stack; stack = stack->next) {
|
||||
frozenSiteIndex = resolveJunctionSite
|
||||
(c, e, s, stack->value, i, frozenSites, frozenSiteIndex);
|
||||
|
||||
i -= footprint(stack);
|
||||
}
|
||||
}
|
||||
|
||||
while (frozenSiteIndex) {
|
||||
frozenSites[--frozenSiteIndex]->thaw(c);
|
||||
}
|
||||
}
|
||||
|
||||
if (e->successors->next) {
|
||||
unsigned size = sizeof(Site*) * frameCount;
|
||||
Site** savedSites = static_cast<Site**>(c->zone->allocate(size));
|
||||
|
||||
for (unsigned i = 0; i < c->localCount; ++i) {
|
||||
savedSites = s->locals[i]->sites;
|
||||
}
|
||||
|
||||
unsigned i = s->stack->index + c->localCount;
|
||||
for (Stack* stack = s->stack; stack; stack = stack->next) {
|
||||
savedSites = stack->value->sites;
|
||||
|
||||
i -= footprint(stack);
|
||||
}
|
||||
if (e->successors) {
|
||||
populateSiteTables(c, e);
|
||||
}
|
||||
|
||||
e->compilePostsync(c);
|
||||
|
||||
|
||||
for (CodePromise* p = e->promises; p; p = p->next) {
|
||||
p->offset = a->offset();
|
||||
}
|
||||
|
||||
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* block = block(c, e->next);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
a->endBlock();
|
||||
|
||||
block->nextInstruction = 0;
|
||||
block->offset = a->offset();
|
||||
|
||||
block = firstBlock;
|
||||
while (block->nextInstruction) {
|
||||
Block* next = block->nextInstruction->firstEvent->block;
|
||||
next->start = block->offset->calculate(block->start);
|
||||
block = next;
|
||||
}
|
||||
|
||||
return block->offset->calculate(block->start);
|
||||
}
|
||||
|
||||
unsigned
|
||||
@ -2486,10 +2590,11 @@ pushState(Context* c)
|
||||
void
|
||||
saveStack(Context* c)
|
||||
{
|
||||
if (c->logicalIp >= 0 and not c->logicalCode[c->logicalIp].stackSaved) {
|
||||
c->logicalCode[c->logicalIp].stackSaved = true;
|
||||
c->logicalCode[c->logicalIp].stack = c->state->stack;
|
||||
c->logicalCode[c->logicalIp].locals = c->locals;
|
||||
if (c->logicalIp >= 0 and not c->logicalCode[c->logicalIp]->stackSaved) {
|
||||
LogicalInstruction* i = c->logicalCode[c->logicalIp];
|
||||
i->stackSaved = true;
|
||||
i->stack = c->state->stack;
|
||||
i->locals = c->locals;
|
||||
|
||||
if (DebugAppend) {
|
||||
unsigned count = 0;
|
||||
@ -2547,7 +2652,7 @@ void
|
||||
updateJunctions(Context* c)
|
||||
{
|
||||
for (Junction* j = c->junctions; j; j = j->next) {
|
||||
LogicalInstruction* i = c->logicalCode + j->logicalIp;
|
||||
LogicalInstruction* i = c->logicalCode[j->logicalIp];
|
||||
LogicalInstruction* p = i->immediatePredecessor;
|
||||
|
||||
p->lastEvent = p->lastEvent->next
|
||||
@ -2561,10 +2666,14 @@ visit(Context* c, unsigned logicalIp)
|
||||
{
|
||||
assert(c, logicalIp < c->logicalCodeLength);
|
||||
|
||||
LogicalInstruction* i = new (c->zone->allocate(sizeof(LogicalInstruction)))
|
||||
LogicalInstruction;
|
||||
|
||||
c->logicalCode[logicalIp] = i;
|
||||
|
||||
if (c->logicalIp >= 0 and (not c->stackReset)) {
|
||||
assert(c, c->logicalCode[logicalIp].immediatePredecessor == 0);
|
||||
c->logicalCode[logicalIp].immediatePredecessor
|
||||
= c->logicalCode + c->logicalIp;
|
||||
assert(c, i->immediatePredecessor == 0);
|
||||
i->immediatePredecessor = c->logicalCode[c->logicalIp];
|
||||
}
|
||||
}
|
||||
|
||||
@ -2635,9 +2744,9 @@ class MyCompiler: public Compiler {
|
||||
c.parameterFootprint = parameterFootprint;
|
||||
c.localFootprint = localFootprint;
|
||||
|
||||
c.logicalCode = static_cast<LogicalInstruction*>
|
||||
(c.zone->allocate(sizeof(LogicalInstruction) * logicalCodeLength));
|
||||
memset(c.logicalCode, 0, sizeof(LogicalInstruction) * logicalCodeLength);
|
||||
c.logicalCode = static_cast<LogicalInstruction**>
|
||||
(c.zone->allocate(sizeof(LogicalInstruction*) * logicalCodeLength));
|
||||
memset(c.logicalCode, 0, sizeof(LogicalInstruction*) * logicalCodeLength);
|
||||
|
||||
c.localTable = static_cast<Local**>
|
||||
(c.zone->allocate(sizeof(Local*) * localFootprint));
|
||||
@ -2649,7 +2758,7 @@ class MyCompiler: public Compiler {
|
||||
|
||||
c.stackReset = false;
|
||||
|
||||
if (c.logicalCode[logicalIp].immediatePredecessor) {
|
||||
if (c.logicalCode[logicalIp]->immediatePredecessor) {
|
||||
c.junctions = new (c.zone->allocate(sizeof(Junction)))
|
||||
Junction(logicalIp, c.junctions);
|
||||
}
|
||||
@ -2739,7 +2848,7 @@ class MyCompiler: public Compiler {
|
||||
}
|
||||
|
||||
Promise* machineIp() {
|
||||
return codePromise(&c, c.logicalCode[c.logicalIp].lastEvent);
|
||||
return codePromise(&c, c.logicalCode[c.logicalIp]->lastEvent);
|
||||
}
|
||||
|
||||
virtual void mark(Operand* label) {
|
||||
@ -3075,8 +3184,7 @@ class MyCompiler: public Compiler {
|
||||
|
||||
virtual unsigned compile() {
|
||||
updateJunctions(&c);
|
||||
::compile(&c);
|
||||
return c.assembler->length();
|
||||
return ::compile(&c);
|
||||
}
|
||||
|
||||
virtual unsigned poolSize() {
|
||||
@ -3085,7 +3193,7 @@ class MyCompiler: public Compiler {
|
||||
|
||||
virtual void writeTo(uint8_t* dst) {
|
||||
c.machineCode = dst;
|
||||
c.assembler->writeTo(dst);
|
||||
c.assembler->writeTo(&c, dst);
|
||||
|
||||
int i = 0;
|
||||
for (ConstantPoolNode* n = c.firstConstant; n; n = n->next) {
|
||||
|
Loading…
Reference in New Issue
Block a user