mirror of
https://github.com/corda/corda.git
synced 2025-01-03 19:54:13 +00:00
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:
parent
4dd1d1eec8
commit
fb770d10fb
@ -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: {
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
|
66
src/x86.cpp
66
src/x86.cpp
@ -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);
|
||||
|
||||
|
@ -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) {
|
||||
|
Loading…
Reference in New Issue
Block a user