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));
// todo: flush stack to memory here
abort(t);
Compiler::State* state = c->saveState();
frame->pushAddress(frame->machineIp(ip));
c->jmp(frame->machineIp(newIp));
// NB: we assume that the stack will look the same on return
// from the subroutine as at call time.
Compiler::Subroutine* sr = c->startSubroutine();
compile(t, frame, newIp);
if (UNLIKELY(t->exception)) return;
frame->pop(1);
frame->poppedInt();
c->restoreState(state);
c->endSubroutine(sr);
} break;
case l2d: {

View File

@ -164,11 +164,18 @@ class ForkState: public Compiler::State {
ForkElement elements[0];
};
class MySubroutine: public Compiler::Subroutine {
public:
MySubroutine(): forkState(0) { }
ForkState* forkState;
};
class LogicalInstruction {
public:
LogicalInstruction(int index, Stack* stack, Local* locals):
firstEvent(0), lastEvent(0), immediatePredecessor(0), stack(stack),
locals(locals), machineOffset(0), index(index)
locals(locals), machineOffset(0), subroutine(0), index(index)
{ }
Event* firstEvent;
@ -177,6 +184,7 @@ class LogicalInstruction {
Stack* stack;
Local* locals;
Promise* machineOffset;
MySubroutine* subroutine;
int index;
};
@ -293,6 +301,7 @@ class Context {
firstEvent(0),
lastEvent(0),
forkState(0),
subroutine(0),
logicalIp(-1),
constantCount(0),
logicalCodeLength(0),
@ -331,6 +340,7 @@ class Context {
Event* firstEvent;
Event* lastEvent;
ForkState* forkState;
MySubroutine* subroutine;
int logicalIp;
unsigned constantCount;
unsigned logicalCodeLength;
@ -3237,7 +3247,9 @@ class FrameSiteEvent: public Event {
}
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;
@ -4005,14 +4017,32 @@ class MyCompiler: public Compiler {
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) {
::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,
unsigned localFootprint, unsigned alignedFrameSize)
{
@ -4075,6 +4105,12 @@ class MyCompiler: public Compiler {
populateJunctionReads(&c, e->predecessors);
}
if (c.subroutine) {
c.subroutine->forkState
= c.logicalCode[logicalIp]->subroutine->forkState;
c.subroutine = 0;
}
c.forkState = false;
}
@ -4096,6 +4132,11 @@ class MyCompiler: public Compiler {
(c.zone->allocate(sizeof(LogicalInstruction)))
LogicalInstruction(logicalIp, c.stack, c.locals);
if (c.subroutine) {
c.logicalCode[logicalIp]->subroutine = c.subroutine;
c.subroutine = 0;
}
c.logicalIp = logicalIp;
}
@ -4177,6 +4218,10 @@ class MyCompiler: public Compiler {
::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) {
return ::pop(&c, footprint);
}

View File

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

View File

@ -257,26 +257,41 @@ appendOffsetTask(Context* c, Promise* promise, Promise* instructionOffset,
class ImmediateTask: public Task {
public:
ImmediateTask(Task* next, Promise* promise, Promise* offset):
ImmediateTask(Task* next, Promise* promise, Promise* offset, unsigned size):
Task(next),
promise(promise),
offset(offset)
offset(offset),
size(size)
{ }
virtual void run(Context* c) {
intptr_t v = promise->value();
memcpy(c->result + offset->value(), &v, BytesPerWord);
switch (size) {
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* offset;
unsigned size;
};
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, promise, offset);
(c->tasks, promise, offset, size);
}
class AlignmentPadding {
@ -885,12 +900,38 @@ moveCR(Context* c, unsigned, Assembler::Constant* a,
if (a->value->resolved()) {
c->code.appendAddress(a->value->value());
} else {
appendImmediateTask(c, a->value, offset(c));
appendImmediateTask(c, a->value, offset(c), BytesPerWord);
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
moveCM(Context* c, unsigned aSize UNUSED, Assembler::Constant* a,
unsigned bSize, Assembler::Memory* b)
@ -911,19 +952,14 @@ moveCM(Context* c, unsigned aSize UNUSED, Assembler::Constant* a,
if (a->value->resolved()) {
c->code.append4(a->value->value());
} else {
appendImmediateTask(c, a->value, offset(c));
appendImmediateTask(c, a->value, offset(c), 4);
c->code.append4(0);
}
break;
case 8: {
int64_t v = a->value->value();
ResolvedPromise high((v >> 32) & 0xFFFFFFFF);
Assembler::Constant ah(&high);
ResolvedPromise low(v & 0xFFFFFFFF);
Assembler::Constant al(&low);
Assembler::Constant ah(shiftMaskPromise(c, a->value, 32, 0xFFFFFFFF));
Assembler::Constant al(shiftMaskPromise(c, a->value, 0, 0xFFFFFFFF));
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();
} finally {
a = x + y;
System.gc();
}
expect(a == x + y);
} catch (DummyException ignored) { }
} catch (DummyException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {