bugfixes involving stack operations

This commit is contained in:
Joel Dice 2008-04-17 21:47:42 -06:00
parent af2c2e019c
commit 329009ae97
2 changed files with 180 additions and 108 deletions

View File

@ -54,8 +54,7 @@ enum OperandType {
ConstantOperand, ConstantOperand,
AddressOperand, AddressOperand,
RegisterOperand, RegisterOperand,
MemoryOperand, MemoryOperand
StackOperand // for compiler use; not used in assembler
}; };
const unsigned OperandTypeCount = MemoryOperand + 1; const unsigned OperandTypeCount = MemoryOperand + 1;

View File

@ -20,6 +20,7 @@ class Value;
class Stack; class Stack;
class Site; class Site;
class Event; class Event;
class PushEvent;
class Read; class Read;
void NO_RETURN abort(Context*); void NO_RETURN abort(Context*);
@ -40,10 +41,6 @@ class Site {
virtual unsigned copyCost(Context*, Site*) = 0; virtual unsigned copyCost(Context*, Site*) = 0;
virtual void accept(Context* c, unsigned size, Site* src) {
apply(c, Move, size, src, this);
}
virtual void acquire(Context*, Stack*, unsigned, Value*, Site*) { } virtual void acquire(Context*, Stack*, unsigned, Value*, Site*) { }
virtual OperandType type(Context*) = 0; virtual OperandType type(Context*) = 0;
@ -56,13 +53,15 @@ class Site {
class Stack { class Stack {
public: public:
Stack(Value* value, unsigned size, unsigned index, Stack* next): Stack(Value* value, unsigned size, unsigned index, Stack* next):
value(value), size(size), index(index), next(next), pushed(false) value(value), size(size), index(index), next(next), pushEvent(0),
pushed(false)
{ } { }
Value* value; Value* value;
unsigned size; unsigned size;
unsigned index; unsigned index;
Stack* next; Stack* next;
PushEvent* pushEvent;
bool pushed; bool pushed;
}; };
@ -131,13 +130,14 @@ class Read {
class Value: public Compiler::Operand { class Value: public Compiler::Operand {
public: public:
Value(Site* site): Value(Site* site):
reads(0), lastRead(0), sites(site), source(0) reads(0), lastRead(0), sites(site), source(0), pushCount(0)
{ } { }
Read* reads; Read* reads;
Read* lastRead; Read* lastRead;
Site* sites; Site* sites;
Site* source; Site* source;
unsigned pushCount;
}; };
class Context { class Context {
@ -429,35 +429,6 @@ anyRegisterSite(Context* c)
return new (c->zone->allocate(sizeof(AnyRegisterSite))) AnyRegisterSite(); return new (c->zone->allocate(sizeof(AnyRegisterSite))) AnyRegisterSite();
} }
class StackSite: public Site {
public:
StackSite(Stack* stack): stack(stack) { }
virtual unsigned copyCost(Context*, Site*) {
return 5;
}
virtual void accept(Context* c, unsigned size, Site* src) {
apply(c, Push, size, src);
}
virtual OperandType type(Context*) {
return StackOperand;
}
virtual Assembler::Operand* asAssemblerOperand(Context* c) {
abort(c);
}
Stack* stack;
};
StackSite*
stackSite(Context* c, Stack* s)
{
return new (c->zone->allocate(sizeof(StackSite))) StackSite(s);
}
inline void NO_RETURN inline void NO_RETURN
abort(Context* c) abort(Context* c)
{ {
@ -502,7 +473,7 @@ pick(Context* c, Site* sites, Site* target = 0, unsigned* cost = 0)
} }
void void
stackSync(Context* c, Stack* start, unsigned count) syncStack(Context* c, Stack* start, unsigned count)
{ {
Stack* segment[count]; Stack* segment[count];
unsigned index = count; unsigned index = count;
@ -512,13 +483,11 @@ stackSync(Context* c, Stack* start, unsigned count)
for (unsigned i = 0; i < count; ++i) { for (unsigned i = 0; i < count; ++i) {
Stack* s = segment[i]; Stack* s = segment[i];
assert(c, not s->pushed);
if (s->value) { if (s->value) {
apply(c, Push, s->size * BytesPerWord, pick(c, s->value->sites)); apply(c, Push, s->size * BytesPerWord, pick(c, s->value->sites));
++ s->value->pushCount;
StackSite* site = stackSite(c, s);
site->next = s->value->sites;
s->value->sites = site;
} else { } else {
Assembler::Register stack(c->assembler->stack()); Assembler::Register stack(c->assembler->stack());
Assembler::Constant offset(resolved(c, s->size * BytesPerWord)); Assembler::Constant offset(resolved(c, s->size * BytesPerWord));
@ -527,20 +496,36 @@ stackSync(Context* c, Stack* start, unsigned count)
RegisterOperand, &stack); RegisterOperand, &stack);
} }
fprintf(stderr, "pushed %p\n", s);
s->pushed = true; s->pushed = true;
} }
} }
void
syncStack(Context* c, Stack* start)
{
unsigned count = 0;
for (Stack* s = start; s and (not s->pushed); s = s->next) {
++ count;
}
syncStack(c, start, count);
}
void void
acquire(Context* c, int r, Stack* stack, unsigned newSize, Value* newValue, acquire(Context* c, int r, Stack* stack, unsigned newSize, Value* newValue,
Site* newSite) Site* newSite)
{ {
Value* oldValue = c->registers[r].value; Value* oldValue = c->registers[r].value;
if (oldValue and findSite(c, oldValue, c->registers[r].site)) { if (oldValue and findSite(c, oldValue, c->registers[r].site)) {
if (oldValue->sites->next == 0 and oldValue->reads) { if (oldValue->pushCount == 0
and oldValue->sites->next == 0
and oldValue->reads)
{
unsigned count = 0; unsigned count = 0;
Stack* start = 0; Stack* start = 0;
for (Stack* s = stack; s and not s->pushed; s = s->next) { for (Stack* s = stack; s and (not s->pushed); s = s->next) {
if (s->value == oldValue) { if (s->value == oldValue) {
start = s; start = s;
} }
@ -551,7 +536,7 @@ acquire(Context* c, int r, Stack* stack, unsigned newSize, Value* newValue,
assert(c, start); assert(c, start);
stackSync(c, start, count); syncStack(c, start, count);
} }
removeSite(c, oldValue, c->registers[r].site); removeSite(c, oldValue, c->registers[r].site);
@ -729,40 +714,18 @@ push(Context* c, unsigned size, Value* v);
class CallEvent: public Event { class CallEvent: public Event {
public: public:
CallEvent(Context* c, Value* address, void* indirection, unsigned flags, CallEvent(Context* c, Value* address, void* indirection, unsigned flags,
TraceHandler* traceHandler, Value* result, unsigned, TraceHandler* traceHandler, Value* result,
Value** arguments, unsigned* argumentSizes, unsigned argumentFootprint):
unsigned argumentCount):
Event(c), Event(c),
address(address), address(address),
indirection(indirection), indirection(indirection),
traceHandler(traceHandler), traceHandler(traceHandler),
result(result), result(result),
flags(flags), flags(flags),
footprint(0) argumentFootprint(argumentFootprint)
{ {
addRead(c, address, BytesPerWord, addRead(c, address, BytesPerWord,
(indirection ? registerSite(c, c->assembler->returnLow()) : 0)); (indirection ? registerSite(c, c->assembler->returnLow()) : 0));
for (int i = argumentCount - 1; i >= 0; --i) {
::push(c, argumentSizes[i], arguments[i]);
}
unsigned index = 0;
Stack* s = c->state->stack;
for (unsigned i = 0; i < argumentCount; ++i) {
Site* target;
if (index < c->assembler->argumentRegisterCount()) {
target = registerSite(c, c->assembler->argumentRegister(index));
} else {
target = stackSite(c, s);
footprint += s->size;
}
addRead(c, s->value, s->size * BytesPerWord, target);
index += s->size;
s = s->next;
}
c->state->stack = stack;
} }
virtual void compile(Context* c) { virtual void compile(Context* c) {
@ -785,9 +748,10 @@ class CallEvent: public Event {
CodePromise(c, c->assembler->length())); CodePromise(c, c->assembler->length()));
} }
if (footprint) { if (argumentFootprint) {
Assembler::Register stack(c->assembler->stack()); Assembler::Register stack(c->assembler->stack());
Assembler::Constant offset(resolved(c, footprint * BytesPerWord)); Assembler::Constant offset
(resolved(c, argumentFootprint * BytesPerWord));
c->assembler->apply c->assembler->apply
(Add, BytesPerWord, ConstantOperand, &offset, RegisterOperand, &stack); (Add, BytesPerWord, ConstantOperand, &offset, RegisterOperand, &stack);
} }
@ -798,17 +762,19 @@ class CallEvent: public Event {
TraceHandler* traceHandler; TraceHandler* traceHandler;
Value* result; Value* result;
unsigned flags; unsigned flags;
unsigned footprint; unsigned argumentFootprint;
}; };
void void
appendCall(Context* c, Value* address, void* indirection, unsigned flags, appendCall(Context* c, Value* address, void* indirection, unsigned flags,
TraceHandler* traceHandler, Value* result, unsigned resultSize, TraceHandler* traceHandler, Value* result,
Value** arguments, unsigned* argumentSizes, unsigned argumentCount) unsigned argumentFootprint)
{ {
fprintf(stderr, "appendCall\n");
new (c->zone->allocate(sizeof(CallEvent))) new (c->zone->allocate(sizeof(CallEvent)))
CallEvent(c, address, indirection, flags, traceHandler, result, CallEvent(c, address, indirection, flags, traceHandler, result,
resultSize, arguments, argumentSizes, argumentCount); argumentFootprint);
} }
class ReturnEvent: public Event { class ReturnEvent: public Event {
@ -842,6 +808,8 @@ class ReturnEvent: public Event {
void void
appendReturn(Context* c, unsigned size, Value* value) appendReturn(Context* c, unsigned size, Value* value)
{ {
fprintf(stderr, "appendReturn\n");
new (c->zone->allocate(sizeof(ReturnEvent))) ReturnEvent(c, size, value); new (c->zone->allocate(sizeof(ReturnEvent))) ReturnEvent(c, size, value);
} }
@ -885,6 +853,8 @@ void
appendMove(Context* c, BinaryOperation type, unsigned size, Value* src, appendMove(Context* c, BinaryOperation type, unsigned size, Value* src,
Value* dst) Value* dst)
{ {
fprintf(stderr, "appendMove\n");
new (c->zone->allocate(sizeof(MoveEvent))) new (c->zone->allocate(sizeof(MoveEvent)))
MoveEvent(c, type, size, src, dst); MoveEvent(c, type, size, src, dst);
} }
@ -913,6 +883,8 @@ class CompareEvent: public Event {
void void
appendCompare(Context* c, unsigned size, Value* first, Value* second) appendCompare(Context* c, unsigned size, Value* first, Value* second)
{ {
fprintf(stderr, "appendCompare\n");
new (c->zone->allocate(sizeof(CompareEvent))) new (c->zone->allocate(sizeof(CompareEvent)))
CompareEvent(c, size, first, second); CompareEvent(c, size, first, second);
} }
@ -938,6 +910,8 @@ class BranchEvent: public Event {
void void
appendBranch(Context* c, UnaryOperation type, Value* address) appendBranch(Context* c, UnaryOperation type, Value* address)
{ {
fprintf(stderr, "appendBranch\n");
new (c->zone->allocate(sizeof(BranchEvent))) BranchEvent(c, type, address); new (c->zone->allocate(sizeof(BranchEvent))) BranchEvent(c, type, address);
} }
@ -979,6 +953,8 @@ void
appendCombine(Context* c, BinaryOperation type, unsigned size, Value* first, appendCombine(Context* c, BinaryOperation type, unsigned size, Value* first,
Value* second, Value* result) Value* second, Value* result)
{ {
fprintf(stderr, "appendCombine\n");
new (c->zone->allocate(sizeof(CombineEvent))) new (c->zone->allocate(sizeof(CombineEvent)))
CombineEvent(c, type, size, first, second, result); CombineEvent(c, type, size, first, second, result);
} }
@ -1010,6 +986,8 @@ void
appendTranslate(Context* c, UnaryOperation type, unsigned size, Value* value, appendTranslate(Context* c, UnaryOperation type, unsigned size, Value* value,
Value* result) Value* result)
{ {
fprintf(stderr, "appendTranslate\n");
new (c->zone->allocate(sizeof(TranslateEvent))) new (c->zone->allocate(sizeof(TranslateEvent)))
TranslateEvent(c, type, size, value, result); TranslateEvent(c, type, size, value, result);
} }
@ -1053,6 +1031,8 @@ void
appendMemory(Context* c, Value* base, int displacement, Value* index, appendMemory(Context* c, Value* base, int displacement, Value* index,
unsigned scale, Value* result) unsigned scale, Value* result)
{ {
fprintf(stderr, "appendMemory\n");
new (c->zone->allocate(sizeof(MemoryEvent))) new (c->zone->allocate(sizeof(MemoryEvent)))
MemoryEvent(c, base, displacement, index, scale, result); MemoryEvent(c, base, displacement, index, scale, result);
} }
@ -1081,13 +1061,13 @@ stackSyncSite(Context* c, unsigned index, unsigned size)
class StackSyncEvent: public Event { class StackSyncEvent: public Event {
public: public:
StackSyncEvent(Context* c, bool forCall): StackSyncEvent(Context* c):
Event(c) Event(c)
{ {
unsigned i = 0; unsigned i = 0;
for (Stack* s = stack; s; s = s->next) { for (Stack* s = stack; s; s = s->next) {
addRead(c, s->value, s->size * BytesPerWord, addRead(c, s->value, s->size * BytesPerWord,
forCall ? stackSite(c, s) : stackSyncSite(c, i, s->size)); stackSyncSite(c, i, s->size));
i += s->size; i += s->size;
} }
} }
@ -1114,9 +1094,97 @@ class StackSyncEvent: public Event {
}; };
void void
appendStackSync(Context* c, bool forCall = false) appendStackSync(Context* c)
{ {
new (c->zone->allocate(sizeof(StackSyncEvent))) StackSyncEvent(c, forCall); fprintf(stderr, "appendStackSync\n");
new (c->zone->allocate(sizeof(StackSyncEvent))) StackSyncEvent(c);
}
class PushEvent: public Event {
public:
PushEvent(Context* c):
Event(c), active(false)
{
stack->pushEvent = this;
}
virtual void compile(Context* c) {
fprintf(stderr, "PushEvent.compile\n");
if (active) {
syncStack(c, stack);
}
}
bool active;
};
void
appendPush(Context* c)
{
fprintf(stderr, "appendPush\n");
new (c->zone->allocate(sizeof(PushEvent))) PushEvent(c);
}
class PopEvent: public Event {
public:
PopEvent(Context* c, unsigned count, bool ignore):
Event(c), count(count), ignore(ignore)
{ }
virtual void compile(Context* c) {
fprintf(stderr, "PopEvent.compile\n");
Stack* s = stack;
unsigned ignored = 0;
for (unsigned i = count; i;) {
if (s->pushed) {
if (s->value->reads and (not ignore)) {
assert(c, ignored == 0);
fprintf(stderr, "pop %p\n", s);
Site* target = writeTarget(c, s->size * BytesPerWord, s->value);
apply(c, Pop, BytesPerWord * s->size, target);
-- s->value->pushCount;
addSite(c, stack, s->size * BytesPerWord, s->value, target);
} else {
fprintf(stderr, "ignore %p\n", s);
ignored += s->size;
}
s->pushed = false;
} else {
fprintf(stderr, "%p not pushed\n", s);
}
i -= s->size;
s = s->next;
}
if (ignored) {
Assembler::Register stack(c->assembler->stack());
Assembler::Constant offset(resolved(c, ignored * BytesPerWord));
c->assembler->apply
(Add, BytesPerWord, ConstantOperand, &offset, RegisterOperand, &stack);
}
}
unsigned count;
bool ignore;
};
void
appendPop(Context* c, unsigned count, bool ignore)
{
fprintf(stderr, "appendPop\n");
new (c->zone->allocate(sizeof(PopEvent))) PopEvent(c, count, ignore);
} }
Site* Site*
@ -1127,31 +1195,11 @@ readSource(Context* c, Stack* stack, Read* r)
unsigned copyCost; unsigned copyCost;
Site* site = pick(c, r->value->sites, target, &copyCost); Site* site = pick(c, r->value->sites, target, &copyCost);
if (site->type(c) == StackOperand) {
bool success = false;;
for (Stack* s = stack; s; s = s->next) {
if (s->pushed) {
target = writeTarget(c, s->size * BytesPerWord, s->value);
addSite(c, stack, s->size * BytesPerWord, s->value, target);
s->pushed = false;
if (s == static_cast<StackSite*>(site)->stack) {
site = pick(c, r->value->sites, target, &copyCost);
success = true;
break;
}
}
}
assert(c, success);
}
if (target) { if (target) {
if (copyCost) { if (copyCost) {
addSite(c, stack, r->size, r->value, target); addSite(c, stack, r->size, r->value, target);
target->accept(c, r->size, site); apply(c, Move, r->size, site, target);
} }
return target; return target;
@ -1239,6 +1287,8 @@ push(Context* c, unsigned size, Value* v)
assert(c, ceiling(size, BytesPerWord)); assert(c, ceiling(size, BytesPerWord));
c->state->stack = stack(c, v, ceiling(size, BytesPerWord), c->state->stack); c->state->stack = stack(c, v, ceiling(size, BytesPerWord), c->state->stack);
appendPush(c);
} }
Value* Value*
@ -1247,7 +1297,7 @@ pop(Context* c, unsigned size UNUSED)
Stack* s = c->state->stack; Stack* s = c->state->stack;
assert(c, ceiling(size, BytesPerWord) == s->size); assert(c, ceiling(size, BytesPerWord) == s->size);
//appendPop(c, s->size, false); appendPop(c, s->size, false);
c->state->stack = s->next; c->state->stack = s->next;
return s->value; return s->value;
@ -1485,12 +1535,11 @@ class MyCompiler: public Compiler {
for (unsigned i = 0; i < count; ++i) { for (unsigned i = 0; i < count; ++i) {
Value* a = value(&c); Value* a = value(&c);
::push(&c, BytesPerWord, a); ::push(&c, BytesPerWord, a);
a->sites = stackSite(&c, c.state->stack);
} }
} }
virtual void popped(unsigned count) { virtual void popped(unsigned count) {
// appendPop(&c, count, true); appendPop(&c, count, true);
for (unsigned i = count; i;) { for (unsigned i = count; i;) {
Stack* s = c.state->stack; Stack* s = c.state->stack;
@ -1513,7 +1562,7 @@ class MyCompiler: public Compiler {
void* indirection, void* indirection,
unsigned flags, unsigned flags,
TraceHandler* traceHandler, TraceHandler* traceHandler,
unsigned resultSize, unsigned,
unsigned argumentCount, unsigned argumentCount,
...) ...)
{ {
@ -1539,12 +1588,36 @@ class MyCompiler: public Compiler {
va_end(a); va_end(a);
appendStackSync(&c, true); Stack* oldStack = c.state->stack;
for (int i = index - 1; i >= 0; --i) {
::push(&c, argumentSizes[i], arguments[i]);
}
unsigned ai = 0;
Stack* s = c.state->stack;
for (unsigned i = 0; i < index; ++i) {
Site* target;
if (ai < c.assembler->argumentRegisterCount()) {
target = registerSite(&c, c.assembler->argumentRegister(index));
} else {
target = 0;
s->pushEvent->active = true;
}
addRead(&c, s->value, s->size * BytesPerWord, target);
ai += s->size;
s = s->next;
}
c.state->stack = oldStack;
for (Stack* s = oldStack; s; s = s->next) {
s->pushEvent->active = true;
}
Value* result = value(&c); Value* result = value(&c);
appendCall(&c, static_cast<Value*>(address), indirection, flags, appendCall(&c, static_cast<Value*>(address), indirection, flags,
traceHandler, result, resultSize, arguments, argumentSizes, traceHandler, result, footprint);
index);
return result; return result;
} }