From fb770d10fb514b5b10b0dd1afd451566bc915187 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Thu, 13 Nov 2008 17:59:21 -0700 Subject: [PATCH] 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. --- src/compile.cpp | 13 +++------ src/compiler.cpp | 57 ++++++++++++++++++++++++++++++++++---- src/compiler.h | 4 +++ src/x86.cpp | 66 ++++++++++++++++++++++++++++++++++---------- test/Subroutine.java | 5 +++- 5 files changed, 114 insertions(+), 31 deletions(-) diff --git a/src/compile.cpp b/src/compile.cpp index c5f710912a..a84497456e 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -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: { diff --git a/src/compiler.cpp b/src/compiler.cpp index 58c226b5ac..0b3cf4c8f6 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -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), footprint, c.saved); - } - virtual void restoreState(State* state) { ::restoreState(&c, static_cast(state)); } + virtual Subroutine* startSubroutine() { + return c.subroutine = new (c.zone->allocate(sizeof(MySubroutine))) + MySubroutine; + } + + virtual void endSubroutine(Subroutine* subroutine) { + MySubroutine* sr = static_cast(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)); } + virtual void save(unsigned footprint, Operand* value) { + c.saved = savedValue(&c, static_cast(value), footprint, c.saved); + } + virtual Operand* pop(unsigned footprint) { return ::pop(&c, footprint); } diff --git a/src/compiler.h b/src/compiler.h index eb4df43bd1..48ad96c300 100644 --- a/src/compiler.h +++ b/src/compiler.h @@ -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; diff --git a/src/x86.cpp b/src/x86.cpp index aa7e1d25f7..09984b25de 100644 --- a/src/x86.cpp +++ b/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(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); diff --git a/test/Subroutine.java b/test/Subroutine.java index c3491e1405..e9b8df97d7 100644 --- a/test/Subroutine.java +++ b/test/Subroutine.java @@ -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) {