mirror of
https://github.com/corda/corda.git
synced 2025-01-06 05:04:20 +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));
|
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: {
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
66
src/x86.cpp
66
src/x86.cpp
@ -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);
|
||||||
|
|
||||||
|
@ -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) {
|
||||||
|
Loading…
Reference in New Issue
Block a user