LSym* sym_divu;
LSym* sym_mod;
LSym* sym_modu;
- LSym* symmorestack[10];
+ LSym* symmorestack[20];
LSym* gmsym;
LSym* plan9tos;
Prog* curp;
break;
case OCLOSUREVAR:
+ if(!curfn->needctxt)
+ fatal("closurevar without needctxt");
a->type = D_OREG;
a->reg = 7;
a->offset = n->xoffset;
break;
case OCLOSUREVAR:
+ if(!curfn->needctxt)
+ fatal("closurevar without needctxt");
a->type = D_DX+D_INDIR;
a->sym = nil;
a->offset = n->xoffset;
break;
case OCLOSUREVAR:
+ if(!curfn->needctxt)
+ fatal("closurevar without needctxt");
a->type = D_DX+D_INDIR;
a->offset = n->xoffset;
a->sym = nil;
// and initialize in entry prologue.
body = nil;
offset = widthptr;
+ xfunc->needctxt = func->cvars != nil;
for(l=func->cvars; l; l=l->next) {
v = l->n;
if(v->op == 0)
// Declare and initialize variable holding receiver.
body = nil;
+ xfunc->needctxt = 1;
cv = nod(OCLOSUREVAR, N, N);
cv->xoffset = widthptr;
cv->type = rcvrtype;
schar likely; // likeliness of if statement
uchar hasbreak; // has break statement
uchar needzero; // if it contains pointers, needs to be zeroed on function entry
+ uchar needctxt; // function uses context register (has closure variables)
uint esc; // EscXXX
int funcdepth;
ptxt->TEXTFLAG |= DUPOK;
if(fn->wrapper)
ptxt->TEXTFLAG |= WRAPPER;
+ if(fn->needctxt)
+ ptxt->TEXTFLAG |= NEEDCTXT;
// Clumsy but important.
// See test/recover.go for test cases and src/pkg/reflect/value.go
#define NOPTR 16
// This is a wrapper function and should not count as disabling 'recover'.
#define WRAPPER 32
+// This function uses its incoming context register.
+#define NEEDCTXT 64
return p;
}
-static Prog* stacksplit(Link*, Prog*, int32);
+static Prog* stacksplit(Link*, Prog*, int32, int);
static void initdiv(Link*);
static void softfloat(Link*, LSym*);
autosize = 0;
- if(ctxt->symmorestack[0] == nil)
+ if(ctxt->symmorestack[0] == nil) {
ctxt->symmorestack[0] = linklookup(ctxt, "runtime.morestack", 0);
-
+ ctxt->symmorestack[1] = linklookup(ctxt, "runtime.morestack_noctxt", 0);
+ }
+
q = nil;
ctxt->cursym = cursym;
}
if(!(p->reg & NOSPLIT))
- p = stacksplit(ctxt, p, autosize); // emit split check
+ p = stacksplit(ctxt, p, autosize, !(cursym->text->from.scale&NEEDCTXT)); // emit split check
// MOVW.W R14,$-autosize(SP)
p = appendp(ctxt, p);
}
static Prog*
-stacksplit(Link *ctxt, Prog *p, int32 framesize)
+stacksplit(Link *ctxt, Prog *p, int32 framesize, int noctxt)
{
int32 arg;
p->as = ABL;
p->scond = C_SCOND_LS;
p->to.type = D_BRANCH;
- p->to.sym = ctxt->symmorestack[0];
+ p->to.sym = ctxt->symmorestack[noctxt];
// BLS start
p = appendp(ctxt, p);
morename[] =
{
"runtime.morestack00",
+ "runtime.morestack00_noctxt",
"runtime.morestack10",
+ "runtime.morestack10_noctxt",
"runtime.morestack01",
+ "runtime.morestack01_noctxt",
"runtime.morestack11",
+ "runtime.morestack11_noctxt",
"runtime.morestack8",
+ "runtime.morestack8_noctxt",
"runtime.morestack16",
+ "runtime.morestack16_noctxt",
"runtime.morestack24",
+ "runtime.morestack24_noctxt",
"runtime.morestack32",
+ "runtime.morestack32_noctxt",
"runtime.morestack40",
+ "runtime.morestack40_noctxt",
"runtime.morestack48",
+ "runtime.morestack48_noctxt",
};
static Prog* load_g_cx(Link*, Prog*);
-static Prog* stacksplit(Link*, Prog*, int32, int32, Prog**);
+static Prog* stacksplit(Link*, Prog*, int32, int32, int, Prog**);
static void indir_cx(Link*, Addr*);
static void
p = load_g_cx(ctxt, p); // load g into CX
}
if(!(cursym->text->from.scale & NOSPLIT))
- p = stacksplit(ctxt, p, autoffset, textarg, &q); // emit split check
+ p = stacksplit(ctxt, p, autoffset, textarg, !(cursym->text->from.scale&NEEDCTXT), &q); // emit split check
if(autoffset) {
if(autoffset%ctxt->arch->regsize != 0)
// On return, *jmpok is the instruction that should jump
// to the stack frame allocation if no split is needed.
static Prog*
-stacksplit(Link *ctxt, Prog *p, int32 framesize, int32 textarg, Prog **jmpok)
+stacksplit(Link *ctxt, Prog *p, int32 framesize, int32 textarg, int noctxt, Prog **jmpok)
{
Prog *q, *q1;
uint32 moreconst1, moreconst2, i;
if(moreconst1 == 0 && moreconst2 == 0) {
p->as = ACALL;
p->to.type = D_BRANCH;
- p->to.sym = ctxt->symmorestack[0];
+ p->to.sym = ctxt->symmorestack[0*2+noctxt];
} else
if(moreconst1 != 0 && moreconst2 == 0) {
p->as = AMOVL;
p = appendp(ctxt, p);
p->as = ACALL;
p->to.type = D_BRANCH;
- p->to.sym = ctxt->symmorestack[1];
+ p->to.sym = ctxt->symmorestack[1*2+noctxt];
} else
if(moreconst1 == 0 && moreconst2 <= 48 && moreconst2%8 == 0) {
i = moreconst2/8 + 3;
p->as = ACALL;
p->to.type = D_BRANCH;
- p->to.sym = ctxt->symmorestack[i];
+ p->to.sym = ctxt->symmorestack[i*2+noctxt];
} else
if(moreconst1 == 0 && moreconst2 != 0) {
p->as = AMOVL;
p = appendp(ctxt, p);
p->as = ACALL;
p->to.type = D_BRANCH;
- p->to.sym = ctxt->symmorestack[2];
+ p->to.sym = ctxt->symmorestack[2*2+noctxt];
} else {
p->as = mov;
p->from.type = D_CONST;
p = appendp(ctxt, p);
p->as = ACALL;
p->to.type = D_BRANCH;
- p->to.sym = ctxt->symmorestack[3];
+ p->to.sym = ctxt->symmorestack[3*2+noctxt];
}
p = appendp(ctxt, p);
}
static Prog* load_g_cx(Link*, Prog*);
-static Prog* stacksplit(Link*, Prog*, int32, Prog**);
+static Prog* stacksplit(Link*, Prog*, int32, int, Prog**);
static void
addstacksplit(Link *ctxt, LSym *cursym)
int32 autoffset, deltasp;
int a;
- if(ctxt->symmorestack[0] == nil)
+ if(ctxt->symmorestack[0] == nil) {
ctxt->symmorestack[0] = linklookup(ctxt, "runtime.morestack", 0);
+ ctxt->symmorestack[1] = linklookup(ctxt, "runtime.morestack_noctxt", 0);
+ }
if(ctxt->headtype == Hplan9 && ctxt->plan9tos == nil)
ctxt->plan9tos = linklookup(ctxt, "_tos", 0);
p = load_g_cx(ctxt, p); // load g into CX
}
if(!(cursym->text->from.scale & NOSPLIT))
- p = stacksplit(ctxt, p, autoffset, &q); // emit split check
+ p = stacksplit(ctxt, p, autoffset, !(cursym->text->from.scale&NEEDCTXT), &q); // emit split check
if(autoffset) {
p = appendp(ctxt, p);
// On return, *jmpok is the instruction that should jump
// to the stack frame allocation if no split is needed.
static Prog*
-stacksplit(Link *ctxt, Prog *p, int32 framesize, Prog **jmpok)
+stacksplit(Link *ctxt, Prog *p, int32 framesize, int noctxt, Prog **jmpok)
{
Prog *q, *q1;
int arg;
p = appendp(ctxt, p);
p->as = ACALL;
p->to.type = D_BRANCH;
- p->to.sym = ctxt->symmorestack[0];
+ p->to.sym = ctxt->symmorestack[noctxt];
p = appendp(ctxt, p);
p->as = AJMP;
MOVL $0, 0x1003 // crash if newstack returns
RET
+TEXT runtime·morestack_noctxt(SB),NOSPLIT,$0-0
+ MOVL $0, DX
+ JMP runtime·morestack(SB)
+
// Called from panic. Mimics morestack,
// reuses stack growth code to create a frame
// with the desired args running the desired function.
MOVQ $runtime·morestack(SB), AX
JMP AX
+TEXT runtime·morestack00_noctxt(SB),NOSPLIT,$0
+ MOVL $0, DX
+ JMP runtime·morestack00(SB)
+
+TEXT runtime·morestack01_noctxt(SB),NOSPLIT,$0
+ MOVL $0, DX
+ JMP runtime·morestack01(SB)
+
+TEXT runtime·morestack10_noctxt(SB),NOSPLIT,$0
+ MOVL $0, DX
+ JMP runtime·morestack10(SB)
+
+TEXT runtime·morestack11_noctxt(SB),NOSPLIT,$0
+ MOVL $0, DX
+ JMP runtime·morestack11(SB)
+
+TEXT runtime·morestack8_noctxt(SB),NOSPLIT,$0
+ MOVL $0, DX
+ JMP runtime·morestack8(SB)
+
+TEXT runtime·morestack16_noctxt(SB),NOSPLIT,$0
+ MOVL $0, DX
+ JMP runtime·morestack16(SB)
+
+TEXT runtime·morestack24_noctxt(SB),NOSPLIT,$0
+ MOVL $0, DX
+ JMP runtime·morestack24(SB)
+
+TEXT runtime·morestack32_noctxt(SB),NOSPLIT,$0
+ MOVL $0, DX
+ JMP runtime·morestack32(SB)
+
+TEXT runtime·morestack40_noctxt(SB),NOSPLIT,$0
+ MOVL $0, DX
+ JMP runtime·morestack40(SB)
+
+TEXT runtime·morestack48_noctxt(SB),NOSPLIT,$0
+ MOVL $0, DX
+ JMP runtime·morestack48(SB)
+
// bool cas(int32 *val, int32 old, int32 new)
// Atomically:
// if(*val == old){
MOVL $runtime·morestack(SB), AX
JMP AX
+TEXT runtime·morestack00_noctxt(SB),NOSPLIT,$0
+ MOVL $0, DX
+ JMP runtime·morestack00(SB)
+
+TEXT runtime·morestack01_noctxt(SB),NOSPLIT,$0
+ MOVL $0, DX
+ JMP runtime·morestack01(SB)
+
+TEXT runtime·morestack10_noctxt(SB),NOSPLIT,$0
+ MOVL $0, DX
+ JMP runtime·morestack10(SB)
+
+TEXT runtime·morestack11_noctxt(SB),NOSPLIT,$0
+ MOVL $0, DX
+ JMP runtime·morestack11(SB)
+
+TEXT runtime·morestack8_noctxt(SB),NOSPLIT,$0
+ MOVL $0, DX
+ JMP runtime·morestack8(SB)
+
+TEXT runtime·morestack16_noctxt(SB),NOSPLIT,$0
+ MOVL $0, DX
+ JMP runtime·morestack16(SB)
+
+TEXT runtime·morestack24_noctxt(SB),NOSPLIT,$0
+ MOVL $0, DX
+ JMP runtime·morestack24(SB)
+
+TEXT runtime·morestack32_noctxt(SB),NOSPLIT,$0
+ MOVL $0, DX
+ JMP runtime·morestack32(SB)
+
+TEXT runtime·morestack40_noctxt(SB),NOSPLIT,$0
+ MOVL $0, DX
+ JMP runtime·morestack40(SB)
+
+TEXT runtime·morestack48_noctxt(SB),NOSPLIT,$0
+ MOVL $0, DX
+ JMP runtime·morestack48(SB)
+
// bool cas(int32 *val, int32 old, int32 new)
// Atomically:
// if(*val == old){
// is still in this function, and not the beginning of the next.
RET
+TEXT runtime·morestack_noctxt(SB),NOSPLIT,$-4-0
+ MOVW $0, R7
+ JMP runtime·morestack(SB)
+
// Called from panic. Mimics morestack,
// reuses stack growth code to create a frame
// with the desired args running the desired function.