package main func main() { a, b := 1, 2 _ = add1(a, b) _ = add2(a, b) } func add1(x, y int) int { return x + y } func add2(x, y int) int { _ = make([]byte, 200) return x + y }
// Called during function prolog when more stack is needed. // // The traceback routines see morestack on a g0 as being // the top of a stack (for example, morestack calling newstack // calling the scheduler calling newm calling gc), so we must // record an argument size. For that purpose, it has no arguments. TEXT runtime·morestack(SB),NOSPLIT,$0-0 // Cannot grow scheduler stack (m->g0). get_tls(CX) MOVQ g(CX), BX MOVQ g_m(BX), BX MOVQ m_g0(BX), SI CMPQ g(CX), SI JNE 3(PC) CALL runtime·badmorestackg0(SB) INT $3 // 省略signal stack、morebuf和sched的处理 ... // Call newstack on m->g0's stack. MOVQ m_g0(BX), BX MOVQ BX, g(CX) MOVQ (g_sched+gobuf_sp)(BX), SP PUSHQ DX // ctxt argument // 调用runtime.newstack完成栈扩容 CALL runtime·newstack(SB) MOVQ $0, 0x1003 // crash if newstack returns POPQ DX // keep balance check happy RET // morestack but not preserving ctxt. TEXT runtime·morestack_noctxt(SB),NOSPLIT,$0 MOVL $0, DX // 调用morestack JMP runtime·morestack(SB)
// Called from runtime·morestack when more stack is needed. // Allocate larger stack and relocate to new stack. // Stack growth is multiplicative, for constant amortized cost. // // g->atomicstatus will be Grunning or Gscanrunning upon entry. // If the GC is trying to stop this g then it will set preemptscan to true. // // ctxt is the value of the context register on morestack. newstack // will write it to g.sched.ctxt. func newstack(ctxt unsafe.Pointer) { thisg := getg() gp := thisg.m.curg // 扩容至现在的2倍 oldsize := int(gp.stackAlloc) newsize := oldsize * 2 // The goroutine must be executing in order to call newstack, // so it must be Grunning (or Gscanrunning). casgstatus(gp, _Grunning, _Gcopystack) // The concurrent GC will not scan the stack while we are doing the copy since // the gp is in a Gcopystack status. // 拷贝栈数据后切换到新栈 copystack(gp, uintptr(newsize), true) if stackDebug >= 1 { print("stack grow done\n") } // 恢复执行 casgstatus(gp, _Gcopystack, _Grunning) gogo(&gp.sched) } // Copies gp's stack to a new stack of a different size. // Caller must have changed gp status to Gcopystack. // // If sync is true, this is a self-triggered stack growth and, in // particular, no other G may be writing to gp's stack (e.g., via a // channel operation). If sync is false, copystack protects against // concurrent channel operations. func copystack(gp *g, newsize uintptr, sync bool) { if gp.syscallsp != 0 { throw("stack growth not allowed in system call") } old := gp.stack if old.lo == 0 { throw("nil stackbase") } used := old.hi - gp.sched.sp // 从缓存或堆分配新栈 new, newstkbar := stackalloc(uint32(newsize)) if stackPoisonCopy != 0 { fillstack(new, 0xfd) } // Compute adjustment. var adjinfo adjustinfo adjinfo.old = old adjinfo.delta = new.hi - old.hi // Adjust sudogs, synchronizing with channel ops if necessary. ncopy := used if sync { adjustsudogs(gp, &adjinfo) } else { // sudogs can point in to the stack. During concurrent // shrinking, these areas may be written to. Find the // highest such pointer so we can handle everything // there and below carefully. (This shouldn't be far // from the bottom of the stack, so there's little // cost in handling everything below it carefully.) adjinfo.sghi = findsghi(gp, old) // Synchronize with channel ops and copy the part of // the stack they may interact with. ncopy -= syncadjustsudogs(gp, used, &adjinfo) } // 拷贝栈到新的位置 memmove(unsafe.Pointer(new.hi-ncopy), unsafe.Pointer(old.hi-ncopy), ncopy) // 切换到新栈 gp.stack = new gp.stackguard0 = new.lo + _StackGuard // NOTE: might clobber a preempt request gp.sched.sp = new.hi - used oldsize := gp.stackAlloc gp.stackAlloc = newsize gp.stkbar = newstkbar gp.stktopsp += adjinfo.delta // Adjust pointers in the new stack. gentraceback(^uintptr(0), ^uintptr(0), 0, gp, 0, nil, 0x7fffffff, adjustframe, noescape(unsafe.Pointer(&adjinfo)), 0) gcUnlockStackBarriers(gp) // 释放旧栈 if stackPoisonCopy != 0 { fillstack(old, 0xfc) } stackfree(old, oldsize) }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 25岁的心里话
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现