avoid tight coupling between deferreturn and jmpdefer.
before, jmpdefer knew the exact frame size of deferreturn
in order to pop it off the stack. now, deferreturn passes
jmpdefer a pointer to the frame above it explicitly.
that avoids a magic constant and should be less fragile.
R=r
DELTA=32 (6 added, 3 deleted, 23 changed)
OCL=29801
CL=29804
MOVL $1, AX
RET
-// void jmpdefer(byte*);
+// void jmpdefer(fn, sp);
+// called from deferreturn.
// 1. pop the caller
// 2. sub 5 bytes from the callers return
// 3. jmp to the argument
TEXT jmpdefer(SB), 7, $0
- MOVL 4(SP), AX // function
- ADDL $(4+56), SP // pop saved PC and callers frame
- SUBL $5, (SP) // reposition his return address
- JMP AX // and goto function
+ MOVL 4(SP), AX // fn
+ MOVL 8(SP), BX // caller sp
+ LEAL -4(BX), SP // caller sp after CALL
+ SUBL $5, (SP) // return to CALL again
+ JMP AX // but first run the deferred function
TEXT sys·memclr(SB),7,$0
MOVL 4(SP), DI // arg 1 addr
MOVQ AX, SP
PUSHQ CX
JMP BX
- POPQ AX
+ POPQ AX // not reached
RET
// bool cas(int32 *val, int32 old, int32 new)
MOVL $1, AX
RET
-// void jmpdefer(byte*);
+// void jmpdefer(fn, sp);
+// called from deferreturn.
// 1. pop the caller
// 2. sub 5 bytes from the callers return
// 3. jmp to the argument
TEXT jmpdefer(SB), 7, $0
- MOVQ 8(SP), AX // function
- ADDQ $(8+56), SP // pop saved PC and callers frame
- SUBQ $5, (SP) // reposition his return address
- JMP AX // and goto function
+ MOVQ 8(SP), AX // fn
+ MOVQ 16(SP), BX // caller sp
+ LEAQ -8(BX), SP // caller sp after CALL
+ SUBQ $5, (SP) // return to CALL again
+ JMP AX // but first run the deferred function
Stktop *top;
uint32 args;
byte *sp;
- uint64 oldsp, oldpc, oldbase, oldguard;
+ uintptr oldsp, oldpc, oldbase, oldguard;
// printf("oldstack m->cret=%p\n", m->cret);
mcpy(top->oldsp+2*sizeof(uintptr), sp, args);
}
- oldsp = (uint64)top->oldsp + 8;
- oldpc = *(uint64*)(top->oldsp + 8);
- oldbase = (uint64)top->oldbase;
- oldguard = (uint64)top->oldguard;
+ oldsp = (uintptr)top->oldsp + sizeof(uintptr);
+ oldpc = *(uintptr*)oldsp;
+ oldbase = (uintptr)top->oldbase;
+ oldguard = (uintptr)top->oldguard;
stackfree((byte*)m->curg->stackguard - StackGuard);
gogoret(&m->morestack, m->cret);
}
+#pragma textflag 7
void
lessstack(void)
{
#pragma textflag 7
void
-sys·deferreturn(int32 arg0)
+sys·deferreturn(uintptr arg0)
{
- // warning: jmpdefer knows the frame size
- // of this routine. dont change anything
- // that might change the frame size
Defer *d;
- byte *sp;
+ byte *sp, *fn;
+ uintptr *caller;
d = g->defer;
if(d == nil)
return;
mcpy(d->sp, d->args, d->siz);
g->defer = d->link;
- sp = d->fn;
+ fn = d->fn;
free(d);
- jmpdefer(sp);
-}
+ jmpdefer(fn, sp);
+ }
void
runtime·Breakpoint(void)
void close(int32);
int32 fstat(int32, void*);
bool cas(uint32*, uint32, uint32);
-void jmpdefer(byte*);
+void jmpdefer(byte*, void*);
void exit1(int32);
void ready(G*);
byte* getenv(int8*);