diff --git a/src/compile.cpp b/src/compile.cpp index 4e974da640..11bf8fcfcc 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -1638,7 +1638,9 @@ class Frame { } void returnFromSubroutine(unsigned returnAddressLocal) { - c->endSubroutine(subroutine->handle); + c->returnFromSubroutine + (subroutine->handle, loadLocal(context, 1, returnAddressLocal)); + subroutine->stackIndex = localOffsetFromStack (t, translateLocalIndex(context, 1, returnAddressLocal), context->method); @@ -4670,8 +4672,6 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, case ret: { unsigned index = codeBody(t, code, ip); - c->saveLocals(); - c->jmp(loadLocal(context, 1, index)); frame->returnFromSubroutine(index); } return; diff --git a/src/compiler.cpp b/src/compiler.cpp index 6d82ed67e7..44217336a2 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -4790,8 +4790,10 @@ appendBranch(Context* c, TernaryOperation type, unsigned size, Value* first, class JumpEvent: public Event { public: - JumpEvent(Context* c, UnaryOperation type, Value* address, bool exit): - Event(c), type(type), address(address), exit(exit) + JumpEvent(Context* c, UnaryOperation type, Value* address, bool exit, + bool cleanLocals): + Event(c), type(type), address(address), exit(exit), + cleanLocals(cleanLocals) { bool thunk; uint8_t typeMask; @@ -4815,6 +4817,13 @@ class JumpEvent: public Event { for (Read* r = reads; r; r = r->eventNext) { popRead(c, this, r->value); } + + if (cleanLocals) { + for (FrameIterator it(c, 0, c->locals); it.hasMore();) { + FrameIterator::Element e = it.next(c); + clean(c, e.value, 0); + } + } } virtual bool isBranch() { return true; } @@ -4826,13 +4835,15 @@ class JumpEvent: public Event { UnaryOperation type; Value* address; bool exit; + bool cleanLocals; }; void -appendJump(Context* c, UnaryOperation type, Value* address, bool exit = false) +appendJump(Context* c, UnaryOperation type, Value* address, bool exit = false, + bool cleanLocals = false) { append(c, new (c->zone->allocate(sizeof(JumpEvent))) - JumpEvent(c, type, address, exit)); + JumpEvent(c, type, address, exit, cleanLocals)); } class BoundsCheckEvent: public Event { @@ -5037,31 +5048,6 @@ appendSaveLocals(Context* c) SaveLocalsEvent(c)); } -class CleanLocalsEvent: public Event { - public: - CleanLocalsEvent(Context* c): - Event(c) - { } - - virtual const char* name() { - return "CleanLocalsEvent"; - } - - virtual void compile(Context* c) { - for (FrameIterator it(c, 0, c->locals); it.hasMore();) { - FrameIterator::Element e = it.next(c); - clean(c, e.value, 0); - } - } -}; - -void -appendCleanLocals(Context* c) -{ - append(c, new (c->zone->allocate(sizeof(CleanLocalsEvent))) - CleanLocalsEvent(c)); -} - class DummyEvent: public Event { public: DummyEvent(Context* c): @@ -5923,8 +5909,9 @@ class MyCompiler: public Compiler { MySubroutine; } - virtual void endSubroutine(Subroutine* subroutine) { - appendCleanLocals(&c); + virtual void returnFromSubroutine(Subroutine* subroutine, Operand* address) { + appendSaveLocals(&c); + appendJump(&c, Jump, static_cast(address), false, true); static_cast(subroutine)->forkState = local::saveState(&c); } diff --git a/src/compiler.h b/src/compiler.h index a513e1e06b..d4484c719e 100644 --- a/src/compiler.h +++ b/src/compiler.h @@ -54,7 +54,8 @@ class Compiler { virtual void restoreState(State* state) = 0; virtual Subroutine* startSubroutine() = 0; - virtual void endSubroutine(Subroutine* subroutine) = 0; + virtual void returnFromSubroutine(Subroutine* subroutine, Operand* address) + = 0; virtual void linkSubroutine(Subroutine* subroutine) = 0; virtual void init(unsigned logicalCodeSize, unsigned parameterFootprint,