diff --git a/src/assembler.h b/src/assembler.h index 6d6033e38f..2ce04b44e7 100644 --- a/src/assembler.h +++ b/src/assembler.h @@ -273,10 +273,13 @@ class Assembler { virtual bool reserved(int register_) = 0; + virtual unsigned frameFootprint(unsigned footprint) = 0; virtual unsigned argumentFootprint(unsigned footprint) = 0; virtual unsigned argumentRegisterCount() = 0; virtual int argumentRegister(unsigned index) = 0; + virtual unsigned stackAlignmentInWords() = 0; + virtual bool matchCall(void* returnAddress, void* target) = 0; virtual void updateCall(UnaryOperation op, bool assertAlignment, @@ -322,7 +325,6 @@ class Assembler { virtual Architecture* arch() = 0; virtual void saveFrame(unsigned stackOffset, unsigned baseOffset) = 0; - virtual void restoreFrame(unsigned stackOffset, unsigned baseOffset) = 0; virtual void pushFrame(unsigned argumentCount, ...) = 0; virtual void allocateFrame(unsigned footprint) = 0; virtual void popFrame() = 0; @@ -331,6 +333,8 @@ class Assembler { int framePointerSurrogate) = 0; virtual void popFrameAndPopArgumentsAndReturn(unsigned argumentFootprint) = 0; + virtual void popFrameAndUpdateStackAndReturn(unsigned stackOffsetFromThread) + = 0; virtual void apply(Operation op) = 0; diff --git a/src/compile.cpp b/src/compile.cpp index 20cbca17bf..3d2457869a 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -378,7 +378,7 @@ alignedFrameSize(MyThread* t, object method) (localSize(t, method) - methodParameterFootprint(t, method) + codeMaxStack(t, methodCode(t, method)) - + t->arch->argumentFootprint(MaxNativeCallFootprint)); + + t->arch->frameFootprint(MaxNativeCallFootprint)); } unsigned @@ -4835,6 +4835,17 @@ invokeNative2(MyThread* t, object method) default: abort(t); } + + if (t->arch->argumentFootprint(footprint) + > t->arch->stackAlignmentInWords()) + { + t->stack = static_cast(t->stack) + + (t->arch->argumentFootprint(footprint) + - t->arch->stackAlignmentInWords()); + } + + t->stack = static_cast(t->stack) + - t->arch->frameReturnAddressSize(); } else { result = 0; } @@ -6119,9 +6130,7 @@ compileThunks(MyThread* t, Allocator* allocator, MyProcessor* p, Assembler::Constant proc(&(nativeContext.promise)); a->apply(LongCall, BytesPerWord, ConstantOperand, &proc); - a->popFrame(); - - a->apply(Return); + a->popFrameAndUpdateStackAndReturn(difference(&(t->stack), t)); a->endBlock(false)->resolve(0, 0); } diff --git a/src/powerpc.cpp b/src/powerpc.cpp index 19c217a3e8..dc1e315ebb 100644 --- a/src/powerpc.cpp +++ b/src/powerpc.cpp @@ -65,6 +65,7 @@ inline int sth(int rs, int ra, int i) { return D(44, rs, ra, i); } inline int sthx(int rs, int ra, int rb) { return X(31, rs, ra, rb, 407, 0); } inline int stw(int rs, int ra, int i) { return D(36, rs, ra, i); } inline int stwu(int rs, int ra, int i) { return D(37, rs, ra, i); } +inline int stwux(int rs, int ra, int i) { return X(31, rs, ra, rb, 183, 0); } inline int stwx(int rs, int ra, int rb) { return X(31, rs, ra, rb, 151, 0); } inline int add(int rt, int ra, int rb) { return XO(31, rt, ra, rb, 0, 266, 0); } inline int addc(int rt, int ra, int rb) { return XO(31, rt, ra, rb, 0, 10, 0); } @@ -907,9 +908,15 @@ moveAndUpdateRM(Context* c, unsigned srcSize UNUSED, Assembler::Register* src, { assert(c, srcSize == BytesPerWord); assert(c, dstSize == BytesPerWord); - assert(c, dst->index == NoRegister); - issue(c, stwu(src->low, dst->base, dst->offset)); + if (dst->index == NoRegister) { + issue(c, stwu(src->low, dst->base, dst->offset)); + } else { + assert(c, dst->offset == 0); + assert(c, dst->scale == 1); + + issue(c, stwux(src->low, dst->base, dst->index)); + } } void @@ -2034,6 +2041,26 @@ class MyAssembler: public Assembler { return_(&c); } + virtual void popFrameAndUpdateStackAndReturn(unsigned stackOffset) { + popFrame(); + + Register tmp1(0); + Memory stackSrc(StackRegister, 0); + moveMR(&c, BytesPerWord, &stackSrc, BytesPerWord, &tmp1); + + Register tmp2(arch_->returnLow()); + Memory newStackSrc(ThreadRegister, stackOffsetFromThread); + moveMR(&c, BytesPerWord, &stackSrc, BytesPerWord, &tmp2); + + Register stack(StackRegister); + subR(&c, BytesPerWord, &tmp2, &stack, &tmp2); + + Memory stackDst(StackRegister, 0, tmp2.low); + moveAndUpdateRM(&c, BytesPerWord, &tmp1, BytesPerWord, &stackDst); + + return_(&c); + } + virtual void apply(Operation op) { arch_->c.operations[op](&c); } diff --git a/src/x86.cpp b/src/x86.cpp index b33b418263..8bdd62e4e5 100644 --- a/src/x86.cpp +++ b/src/x86.cpp @@ -2062,7 +2062,7 @@ class MyArchitecture: public Assembler::Architecture { } } - virtual unsigned stackPadding(unsigned footprint) { + virtual unsigned frameFootprint(unsigned footprint) { return max(footprint > argumentRegisterCount() ? footprint - argumentRegisterCount() : 0, StackAlignmentInWords); @@ -2097,6 +2097,10 @@ class MyArchitecture: public Assembler::Architecture { } } + virtual unsigned stackAlignmentInWords() { + return StackAlignmentInWords; + } + virtual bool matchCall(void* returnAddress, void* target) { uint8_t* instruction = static_cast(returnAddress) - 5; int32_t actualOffset; memcpy(&actualOffset, instruction + 1, 4); @@ -2346,18 +2350,6 @@ class MyAssembler: public Assembler { BytesPerWord, MemoryOperand, &baseDst); } - virtual void restoreFrame(unsigned stackOffset, unsigned baseOffset) { - Register stack(rsp); - Memory stackDst(rbx, stackOffset); - apply(Move, BytesPerWord, MemoryOperand, &stackDst, - BytesPerWord, RegisterOperand, &stack); - - Register base(rbp); - Memory baseDst(rbx, baseOffset); - apply(Move, BytesPerWord, MemoryOperand, &baseDst, - BytesPerWord, RegisterOperand, &base); - } - virtual void pushFrame(unsigned argumentCount, ...) { struct { unsigned size; @@ -2483,6 +2475,20 @@ class MyAssembler: public Assembler { } } + virtual void popFrameAndUpdateStackAndReturn(unsigned stackOffsetFromThread) + { + popFrame(); + + Register returnAddress(rcx); + popR(&c, BytesPerWord, &returnAddress); + + Register stack(rsp); + Memory stackSrc(rbx, stackOffsetFromThread); + moveMR(&c, BytesPerWord, &stackSrc, BytesPerWord, &stack); + + jumpR(&c, BytesPerWord, &returnAddress); + } + virtual void apply(Operation op) { arch_->c.operations[op](&c); }