use stack instead of registers to save data across jumps and branches; bugfixes

This commit is contained in:
Joel Dice 2008-04-26 14:56:03 -06:00
parent 571bffde09
commit d5137a7cdf
4 changed files with 204 additions and 167 deletions

View File

@ -751,7 +751,7 @@ class Frame {
void pushLongQuiet(Compiler::Operand* o) {
if (BytesPerWord == 8) {
c->pushed(1);
c->push(8);
}
c->push(8, o);
}
@ -774,7 +774,7 @@ class Frame {
Compiler::Operand* popLongQuiet() {
Compiler::Operand* r = c->pop(8);
if (BytesPerWord == 8) {
c->popped(1);
c->pop(8);
}
return r;
}
@ -1364,16 +1364,28 @@ longToFloat(int64_t a)
}
object FORCE_ALIGN
makeBlankObjectArray(Thread* t, object class_, int32_t length)
makeBlankObjectArray(MyThread* t, object class_, int32_t length)
{
return makeObjectArray(t, class_, length, true);
if (length >= 0) {
return makeObjectArray(t, class_, length, true);
} else {
object message = makeString(t, "%d", length);
t->exception = makeNegativeArraySizeException(t, message);
unwind(t);
}
}
object FORCE_ALIGN
makeBlankArray(Thread* t, object (*constructor)(Thread*, uintptr_t, bool),
makeBlankArray(MyThread* t, object (*constructor)(Thread*, uintptr_t, bool),
int32_t length)
{
return constructor(t, length, true);
if (length >= 0) {
return constructor(t, length, true);
} else {
object message = makeString(t, "%d", length);
t->exception = makeNegativeArraySizeException(t, message);
unwind(t);
}
}
uintptr_t
@ -1478,14 +1490,6 @@ throwArrayIndexOutOfBounds(MyThread* t, object array, int32_t index)
unwind(t);
}
void NO_RETURN FORCE_ALIGN
throwNegativeArraySize(MyThread* t, int32_t length)
{
object message = makeString(t, "%d", length);
t->exception = makeArrayIndexOutOfBoundsException(t, message);
unwind(t);
}
void NO_RETURN FORCE_ALIGN
throw_(MyThread* t, object o)
{
@ -2008,30 +2012,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
object class_ = resolveClassInPool(t, codePool(t, code), index - 1);
if (UNLIKELY(t->exception)) return;
Compiler::Operand* length = c->peek(4, 0);
if (c->isConstant(length)) {
expect(t, c->constantValue(length) >= 0);
} else{
Compiler::Operand* nonnegative = c->label();
c->cmp(4, c->constant(0), length);
c->jge(nonnegative);
length = c->peek(4, 0);
c->call
(c->constant(reinterpret_cast<intptr_t>(throwNegativeArraySize)),
context->indirection,
Compiler::NoReturn,
frame->trace(0, false),
0,
2, c->thread(), length);
c->mark(nonnegative);
}
length = frame->popInt();
Compiler::Operand* length = frame->popInt();
frame->pushObject
(c->call
@ -3197,30 +3178,7 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
case newarray: {
uint8_t type = codeBody(t, code, ip++);
Compiler::Operand* length = c->peek(4, 0);
if (c->isConstant(length)) {
expect(t, c->constantValue(length) >= 0);
} else{
Compiler::Operand* nonnegative = c->label();
c->cmp(4, c->constant(0), length);
c->jge(nonnegative);
length = c->peek(4, 0);
c->call
(c->constant(reinterpret_cast<intptr_t>(throwNegativeArraySize)),
context->indirection,
Compiler::NoReturn,
frame->trace(0, false),
0,
2, c->thread(), length);
c->mark(nonnegative);
}
length = frame->popInt();
Compiler::Operand* length = frame->popInt();
object (*constructor)(Thread*, uintptr_t, bool);
switch (type) {
@ -3870,11 +3828,11 @@ finish(MyThread* t, Context* context)
strcmp
(reinterpret_cast<const char*>
(&byteArrayBody(t, className(t, methodClass(t, context->method)), 0)),
"Enums") == 0 and
"java/lang/StringBuilder") == 0 and
strcmp
(reinterpret_cast<const char*>
(&byteArrayBody(t, methodName(t, context->method), 0)),
"main") == 0)
"<init>") == 0)
{
asm("int3");
}

View File

@ -17,8 +17,8 @@ namespace {
const bool DebugAppend = true;
const bool DebugCompile = true;
const bool DebugStack = false;
const bool DebugRegisters = false;
const bool DebugStack = true;
const bool DebugRegisters = true;
class Context;
class Value;
@ -61,7 +61,7 @@ class Stack {
public:
Stack(Value* value, unsigned size, unsigned index, Stack* next):
value(value), size(size), index(index), next(next), pushEvent(0),
pushSite(0), syncSite(0), pushed(false)
pushSite(0), pushed(false)
{ }
Value* value;
@ -70,7 +70,6 @@ class Stack {
Stack* next;
PushEvent* pushEvent;
Site* pushSite;
Site* syncSite;
bool pushed;
};
@ -141,8 +140,8 @@ class Read {
class Value: public Compiler::Operand {
public:
Value(Site* site):
reads(0), lastRead(0), sites(site), source(0), target(site)
Value(Site* site, Site* target):
reads(0), lastRead(0), sites(site), source(0), target(target)
{ }
Read* reads;
@ -330,8 +329,6 @@ class Event {
virtual ~Event() { }
virtual void prepare(Context*) { }
virtual void compile(Context* c) = 0;
virtual bool isBranch() { return false; };
@ -773,6 +770,14 @@ pick(Context* c, Site* sites, Site* target = 0, unsigned* cost = 0)
return site;
}
Site*
pushSite(Context* c, unsigned index)
{
return memorySite
(c, c->assembler->base(),
- (c->stackOffset + index + 1) * BytesPerWord, NoRegister, 1);
}
void
pushNow(Context* c, Stack* start, unsigned count)
{
@ -787,11 +792,12 @@ pushNow(Context* c, Stack* start, unsigned count)
assert(c, not s->pushed);
if (s->value and s->value->sites) {
apply(c, Push, s->size * BytesPerWord, pick(c, s->value->sites));
s->pushSite = memorySite
(c, c->assembler->base(),
- (c->stackOffset + s->index + 1) * BytesPerWord, NoRegister, 1);
Site* source = pick(c, s->value->sites);
s->pushSite = pushSite(c, s->index);
addSite(c, 0, s->size * BytesPerWord, s->value, s->pushSite);
apply(c, Push, s->size * BytesPerWord, source);
} else {
Assembler::Register stack(c->assembler->stack());
Assembler::Constant offset(resolved(c, s->size * BytesPerWord));
@ -959,7 +965,7 @@ class PushEvent: public Event {
virtual void compile(Context* c) {
if (DebugCompile) {
fprintf(stderr, "PushEvent.compile\n");
fprintf(stderr, "PushEvent.compile active: %d\n", active);
}
if (active) {
@ -1161,17 +1167,17 @@ class MoveEvent: public Event {
}
Site* target;
unsigned cost;
if (type == Move
and size >= BytesPerWord
and dst->reads
and next == dst->reads->event)
{
target = src->source;
cost = 0;
} else {
target = targetOrRegister(c, size, dst, this);
if (src->source->copyCost(c, target)) {
apply(c, type, size, src->source, target);
}
cost = src->source->copyCost(c, target);
}
nextRead(c, src);
@ -1181,6 +1187,10 @@ class MoveEvent: public Event {
} else {
removeSite(c, dst, target);
}
if (cost) {
apply(c, type, size, src->source, target);
}
}
BinaryOperation type;
@ -1390,16 +1400,6 @@ appendMemory(Context* c, Value* base, int displacement, Value* index,
MemoryEvent(c, base, displacement, index, scale, result);
}
Site*
stackSyncSite(Context* c, unsigned index, unsigned size)
{
assert(c, index + size <= c->freeRegisterCount);
return registerSite
(c, c->freeRegisters[index],
size == 2 ? c->freeRegisters[index + 1] : NoRegister);
}
Stack*
stack(Context* c, Value* value, unsigned size, unsigned index, Stack* next)
{
@ -1408,9 +1408,9 @@ stack(Context* c, Value* value, unsigned size, unsigned index, Stack* next)
}
Value*
value(Context* c, Site* site = 0)
value(Context* c, Site* site = 0, Site* target = 0)
{
return new (c->zone->allocate(sizeof(Value))) Value(site);
return new (c->zone->allocate(sizeof(Value))) Value(site, target);
}
void
@ -1419,8 +1419,9 @@ resetStack(Context* c)
unsigned i = 0;
Stack* p = 0;
for (Stack* s = c->state->stack; s; s = s->next) {
Stack* n = stack
(c, value(c, stackSyncSite(c, i, s->size)), s->size, s->index, 0);
Stack* n = stack(c, value(c), s->size, s->index, 0);
n->value->sites = n->pushSite = pushSite(c, s->index);
n->pushed = true;
if (p) {
p->next = n;
@ -1453,9 +1454,9 @@ popNow(Context* c, Event* event, Stack* stack, unsigned count, bool ignore)
s, s->value, target);
}
apply(c, Pop, BytesPerWord * s->size, target);
addSite(c, stack, s->size * BytesPerWord, s->value, target);
apply(c, Pop, BytesPerWord * s->size, target);
} else {
if (DebugStack) {
fprintf(stderr, "ignore %p value: %p\n", s, s->value);
@ -1485,31 +1486,21 @@ class StackSyncEvent: public Event {
StackSyncEvent(Context* c):
Event(c)
{
unsigned i = 0;
for (Stack* s = stack; s; s = s->next) {
s->syncSite = stackSyncSite(c, i, s->size);
addRead(c, s->value, s->size * BytesPerWord, s->syncSite);
i += s->size;
}
if (s->pushEvent) s->pushEvent->active = true;
addRead(c, s->value, s->size * BytesPerWord, 0);
}
}
StackSyncEvent(Context* c, unsigned sequence, Stack* stack):
Event(c, sequence, stack)
{
unsigned i = 0;
for (Stack* s = stack; s; s = s->next) {
s->syncSite = stackSyncSite(c, i, s->size);
insertRead(c, this, sequence, s->value, s->size * BytesPerWord,
s->syncSite);
if (s->pushEvent) s->pushEvent->active = false;
i += s->size;
if (s->pushEvent) s->pushEvent->active = true;
insertRead(c, this, sequence, s->value, s->size * BytesPerWord, 0);
}
}
virtual void prepare(Context* c) {
popNow(c, this, stack, 0xFFFFFFFF, false);
}
virtual void compile(Context* c) {
if (DebugCompile) {
fprintf(stderr, "StackSyncEvent.compile\n");
@ -1520,7 +1511,9 @@ class StackSyncEvent: public Event {
}
for (Stack* s = stack; s; s = s->next) {
addSite(c, 0, s->size * BytesPerWord, s->value, s->syncSite);
if (s->pushSite) {
addSite(c, 0, s->size * BytesPerWord, s->value, s->pushSite);
}
}
for (Read* r = reads; r; r = r->eventNext) {
@ -1642,23 +1635,23 @@ appendPop(Context* c, unsigned count, bool ignore)
new (c->zone->allocate(sizeof(PopEvent))) PopEvent(c, count, ignore);
}
void
swapRegisters(Context* c, int* ap, int* bp)
{
Assembler::Register a(*ap);
Assembler::Register b(*bp);
// void
// swapRegisters(Context* c, int* ap, int* bp)
// {
// Assembler::Register a(*ap);
// Assembler::Register b(*bp);
c->assembler->apply
(Xor, BytesPerWord, RegisterOperand, &a, RegisterOperand, &b);
c->assembler->apply
(Xor, BytesPerWord, RegisterOperand, &b, RegisterOperand, &a);
c->assembler->apply
(Xor, BytesPerWord, RegisterOperand, &a, RegisterOperand, &b);
// c->assembler->apply
// (Xor, BytesPerWord, RegisterOperand, &a, RegisterOperand, &b);
// c->assembler->apply
// (Xor, BytesPerWord, RegisterOperand, &b, RegisterOperand, &a);
// c->assembler->apply
// (Xor, BytesPerWord, RegisterOperand, &a, RegisterOperand, &b);
int t = *ap;
*ap = *bp;
*bp = t;
}
// int t = *ap;
// *ap = *bp;
// *bp = t;
// }
Site*
readSource(Context* c, Stack* stack, Read* r, Event* e)
@ -1674,29 +1667,30 @@ readSource(Context* c, Stack* stack, Read* r, Event* e)
apply(c, Move, r->size, site, target);
return target;
} else {
// this is a filthy hack, but I think the core idea is right:
abort(c);
// // this is a filthy hack, but I think the core idea is right:
assert(c, target->type(c) == RegisterOperand);
// assert(c, target->type(c) == RegisterOperand);
RegisterSite* ts = static_cast<RegisterSite*>(target);
// RegisterSite* ts = static_cast<RegisterSite*>(target);
for (Site* s = r->value->sites; s; s = s->next) {
if (s->type(c) == RegisterOperand) {
RegisterSite* rs = static_cast<RegisterSite*>(s);
// for (Site* s = r->value->sites; s; s = s->next) {
// if (s->type(c) == RegisterOperand) {
// RegisterSite* rs = static_cast<RegisterSite*>(s);
RegisterSite* os = static_cast<RegisterSite*>
(c->registers[ts->register_.low].site);
// RegisterSite* os = static_cast<RegisterSite*>
// (c->registers[ts->register_.low].site);
assert(c, os->register_.low == ts->register_.low);
assert(c, os->register_.high == NoRegister);
assert(c, ts->register_.high == NoRegister);
assert(c, rs->register_.high == NoRegister);
// assert(c, os->register_.low == ts->register_.low);
// assert(c, os->register_.high == NoRegister);
// assert(c, ts->register_.high == NoRegister);
// assert(c, rs->register_.high == NoRegister);
swapRegisters(c, &(os->register_.low), &(rs->register_.low));
// swapRegisters(c, &(os->register_.low), &(rs->register_.low));
return rs;
}
}
// return rs;
// }
// }
}
abort(c);
@ -1736,7 +1730,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);
@ -1748,8 +1742,6 @@ compile(Context* c)
}
}
e->prepare(c);
for (Read* r = e->reads; r; r = r->eventNext) {
r->value->source = readSource(c, e->stack, r, e);
}
@ -1852,14 +1844,12 @@ used(Context* c, int r)
return v and findSite(c, v, c->registers[r].site);
}
// bool
// usedExclusively(Context* c, int r)
// {
// Value* v = c->registers[r].value;
// return used(c, r)
// and v->pushCount == 0
// and v->sites->next == 0;
// }
bool
usedExclusively(Context* c, int r)
{
Value* v = c->registers[r].value;
return used(c, r) and v->sites->next == 0;
}
int
freeRegisterExcept(Context* c, int except, bool allowAcquired)
@ -1873,14 +1863,14 @@ 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;
// }
// }
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) {
@ -2048,15 +2038,18 @@ class MyCompiler: public Compiler {
}
virtual Operand* stack() {
return value(&c, registerSite(&c, c.assembler->stack()));
Site* s = registerSite(&c, c.assembler->stack());
return value(&c, s, s);
}
virtual Operand* base() {
return value(&c, registerSite(&c, c.assembler->base()));
Site* s = registerSite(&c, c.assembler->base());
return value(&c, s, s);
}
virtual Operand* thread() {
return value(&c, registerSite(&c, c.assembler->thread()));
Site* s = registerSite(&c, c.assembler->thread());
return value(&c, s, s);
}
virtual bool isConstant(Operand* a) {
@ -2098,6 +2091,10 @@ class MyCompiler: public Compiler {
abort(&c);
}
virtual void push(unsigned size) {
::push(&c, size, value(&c));
}
virtual void push(unsigned size, Operand* value) {
::push(&c, size, static_cast<Value*>(value));
}

View File

@ -57,6 +57,7 @@ class Compiler {
virtual Operand* label() = 0;
virtual void mark(Operand* label) = 0;
virtual void push(unsigned size) = 0;
virtual void push(unsigned size, Operand* value) = 0;
virtual Operand* pop(unsigned size) = 0;
virtual void pushed(unsigned count) = 0;

View File

@ -35,6 +35,18 @@ enum {
r15 = 15,
};
int64_t FORCE_ALIGN
divideLong(int64_t a, int64_t b)
{
return a / b;
}
int64_t FORCE_ALIGN
moduloLong(int64_t a, int64_t b)
{
return a % b;
}
inline bool
isInt8(intptr_t v)
{
@ -523,6 +535,17 @@ popM(Context* c, unsigned size, Assembler::Memory* a)
}
}
void
negateR(Context* c, unsigned size, Assembler::Register* a)
{
assert(c, BytesPerWord == 8 or size == 4); // todo
rex(c);
c->code.append(0xf7);
c->code.append(0xd8 | a->low);
}
void
leaMR(Context* c, unsigned size, Assembler::Memory* b, Assembler::Register* a)
{
@ -575,13 +598,19 @@ moveRR(Context* c, unsigned size, Assembler::Register* a,
} else {
switch (size) {
case 1:
if (BytesPerWord == 8) {
c->code.append(0x0f);
}
c->code.append(0xbe);
c->code.append(0xc0 | (a->low << 3) | b->low);
c->code.append(0xc0 | (b->low << 3) | a->low);
break;
case 2:
if (BytesPerWord == 8) {
c->code.append(0x0f);
}
c->code.append(0xbf);
c->code.append(0xc0 | (a->low << 3) | b->low);
c->code.append(0xc0 | (b->low << 3) | a->low);
break;
case 8:
@ -863,6 +892,54 @@ addRM(Context* c, unsigned size UNUSED, Assembler::Register* a,
encode(c, 0x01, a->low, b, true);
}
void
divideRR(Context* c, unsigned size, Assembler::Register* a,
Assembler::Register* b)
{
if (BytesPerWord == 4 and size == 8) {
Assembler::Register axdx(c->client->acquireTemporary(rax),
c->client->acquireTemporary(rdx));
pushR(c, size, a);
pushR(c, size, b);
ResolvedPromise addressPromise(reinterpret_cast<intptr_t>(divideLong));
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(c->client->acquireTemporary(rdx));
if (b->low != rax) {
c->client->acquireTemporary(ax.low);
moveRR(c, BytesPerWord, b, &ax);
}
rex(c);
c->code.append(0x99);
rex(c);
c->code.append(0xf7);
c->code.append(0xf8 | a->low);
if (b->low != rax) {
moveRR(c, BytesPerWord, &ax, b);
c->client->releaseTemporary(ax.low);
}
c->client->releaseTemporary(dx.low);
}
}
void
andCR(Context* c, unsigned size UNUSED, Assembler::Constant* a,
Assembler::Register* b)
@ -1065,6 +1142,8 @@ populateTables()
UnaryOperations[INDEX1(Pop, Register)] = CAST1(popR);
UnaryOperations[INDEX1(Pop, Memory)] = CAST1(popM);
UnaryOperations[INDEX1(Negate, Register)] = CAST1(negateR);
BinaryOperations[INDEX2(LoadAddress, Memory, Register)] = CAST2(leaMR);
BinaryOperations[INDEX2(Move, Constant, Register)] = CAST2(moveCR);
@ -1086,6 +1165,8 @@ populateTables()
BinaryOperations[INDEX2(Add, Register, Register)] = CAST2(addRR);
BinaryOperations[INDEX2(Add, Register, Memory)] = CAST2(addRM);
BinaryOperations[INDEX2(Divide, Register, Register)] = CAST2(divideRR);
BinaryOperations[INDEX2(And, Constant, Register)] = CAST2(andCR);
BinaryOperations[INDEX2(And, Constant, Memory)] = CAST2(andCM);