Пример #1
0
// Called from reflect·call or from runtime·morestack when a new
// stack segment is needed.  Allocate a new stack big enough for
// m->moreframesize bytes, copy m->moreargsize bytes to the new frame,
// and then act as though runtime·lessstack called the function at
// m->morepc.
// 当需要一个新的栈段时调用,被reflect.call或者runtime.morestack调用
// 分配一个足够大的新栈,至少大于m->moreframesize。将m->moreargsize字节复制到新的栈帧。
// 然后伪装成在m->morepc处调用函数runtime.lessstack的样子。
void
runtime·newstack(void)
{
	int32 framesize, minalloc, argsize;
	Stktop *top;
	byte *stk, *sp;
	uintptr *src, *dst, *dstend;
	G *gp;
	Gobuf label;
	bool reflectcall;
	uintptr free;

	framesize = m->moreframesize;
	argsize = m->moreargsize;
	gp = m->curg;

	if(m->morebuf.sp < gp->stackguard - StackGuard) { //栈已经溢出
		runtime·printf("runtime: split stack overflow: %p < %p\n", m->morebuf.sp, gp->stackguard - StackGuard);
		runtime·throw("runtime: split stack overflow");
	}
	if(argsize % sizeof(uintptr) != 0) { //参数未对齐
		runtime·printf("runtime: stack split with misaligned argsize %d\n", argsize);
		runtime·throw("runtime: stack split argsize");
	}

	minalloc = 0;
	reflectcall = framesize==1;
	if(reflectcall) {
		framesize = 0;
		// moreframesize_minalloc is only set in runtime·gc(),
		// that calls newstack via reflect·call().
		minalloc = m->moreframesize_minalloc;
		m->moreframesize_minalloc = 0;
		if(framesize < minalloc)
			framesize = minalloc;
	}

	if(reflectcall && minalloc == 0 && m->morebuf.sp - sizeof(Stktop) - argsize - 32 > gp->stackguard) {
		// special case: called from reflect.call (framesize==1)
		// to call code with an arbitrary argument size,
		// and we have enough space on the current stack.
		// the new Stktop* is necessary to unwind, but
		// we don't need to create a new segment.
		top = (Stktop*)(m->morebuf.sp - sizeof(*top));
		stk = (byte*)gp->stackguard - StackGuard;
		free = 0;
	} else {
		// 分配新空间
		// framesize大小,必须包含参数大小部分,为调用runtime.morestack保留部分,并且至少大于StackMin。然后还要加上StackSystem部分
		framesize += argsize;
		framesize += StackExtra;	// room for more functions, Stktop.
		if(framesize < StackMin)
			framesize = StackMin;
		framesize += StackSystem;
		stk = runtime·stackalloc(framesize);
		top = (Stktop*)(stk+framesize-sizeof(*top)); 
		free = framesize;
	}

	if(0) {
		runtime·printf("newstack framesize=%d argsize=%d morepc=%p moreargp=%p gobuf=%p, %p top=%p old=%p\n",
			framesize, argsize, m->morepc, m->moreargp, m->morebuf.pc, m->morebuf.sp, top, gp->stackbase);
	}

	//将一些重要信息从结构体g中移到栈顶Stktop中
	top->stackbase = (byte*)gp->stackbase;
	top->stackguard = (byte*)gp->stackguard; 
	top->gobuf = m->morebuf; //只是借助m结构体临时传了一下参数,morebuf中记录的是栈空间不够的那个函数的pc,sp,g
	top->argp = m->moreargp; //参数
	top->argsize = argsize; //参数大小
	top->free = free; //可用空间大小
	m->moreargp = nil;
	m->morebuf.pc = nil;
	m->morebuf.sp = (uintptr)nil;

	// copy flag from panic
	top->panic = gp->ispanic;
	gp->ispanic = false;

	gp->stackbase = (uintptr)top;
	gp->stackguard = (uintptr)stk + StackGuard; //每个goroutine的g->stackguard设置成指向栈底上面StackGuard的位置。

	//装饰栈顶的参数区域
	sp = (byte*)top;
	if(argsize > 0) { //将参数移过来
		sp -= argsize;
		dst = (uintptr*)sp;
		dstend = dst + argsize/sizeof(*dst);
		src = (uintptr*)top->argp;
		while(dst < dstend)
			*dst++ = *src++;
	}
	if(thechar == '5') { //编译器标识
		// caller would have saved its LR below args.
		sp -= sizeof(void*);
		*(void**)sp = nil;
	}

	// Continue as if lessstack had just called m->morepc
	// (the PC that decided to grow the stack).
	// 继续,伪装成好像是从m->morepc中调用lessstack函数的状态
	// 跳转
	label.sp = (uintptr)sp;
	label.pc = (byte*)runtime·lessstack;
	label.g = m->curg;
	if(reflectcall)
		runtime·gogocallfn(&label, (FuncVal*)m->morepc);
	else
		runtime·gogocall(&label, m->morepc, m->cret); //gogocall相当于一个直接的jmp,不是按函数协议跳转的

	*(int32*)345 = 123;	// never return
}
Пример #2
0
// Called from reflect·call or from runtime·morestack when a new
// stack segment is needed.  Allocate a new stack big enough for
// m->moreframesize bytes, copy m->moreargsize bytes to the new frame,
// and then act as though runtime·lessstack called the function at
// m->morepc.
void
runtime·newstack(void)
{
	int32 framesize, minalloc, argsize;
	Stktop *top;
	byte *stk, *sp;
	uintptr *src, *dst, *dstend;
	G *gp;
	Gobuf label;
	bool reflectcall;
	uintptr free;

	framesize = m->moreframesize;
	argsize = m->moreargsize;
	gp = m->curg;

	if(m->morebuf.sp < gp->stackguard - StackGuard) {
		runtime·printf("runtime: split stack overflow: %p < %p\n", m->morebuf.sp, gp->stackguard - StackGuard);
		runtime·throw("runtime: split stack overflow");
	}
	if(argsize % sizeof(uintptr) != 0) {
		runtime·printf("runtime: stack split with misaligned argsize %d\n", argsize);
		runtime·throw("runtime: stack split argsize");
	}

	minalloc = 0;
	reflectcall = framesize==1;
	if(reflectcall) {
		framesize = 0;
		// moreframesize_minalloc is only set in runtime·gc(),
		// that calls newstack via reflect·call().
		minalloc = m->moreframesize_minalloc;
		m->moreframesize_minalloc = 0;
		if(framesize < minalloc)
			framesize = minalloc;
	}

	if(reflectcall && minalloc == 0 && m->morebuf.sp - sizeof(Stktop) - argsize - 32 > gp->stackguard) {
		// special case: called from reflect.call (framesize==1)
		// to call code with an arbitrary argument size,
		// and we have enough space on the current stack.
		// the new Stktop* is necessary to unwind, but
		// we don't need to create a new segment.
		top = (Stktop*)(m->morebuf.sp - sizeof(*top));
		stk = (byte*)gp->stackguard - StackGuard;
		free = 0;
	} else {
		// allocate new segment.
		framesize += argsize;
		framesize += StackExtra;	// room for more functions, Stktop.
		if(framesize < StackMin)
			framesize = StackMin;
		framesize += StackSystem;
		stk = runtime·stackalloc(framesize);
		top = (Stktop*)(stk+framesize-sizeof(*top));
		free = framesize;
	}

	if(0) {
		runtime·printf("newstack framesize=%d argsize=%d morepc=%p moreargp=%p gobuf=%p, %p top=%p old=%p\n",
			framesize, argsize, m->morepc, m->moreargp, m->morebuf.pc, m->morebuf.sp, top, gp->stackbase);
	}

	top->stackbase = (byte*)gp->stackbase;
	top->stackguard = (byte*)gp->stackguard;
	top->gobuf = m->morebuf;
	top->argp = m->moreargp;
	top->argsize = argsize;
	top->free = free;
	m->moreargp = nil;
	m->morebuf.pc = nil;
	m->morebuf.sp = (uintptr)nil;

	// copy flag from panic
	top->panic = gp->ispanic;
	gp->ispanic = false;

	gp->stackbase = (uintptr)top;
	gp->stackguard = (uintptr)stk + StackGuard;

	sp = (byte*)top;
	if(argsize > 0) {
		sp -= argsize;
		dst = (uintptr*)sp;
		dstend = dst + argsize/sizeof(*dst);
		src = (uintptr*)top->argp;
		while(dst < dstend)
			*dst++ = *src++;
	}
	if(thechar == '5') {
		// caller would have saved its LR below args.
		sp -= sizeof(void*);
		*(void**)sp = nil;
	}

	// Continue as if lessstack had just called m->morepc
	// (the PC that decided to grow the stack).
	label.sp = (uintptr)sp;
	label.pc = (byte*)runtime·lessstack;
	label.g = m->curg;
	if(reflectcall)
		runtime·gogocallfn(&label, (FuncVal*)m->morepc);
	else
		runtime·gogocall(&label, m->morepc, m->cret);

	*(int32*)345 = 123;	// never return
}