runtime: remove unused stack.go

We're never going to use stack.go for gccgo.  Although a build tag
keeps it from being built, even having it around can be confusing.
Remove it.

Change-Id: If23657d400608226c3aaf70d37808b957f0c0528
Reviewed-on: https://go-review.googlesource.com/40774
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Reviewed-by: Than McIntosh <thanm@google.com>
diff --git a/libgo/go/runtime/stack.go b/libgo/go/runtime/stack.go
deleted file mode 100644
index fd99e4d..0000000
--- a/libgo/go/runtime/stack.go
+++ /dev/null
@@ -1,1229 +0,0 @@
-// Copyright 2013 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// +build ignore
-
-package runtime
-
-import (
-	"runtime/internal/atomic"
-	"runtime/internal/sys"
-	"unsafe"
-)
-
-/*
-Stack layout parameters.
-Included both by runtime (compiled via 6c) and linkers (compiled via gcc).
-
-The per-goroutine g->stackguard is set to point StackGuard bytes
-above the bottom of the stack.  Each function compares its stack
-pointer against g->stackguard to check for overflow.  To cut one
-instruction from the check sequence for functions with tiny frames,
-the stack is allowed to protrude StackSmall bytes below the stack
-guard.  Functions with large frames don't bother with the check and
-always call morestack.  The sequences are (for amd64, others are
-similar):
-
-	guard = g->stackguard
-	frame = function's stack frame size
-	argsize = size of function arguments (call + return)
-
-	stack frame size <= StackSmall:
-		CMPQ guard, SP
-		JHI 3(PC)
-		MOVQ m->morearg, $(argsize << 32)
-		CALL morestack(SB)
-
-	stack frame size > StackSmall but < StackBig
-		LEAQ (frame-StackSmall)(SP), R0
-		CMPQ guard, R0
-		JHI 3(PC)
-		MOVQ m->morearg, $(argsize << 32)
-		CALL morestack(SB)
-
-	stack frame size >= StackBig:
-		MOVQ m->morearg, $((argsize << 32) | frame)
-		CALL morestack(SB)
-
-The bottom StackGuard - StackSmall bytes are important: there has
-to be enough room to execute functions that refuse to check for
-stack overflow, either because they need to be adjacent to the
-actual caller's frame (deferproc) or because they handle the imminent
-stack overflow (morestack).
-
-For example, deferproc might call malloc, which does one of the
-above checks (without allocating a full frame), which might trigger
-a call to morestack.  This sequence needs to fit in the bottom
-section of the stack.  On amd64, morestack's frame is 40 bytes, and
-deferproc's frame is 56 bytes.  That fits well within the
-StackGuard - StackSmall bytes at the bottom.
-The linkers explore all possible call traces involving non-splitting
-functions to make sure that this limit cannot be violated.
-*/
-
-const (
-	// StackSystem is a number of additional bytes to add
-	// to each stack below the usual guard area for OS-specific
-	// purposes like signal handling. Used on Windows, Plan 9,
-	// and Darwin/ARM because they do not use a separate stack.
-	_StackSystem = sys.GoosWindows*512*sys.PtrSize + sys.GoosPlan9*512 + sys.GoosDarwin*sys.GoarchArm*1024
-
-	// The minimum size of stack used by Go code
-	_StackMin = 2048
-
-	// The minimum stack size to allocate.
-	// The hackery here rounds FixedStack0 up to a power of 2.
-	_FixedStack0 = _StackMin + _StackSystem
-	_FixedStack1 = _FixedStack0 - 1
-	_FixedStack2 = _FixedStack1 | (_FixedStack1 >> 1)
-	_FixedStack3 = _FixedStack2 | (_FixedStack2 >> 2)
-	_FixedStack4 = _FixedStack3 | (_FixedStack3 >> 4)
-	_FixedStack5 = _FixedStack4 | (_FixedStack4 >> 8)
-	_FixedStack6 = _FixedStack5 | (_FixedStack5 >> 16)
-	_FixedStack  = _FixedStack6 + 1
-
-	// Functions that need frames bigger than this use an extra
-	// instruction to do the stack split check, to avoid overflow
-	// in case SP - framesize wraps below zero.
-	// This value can be no bigger than the size of the unmapped
-	// space at zero.
-	_StackBig = 4096
-
-	// The stack guard is a pointer this many bytes above the
-	// bottom of the stack.
-	_StackGuard = 880*sys.StackGuardMultiplier + _StackSystem
-
-	// After a stack split check the SP is allowed to be this
-	// many bytes below the stack guard. This saves an instruction
-	// in the checking sequence for tiny frames.
-	_StackSmall = 128
-
-	// The maximum number of bytes that a chain of NOSPLIT
-	// functions can use.
-	_StackLimit = _StackGuard - _StackSystem - _StackSmall
-)
-
-// Goroutine preemption request.
-// Stored into g->stackguard0 to cause split stack check failure.
-// Must be greater than any real sp.
-// 0xfffffade in hex.
-const (
-	_StackPreempt = uintptrMask & -1314
-	_StackFork    = uintptrMask & -1234
-)
-
-const (
-	// stackDebug == 0: no logging
-	//            == 1: logging of per-stack operations
-	//            == 2: logging of per-frame operations
-	//            == 3: logging of per-word updates
-	//            == 4: logging of per-word reads
-	stackDebug       = 0
-	stackFromSystem  = 0 // allocate stacks from system memory instead of the heap
-	stackFaultOnFree = 0 // old stacks are mapped noaccess to detect use after free
-	stackPoisonCopy  = 0 // fill stack that should not be accessed with garbage, to detect bad dereferences during copy
-
-	stackCache = 1
-
-	// check the BP links during traceback.
-	debugCheckBP = false
-)
-
-const (
-	uintptrMask = 1<<(8*sys.PtrSize) - 1
-
-	// Goroutine preemption request.
-	// Stored into g->stackguard0 to cause split stack check failure.
-	// Must be greater than any real sp.
-	// 0xfffffade in hex.
-	stackPreempt = uintptrMask & -1314
-
-	// Thread is forking.
-	// Stored into g->stackguard0 to cause split stack check failure.
-	// Must be greater than any real sp.
-	stackFork = uintptrMask & -1234
-)
-
-// Global pool of spans that have free stacks.
-// Stacks are assigned an order according to size.
-//     order = log_2(size/FixedStack)
-// There is a free list for each order.
-// TODO: one lock per order?
-var stackpool [_NumStackOrders]mSpanList
-var stackpoolmu mutex
-
-// Global pool of large stack spans.
-var stackLarge struct {
-	lock mutex
-	free [_MHeapMap_Bits]mSpanList // free lists by log_2(s.npages)
-}
-
-func stackinit() {
-	if _StackCacheSize&_PageMask != 0 {
-		throw("cache size must be a multiple of page size")
-	}
-	for i := range stackpool {
-		stackpool[i].init()
-	}
-	for i := range stackLarge.free {
-		stackLarge.free[i].init()
-	}
-}
-
-// stacklog2 returns ⌊log_2(n)⌋.
-func stacklog2(n uintptr) int {
-	log2 := 0
-	for n > 1 {
-		n >>= 1
-		log2++
-	}
-	return log2
-}
-
-// Allocates a stack from the free pool. Must be called with
-// stackpoolmu held.
-func stackpoolalloc(order uint8) gclinkptr {
-	list := &stackpool[order]
-	s := list.first
-	if s == nil {
-		// no free stacks. Allocate another span worth.
-		s = mheap_.allocStack(_StackCacheSize >> _PageShift)
-		if s == nil {
-			throw("out of memory")
-		}
-		if s.allocCount != 0 {
-			throw("bad allocCount")
-		}
-		if s.stackfreelist.ptr() != nil {
-			throw("bad stackfreelist")
-		}
-		for i := uintptr(0); i < _StackCacheSize; i += _FixedStack << order {
-			x := gclinkptr(s.base() + i)
-			x.ptr().next = s.stackfreelist
-			s.stackfreelist = x
-		}
-		list.insert(s)
-	}
-	x := s.stackfreelist
-	if x.ptr() == nil {
-		throw("span has no free stacks")
-	}
-	s.stackfreelist = x.ptr().next
-	s.allocCount++
-	if s.stackfreelist.ptr() == nil {
-		// all stacks in s are allocated.
-		list.remove(s)
-	}
-	return x
-}
-
-// Adds stack x to the free pool. Must be called with stackpoolmu held.
-func stackpoolfree(x gclinkptr, order uint8) {
-	s := mheap_.lookup(unsafe.Pointer(x))
-	if s.state != _MSpanStack {
-		throw("freeing stack not in a stack span")
-	}
-	if s.stackfreelist.ptr() == nil {
-		// s will now have a free stack
-		stackpool[order].insert(s)
-	}
-	x.ptr().next = s.stackfreelist
-	s.stackfreelist = x
-	s.allocCount--
-	if gcphase == _GCoff && s.allocCount == 0 {
-		// Span is completely free. Return it to the heap
-		// immediately if we're sweeping.
-		//
-		// If GC is active, we delay the free until the end of
-		// GC to avoid the following type of situation:
-		//
-		// 1) GC starts, scans a SudoG but does not yet mark the SudoG.elem pointer
-		// 2) The stack that pointer points to is copied
-		// 3) The old stack is freed
-		// 4) The containing span is marked free
-		// 5) GC attempts to mark the SudoG.elem pointer. The
-		//    marking fails because the pointer looks like a
-		//    pointer into a free span.
-		//
-		// By not freeing, we prevent step #4 until GC is done.
-		stackpool[order].remove(s)
-		s.stackfreelist = 0
-		mheap_.freeStack(s)
-	}
-}
-
-// stackcacherefill/stackcacherelease implement a global pool of stack segments.
-// The pool is required to prevent unlimited growth of per-thread caches.
-//
-//go:systemstack
-func stackcacherefill(c *mcache, order uint8) {
-	if stackDebug >= 1 {
-		print("stackcacherefill order=", order, "\n")
-	}
-
-	// Grab some stacks from the global cache.
-	// Grab half of the allowed capacity (to prevent thrashing).
-	var list gclinkptr
-	var size uintptr
-	lock(&stackpoolmu)
-	for size < _StackCacheSize/2 {
-		x := stackpoolalloc(order)
-		x.ptr().next = list
-		list = x
-		size += _FixedStack << order
-	}
-	unlock(&stackpoolmu)
-	c.stackcache[order].list = list
-	c.stackcache[order].size = size
-}
-
-//go:systemstack
-func stackcacherelease(c *mcache, order uint8) {
-	if stackDebug >= 1 {
-		print("stackcacherelease order=", order, "\n")
-	}
-	x := c.stackcache[order].list
-	size := c.stackcache[order].size
-	lock(&stackpoolmu)
-	for size > _StackCacheSize/2 {
-		y := x.ptr().next
-		stackpoolfree(x, order)
-		x = y
-		size -= _FixedStack << order
-	}
-	unlock(&stackpoolmu)
-	c.stackcache[order].list = x
-	c.stackcache[order].size = size
-}
-
-//go:systemstack
-func stackcache_clear(c *mcache) {
-	if stackDebug >= 1 {
-		print("stackcache clear\n")
-	}
-	lock(&stackpoolmu)
-	for order := uint8(0); order < _NumStackOrders; order++ {
-		x := c.stackcache[order].list
-		for x.ptr() != nil {
-			y := x.ptr().next
-			stackpoolfree(x, order)
-			x = y
-		}
-		c.stackcache[order].list = 0
-		c.stackcache[order].size = 0
-	}
-	unlock(&stackpoolmu)
-}
-
-// stackalloc allocates an n byte stack.
-//
-// stackalloc must run on the system stack because it uses per-P
-// resources and must not split the stack.
-//
-//go:systemstack
-func stackalloc(n uint32) (stack, []stkbar) {
-	// Stackalloc must be called on scheduler stack, so that we
-	// never try to grow the stack during the code that stackalloc runs.
-	// Doing so would cause a deadlock (issue 1547).
-	thisg := getg()
-	if thisg != thisg.m.g0 {
-		throw("stackalloc not on scheduler stack")
-	}
-	if n&(n-1) != 0 {
-		throw("stack size not a power of 2")
-	}
-	if stackDebug >= 1 {
-		print("stackalloc ", n, "\n")
-	}
-
-	// Compute the size of stack barrier array.
-	maxstkbar := gcMaxStackBarriers(int(n))
-	nstkbar := unsafe.Sizeof(stkbar{}) * uintptr(maxstkbar)
-	var stkbarSlice slice
-
-	if debug.efence != 0 || stackFromSystem != 0 {
-		v := sysAlloc(round(uintptr(n), _PageSize), &memstats.stacks_sys)
-		if v == nil {
-			throw("out of memory (stackalloc)")
-		}
-		top := uintptr(n) - nstkbar
-		if maxstkbar != 0 {
-			stkbarSlice = slice{add(v, top), 0, maxstkbar}
-		}
-		return stack{uintptr(v), uintptr(v) + top}, *(*[]stkbar)(unsafe.Pointer(&stkbarSlice))
-	}
-
-	// Small stacks are allocated with a fixed-size free-list allocator.
-	// If we need a stack of a bigger size, we fall back on allocating
-	// a dedicated span.
-	var v unsafe.Pointer
-	if stackCache != 0 && n < _FixedStack<<_NumStackOrders && n < _StackCacheSize {
-		order := uint8(0)
-		n2 := n
-		for n2 > _FixedStack {
-			order++
-			n2 >>= 1
-		}
-		var x gclinkptr
-		c := thisg.m.mcache
-		if c == nil || thisg.m.preemptoff != "" || thisg.m.helpgc != 0 {
-			// c == nil can happen in the guts of exitsyscall or
-			// procresize. Just get a stack from the global pool.
-			// Also don't touch stackcache during gc
-			// as it's flushed concurrently.
-			lock(&stackpoolmu)
-			x = stackpoolalloc(order)
-			unlock(&stackpoolmu)
-		} else {
-			x = c.stackcache[order].list
-			if x.ptr() == nil {
-				stackcacherefill(c, order)
-				x = c.stackcache[order].list
-			}
-			c.stackcache[order].list = x.ptr().next
-			c.stackcache[order].size -= uintptr(n)
-		}
-		v = unsafe.Pointer(x)
-	} else {
-		var s *mspan
-		npage := uintptr(n) >> _PageShift
-		log2npage := stacklog2(npage)
-
-		// Try to get a stack from the large stack cache.
-		lock(&stackLarge.lock)
-		if !stackLarge.free[log2npage].isEmpty() {
-			s = stackLarge.free[log2npage].first
-			stackLarge.free[log2npage].remove(s)
-		}
-		unlock(&stackLarge.lock)
-
-		if s == nil {
-			// Allocate a new stack from the heap.
-			s = mheap_.allocStack(npage)
-			if s == nil {
-				throw("out of memory")
-			}
-		}
-		v = unsafe.Pointer(s.base())
-	}
-
-	if raceenabled {
-		racemalloc(v, uintptr(n))
-	}
-	if msanenabled {
-		msanmalloc(v, uintptr(n))
-	}
-	if stackDebug >= 1 {
-		print("  allocated ", v, "\n")
-	}
-	top := uintptr(n) - nstkbar
-	if maxstkbar != 0 {
-		stkbarSlice = slice{add(v, top), 0, maxstkbar}
-	}
-	return stack{uintptr(v), uintptr(v) + top}, *(*[]stkbar)(unsafe.Pointer(&stkbarSlice))
-}
-
-// stackfree frees an n byte stack allocation at stk.
-//
-// stackfree must run on the system stack because it uses per-P
-// resources and must not split the stack.
-//
-//go:systemstack
-func stackfree(stk stack, n uintptr) {
-	gp := getg()
-	v := unsafe.Pointer(stk.lo)
-	if n&(n-1) != 0 {
-		throw("stack not a power of 2")
-	}
-	if stk.lo+n < stk.hi {
-		throw("bad stack size")
-	}
-	if stackDebug >= 1 {
-		println("stackfree", v, n)
-		memclrNoHeapPointers(v, n) // for testing, clobber stack data
-	}
-	if debug.efence != 0 || stackFromSystem != 0 {
-		if debug.efence != 0 || stackFaultOnFree != 0 {
-			sysFault(v, n)
-		} else {
-			sysFree(v, n, &memstats.stacks_sys)
-		}
-		return
-	}
-	if msanenabled {
-		msanfree(v, n)
-	}
-	if stackCache != 0 && n < _FixedStack<<_NumStackOrders && n < _StackCacheSize {
-		order := uint8(0)
-		n2 := n
-		for n2 > _FixedStack {
-			order++
-			n2 >>= 1
-		}
-		x := gclinkptr(v)
-		c := gp.m.mcache
-		if c == nil || gp.m.preemptoff != "" || gp.m.helpgc != 0 {
-			lock(&stackpoolmu)
-			stackpoolfree(x, order)
-			unlock(&stackpoolmu)
-		} else {
-			if c.stackcache[order].size >= _StackCacheSize {
-				stackcacherelease(c, order)
-			}
-			x.ptr().next = c.stackcache[order].list
-			c.stackcache[order].list = x
-			c.stackcache[order].size += n
-		}
-	} else {
-		s := mheap_.lookup(v)
-		if s.state != _MSpanStack {
-			println(hex(s.base()), v)
-			throw("bad span state")
-		}
-		if gcphase == _GCoff {
-			// Free the stack immediately if we're
-			// sweeping.
-			mheap_.freeStack(s)
-		} else {
-			// If the GC is running, we can't return a
-			// stack span to the heap because it could be
-			// reused as a heap span, and this state
-			// change would race with GC. Add it to the
-			// large stack cache instead.
-			log2npage := stacklog2(s.npages)
-			lock(&stackLarge.lock)
-			stackLarge.free[log2npage].insert(s)
-			unlock(&stackLarge.lock)
-		}
-	}
-}
-
-var maxstacksize uintptr = 1 << 20 // enough until runtime.main sets it for real
-
-var ptrnames = []string{
-	0: "scalar",
-	1: "ptr",
-}
-
-// Stack frame layout
-//
-// (x86)
-// +------------------+
-// | args from caller |
-// +------------------+ <- frame->argp
-// |  return address  |
-// +------------------+
-// |  caller's BP (*) | (*) if framepointer_enabled && varp < sp
-// +------------------+ <- frame->varp
-// |     locals       |
-// +------------------+
-// |  args to callee  |
-// +------------------+ <- frame->sp
-//
-// (arm)
-// +------------------+
-// | args from caller |
-// +------------------+ <- frame->argp
-// | caller's retaddr |
-// +------------------+ <- frame->varp
-// |     locals       |
-// +------------------+
-// |  args to callee  |
-// +------------------+
-// |  return address  |
-// +------------------+ <- frame->sp
-
-type adjustinfo struct {
-	old   stack
-	delta uintptr // ptr distance from old to new stack (newbase - oldbase)
-	cache pcvalueCache
-
-	// sghi is the highest sudog.elem on the stack.
-	sghi uintptr
-}
-
-// Adjustpointer checks whether *vpp is in the old stack described by adjinfo.
-// If so, it rewrites *vpp to point into the new stack.
-func adjustpointer(adjinfo *adjustinfo, vpp unsafe.Pointer) {
-	pp := (*uintptr)(vpp)
-	p := *pp
-	if stackDebug >= 4 {
-		print("        ", pp, ":", hex(p), "\n")
-	}
-	if adjinfo.old.lo <= p && p < adjinfo.old.hi {
-		*pp = p + adjinfo.delta
-		if stackDebug >= 3 {
-			print("        adjust ptr ", pp, ":", hex(p), " -> ", hex(*pp), "\n")
-		}
-	}
-}
-
-// Information from the compiler about the layout of stack frames.
-type bitvector struct {
-	n        int32 // # of bits
-	bytedata *uint8
-}
-
-type gobitvector struct {
-	n        uintptr
-	bytedata []uint8
-}
-
-func gobv(bv bitvector) gobitvector {
-	return gobitvector{
-		uintptr(bv.n),
-		(*[1 << 30]byte)(unsafe.Pointer(bv.bytedata))[:(bv.n+7)/8],
-	}
-}
-
-func ptrbit(bv *gobitvector, i uintptr) uint8 {
-	return (bv.bytedata[i/8] >> (i % 8)) & 1
-}
-
-// bv describes the memory starting at address scanp.
-// Adjust any pointers contained therein.
-func adjustpointers(scanp unsafe.Pointer, cbv *bitvector, adjinfo *adjustinfo, f *_func) {
-	bv := gobv(*cbv)
-	minp := adjinfo.old.lo
-	maxp := adjinfo.old.hi
-	delta := adjinfo.delta
-	num := bv.n
-	// If this frame might contain channel receive slots, use CAS
-	// to adjust pointers. If the slot hasn't been received into
-	// yet, it may contain stack pointers and a concurrent send
-	// could race with adjusting those pointers. (The sent value
-	// itself can never contain stack pointers.)
-	useCAS := uintptr(scanp) < adjinfo.sghi
-	for i := uintptr(0); i < num; i++ {
-		if stackDebug >= 4 {
-			print("        ", add(scanp, i*sys.PtrSize), ":", ptrnames[ptrbit(&bv, i)], ":", hex(*(*uintptr)(add(scanp, i*sys.PtrSize))), " # ", i, " ", bv.bytedata[i/8], "\n")
-		}
-		if ptrbit(&bv, i) == 1 {
-			pp := (*uintptr)(add(scanp, i*sys.PtrSize))
-		retry:
-			p := *pp
-			if f != nil && 0 < p && p < minLegalPointer && debug.invalidptr != 0 {
-				// Looks like a junk value in a pointer slot.
-				// Live analysis wrong?
-				getg().m.traceback = 2
-				print("runtime: bad pointer in frame ", funcname(f), " at ", pp, ": ", hex(p), "\n")
-				throw("invalid pointer found on stack")
-			}
-			if minp <= p && p < maxp {
-				if stackDebug >= 3 {
-					print("adjust ptr ", hex(p), " ", funcname(f), "\n")
-				}
-				if useCAS {
-					ppu := (*unsafe.Pointer)(unsafe.Pointer(pp))
-					if !atomic.Casp1(ppu, unsafe.Pointer(p), unsafe.Pointer(p+delta)) {
-						goto retry
-					}
-				} else {
-					*pp = p + delta
-				}
-			}
-		}
-	}
-}
-
-// Note: the argument/return area is adjusted by the callee.
-func adjustframe(frame *stkframe, arg unsafe.Pointer) bool {
-	adjinfo := (*adjustinfo)(arg)
-	targetpc := frame.continpc
-	if targetpc == 0 {
-		// Frame is dead.
-		return true
-	}
-	f := frame.fn
-	if stackDebug >= 2 {
-		print("    adjusting ", funcname(f), " frame=[", hex(frame.sp), ",", hex(frame.fp), "] pc=", hex(frame.pc), " continpc=", hex(frame.continpc), "\n")
-	}
-	if f.entry == systemstack_switchPC {
-		// A special routine at the bottom of stack of a goroutine that does an systemstack call.
-		// We will allow it to be copied even though we don't
-		// have full GC info for it (because it is written in asm).
-		return true
-	}
-	if targetpc != f.entry {
-		targetpc--
-	}
-	pcdata := pcdatavalue(f, _PCDATA_StackMapIndex, targetpc, &adjinfo.cache)
-	if pcdata == -1 {
-		pcdata = 0 // in prologue
-	}
-
-	// Adjust local variables if stack frame has been allocated.
-	size := frame.varp - frame.sp
-	var minsize uintptr
-	switch sys.ArchFamily {
-	case sys.ARM64:
-		minsize = sys.SpAlign
-	default:
-		minsize = sys.MinFrameSize
-	}
-	if size > minsize {
-		var bv bitvector
-		stackmap := (*stackmap)(funcdata(f, _FUNCDATA_LocalsPointerMaps))
-		if stackmap == nil || stackmap.n <= 0 {
-			print("runtime: frame ", funcname(f), " untyped locals ", hex(frame.varp-size), "+", hex(size), "\n")
-			throw("missing stackmap")
-		}
-		// Locals bitmap information, scan just the pointers in locals.
-		if pcdata < 0 || pcdata >= stackmap.n {
-			// don't know where we are
-			print("runtime: pcdata is ", pcdata, " and ", stackmap.n, " locals stack map entries for ", funcname(f), " (targetpc=", targetpc, ")\n")
-			throw("bad symbol table")
-		}
-		bv = stackmapdata(stackmap, pcdata)
-		size = uintptr(bv.n) * sys.PtrSize
-		if stackDebug >= 3 {
-			print("      locals ", pcdata, "/", stackmap.n, " ", size/sys.PtrSize, " words ", bv.bytedata, "\n")
-		}
-		adjustpointers(unsafe.Pointer(frame.varp-size), &bv, adjinfo, f)
-	}
-
-	// Adjust saved base pointer if there is one.
-	if sys.ArchFamily == sys.AMD64 && frame.argp-frame.varp == 2*sys.RegSize {
-		if !framepointer_enabled {
-			print("runtime: found space for saved base pointer, but no framepointer experiment\n")
-			print("argp=", hex(frame.argp), " varp=", hex(frame.varp), "\n")
-			throw("bad frame layout")
-		}
-		if stackDebug >= 3 {
-			print("      saved bp\n")
-		}
-		if debugCheckBP {
-			// Frame pointers should always point to the next higher frame on
-			// the Go stack (or be nil, for the top frame on the stack).
-			bp := *(*uintptr)(unsafe.Pointer(frame.varp))
-			if bp != 0 && (bp < adjinfo.old.lo || bp >= adjinfo.old.hi) {
-				println("runtime: found invalid frame pointer")
-				print("bp=", hex(bp), " min=", hex(adjinfo.old.lo), " max=", hex(adjinfo.old.hi), "\n")
-				throw("bad frame pointer")
-			}
-		}
-		adjustpointer(adjinfo, unsafe.Pointer(frame.varp))
-	}
-
-	// Adjust arguments.
-	if frame.arglen > 0 {
-		var bv bitvector
-		if frame.argmap != nil {
-			bv = *frame.argmap
-		} else {
-			stackmap := (*stackmap)(funcdata(f, _FUNCDATA_ArgsPointerMaps))
-			if stackmap == nil || stackmap.n <= 0 {
-				print("runtime: frame ", funcname(f), " untyped args ", frame.argp, "+", frame.arglen, "\n")
-				throw("missing stackmap")
-			}
-			if pcdata < 0 || pcdata >= stackmap.n {
-				// don't know where we are
-				print("runtime: pcdata is ", pcdata, " and ", stackmap.n, " args stack map entries for ", funcname(f), " (targetpc=", targetpc, ")\n")
-				throw("bad symbol table")
-			}
-			bv = stackmapdata(stackmap, pcdata)
-		}
-		if stackDebug >= 3 {
-			print("      args\n")
-		}
-		adjustpointers(unsafe.Pointer(frame.argp), &bv, adjinfo, nil)
-	}
-	return true
-}
-
-func adjustctxt(gp *g, adjinfo *adjustinfo) {
-	adjustpointer(adjinfo, unsafe.Pointer(&gp.sched.ctxt))
-	if !framepointer_enabled {
-		return
-	}
-	if debugCheckBP {
-		bp := gp.sched.bp
-		if bp != 0 && (bp < adjinfo.old.lo || bp >= adjinfo.old.hi) {
-			println("runtime: found invalid top frame pointer")
-			print("bp=", hex(bp), " min=", hex(adjinfo.old.lo), " max=", hex(adjinfo.old.hi), "\n")
-			throw("bad top frame pointer")
-		}
-	}
-	adjustpointer(adjinfo, unsafe.Pointer(&gp.sched.bp))
-}
-
-func adjustdefers(gp *g, adjinfo *adjustinfo) {
-	// Adjust defer argument blocks the same way we adjust active stack frames.
-	tracebackdefers(gp, adjustframe, noescape(unsafe.Pointer(adjinfo)))
-
-	// Adjust pointers in the Defer structs.
-	// Defer structs themselves are never on the stack.
-	for d := gp._defer; d != nil; d = d.link {
-		adjustpointer(adjinfo, unsafe.Pointer(&d.fn))
-		adjustpointer(adjinfo, unsafe.Pointer(&d.sp))
-		adjustpointer(adjinfo, unsafe.Pointer(&d._panic))
-	}
-}
-
-func adjustpanics(gp *g, adjinfo *adjustinfo) {
-	// Panics are on stack and already adjusted.
-	// Update pointer to head of list in G.
-	adjustpointer(adjinfo, unsafe.Pointer(&gp._panic))
-}
-
-func adjustsudogs(gp *g, adjinfo *adjustinfo) {
-	// the data elements pointed to by a SudoG structure
-	// might be in the stack.
-	for s := gp.waiting; s != nil; s = s.waitlink {
-		adjustpointer(adjinfo, unsafe.Pointer(&s.elem))
-		adjustpointer(adjinfo, unsafe.Pointer(&s.selectdone))
-	}
-}
-
-func adjuststkbar(gp *g, adjinfo *adjustinfo) {
-	for i := int(gp.stkbarPos); i < len(gp.stkbar); i++ {
-		adjustpointer(adjinfo, unsafe.Pointer(&gp.stkbar[i].savedLRPtr))
-	}
-}
-
-func fillstack(stk stack, b byte) {
-	for p := stk.lo; p < stk.hi; p++ {
-		*(*byte)(unsafe.Pointer(p)) = b
-	}
-}
-
-func findsghi(gp *g, stk stack) uintptr {
-	var sghi uintptr
-	for sg := gp.waiting; sg != nil; sg = sg.waitlink {
-		p := uintptr(sg.elem) + uintptr(sg.c.elemsize)
-		if stk.lo <= p && p < stk.hi && p > sghi {
-			sghi = p
-		}
-		p = uintptr(unsafe.Pointer(sg.selectdone)) + unsafe.Sizeof(sg.selectdone)
-		if stk.lo <= p && p < stk.hi && p > sghi {
-			sghi = p
-		}
-	}
-	return sghi
-}
-
-// syncadjustsudogs adjusts gp's sudogs and copies the part of gp's
-// stack they refer to while synchronizing with concurrent channel
-// operations. It returns the number of bytes of stack copied.
-func syncadjustsudogs(gp *g, used uintptr, adjinfo *adjustinfo) uintptr {
-	if gp.waiting == nil {
-		return 0
-	}
-
-	// Lock channels to prevent concurrent send/receive.
-	// It's important that we *only* do this for async
-	// copystack; otherwise, gp may be in the middle of
-	// putting itself on wait queues and this would
-	// self-deadlock.
-	var lastc *hchan
-	for sg := gp.waiting; sg != nil; sg = sg.waitlink {
-		if sg.c != lastc {
-			lock(&sg.c.lock)
-		}
-		lastc = sg.c
-	}
-
-	// Adjust sudogs.
-	adjustsudogs(gp, adjinfo)
-
-	// Copy the part of the stack the sudogs point in to
-	// while holding the lock to prevent races on
-	// send/receive slots.
-	var sgsize uintptr
-	if adjinfo.sghi != 0 {
-		oldBot := adjinfo.old.hi - used
-		newBot := oldBot + adjinfo.delta
-		sgsize = adjinfo.sghi - oldBot
-		memmove(unsafe.Pointer(newBot), unsafe.Pointer(oldBot), sgsize)
-	}
-
-	// Unlock channels.
-	lastc = nil
-	for sg := gp.waiting; sg != nil; sg = sg.waitlink {
-		if sg.c != lastc {
-			unlock(&sg.c.lock)
-		}
-		lastc = sg.c
-	}
-
-	return sgsize
-}
-
-// 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
-
-	// allocate new stack
-	new, newstkbar := stackalloc(uint32(newsize))
-	if stackPoisonCopy != 0 {
-		fillstack(new, 0xfd)
-	}
-	if stackDebug >= 1 {
-		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")
-	}
-
-	// 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)
-	}
-
-	// Copy the stack (or the rest of it) to the new location
-	memmove(unsafe.Pointer(new.hi-ncopy), unsafe.Pointer(old.hi-ncopy), ncopy)
-
-	// Disallow sigprof scans of this stack and block if there's
-	// one in progress.
-	gcLockStackBarriers(gp)
-
-	// Adjust remaining structures that have pointers into stacks.
-	// We have to do most of these before we traceback the new
-	// stack because gentraceback uses them.
-	adjustctxt(gp, &adjinfo)
-	adjustdefers(gp, &adjinfo)
-	adjustpanics(gp, &adjinfo)
-	adjuststkbar(gp, &adjinfo)
-	if adjinfo.sghi != 0 {
-		adjinfo.sghi += adjinfo.delta
-	}
-
-	// copy old stack barriers to new stack barrier array
-	newstkbar = newstkbar[:len(gp.stkbar)]
-	copy(newstkbar, gp.stkbar)
-
-	// Swap out old stack for new one
-	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)
-
-	// free old stack
-	if stackPoisonCopy != 0 {
-		fillstack(old, 0xfc)
-	}
-	stackfree(old, oldsize)
-}
-
-// round x up to a power of 2.
-func round2(x int32) int32 {
-	s := uint(0)
-	for 1<<s < x {
-		s++
-	}
-	return 1 << s
-}
-
-// 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()
-	// TODO: double check all gp. shouldn't be getg().
-	if thisg.m.morebuf.g.ptr().stackguard0 == stackFork {
-		throw("stack growth after fork")
-	}
-	if thisg.m.morebuf.g.ptr() != thisg.m.curg {
-		print("runtime: newstack called from g=", hex(thisg.m.morebuf.g), "\n"+"\tm=", thisg.m, " m->curg=", thisg.m.curg, " m->g0=", thisg.m.g0, " m->gsignal=", thisg.m.gsignal, "\n")
-		morebuf := thisg.m.morebuf
-		traceback(morebuf.pc, morebuf.sp, morebuf.lr, morebuf.g.ptr())
-		throw("runtime: wrong goroutine in newstack")
-	}
-
-	gp := thisg.m.curg
-	// Write ctxt to gp.sched. We do this here instead of in
-	// morestack so it has the necessary write barrier.
-	gp.sched.ctxt = ctxt
-
-	if thisg.m.curg.throwsplit {
-		// Update syscallsp, syscallpc in case traceback uses them.
-		morebuf := thisg.m.morebuf
-		gp.syscallsp = morebuf.sp
-		gp.syscallpc = morebuf.pc
-		print("runtime: newstack sp=", hex(gp.sched.sp), " stack=[", hex(gp.stack.lo), ", ", hex(gp.stack.hi), "]\n",
-			"\tmorebuf={pc:", hex(morebuf.pc), " sp:", hex(morebuf.sp), " lr:", hex(morebuf.lr), "}\n",
-			"\tsched={pc:", hex(gp.sched.pc), " sp:", hex(gp.sched.sp), " lr:", hex(gp.sched.lr), " ctxt:", gp.sched.ctxt, "}\n")
-
-		traceback(morebuf.pc, morebuf.sp, morebuf.lr, gp)
-		throw("runtime: stack split at bad time")
-	}
-
-	morebuf := thisg.m.morebuf
-	thisg.m.morebuf.pc = 0
-	thisg.m.morebuf.lr = 0
-	thisg.m.morebuf.sp = 0
-	thisg.m.morebuf.g = 0
-
-	// NOTE: stackguard0 may change underfoot, if another thread
-	// is about to try to preempt gp. Read it just once and use that same
-	// value now and below.
-	preempt := atomic.Loaduintptr(&gp.stackguard0) == stackPreempt
-
-	// Be conservative about where we preempt.
-	// We are interested in preempting user Go code, not runtime code.
-	// If we're holding locks, mallocing, or preemption is disabled, don't
-	// preempt.
-	// This check is very early in newstack so that even the status change
-	// from Grunning to Gwaiting and back doesn't happen in this case.
-	// That status change by itself can be viewed as a small preemption,
-	// because the GC might change Gwaiting to Gscanwaiting, and then
-	// this goroutine has to wait for the GC to finish before continuing.
-	// If the GC is in some way dependent on this goroutine (for example,
-	// it needs a lock held by the goroutine), that small preemption turns
-	// into a real deadlock.
-	if preempt {
-		if thisg.m.locks != 0 || thisg.m.mallocing != 0 || thisg.m.preemptoff != "" || thisg.m.p.ptr().status != _Prunning {
-			// Let the goroutine keep running for now.
-			// gp->preempt is set, so it will be preempted next time.
-			gp.stackguard0 = gp.stack.lo + _StackGuard
-			gogo(&gp.sched) // never return
-		}
-	}
-
-	if gp.stack.lo == 0 {
-		throw("missing stack in newstack")
-	}
-	sp := gp.sched.sp
-	if sys.ArchFamily == sys.AMD64 || sys.ArchFamily == sys.I386 {
-		// The call to morestack cost a word.
-		sp -= sys.PtrSize
-	}
-	if stackDebug >= 1 || sp < gp.stack.lo {
-		print("runtime: newstack sp=", hex(sp), " stack=[", hex(gp.stack.lo), ", ", hex(gp.stack.hi), "]\n",
-			"\tmorebuf={pc:", hex(morebuf.pc), " sp:", hex(morebuf.sp), " lr:", hex(morebuf.lr), "}\n",
-			"\tsched={pc:", hex(gp.sched.pc), " sp:", hex(gp.sched.sp), " lr:", hex(gp.sched.lr), " ctxt:", gp.sched.ctxt, "}\n")
-	}
-	if sp < gp.stack.lo {
-		print("runtime: gp=", gp, ", gp->status=", hex(readgstatus(gp)), "\n ")
-		print("runtime: split stack overflow: ", hex(sp), " < ", hex(gp.stack.lo), "\n")
-		throw("runtime: split stack overflow")
-	}
-
-	if preempt {
-		if gp == thisg.m.g0 {
-			throw("runtime: preempt g0")
-		}
-		if thisg.m.p == 0 && thisg.m.locks == 0 {
-			throw("runtime: g is running but p is not")
-		}
-		// Synchronize with scang.
-		casgstatus(gp, _Grunning, _Gwaiting)
-		if gp.preemptscan {
-			for !castogscanstatus(gp, _Gwaiting, _Gscanwaiting) {
-				// Likely to be racing with the GC as
-				// it sees a _Gwaiting and does the
-				// stack scan. If so, gcworkdone will
-				// be set and gcphasework will simply
-				// return.
-			}
-			if !gp.gcscandone {
-				// gcw is safe because we're on the
-				// system stack.
-				gcw := &gp.m.p.ptr().gcw
-				scanstack(gp, gcw)
-				if gcBlackenPromptly {
-					gcw.dispose()
-				}
-				gp.gcscandone = true
-			}
-			gp.preemptscan = false
-			gp.preempt = false
-			casfrom_Gscanstatus(gp, _Gscanwaiting, _Gwaiting)
-			// This clears gcscanvalid.
-			casgstatus(gp, _Gwaiting, _Grunning)
-			gp.stackguard0 = gp.stack.lo + _StackGuard
-			gogo(&gp.sched) // never return
-		}
-
-		// Act like goroutine called runtime.Gosched.
-		casgstatus(gp, _Gwaiting, _Grunning)
-		gopreempt_m(gp) // never return
-	}
-
-	// Allocate a bigger segment and move the stack.
-	oldsize := int(gp.stackAlloc)
-	newsize := oldsize * 2
-	if uintptr(newsize) > maxstacksize {
-		print("runtime: goroutine stack exceeds ", maxstacksize, "-byte limit\n")
-		throw("stack overflow")
-	}
-
-	// 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)
-}
-
-//go:nosplit
-func nilfunc() {
-	*(*uint8)(nil) = 0
-}
-
-// adjust Gobuf as if it executed a call to fn
-// and then did an immediate gosave.
-func gostartcallfn(gobuf *gobuf, fv *funcval) {
-	var fn unsafe.Pointer
-	if fv != nil {
-		fn = unsafe.Pointer(fv.fn)
-	} else {
-		fn = unsafe.Pointer(funcPC(nilfunc))
-	}
-	gostartcall(gobuf, fn, unsafe.Pointer(fv))
-}
-
-// Maybe shrink the stack being used by gp.
-// Called at garbage collection time.
-// gp must be stopped, but the world need not be.
-func shrinkstack(gp *g) {
-	gstatus := readgstatus(gp)
-	if gstatus&^_Gscan == _Gdead {
-		if gp.stack.lo != 0 {
-			// Free whole stack - it will get reallocated
-			// if G is used again.
-			stackfree(gp.stack, gp.stackAlloc)
-			gp.stack.lo = 0
-			gp.stack.hi = 0
-			gp.stkbar = nil
-			gp.stkbarPos = 0
-		}
-		return
-	}
-	if gp.stack.lo == 0 {
-		throw("missing stack in shrinkstack")
-	}
-	if gstatus&_Gscan == 0 {
-		throw("bad status in shrinkstack")
-	}
-
-	if debug.gcshrinkstackoff > 0 {
-		return
-	}
-	if gp.startpc == gcBgMarkWorkerPC {
-		// We're not allowed to shrink the gcBgMarkWorker
-		// stack (see gcBgMarkWorker for explanation).
-		return
-	}
-
-	oldsize := gp.stackAlloc
-	newsize := oldsize / 2
-	// Don't shrink the allocation below the minimum-sized stack
-	// allocation.
-	if newsize < _FixedStack {
-		return
-	}
-	// Compute how much of the stack is currently in use and only
-	// shrink the stack if gp is using less than a quarter of its
-	// current stack. The currently used stack includes everything
-	// down to the SP plus the stack guard space that ensures
-	// there's room for nosplit functions.
-	avail := gp.stack.hi - gp.stack.lo
-	if used := gp.stack.hi - gp.sched.sp + _StackLimit; used >= avail/4 {
-		return
-	}
-
-	// We can't copy the stack if we're in a syscall.
-	// The syscall might have pointers into the stack.
-	if gp.syscallsp != 0 {
-		return
-	}
-	if sys.GoosWindows != 0 && gp.m != nil && gp.m.libcallsp != 0 {
-		return
-	}
-
-	if stackDebug > 0 {
-		print("shrinking stack ", oldsize, "->", newsize, "\n")
-	}
-
-	copystack(gp, newsize, false)
-}
-
-// freeStackSpans frees unused stack spans at the end of GC.
-func freeStackSpans() {
-	lock(&stackpoolmu)
-
-	// Scan stack pools for empty stack spans.
-	for order := range stackpool {
-		list := &stackpool[order]
-		for s := list.first; s != nil; {
-			next := s.next
-			if s.allocCount == 0 {
-				list.remove(s)
-				s.stackfreelist = 0
-				mheap_.freeStack(s)
-			}
-			s = next
-		}
-	}
-
-	unlock(&stackpoolmu)
-
-	// Free large stack spans.
-	lock(&stackLarge.lock)
-	for i := range stackLarge.free {
-		for s := stackLarge.free[i].first; s != nil; {
-			next := s.next
-			stackLarge.free[i].remove(s)
-			mheap_.freeStack(s)
-			s = next
-		}
-	}
-	unlock(&stackLarge.lock)
-}
-
-//go:nosplit
-func morestackc() {
-	systemstack(func() {
-		throw("attempt to execute C code on Go stack")
-	})
-}