implement jsr/ret support

The Subroutine test won't pass due to a bug in the stack mapping code
such that objects may be missed during GC.
This commit is contained in:
Joel Dice 2008-11-13 17:59:21 -07:00
parent 4dd1d1eec8
commit fb770d10fb
5 changed files with 114 additions and 31 deletions

View File

@ -2839,22 +2839,17 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip,
assert(t, newIp < codeLength(t, code)); assert(t, newIp < codeLength(t, code));
// todo: flush stack to memory here
abort(t);
Compiler::State* state = c->saveState();
frame->pushAddress(frame->machineIp(ip)); frame->pushAddress(frame->machineIp(ip));
c->jmp(frame->machineIp(newIp)); c->jmp(frame->machineIp(newIp));
// NB: we assume that the stack will look the same on return Compiler::Subroutine* sr = c->startSubroutine();
// from the subroutine as at call time.
compile(t, frame, newIp); compile(t, frame, newIp);
if (UNLIKELY(t->exception)) return; if (UNLIKELY(t->exception)) return;
frame->pop(1); frame->poppedInt();
c->restoreState(state); c->endSubroutine(sr);
} break; } break;
case l2d: { case l2d: {

View File

@ -164,11 +164,18 @@ class ForkState: public Compiler::State {
ForkElement elements[0]; ForkElement elements[0];
}; };
class MySubroutine: public Compiler::Subroutine {
public:
MySubroutine(): forkState(0) { }
ForkState* forkState;
};
class LogicalInstruction { class LogicalInstruction {
public: public:
LogicalInstruction(int index, Stack* stack, Local* locals): LogicalInstruction(int index, Stack* stack, Local* locals):
firstEvent(0), lastEvent(0), immediatePredecessor(0), stack(stack), firstEvent(0), lastEvent(0), immediatePredecessor(0), stack(stack),
locals(locals), machineOffset(0), index(index) locals(locals), machineOffset(0), subroutine(0), index(index)
{ } { }
Event* firstEvent; Event* firstEvent;
@ -177,6 +184,7 @@ class LogicalInstruction {
Stack* stack; Stack* stack;
Local* locals; Local* locals;
Promise* machineOffset; Promise* machineOffset;
MySubroutine* subroutine;
int index; int index;
}; };
@ -293,6 +301,7 @@ class Context {
firstEvent(0), firstEvent(0),
lastEvent(0), lastEvent(0),
forkState(0), forkState(0),
subroutine(0),
logicalIp(-1), logicalIp(-1),
constantCount(0), constantCount(0),
logicalCodeLength(0), logicalCodeLength(0),
@ -331,6 +340,7 @@ class Context {
Event* firstEvent; Event* firstEvent;
Event* lastEvent; Event* lastEvent;
ForkState* forkState; ForkState* forkState;
MySubroutine* subroutine;
int logicalIp; int logicalIp;
unsigned constantCount; unsigned constantCount;
unsigned logicalCodeLength; unsigned logicalCodeLength;
@ -3237,7 +3247,9 @@ class FrameSiteEvent: public Event {
} }
virtual void compile(Context* c) { virtual void compile(Context* c) {
addSite(c, stackBefore, localsBefore, size, value, frameSite(c, index)); if (live(value)) {
addSite(c, stackBefore, localsBefore, size, value, frameSite(c, index));
}
} }
Value* value; Value* value;
@ -4005,14 +4017,32 @@ class MyCompiler: public Compiler {
return ::saveState(&c); return ::saveState(&c);
} }
virtual void save(unsigned footprint, Operand* value) {
c.saved = savedValue(&c, static_cast<Value*>(value), footprint, c.saved);
}
virtual void restoreState(State* state) { virtual void restoreState(State* state) {
::restoreState(&c, static_cast<ForkState*>(state)); ::restoreState(&c, static_cast<ForkState*>(state));
} }
virtual Subroutine* startSubroutine() {
return c.subroutine = new (c.zone->allocate(sizeof(MySubroutine)))
MySubroutine;
}
virtual void endSubroutine(Subroutine* subroutine) {
MySubroutine* sr = static_cast<MySubroutine*>(subroutine);
if (sr->forkState) {
fprintf(stderr, "restore sr forkstate\n");
Local* locals = c.locals;
::restoreState(&c, sr->forkState);
for (int i = c.localFootprint - 1; i >= 0; --i) {
if (locals[i].value and c.locals[i].value == 0) {
storeLocal(locals[i].footprint, locals[i].value, i);
}
}
} else {
fprintf(stderr, "save sr forkstate\n");
sr->forkState = ::saveState(&c);
}
}
virtual void init(unsigned logicalCodeLength, unsigned parameterFootprint, virtual void init(unsigned logicalCodeLength, unsigned parameterFootprint,
unsigned localFootprint, unsigned alignedFrameSize) unsigned localFootprint, unsigned alignedFrameSize)
{ {
@ -4075,6 +4105,12 @@ class MyCompiler: public Compiler {
populateJunctionReads(&c, e->predecessors); populateJunctionReads(&c, e->predecessors);
} }
if (c.subroutine) {
c.subroutine->forkState
= c.logicalCode[logicalIp]->subroutine->forkState;
c.subroutine = 0;
}
c.forkState = false; c.forkState = false;
} }
@ -4096,6 +4132,11 @@ class MyCompiler: public Compiler {
(c.zone->allocate(sizeof(LogicalInstruction))) (c.zone->allocate(sizeof(LogicalInstruction)))
LogicalInstruction(logicalIp, c.stack, c.locals); LogicalInstruction(logicalIp, c.stack, c.locals);
if (c.subroutine) {
c.logicalCode[logicalIp]->subroutine = c.subroutine;
c.subroutine = 0;
}
c.logicalIp = logicalIp; c.logicalIp = logicalIp;
} }
@ -4177,6 +4218,10 @@ class MyCompiler: public Compiler {
::push(&c, footprint, static_cast<Value*>(value)); ::push(&c, footprint, static_cast<Value*>(value));
} }
virtual void save(unsigned footprint, Operand* value) {
c.saved = savedValue(&c, static_cast<Value*>(value), footprint, c.saved);
}
virtual Operand* pop(unsigned footprint) { virtual Operand* pop(unsigned footprint) {
return ::pop(&c, footprint); return ::pop(&c, footprint);
} }

