github.com/zxy12/golang151_with_comment@v0.0.0-20190507085033-721809559d3c/runtime/stack1.go (about)

     1  // Copyright 2013 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package runtime
     6  
     7  import "unsafe"
     8  
     9  const (
    10  	// stackDebug == 0: no logging
    11  	//            == 1: logging of per-stack operations
    12  	//            == 2: logging of per-frame operations
    13  	//            == 3: logging of per-word updates
    14  	//            == 4: logging of per-word reads
    15  	stackDebug       = 0
    16  	stackFromSystem  = 0 // allocate stacks from system memory instead of the heap
    17  	stackFaultOnFree = 0 // old stacks are mapped noaccess to detect use after free
    18  	stackPoisonCopy  = 0 // fill stack that should not be accessed with garbage, to detect bad dereferences during copy
    19  
    20  	stackCache = 1
    21  )
    22  
    23  const (
    24  	uintptrMask = 1<<(8*ptrSize) - 1
    25  	poisonStack = uintptrMask & 0x6868686868686868
    26  
    27  	// Goroutine preemption request.
    28  	// Stored into g->stackguard0 to cause split stack check failure.
    29  	// Must be greater than any real sp.
    30  	// 0xfffffade in hex.
    31  	stackPreempt = uintptrMask & -1314
    32  
    33  	// Thread is forking.
    34  	// Stored into g->stackguard0 to cause split stack check failure.
    35  	// Must be greater than any real sp.
    36  	stackFork = uintptrMask & -1234
    37  )
    38  
    39  // Global pool of spans that have free stacks.
    40  // Stacks are assigned an order according to size.
    41  //     order = log_2(size/FixedStack)
    42  // There is a free list for each order.
    43  // TODO: one lock per order?
    44  var stackpool [_NumStackOrders]mspan
    45  var stackpoolmu mutex
    46  
    47  // List of stack spans to be freed at the end of GC. Protected by
    48  // stackpoolmu.
    49  var stackFreeQueue mspan
    50  
    51  // Cached value of haveexperiment("framepointer")
    52  var framepointer_enabled bool
    53  
    54  func stackinit() {
    55  	if _StackCacheSize&_PageMask != 0 {
    56  		throw("cache size must be a multiple of page size")
    57  	}
    58  	for i := range stackpool {
    59  		mSpanList_Init(&stackpool[i])
    60  	}
    61  	mSpanList_Init(&stackFreeQueue)
    62  }
    63  
    64  // Allocates a stack from the free pool.  Must be called with
    65  // stackpoolmu held.
    66  func stackpoolalloc(order uint8) gclinkptr {
    67  	list := &stackpool[order]
    68  	s := list.next
    69  	if s == list {
    70  		// no free stacks.  Allocate another span worth.
    71  		s = mHeap_AllocStack(&mheap_, _StackCacheSize>>_PageShift)
    72  		if s == nil {
    73  			throw("out of memory")
    74  		}
    75  		if s.ref != 0 {
    76  			throw("bad ref")
    77  		}
    78  		if s.freelist.ptr() != nil {
    79  			throw("bad freelist")
    80  		}
    81  		for i := uintptr(0); i < _StackCacheSize; i += _FixedStack << order {
    82  			x := gclinkptr(uintptr(s.start)<<_PageShift + i)
    83  			x.ptr().next = s.freelist
    84  			s.freelist = x
    85  		}
    86  		mSpanList_Insert(list, s)
    87  	}
    88  	x := s.freelist
    89  	if x.ptr() == nil {
    90  		throw("span has no free stacks")
    91  	}
    92  	s.freelist = x.ptr().next
    93  	s.ref++
    94  	if s.freelist.ptr() == nil {
    95  		// all stacks in s are allocated.
    96  		mSpanList_Remove(s)
    97  	}
    98  	return x
    99  }
   100  
   101  // Adds stack x to the free pool.  Must be called with stackpoolmu held.
   102  func stackpoolfree(x gclinkptr, order uint8) {
   103  	s := mHeap_Lookup(&mheap_, (unsafe.Pointer)(x))
   104  	if s.state != _MSpanStack {
   105  		throw("freeing stack not in a stack span")
   106  	}
   107  	if s.freelist.ptr() == nil {
   108  		// s will now have a free stack
   109  		mSpanList_Insert(&stackpool[order], s)
   110  	}
   111  	x.ptr().next = s.freelist
   112  	s.freelist = x
   113  	s.ref--
   114  	if gcphase == _GCoff && s.ref == 0 {
   115  		// Span is completely free. Return it to the heap
   116  		// immediately if we're sweeping.
   117  		//
   118  		// If GC is active, we delay the free until the end of
   119  		// GC to avoid the following type of situation:
   120  		//
   121  		// 1) GC starts, scans a SudoG but does not yet mark the SudoG.elem pointer
   122  		// 2) The stack that pointer points to is copied
   123  		// 3) The old stack is freed
   124  		// 4) The containing span is marked free
   125  		// 5) GC attempts to mark the SudoG.elem pointer. The
   126  		//    marking fails because the pointer looks like a
   127  		//    pointer into a free span.
   128  		//
   129  		// By not freeing, we prevent step #4 until GC is done.
   130  		mSpanList_Remove(s)
   131  		s.freelist = 0
   132  		mHeap_FreeStack(&mheap_, s)
   133  	}
   134  }
   135  
   136  // stackcacherefill/stackcacherelease implement a global pool of stack segments.
   137  // The pool is required to prevent unlimited growth of per-thread caches.
   138  func stackcacherefill(c *mcache, order uint8) {
   139  	if stackDebug >= 1 {
   140  		print("stackcacherefill order=", order, "\n")
   141  	}
   142  
   143  	// Grab some stacks from the global cache.
   144  	// Grab half of the allowed capacity (to prevent thrashing).
   145  	var list gclinkptr
   146  	var size uintptr
   147  	lock(&stackpoolmu)
   148  	for size < _StackCacheSize/2 {
   149  		x := stackpoolalloc(order)
   150  		x.ptr().next = list
   151  		list = x
   152  		size += _FixedStack << order
   153  	}
   154  	unlock(&stackpoolmu)
   155  	c.stackcache[order].list = list
   156  	c.stackcache[order].size = size
   157  }
   158  
   159  func stackcacherelease(c *mcache, order uint8) {
   160  	if stackDebug >= 1 {
   161  		print("stackcacherelease order=", order, "\n")
   162  	}
   163  	x := c.stackcache[order].list
   164  	size := c.stackcache[order].size
   165  	lock(&stackpoolmu)
   166  	for size > _StackCacheSize/2 {
   167  		y := x.ptr().next
   168  		stackpoolfree(x, order)
   169  		x = y
   170  		size -= _FixedStack << order
   171  	}
   172  	unlock(&stackpoolmu)
   173  	c.stackcache[order].list = x
   174  	c.stackcache[order].size = size
   175  }
   176  
   177  func stackcache_clear(c *mcache) {
   178  	if stackDebug >= 1 {
   179  		print("stackcache clear\n")
   180  	}
   181  	lock(&stackpoolmu)
   182  	for order := uint8(0); order < _NumStackOrders; order++ {
   183  		x := c.stackcache[order].list
   184  		for x.ptr() != nil {
   185  			y := x.ptr().next
   186  			stackpoolfree(x, order)
   187  			x = y
   188  		}
   189  		c.stackcache[order].list = 0
   190  		c.stackcache[order].size = 0
   191  	}
   192  	unlock(&stackpoolmu)
   193  }
   194  
   195  func stackalloc(n uint32) (stack, []stkbar) {
   196  	// Stackalloc must be called on scheduler stack, so that we
   197  	// never try to grow the stack during the code that stackalloc runs.
   198  	// Doing so would cause a deadlock (issue 1547).
   199  	thisg := getg()
   200  	if thisg != thisg.m.g0 {
   201  		throw("stackalloc not on scheduler stack")
   202  	}
   203  	if n&(n-1) != 0 {
   204  		throw("stack size not a power of 2")
   205  	}
   206  	if stackDebug >= 1 {
   207  		print("stackalloc ", n, "\n")
   208  	}
   209  
   210  	// Compute the size of stack barrier array.
   211  	maxstkbar := gcMaxStackBarriers(int(n))
   212  	nstkbar := unsafe.Sizeof(stkbar{}) * uintptr(maxstkbar)
   213  
   214  	if debug.efence != 0 || stackFromSystem != 0 {
   215  		v := sysAlloc(round(uintptr(n), _PageSize), &memstats.stacks_sys)
   216  		if v == nil {
   217  			throw("out of memory (stackalloc)")
   218  		}
   219  		top := uintptr(n) - nstkbar
   220  		stkbarSlice := slice{add(v, top), 0, maxstkbar}
   221  		return stack{uintptr(v), uintptr(v) + top}, *(*[]stkbar)(unsafe.Pointer(&stkbarSlice))
   222  	}
   223  
   224  	// Small stacks are allocated with a fixed-size free-list allocator.
   225  	// If we need a stack of a bigger size, we fall back on allocating
   226  	// a dedicated span.
   227  	var v unsafe.Pointer
   228  	if stackCache != 0 && n < _FixedStack<<_NumStackOrders && n < _StackCacheSize {
   229  		order := uint8(0)
   230  		n2 := n
   231  		for n2 > _FixedStack {
   232  			order++
   233  			n2 >>= 1
   234  		}
   235  		var x gclinkptr
   236  		c := thisg.m.mcache
   237  		if c == nil || thisg.m.preemptoff != "" || thisg.m.helpgc != 0 {
   238  			// c == nil can happen in the guts of exitsyscall or
   239  			// procresize. Just get a stack from the global pool.
   240  			// Also don't touch stackcache during gc
   241  			// as it's flushed concurrently.
   242  			lock(&stackpoolmu)
   243  			x = stackpoolalloc(order)
   244  			unlock(&stackpoolmu)
   245  		} else {
   246  			x = c.stackcache[order].list
   247  			if x.ptr() == nil {
   248  				stackcacherefill(c, order)
   249  				x = c.stackcache[order].list
   250  			}
   251  			c.stackcache[order].list = x.ptr().next
   252  			c.stackcache[order].size -= uintptr(n)
   253  		}
   254  		v = (unsafe.Pointer)(x)
   255  	} else {
   256  		s := mHeap_AllocStack(&mheap_, round(uintptr(n), _PageSize)>>_PageShift)
   257  		if s == nil {
   258  			throw("out of memory")
   259  		}
   260  		v = (unsafe.Pointer)(s.start << _PageShift)
   261  	}
   262  
   263  	if raceenabled {
   264  		racemalloc(v, uintptr(n))
   265  	}
   266  	if stackDebug >= 1 {
   267  		print("  allocated ", v, "\n")
   268  	}
   269  	top := uintptr(n) - nstkbar
   270  	stkbarSlice := slice{add(v, top), 0, maxstkbar}
   271  	return stack{uintptr(v), uintptr(v) + top}, *(*[]stkbar)(unsafe.Pointer(&stkbarSlice))
   272  }
   273  
   274  func stackfree(stk stack, n uintptr) {
   275  	gp := getg()
   276  	v := (unsafe.Pointer)(stk.lo)
   277  	if n&(n-1) != 0 {
   278  		throw("stack not a power of 2")
   279  	}
   280  	if stk.lo+n < stk.hi {
   281  		throw("bad stack size")
   282  	}
   283  	if stackDebug >= 1 {
   284  		println("stackfree", v, n)
   285  		memclr(v, n) // for testing, clobber stack data
   286  	}
   287  	if debug.efence != 0 || stackFromSystem != 0 {
   288  		if debug.efence != 0 || stackFaultOnFree != 0 {
   289  			sysFault(v, n)
   290  		} else {
   291  			sysFree(v, n, &memstats.stacks_sys)
   292  		}
   293  		return
   294  	}
   295  	if stackCache != 0 && n < _FixedStack<<_NumStackOrders && n < _StackCacheSize {
   296  		order := uint8(0)
   297  		n2 := n
   298  		for n2 > _FixedStack {
   299  			order++
   300  			n2 >>= 1
   301  		}
   302  		x := gclinkptr(v)
   303  		c := gp.m.mcache
   304  		if c == nil || gp.m.preemptoff != "" || gp.m.helpgc != 0 {
   305  			lock(&stackpoolmu)
   306  			stackpoolfree(x, order)
   307  			unlock(&stackpoolmu)
   308  		} else {
   309  			if c.stackcache[order].size >= _StackCacheSize {
   310  				stackcacherelease(c, order)
   311  			}
   312  			x.ptr().next = c.stackcache[order].list
   313  			c.stackcache[order].list = x
   314  			c.stackcache[order].size += n
   315  		}
   316  	} else {
   317  		s := mHeap_Lookup(&mheap_, v)
   318  		if s.state != _MSpanStack {
   319  			println(hex(s.start<<_PageShift), v)
   320  			throw("bad span state")
   321  		}
   322  		if gcphase == _GCoff {
   323  			// Free the stack immediately if we're
   324  			// sweeping.
   325  			mHeap_FreeStack(&mheap_, s)
   326  		} else {
   327  			// Otherwise, add it to a list of stack spans
   328  			// to be freed at the end of GC.
   329  			//
   330  			// TODO(austin): Make it possible to re-use
   331  			// these spans as stacks, like we do for small
   332  			// stack spans. (See issue #11466.)
   333  			lock(&stackpoolmu)
   334  			mSpanList_Insert(&stackFreeQueue, s)
   335  			unlock(&stackpoolmu)
   336  		}
   337  	}
   338  }
   339  
   340  var maxstacksize uintptr = 1 << 20 // enough until runtime.main sets it for real
   341  
   342  var ptrnames = []string{
   343  	0: "scalar",
   344  	1: "ptr",
   345  }
   346  
   347  // Stack frame layout
   348  //
   349  // (x86)
   350  // +------------------+
   351  // | args from caller |
   352  // +------------------+ <- frame->argp
   353  // |  return address  |
   354  // +------------------+
   355  // |  caller's BP (*) | (*) if framepointer_enabled && varp < sp
   356  // +------------------+ <- frame->varp
   357  // |     locals       |
   358  // +------------------+
   359  // |  args to callee  |
   360  // +------------------+ <- frame->sp
   361  //
   362  // (arm)
   363  // +------------------+
   364  // | args from caller |
   365  // +------------------+ <- frame->argp
   366  // | caller's retaddr |
   367  // +------------------+ <- frame->varp
   368  // |     locals       |
   369  // +------------------+
   370  // |  args to callee  |
   371  // +------------------+
   372  // |  return address  |
   373  // +------------------+ <- frame->sp
   374  
   375  type adjustinfo struct {
   376  	old   stack
   377  	delta uintptr // ptr distance from old to new stack (newbase - oldbase)
   378  }
   379  
   380  // Adjustpointer checks whether *vpp is in the old stack described by adjinfo.
   381  // If so, it rewrites *vpp to point into the new stack.
   382  func adjustpointer(adjinfo *adjustinfo, vpp unsafe.Pointer) {
   383  	pp := (*unsafe.Pointer)(vpp)
   384  	p := *pp
   385  	if stackDebug >= 4 {
   386  		print("        ", pp, ":", p, "\n")
   387  	}
   388  	if adjinfo.old.lo <= uintptr(p) && uintptr(p) < adjinfo.old.hi {
   389  		*pp = add(p, adjinfo.delta)
   390  		if stackDebug >= 3 {
   391  			print("        adjust ptr ", pp, ":", p, " -> ", *pp, "\n")
   392  		}
   393  	}
   394  }
   395  
   396  // Information from the compiler about the layout of stack frames.
   397  type bitvector struct {
   398  	n        int32 // # of bits
   399  	bytedata *uint8
   400  }
   401  
   402  type gobitvector struct {
   403  	n        uintptr
   404  	bytedata []uint8
   405  }
   406  
   407  func gobv(bv bitvector) gobitvector {
   408  	return gobitvector{
   409  		uintptr(bv.n),
   410  		(*[1 << 30]byte)(unsafe.Pointer(bv.bytedata))[:(bv.n+7)/8],
   411  	}
   412  }
   413  
   414  func ptrbit(bv *gobitvector, i uintptr) uint8 {
   415  	return (bv.bytedata[i/8] >> (i % 8)) & 1
   416  }
   417  
   418  // bv describes the memory starting at address scanp.
   419  // Adjust any pointers contained therein.
   420  func adjustpointers(scanp unsafe.Pointer, cbv *bitvector, adjinfo *adjustinfo, f *_func) {
   421  	bv := gobv(*cbv)
   422  	minp := adjinfo.old.lo
   423  	maxp := adjinfo.old.hi
   424  	delta := adjinfo.delta
   425  	num := uintptr(bv.n)
   426  	for i := uintptr(0); i < num; i++ {
   427  		if stackDebug >= 4 {
   428  			print("        ", add(scanp, i*ptrSize), ":", ptrnames[ptrbit(&bv, i)], ":", hex(*(*uintptr)(add(scanp, i*ptrSize))), " # ", i, " ", bv.bytedata[i/8], "\n")
   429  		}
   430  		if ptrbit(&bv, i) == 1 {
   431  			pp := (*uintptr)(add(scanp, i*ptrSize))
   432  			p := *pp
   433  			if f != nil && 0 < p && p < _PageSize && debug.invalidptr != 0 || p == poisonStack {
   434  				// Looks like a junk value in a pointer slot.
   435  				// Live analysis wrong?
   436  				getg().m.traceback = 2
   437  				print("runtime: bad pointer in frame ", funcname(f), " at ", pp, ": ", hex(p), "\n")
   438  				throw("invalid stack pointer")
   439  			}
   440  			if minp <= p && p < maxp {
   441  				if stackDebug >= 3 {
   442  					print("adjust ptr ", p, " ", funcname(f), "\n")
   443  				}
   444  				*pp = p + delta
   445  			}
   446  		}
   447  	}
   448  }
   449  
   450  // Note: the argument/return area is adjusted by the callee.
   451  func adjustframe(frame *stkframe, arg unsafe.Pointer) bool {
   452  	adjinfo := (*adjustinfo)(arg)
   453  	targetpc := frame.continpc
   454  	if targetpc == 0 {
   455  		// Frame is dead.
   456  		return true
   457  	}
   458  	f := frame.fn
   459  	if stackDebug >= 2 {
   460  		print("    adjusting ", funcname(f), " frame=[", hex(frame.sp), ",", hex(frame.fp), "] pc=", hex(frame.pc), " continpc=", hex(frame.continpc), "\n")
   461  	}
   462  	if f.entry == systemstack_switchPC {
   463  		// A special routine at the bottom of stack of a goroutine that does an systemstack call.
   464  		// We will allow it to be copied even though we don't
   465  		// have full GC info for it (because it is written in asm).
   466  		return true
   467  	}
   468  	if targetpc != f.entry {
   469  		targetpc--
   470  	}
   471  	pcdata := pcdatavalue(f, _PCDATA_StackMapIndex, targetpc)
   472  	if pcdata == -1 {
   473  		pcdata = 0 // in prologue
   474  	}
   475  
   476  	// Adjust local variables if stack frame has been allocated.
   477  	size := frame.varp - frame.sp
   478  	var minsize uintptr
   479  	switch thechar {
   480  	case '6', '8':
   481  		minsize = 0
   482  	case '7':
   483  		minsize = spAlign
   484  	default:
   485  		minsize = ptrSize
   486  	}
   487  	if size > minsize {
   488  		var bv bitvector
   489  		stackmap := (*stackmap)(funcdata(f, _FUNCDATA_LocalsPointerMaps))
   490  		if stackmap == nil || stackmap.n <= 0 {
   491  			print("runtime: frame ", funcname(f), " untyped locals ", hex(frame.varp-size), "+", hex(size), "\n")
   492  			throw("missing stackmap")
   493  		}
   494  		// Locals bitmap information, scan just the pointers in locals.
   495  		if pcdata < 0 || pcdata >= stackmap.n {
   496  			// don't know where we are
   497  			print("runtime: pcdata is ", pcdata, " and ", stackmap.n, " locals stack map entries for ", funcname(f), " (targetpc=", targetpc, ")\n")
   498  			throw("bad symbol table")
   499  		}
   500  		bv = stackmapdata(stackmap, pcdata)
   501  		size = uintptr(bv.n) * ptrSize
   502  		if stackDebug >= 3 {
   503  			print("      locals ", pcdata, "/", stackmap.n, " ", size/ptrSize, " words ", bv.bytedata, "\n")
   504  		}
   505  		adjustpointers(unsafe.Pointer(frame.varp-size), &bv, adjinfo, f)
   506  	}
   507  
   508  	// Adjust saved base pointer if there is one.
   509  	if thechar == '6' && frame.argp-frame.varp == 2*regSize {
   510  		if !framepointer_enabled {
   511  			print("runtime: found space for saved base pointer, but no framepointer experiment\n")
   512  			print("argp=", hex(frame.argp), " varp=", hex(frame.varp), "\n")
   513  			throw("bad frame layout")
   514  		}
   515  		if stackDebug >= 3 {
   516  			print("      saved bp\n")
   517  		}
   518  		adjustpointer(adjinfo, unsafe.Pointer(frame.varp))
   519  	}
   520  
   521  	// Adjust arguments.
   522  	if frame.arglen > 0 {
   523  		var bv bitvector
   524  		if frame.argmap != nil {
   525  			bv = *frame.argmap
   526  		} else {
   527  			stackmap := (*stackmap)(funcdata(f, _FUNCDATA_ArgsPointerMaps))
   528  			if stackmap == nil || stackmap.n <= 0 {
   529  				print("runtime: frame ", funcname(f), " untyped args ", frame.argp, "+", uintptr(frame.arglen), "\n")
   530  				throw("missing stackmap")
   531  			}
   532  			if pcdata < 0 || pcdata >= stackmap.n {
   533  				// don't know where we are
   534  				print("runtime: pcdata is ", pcdata, " and ", stackmap.n, " args stack map entries for ", funcname(f), " (targetpc=", targetpc, ")\n")
   535  				throw("bad symbol table")
   536  			}
   537  			bv = stackmapdata(stackmap, pcdata)
   538  		}
   539  		if stackDebug >= 3 {
   540  			print("      args\n")
   541  		}
   542  		adjustpointers(unsafe.Pointer(frame.argp), &bv, adjinfo, nil)
   543  	}
   544  	return true
   545  }
   546  
   547  func adjustctxt(gp *g, adjinfo *adjustinfo) {
   548  	adjustpointer(adjinfo, (unsafe.Pointer)(&gp.sched.ctxt))
   549  }
   550  
   551  func adjustdefers(gp *g, adjinfo *adjustinfo) {
   552  	// Adjust defer argument blocks the same way we adjust active stack frames.
   553  	tracebackdefers(gp, adjustframe, noescape(unsafe.Pointer(adjinfo)))
   554  
   555  	// Adjust pointers in the Defer structs.
   556  	// Defer structs themselves are never on the stack.
   557  	for d := gp._defer; d != nil; d = d.link {
   558  		adjustpointer(adjinfo, (unsafe.Pointer)(&d.fn))
   559  		adjustpointer(adjinfo, (unsafe.Pointer)(&d.sp))
   560  		adjustpointer(adjinfo, (unsafe.Pointer)(&d._panic))
   561  	}
   562  }
   563  
   564  func adjustpanics(gp *g, adjinfo *adjustinfo) {
   565  	// Panics are on stack and already adjusted.
   566  	// Update pointer to head of list in G.
   567  	adjustpointer(adjinfo, (unsafe.Pointer)(&gp._panic))
   568  }
   569  
   570  func adjustsudogs(gp *g, adjinfo *adjustinfo) {
   571  	// the data elements pointed to by a SudoG structure
   572  	// might be in the stack.
   573  	for s := gp.waiting; s != nil; s = s.waitlink {
   574  		adjustpointer(adjinfo, (unsafe.Pointer)(&s.elem))
   575  		adjustpointer(adjinfo, (unsafe.Pointer)(&s.selectdone))
   576  	}
   577  }
   578  
   579  func adjuststkbar(gp *g, adjinfo *adjustinfo) {
   580  	for i := int(gp.stkbarPos); i < len(gp.stkbar); i++ {
   581  		adjustpointer(adjinfo, (unsafe.Pointer)(&gp.stkbar[i].savedLRPtr))
   582  	}
   583  }
   584  
   585  func fillstack(stk stack, b byte) {
   586  	for p := stk.lo; p < stk.hi; p++ {
   587  		*(*byte)(unsafe.Pointer(p)) = b
   588  	}
   589  }
   590  
   591  // Copies gp's stack to a new stack of a different size.
   592  // Caller must have changed gp status to Gcopystack.
   593  func copystack(gp *g, newsize uintptr) {
   594  	if gp.syscallsp != 0 {
   595  		throw("stack growth not allowed in system call")
   596  	}
   597  	old := gp.stack
   598  	if old.lo == 0 {
   599  		throw("nil stackbase")
   600  	}
   601  	used := old.hi - gp.sched.sp
   602  
   603  	// allocate new stack
   604  	new, newstkbar := stackalloc(uint32(newsize))
   605  	if stackPoisonCopy != 0 {
   606  		fillstack(new, 0xfd)
   607  	}
   608  	if stackDebug >= 1 {
   609  		print("copystack gp=", gp, " [", hex(old.lo), " ", hex(old.hi-used), " ", hex(old.hi), "]/", gp.stackAlloc, " -> [", hex(new.lo), " ", hex(new.hi-used), " ", hex(new.hi), "]/", newsize, "\n")
   610  	}
   611  
   612  	// adjust pointers in the to-be-copied frames
   613  	var adjinfo adjustinfo
   614  	adjinfo.old = old
   615  	adjinfo.delta = new.hi - old.hi
   616  	gentraceback(^uintptr(0), ^uintptr(0), 0, gp, 0, nil, 0x7fffffff, adjustframe, noescape(unsafe.Pointer(&adjinfo)), 0)
   617  
   618  	// adjust other miscellaneous things that have pointers into stacks.
   619  	adjustctxt(gp, &adjinfo)
   620  	adjustdefers(gp, &adjinfo)
   621  	adjustpanics(gp, &adjinfo)
   622  	adjustsudogs(gp, &adjinfo)
   623  	adjuststkbar(gp, &adjinfo)
   624  
   625  	// copy the stack to the new location
   626  	if stackPoisonCopy != 0 {
   627  		fillstack(new, 0xfb)
   628  	}
   629  	memmove(unsafe.Pointer(new.hi-used), unsafe.Pointer(old.hi-used), used)
   630  
   631  	// copy old stack barriers to new stack barrier array
   632  	newstkbar = newstkbar[:len(gp.stkbar)]
   633  	copy(newstkbar, gp.stkbar)
   634  
   635  	// Swap out old stack for new one
   636  	gp.stack = new
   637  	gp.stackguard0 = new.lo + _StackGuard // NOTE: might clobber a preempt request
   638  	gp.sched.sp = new.hi - used
   639  	oldsize := gp.stackAlloc
   640  	gp.stackAlloc = newsize
   641  	gp.stkbar = newstkbar
   642  
   643  	// free old stack
   644  	if stackPoisonCopy != 0 {
   645  		fillstack(old, 0xfc)
   646  	}
   647  	stackfree(old, oldsize)
   648  }
   649  
   650  // round x up to a power of 2.
   651  func round2(x int32) int32 {
   652  	s := uint(0)
   653  	for 1<<s < x {
   654  		s++
   655  	}
   656  	return 1 << s
   657  }
   658  
   659  // Called from runtime·morestack when more stack is needed.
   660  // Allocate larger stack and relocate to new stack.
   661  // Stack growth is multiplicative, for constant amortized cost.
   662  //
   663  // g->atomicstatus will be Grunning or Gscanrunning upon entry.
   664  // If the GC is trying to stop this g then it will set preemptscan to true.
   665  func newstack() {
   666  	thisg := getg()
   667  	// TODO: double check all gp. shouldn't be getg().
   668  	if thisg.m.morebuf.g.ptr().stackguard0 == stackFork {
   669  		throw("stack growth after fork")
   670  	}
   671  	if thisg.m.morebuf.g.ptr() != thisg.m.curg {
   672  		print("runtime: newstack called from g=", thisg.m.morebuf.g, "\n"+"\tm=", thisg.m, " m->curg=", thisg.m.curg, " m->g0=", thisg.m.g0, " m->gsignal=", thisg.m.gsignal, "\n")
   673  		morebuf := thisg.m.morebuf
   674  		traceback(morebuf.pc, morebuf.sp, morebuf.lr, morebuf.g.ptr())
   675  		throw("runtime: wrong goroutine in newstack")
   676  	}
   677  	if thisg.m.curg.throwsplit {
   678  		gp := thisg.m.curg
   679  		// Update syscallsp, syscallpc in case traceback uses them.
   680  		morebuf := thisg.m.morebuf
   681  		gp.syscallsp = morebuf.sp
   682  		gp.syscallpc = morebuf.pc
   683  		print("runtime: newstack sp=", hex(gp.sched.sp), " stack=[", hex(gp.stack.lo), ", ", hex(gp.stack.hi), "]\n",
   684  			"\tmorebuf={pc:", hex(morebuf.pc), " sp:", hex(morebuf.sp), " lr:", hex(morebuf.lr), "}\n",
   685  			"\tsched={pc:", hex(gp.sched.pc), " sp:", hex(gp.sched.sp), " lr:", hex(gp.sched.lr), " ctxt:", gp.sched.ctxt, "}\n")
   686  
   687  		traceback(morebuf.pc, morebuf.sp, morebuf.lr, gp)
   688  		throw("runtime: stack split at bad time")
   689  	}
   690  
   691  	gp := thisg.m.curg
   692  	morebuf := thisg.m.morebuf
   693  	thisg.m.morebuf.pc = 0
   694  	thisg.m.morebuf.lr = 0
   695  	thisg.m.morebuf.sp = 0
   696  	thisg.m.morebuf.g = 0
   697  	rewindmorestack(&gp.sched)
   698  
   699  	// NOTE: stackguard0 may change underfoot, if another thread
   700  	// is about to try to preempt gp. Read it just once and use that same
   701  	// value now and below.
   702  	preempt := atomicloaduintptr(&gp.stackguard0) == stackPreempt
   703  
   704  	// Be conservative about where we preempt.
   705  	// We are interested in preempting user Go code, not runtime code.
   706  	// If we're holding locks, mallocing, or preemption is disabled, don't
   707  	// preempt.
   708  	// This check is very early in newstack so that even the status change
   709  	// from Grunning to Gwaiting and back doesn't happen in this case.
   710  	// That status change by itself can be viewed as a small preemption,
   711  	// because the GC might change Gwaiting to Gscanwaiting, and then
   712  	// this goroutine has to wait for the GC to finish before continuing.
   713  	// If the GC is in some way dependent on this goroutine (for example,
   714  	// it needs a lock held by the goroutine), that small preemption turns
   715  	// into a real deadlock.
   716  	if preempt {
   717  		if thisg.m.locks != 0 || thisg.m.mallocing != 0 || thisg.m.preemptoff != "" || thisg.m.p.ptr().status != _Prunning {
   718  			// Let the goroutine keep running for now.
   719  			// gp->preempt is set, so it will be preempted next time.
   720  			gp.stackguard0 = gp.stack.lo + _StackGuard
   721  			gogo(&gp.sched) // never return
   722  		}
   723  	}
   724  
   725  	// The goroutine must be executing in order to call newstack,
   726  	// so it must be Grunning (or Gscanrunning).
   727  	casgstatus(gp, _Grunning, _Gwaiting)
   728  	gp.waitreason = "stack growth"
   729  
   730  	if gp.stack.lo == 0 {
   731  		throw("missing stack in newstack")
   732  	}
   733  	sp := gp.sched.sp
   734  	if thechar == '6' || thechar == '8' {
   735  		// The call to morestack cost a word.
   736  		sp -= ptrSize
   737  	}
   738  	if stackDebug >= 1 || sp < gp.stack.lo {
   739  		print("runtime: newstack sp=", hex(sp), " stack=[", hex(gp.stack.lo), ", ", hex(gp.stack.hi), "]\n",
   740  			"\tmorebuf={pc:", hex(morebuf.pc), " sp:", hex(morebuf.sp), " lr:", hex(morebuf.lr), "}\n",
   741  			"\tsched={pc:", hex(gp.sched.pc), " sp:", hex(gp.sched.sp), " lr:", hex(gp.sched.lr), " ctxt:", gp.sched.ctxt, "}\n")
   742  	}
   743  	if sp < gp.stack.lo {
   744  		print("runtime: gp=", gp, ", gp->status=", hex(readgstatus(gp)), "\n ")
   745  		print("runtime: split stack overflow: ", hex(sp), " < ", hex(gp.stack.lo), "\n")
   746  		throw("runtime: split stack overflow")
   747  	}
   748  
   749  	if gp.sched.ctxt != nil {
   750  		// morestack wrote sched.ctxt on its way in here,
   751  		// without a write barrier. Run the write barrier now.
   752  		// It is not possible to be preempted between then
   753  		// and now, so it's okay.
   754  		writebarrierptr_nostore((*uintptr)(unsafe.Pointer(&gp.sched.ctxt)), uintptr(gp.sched.ctxt))
   755  	}
   756  
   757  	if preempt {
   758  		if gp == thisg.m.g0 {
   759  			throw("runtime: preempt g0")
   760  		}
   761  		if thisg.m.p == 0 && thisg.m.locks == 0 {
   762  			throw("runtime: g is running but p is not")
   763  		}
   764  		if gp.preemptscan {
   765  			for !castogscanstatus(gp, _Gwaiting, _Gscanwaiting) {
   766  				// Likely to be racing with the GC as
   767  				// it sees a _Gwaiting and does the
   768  				// stack scan. If so, gcworkdone will
   769  				// be set and gcphasework will simply
   770  				// return.
   771  			}
   772  			if !gp.gcscandone {
   773  				scanstack(gp)
   774  				gp.gcscandone = true
   775  			}
   776  			gp.preemptscan = false
   777  			gp.preempt = false
   778  			casfrom_Gscanstatus(gp, _Gscanwaiting, _Gwaiting)
   779  			casgstatus(gp, _Gwaiting, _Grunning)
   780  			gp.stackguard0 = gp.stack.lo + _StackGuard
   781  			gogo(&gp.sched) // never return
   782  		}
   783  
   784  		// Act like goroutine called runtime.Gosched.
   785  		casgstatus(gp, _Gwaiting, _Grunning)
   786  		gopreempt_m(gp) // never return
   787  	}
   788  
   789  	// Allocate a bigger segment and move the stack.
   790  	oldsize := int(gp.stackAlloc)
   791  	newsize := oldsize * 2
   792  	if uintptr(newsize) > maxstacksize {
   793  		print("runtime: goroutine stack exceeds ", maxstacksize, "-byte limit\n")
   794  		throw("stack overflow")
   795  	}
   796  
   797  	casgstatus(gp, _Gwaiting, _Gcopystack)
   798  
   799  	// The concurrent GC will not scan the stack while we are doing the copy since
   800  	// the gp is in a Gcopystack status.
   801  	copystack(gp, uintptr(newsize))
   802  	if stackDebug >= 1 {
   803  		print("stack grow done\n")
   804  	}
   805  	casgstatus(gp, _Gcopystack, _Grunning)
   806  	gogo(&gp.sched)
   807  }
   808  
   809  //go:nosplit
   810  func nilfunc() {
   811  	*(*uint8)(nil) = 0
   812  }
   813  
   814  // adjust Gobuf as if it executed a call to fn
   815  // and then did an immediate gosave.
   816  func gostartcallfn(gobuf *gobuf, fv *funcval) {
   817  	var fn unsafe.Pointer
   818  	if fv != nil {
   819  		fn = (unsafe.Pointer)(fv.fn)
   820  	} else {
   821  		fn = unsafe.Pointer(funcPC(nilfunc))
   822  	}
   823  	gostartcall(gobuf, fn, (unsafe.Pointer)(fv))
   824  }
   825  
   826  // Maybe shrink the stack being used by gp.
   827  // Called at garbage collection time.
   828  func shrinkstack(gp *g) {
   829  	if readgstatus(gp) == _Gdead {
   830  		if gp.stack.lo != 0 {
   831  			// Free whole stack - it will get reallocated
   832  			// if G is used again.
   833  			stackfree(gp.stack, gp.stackAlloc)
   834  			gp.stack.lo = 0
   835  			gp.stack.hi = 0
   836  			gp.stkbar = nil
   837  			gp.stkbarPos = 0
   838  		}
   839  		return
   840  	}
   841  	if gp.stack.lo == 0 {
   842  		throw("missing stack in shrinkstack")
   843  	}
   844  
   845  	if debug.gcshrinkstackoff > 0 {
   846  		return
   847  	}
   848  
   849  	oldsize := gp.stackAlloc
   850  	newsize := oldsize / 2
   851  	// Don't shrink the allocation below the minimum-sized stack
   852  	// allocation.
   853  	if newsize < _FixedStack {
   854  		return
   855  	}
   856  	// Compute how much of the stack is currently in use and only
   857  	// shrink the stack if gp is using less than a quarter of its
   858  	// current stack. The currently used stack includes everything
   859  	// down to the SP plus the stack guard space that ensures
   860  	// there's room for nosplit functions.
   861  	avail := gp.stack.hi - gp.stack.lo
   862  	if used := gp.stack.hi - gp.sched.sp + _StackLimit; used >= avail/4 {
   863  		return
   864  	}
   865  
   866  	// We can't copy the stack if we're in a syscall.
   867  	// The syscall might have pointers into the stack.
   868  	if gp.syscallsp != 0 {
   869  		return
   870  	}
   871  	if goos_windows != 0 && gp.m != nil && gp.m.libcallsp != 0 {
   872  		return
   873  	}
   874  
   875  	if stackDebug > 0 {
   876  		print("shrinking stack ", oldsize, "->", newsize, "\n")
   877  	}
   878  
   879  	oldstatus := casgcopystack(gp)
   880  	copystack(gp, newsize)
   881  	casgstatus(gp, _Gcopystack, oldstatus)
   882  }
   883  
   884  // freeStackSpans frees unused stack spans at the end of GC.
   885  func freeStackSpans() {
   886  	lock(&stackpoolmu)
   887  
   888  	// Scan stack pools for empty stack spans.
   889  	for order := range stackpool {
   890  		list := &stackpool[order]
   891  		for s := list.next; s != list; {
   892  			next := s.next
   893  			if s.ref == 0 {
   894  				mSpanList_Remove(s)
   895  				s.freelist = 0
   896  				mHeap_FreeStack(&mheap_, s)
   897  			}
   898  			s = next
   899  		}
   900  	}
   901  
   902  	// Free queued stack spans.
   903  	for stackFreeQueue.next != &stackFreeQueue {
   904  		s := stackFreeQueue.next
   905  		mSpanList_Remove(s)
   906  		mHeap_FreeStack(&mheap_, s)
   907  	}
   908  
   909  	unlock(&stackpoolmu)
   910  }
   911  
   912  //go:nosplit
   913  func morestackc() {
   914  	systemstack(func() {
   915  		throw("attempt to execute C code on Go stack")
   916  	})
   917  }