View File

@ -31,10 +31,14 @@ class Compiler {
class Operand { }; class Operand { };
class StackElement { }; class StackElement { };
class State { }; class State { };
class Subroutine { };
virtual State* saveState() = 0; virtual State* saveState() = 0;
virtual void restoreState(State* state) = 0; virtual void restoreState(State* state) = 0;
virtual Subroutine* startSubroutine() = 0;
virtual void endSubroutine(Subroutine* subroutine) = 0;
virtual void init(unsigned logicalCodeSize, unsigned parameterFootprint, virtual void init(unsigned logicalCodeSize, unsigned parameterFootprint,
unsigned localFootprint, unsigned alignedFrameSize) = 0; unsigned localFootprint, unsigned alignedFrameSize) = 0;

View File

@ -257,26 +257,41 @@ appendOffsetTask(Context* c, Promise* promise, Promise* instructionOffset,
class ImmediateTask: public Task { class ImmediateTask: public Task {
public: public:
ImmediateTask(Task* next, Promise* promise, Promise* offset): ImmediateTask(Task* next, Promise* promise, Promise* offset, unsigned size):
Task(next), Task(next),
promise(promise), promise(promise),
offset(offset) offset(offset),
size(size)
{ } { }
virtual void run(Context* c) { virtual void run(Context* c) {
intptr_t v = promise->value(); switch (size) {
memcpy(c->result + offset->value(), &v, BytesPerWord); case 4: {
int32_t v = promise->value();
memcpy(c->result + offset->value(), &v, size);
} break;
case 8: {
int64_t v = promise->value();
memcpy(c->result + offset->value(), &v, size);
} break;
default:
abort(c);
}
} }
Promise* promise; Promise* promise;
Promise* offset; Promise* offset;
unsigned size;
}; };
void void
appendImmediateTask(Context* c, Promise* promise, Promise* offset) appendImmediateTask(Context* c, Promise* promise, Promise* offset,
unsigned size)
{ {
c->tasks = new (c->zone->allocate(sizeof(ImmediateTask))) ImmediateTask c->tasks = new (c->zone->allocate(sizeof(ImmediateTask))) ImmediateTask
(c->tasks, promise, offset); (c->tasks, promise, offset, size);
} }
class AlignmentPadding { class AlignmentPadding {
@ -885,12 +900,38 @@ moveCR(Context* c, unsigned, Assembler::Constant* a,
if (a->value->resolved()) { if (a->value->resolved()) {
c->code.appendAddress(a->value->value()); c->code.appendAddress(a->value->value());
} else { } else {
appendImmediateTask(c, a->value, offset(c)); appendImmediateTask(c, a->value, offset(c), BytesPerWord);
c->code.appendAddress(static_cast<uintptr_t>(0)); c->code.appendAddress(static_cast<uintptr_t>(0));
} }
} }
} }
class ShiftMaskPromise: public Promise {
public:
ShiftMaskPromise(Promise* base, unsigned shift, int64_t mask):
base(base), shift(shift), mask(mask)
{ }
virtual int64_t value() {
return (base->value() >> shift) & mask;
}
virtual bool resolved() {
return base->resolved();
}
Promise* base;
unsigned shift;
int64_t mask;
};
ShiftMaskPromise*
shiftMaskPromise(Context* c, Promise* base, unsigned shift, int64_t mask)
{
return new (c->zone->allocate(sizeof(ShiftMaskPromise)))
ShiftMaskPromise(base, shift, mask);
}
void void
moveCM(Context* c, unsigned aSize UNUSED, Assembler::Constant* a, moveCM(Context* c, unsigned aSize UNUSED, Assembler::Constant* a,
unsigned bSize, Assembler::Memory* b) unsigned bSize, Assembler::Memory* b)
@ -911,19 +952,14 @@ moveCM(Context* c, unsigned aSize UNUSED, Assembler::Constant* a,
if (a->value->resolved()) { if (a->value->resolved()) {
c->code.append4(a->value->value()); c->code.append4(a->value->value());
} else { } else {
appendImmediateTask(c, a->value, offset(c)); appendImmediateTask(c, a->value, offset(c), 4);
c->code.append4(0); c->code.append4(0);
} }
break; break;
case 8: { case 8: {
int64_t v = a->value->value(); Assembler::Constant ah(shiftMaskPromise(c, a->value, 32, 0xFFFFFFFF));
Assembler::Constant al(shiftMaskPromise(c, a->value, 0, 0xFFFFFFFF));
ResolvedPromise high((v >> 32) & 0xFFFFFFFF);
Assembler::Constant ah(&high);
ResolvedPromise low(v & 0xFFFFFFFF);
Assembler::Constant al(&low);
Assembler::Memory bh(b->base, b->offset + 4, b->index, b->scale); Assembler::Memory bh(b->base, b->offset + 4, b->index, b->scale);

View File

@ -21,9 +21,12 @@ public class Subroutine {
Integer.valueOf(z).toString(); Integer.valueOf(z).toString();
} finally { } finally {
a = x + y; a = x + y;
System.gc();
} }
expect(a == x + y); expect(a == x + y);
} catch (DummyException ignored) { } } catch (DummyException e) {
e.printStackTrace();
}
} }
public static void main(String[] args) { public static void main(String[] args) {