github.com/c0deoo1/golang1.5@v0.0.0-20220525150107-c87c805d4593/src/runtime/mgcmark.go (about)

     1  // Copyright 2009 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  // Garbage collector: marking and scanning
     6  
     7  package runtime
     8  
     9  import "unsafe"
    10  
    11  // Scan all of the stacks, greying (or graying if in America) the referents
    12  // but not blackening them since the mark write barrier isn't installed.
    13  //go:nowritebarrier
    14  func gcscan_m() {
    15  	_g_ := getg()
    16  
    17  	// Grab the g that called us and potentially allow rescheduling.
    18  	// This allows it to be scanned like other goroutines.
    19  	mastergp := _g_.m.curg
    20  	casgstatus(mastergp, _Grunning, _Gwaiting)
    21  	mastergp.waitreason = "garbage collection scan"
    22  
    23  	// Span sweeping has been done by finishsweep_m.
    24  	// Long term we will want to make this goroutine runnable
    25  	// by placing it onto a scanenqueue state and then calling
    26  	// runtimeĀ·restartg(mastergp) to make it Grunnable.
    27  	// At the bottom we will want to return this p back to the scheduler.
    28  
    29  	// Prepare flag indicating that the scan has not been completed.
    30  	local_allglen := gcResetGState()
    31  
    32  	work.ndone = 0
    33  	useOneP := uint32(1) // For now do not do this in parallel.
    34  	//	ackgcphase is not needed since we are not scanning running goroutines.
    35  	parforsetup(work.markfor, useOneP, uint32(_RootCount+local_allglen), false, markroot)
    36  	parfordo(work.markfor)
    37  
    38  	lock(&allglock)
    39  	// Check that gc work is done.
    40  	for i := 0; i < local_allglen; i++ {
    41  		gp := allgs[i]
    42  		if !gp.gcscandone {
    43  			throw("scan missed a g")
    44  		}
    45  	}
    46  	unlock(&allglock)
    47  
    48  	casgstatus(mastergp, _Gwaiting, _Grunning)
    49  	// Let the g that called us continue to run.
    50  }
    51  
    52  // ptrmask for an allocation containing a single pointer.
    53  var oneptrmask = [...]uint8{1}
    54  
    55  //go:nowritebarrier
    56  func markroot(desc *parfor, i uint32) {
    57  	// TODO: Consider using getg().m.p.ptr().gcw.
    58  	var gcw gcWork
    59  
    60  	// Note: if you add a case here, please also update heapdump.go:dumproots.
    61  	switch i {
    62  	case _RootData:
    63  		for datap := &firstmoduledata; datap != nil; datap = datap.next {
    64  			scanblock(datap.data, datap.edata-datap.data, datap.gcdatamask.bytedata, &gcw)
    65  		}
    66  
    67  	case _RootBss:
    68  		for datap := &firstmoduledata; datap != nil; datap = datap.next {
    69  			scanblock(datap.bss, datap.ebss-datap.bss, datap.gcbssmask.bytedata, &gcw)
    70  		}
    71  
    72  	case _RootFinalizers:
    73  		for fb := allfin; fb != nil; fb = fb.alllink {
    74  			scanblock(uintptr(unsafe.Pointer(&fb.fin[0])), uintptr(fb.cnt)*unsafe.Sizeof(fb.fin[0]), &finptrmask[0], &gcw)
    75  		}
    76  
    77  	case _RootSpans:
    78  		// mark MSpan.specials
    79  		sg := mheap_.sweepgen
    80  		for spanidx := uint32(0); spanidx < uint32(len(work.spans)); spanidx++ {
    81  			s := work.spans[spanidx]
    82  			if s.state != mSpanInUse {
    83  				continue
    84  			}
    85  			if !useCheckmark && s.sweepgen != sg {
    86  				// sweepgen was updated (+2) during non-checkmark GC pass
    87  				print("sweep ", s.sweepgen, " ", sg, "\n")
    88  				throw("gc: unswept span")
    89  			}
    90  			for sp := s.specials; sp != nil; sp = sp.next {
    91  				if sp.kind != _KindSpecialFinalizer {
    92  					continue
    93  				}
    94  				// don't mark finalized object, but scan it so we
    95  				// retain everything it points to.
    96  				spf := (*specialfinalizer)(unsafe.Pointer(sp))
    97  				// A finalizer can be set for an inner byte of an object, find object beginning.
    98  				p := uintptr(s.start<<_PageShift) + uintptr(spf.special.offset)/s.elemsize*s.elemsize
    99  				if gcphase != _GCscan {
   100  					scanobject(p, &gcw) // scanned during mark termination
   101  				}
   102  				scanblock(uintptr(unsafe.Pointer(&spf.fn)), ptrSize, &oneptrmask[0], &gcw)
   103  			}
   104  		}
   105  
   106  	case _RootFlushCaches:
   107  		if gcphase != _GCscan { // Do not flush mcaches during GCscan phase.
   108  			flushallmcaches()
   109  		}
   110  
   111  	default:
   112  		// the rest is scanning goroutine stacks
   113  		if uintptr(i-_RootCount) >= allglen {
   114  			throw("markroot: bad index")
   115  		}
   116  		gp := allgs[i-_RootCount]
   117  
   118  		// remember when we've first observed the G blocked
   119  		// needed only to output in traceback
   120  		status := readgstatus(gp) // We are not in a scan state
   121  		if (status == _Gwaiting || status == _Gsyscall) && gp.waitsince == 0 {
   122  			gp.waitsince = work.tstart
   123  		}
   124  
   125  		// Shrink a stack if not much of it is being used but not in the scan phase.
   126  		if gcphase == _GCmarktermination {
   127  			// Shrink during STW GCmarktermination phase thus avoiding
   128  			// complications introduced by shrinking during
   129  			// non-STW phases.
   130  			shrinkstack(gp)
   131  		}
   132  
   133  		scang(gp)
   134  	}
   135  
   136  	gcw.dispose()
   137  }
   138  
   139  // gcAssistAlloc records and allocation of size bytes and, if
   140  // allowAssist is true, may assist GC scanning in proportion to the
   141  // allocations performed by this mutator since the last assist.
   142  //
   143  // It should only be called if gcAssistAlloc != 0.
   144  //
   145  // This must be called with preemption disabled.
   146  //go:nowritebarrier
   147  func gcAssistAlloc(size uintptr, allowAssist bool) {
   148  	// Find the G responsible for this assist.
   149  	gp := getg()
   150  	if gp.m.curg != nil {
   151  		gp = gp.m.curg
   152  	}
   153  
   154  	// Record allocation.
   155  	gp.gcalloc += size
   156  
   157  	if !allowAssist {
   158  		return
   159  	}
   160  
   161  	// Don't assist in non-preemptible contexts. These are
   162  	// generally fragile and won't allow the assist to block.
   163  	if getg() == gp.m.g0 {
   164  		return
   165  	}
   166  	if mp := getg().m; mp.locks > 0 || mp.preemptoff != "" {
   167  		return
   168  	}
   169  
   170  	// Compute the amount of assist scan work we need to do.
   171  	scanWork := int64(gcController.assistRatio*float64(gp.gcalloc)) - gp.gcscanwork
   172  	// scanWork can be negative if the last assist scanned a large
   173  	// object and we're still ahead of our assist goal.
   174  	if scanWork <= 0 {
   175  		return
   176  	}
   177  
   178  retry:
   179  	// Steal as much credit as we can from the background GC's
   180  	// scan credit. This is racy and may drop the background
   181  	// credit below 0 if two mutators steal at the same time. This
   182  	// will just cause steals to fail until credit is accumulated
   183  	// again, so in the long run it doesn't really matter, but we
   184  	// do have to handle the negative credit case.
   185  	bgScanCredit := atomicloadint64(&gcController.bgScanCredit)
   186  	stolen := int64(0)
   187  	if bgScanCredit > 0 {
   188  		if bgScanCredit < scanWork {
   189  			stolen = bgScanCredit
   190  		} else {
   191  			stolen = scanWork
   192  		}
   193  		xaddint64(&gcController.bgScanCredit, -stolen)
   194  
   195  		scanWork -= stolen
   196  		gp.gcscanwork += stolen
   197  
   198  		if scanWork == 0 {
   199  			return
   200  		}
   201  	}
   202  
   203  	// Perform assist work
   204  	completed := false
   205  	systemstack(func() {
   206  		if atomicload(&gcBlackenEnabled) == 0 {
   207  			// The gcBlackenEnabled check in malloc races with the
   208  			// store that clears it but an atomic check in every malloc
   209  			// would be a performance hit.
   210  			// Instead we recheck it here on the non-preemptable system
   211  			// stack to determine if we should preform an assist.
   212  
   213  			// GC is done, so ignore any remaining debt.
   214  			scanWork = 0
   215  			return
   216  		}
   217  		// Track time spent in this assist. Since we're on the
   218  		// system stack, this is non-preemptible, so we can
   219  		// just measure start and end time.
   220  		startTime := nanotime()
   221  
   222  		decnwait := xadd(&work.nwait, -1)
   223  		if decnwait == work.nproc {
   224  			println("runtime: work.nwait =", decnwait, "work.nproc=", work.nproc)
   225  			throw("nwait > work.nprocs")
   226  		}
   227  
   228  		// drain own cached work first in the hopes that it
   229  		// will be more cache friendly.
   230  		gcw := &getg().m.p.ptr().gcw
   231  		startScanWork := gcw.scanWork
   232  		gcDrainN(gcw, scanWork)
   233  		// Record that we did this much scan work.
   234  		workDone := gcw.scanWork - startScanWork
   235  		gp.gcscanwork += workDone
   236  		scanWork -= workDone
   237  		// If we are near the end of the mark phase
   238  		// dispose of the gcw.
   239  		if gcBlackenPromptly {
   240  			gcw.dispose()
   241  		}
   242  		// If this is the last worker and we ran out of work,
   243  		// signal a completion point.
   244  		incnwait := xadd(&work.nwait, +1)
   245  		if incnwait > work.nproc {
   246  			println("runtime: work.nwait=", incnwait,
   247  				"work.nproc=", work.nproc,
   248  				"gcBlackenPromptly=", gcBlackenPromptly)
   249  			throw("work.nwait > work.nproc")
   250  		}
   251  
   252  		if incnwait == work.nproc && work.full == 0 && work.partial == 0 {
   253  			// This has reached a background completion
   254  			// point.
   255  			if gcBlackenPromptly {
   256  				if work.bgMark1.done == 0 {
   257  					throw("completing mark 2, but bgMark1.done == 0")
   258  				}
   259  				work.bgMark2.complete()
   260  			} else {
   261  				work.bgMark1.complete()
   262  			}
   263  			completed = true
   264  		}
   265  		duration := nanotime() - startTime
   266  		_p_ := gp.m.p.ptr()
   267  		_p_.gcAssistTime += duration
   268  		if _p_.gcAssistTime > gcAssistTimeSlack {
   269  			xaddint64(&gcController.assistTime, _p_.gcAssistTime)
   270  			_p_.gcAssistTime = 0
   271  		}
   272  	})
   273  
   274  	if completed {
   275  		// We called complete() above, so we should yield to
   276  		// the now-runnable GC coordinator.
   277  		Gosched()
   278  
   279  		// It's likely that this assist wasn't able to pay off
   280  		// its debt, but it's also likely that the Gosched let
   281  		// the GC finish this cycle and there's no point in
   282  		// waiting. If the GC finished, skip the delay below.
   283  		if atomicload(&gcBlackenEnabled) == 0 {
   284  			scanWork = 0
   285  		}
   286  	}
   287  
   288  	if scanWork > 0 {
   289  		// We were unable steal enough credit or perform
   290  		// enough work to pay off the assist debt. We need to
   291  		// do one of these before letting the mutator allocate
   292  		// more, so go around again after performing an
   293  		// interruptible sleep for 100 us (the same as the
   294  		// getfull barrier) to let other mutators run.
   295  		timeSleep(100 * 1000)
   296  		goto retry
   297  	}
   298  }
   299  
   300  //go:nowritebarrier
   301  func scanstack(gp *g) {
   302  	if gp.gcscanvalid {
   303  		if gcphase == _GCmarktermination {
   304  			gcRemoveStackBarriers(gp)
   305  		}
   306  		return
   307  	}
   308  
   309  	if readgstatus(gp)&_Gscan == 0 {
   310  		print("runtime:scanstack: gp=", gp, ", goid=", gp.goid, ", gp->atomicstatus=", hex(readgstatus(gp)), "\n")
   311  		throw("scanstack - bad status")
   312  	}
   313  
   314  	switch readgstatus(gp) &^ _Gscan {
   315  	default:
   316  		print("runtime: gp=", gp, ", goid=", gp.goid, ", gp->atomicstatus=", readgstatus(gp), "\n")
   317  		throw("mark - bad status")
   318  	case _Gdead:
   319  		return
   320  	case _Grunning:
   321  		print("runtime: gp=", gp, ", goid=", gp.goid, ", gp->atomicstatus=", readgstatus(gp), "\n")
   322  		throw("scanstack: goroutine not stopped")
   323  	case _Grunnable, _Gsyscall, _Gwaiting:
   324  		// ok
   325  	}
   326  
   327  	if gp == getg() {
   328  		throw("can't scan our own stack")
   329  	}
   330  	mp := gp.m
   331  	if mp != nil && mp.helpgc != 0 {
   332  		throw("can't scan gchelper stack")
   333  	}
   334  
   335  	var sp, barrierOffset, nextBarrier uintptr
   336  	if gp.syscallsp != 0 {
   337  		sp = gp.syscallsp
   338  	} else {
   339  		sp = gp.sched.sp
   340  	}
   341  	switch gcphase {
   342  	case _GCscan:
   343  		// Install stack barriers during stack scan.
   344  		barrierOffset = firstStackBarrierOffset
   345  		nextBarrier = sp + barrierOffset
   346  
   347  		if debug.gcstackbarrieroff > 0 {
   348  			nextBarrier = ^uintptr(0)
   349  		}
   350  
   351  		if gp.stkbarPos != 0 || len(gp.stkbar) != 0 {
   352  			// If this happens, it's probably because we
   353  			// scanned a stack twice in the same phase.
   354  			print("stkbarPos=", gp.stkbarPos, " len(stkbar)=", len(gp.stkbar), " goid=", gp.goid, " gcphase=", gcphase, "\n")
   355  			throw("g already has stack barriers")
   356  		}
   357  
   358  	case _GCmarktermination:
   359  		if int(gp.stkbarPos) == len(gp.stkbar) {
   360  			// gp hit all of the stack barriers (or there
   361  			// were none). Re-scan the whole stack.
   362  			nextBarrier = ^uintptr(0)
   363  		} else {
   364  			// Only re-scan up to the lowest un-hit
   365  			// barrier. Any frames above this have not
   366  			// executed since the _GCscan scan of gp and
   367  			// any writes through up-pointers to above
   368  			// this barrier had write barriers.
   369  			nextBarrier = gp.stkbar[gp.stkbarPos].savedLRPtr
   370  			if debugStackBarrier {
   371  				print("rescan below ", hex(nextBarrier), " in [", hex(sp), ",", hex(gp.stack.hi), ") goid=", gp.goid, "\n")
   372  			}
   373  		}
   374  
   375  		gcRemoveStackBarriers(gp)
   376  
   377  	default:
   378  		throw("scanstack in wrong phase")
   379  	}
   380  
   381  	gcw := &getg().m.p.ptr().gcw
   382  	n := 0
   383  	scanframe := func(frame *stkframe, unused unsafe.Pointer) bool {
   384  		scanframeworker(frame, unused, gcw)
   385  
   386  		if frame.fp > nextBarrier {
   387  			// We skip installing a barrier on bottom-most
   388  			// frame because on LR machines this LR is not
   389  			// on the stack.
   390  			if gcphase == _GCscan && n != 0 {
   391  				gcInstallStackBarrier(gp, frame)
   392  				barrierOffset *= 2
   393  				nextBarrier = sp + barrierOffset
   394  			} else if gcphase == _GCmarktermination {
   395  				// We just scanned a frame containing
   396  				// a return to a stack barrier. Since
   397  				// this frame never returned, we can
   398  				// stop scanning.
   399  				return false
   400  			}
   401  		}
   402  		n++
   403  
   404  		return true
   405  	}
   406  	gentraceback(^uintptr(0), ^uintptr(0), 0, gp, 0, nil, 0x7fffffff, scanframe, nil, 0)
   407  	tracebackdefers(gp, scanframe, nil)
   408  	if gcphase == _GCmarktermination {
   409  		gcw.dispose()
   410  	}
   411  	gp.gcscanvalid = true
   412  }
   413  
   414  // Scan a stack frame: local variables and function arguments/results.
   415  //go:nowritebarrier
   416  func scanframeworker(frame *stkframe, unused unsafe.Pointer, gcw *gcWork) {
   417  
   418  	f := frame.fn
   419  	targetpc := frame.continpc
   420  	if targetpc == 0 {
   421  		// Frame is dead.
   422  		return
   423  	}
   424  	if _DebugGC > 1 {
   425  		print("scanframe ", funcname(f), "\n")
   426  	}
   427  	if targetpc != f.entry {
   428  		targetpc--
   429  	}
   430  	pcdata := pcdatavalue(f, _PCDATA_StackMapIndex, targetpc)
   431  	if pcdata == -1 {
   432  		// We do not have a valid pcdata value but there might be a
   433  		// stackmap for this function.  It is likely that we are looking
   434  		// at the function prologue, assume so and hope for the best.
   435  		pcdata = 0
   436  	}
   437  
   438  	// Scan local variables if stack frame has been allocated.
   439  	size := frame.varp - frame.sp
   440  	var minsize uintptr
   441  	switch thechar {
   442  	case '6', '8':
   443  		minsize = 0
   444  	case '7':
   445  		minsize = spAlign
   446  	default:
   447  		minsize = ptrSize
   448  	}
   449  	if size > minsize {
   450  		stkmap := (*stackmap)(funcdata(f, _FUNCDATA_LocalsPointerMaps))
   451  		if stkmap == nil || stkmap.n <= 0 {
   452  			print("runtime: frame ", funcname(f), " untyped locals ", hex(frame.varp-size), "+", hex(size), "\n")
   453  			throw("missing stackmap")
   454  		}
   455  
   456  		// Locals bitmap information, scan just the pointers in locals.
   457  		if pcdata < 0 || pcdata >= stkmap.n {
   458  			// don't know where we are
   459  			print("runtime: pcdata is ", pcdata, " and ", stkmap.n, " locals stack map entries for ", funcname(f), " (targetpc=", targetpc, ")\n")
   460  			throw("scanframe: bad symbol table")
   461  		}
   462  		bv := stackmapdata(stkmap, pcdata)
   463  		size = uintptr(bv.n) * ptrSize
   464  		scanblock(frame.varp-size, size, bv.bytedata, gcw)
   465  	}
   466  
   467  	// Scan arguments.
   468  	if frame.arglen > 0 {
   469  		var bv bitvector
   470  		if frame.argmap != nil {
   471  			bv = *frame.argmap
   472  		} else {
   473  			stkmap := (*stackmap)(funcdata(f, _FUNCDATA_ArgsPointerMaps))
   474  			if stkmap == nil || stkmap.n <= 0 {
   475  				print("runtime: frame ", funcname(f), " untyped args ", hex(frame.argp), "+", hex(frame.arglen), "\n")
   476  				throw("missing stackmap")
   477  			}
   478  			if pcdata < 0 || pcdata >= stkmap.n {
   479  				// don't know where we are
   480  				print("runtime: pcdata is ", pcdata, " and ", stkmap.n, " args stack map entries for ", funcname(f), " (targetpc=", targetpc, ")\n")
   481  				throw("scanframe: bad symbol table")
   482  			}
   483  			bv = stackmapdata(stkmap, pcdata)
   484  		}
   485  		scanblock(frame.argp, uintptr(bv.n)*ptrSize, bv.bytedata, gcw)
   486  	}
   487  }
   488  
   489  // gcMaxStackBarriers returns the maximum number of stack barriers
   490  // that can be installed in a stack of stackSize bytes.
   491  func gcMaxStackBarriers(stackSize int) (n int) {
   492  	if firstStackBarrierOffset == 0 {
   493  		// Special debugging case for inserting stack barriers
   494  		// at every frame. Steal half of the stack for the
   495  		// []stkbar. Technically, if the stack were to consist
   496  		// solely of return PCs we would need two thirds of
   497  		// the stack, but stealing that much breaks things and
   498  		// this doesn't happen in practice.
   499  		return stackSize / 2 / int(unsafe.Sizeof(stkbar{}))
   500  	}
   501  
   502  	offset := firstStackBarrierOffset
   503  	for offset < stackSize {
   504  		n++
   505  		offset *= 2
   506  	}
   507  	return n + 1
   508  }
   509  
   510  // gcInstallStackBarrier installs a stack barrier over the return PC of frame.
   511  //go:nowritebarrier
   512  func gcInstallStackBarrier(gp *g, frame *stkframe) {
   513  	if frame.lr == 0 {
   514  		if debugStackBarrier {
   515  			print("not installing stack barrier with no LR, goid=", gp.goid, "\n")
   516  		}
   517  		return
   518  	}
   519  
   520  	// Save the return PC and overwrite it with stackBarrier.
   521  	var lrUintptr uintptr
   522  	if usesLR {
   523  		lrUintptr = frame.sp
   524  	} else {
   525  		lrUintptr = frame.fp - regSize
   526  	}
   527  	lrPtr := (*uintreg)(unsafe.Pointer(lrUintptr))
   528  	if debugStackBarrier {
   529  		print("install stack barrier at ", hex(lrUintptr), " over ", hex(*lrPtr), ", goid=", gp.goid, "\n")
   530  		if uintptr(*lrPtr) != frame.lr {
   531  			print("frame.lr=", hex(frame.lr))
   532  			throw("frame.lr differs from stack LR")
   533  		}
   534  	}
   535  
   536  	gp.stkbar = gp.stkbar[:len(gp.stkbar)+1]
   537  	stkbar := &gp.stkbar[len(gp.stkbar)-1]
   538  	stkbar.savedLRPtr = lrUintptr
   539  	stkbar.savedLRVal = uintptr(*lrPtr)
   540  	*lrPtr = uintreg(stackBarrierPC)
   541  }
   542  
   543  // gcRemoveStackBarriers removes all stack barriers installed in gp's stack.
   544  //go:nowritebarrier
   545  func gcRemoveStackBarriers(gp *g) {
   546  	if debugStackBarrier && gp.stkbarPos != 0 {
   547  		print("hit ", gp.stkbarPos, " stack barriers, goid=", gp.goid, "\n")
   548  	}
   549  
   550  	// Remove stack barriers that we didn't hit.
   551  	for _, stkbar := range gp.stkbar[gp.stkbarPos:] {
   552  		gcRemoveStackBarrier(gp, stkbar)
   553  	}
   554  
   555  	// Clear recorded stack barriers so copystack doesn't try to
   556  	// adjust them.
   557  	gp.stkbarPos = 0
   558  	gp.stkbar = gp.stkbar[:0]
   559  }
   560  
   561  // gcRemoveStackBarrier removes a single stack barrier. It is the
   562  // inverse operation of gcInstallStackBarrier.
   563  //
   564  // This is nosplit to ensure gp's stack does not move.
   565  //
   566  //go:nowritebarrier
   567  //go:nosplit
   568  func gcRemoveStackBarrier(gp *g, stkbar stkbar) {
   569  	if debugStackBarrier {
   570  		print("remove stack barrier at ", hex(stkbar.savedLRPtr), " with ", hex(stkbar.savedLRVal), ", goid=", gp.goid, "\n")
   571  	}
   572  	lrPtr := (*uintreg)(unsafe.Pointer(stkbar.savedLRPtr))
   573  	if val := *lrPtr; val != uintreg(stackBarrierPC) {
   574  		printlock()
   575  		print("at *", hex(stkbar.savedLRPtr), " expected stack barrier PC ", hex(stackBarrierPC), ", found ", hex(val), ", goid=", gp.goid, "\n")
   576  		print("gp.stkbar=")
   577  		gcPrintStkbars(gp.stkbar)
   578  		print(", gp.stkbarPos=", gp.stkbarPos, ", gp.stack=[", hex(gp.stack.lo), ",", hex(gp.stack.hi), ")\n")
   579  		throw("stack barrier lost")
   580  	}
   581  	*lrPtr = uintreg(stkbar.savedLRVal)
   582  }
   583  
   584  // gcPrintStkbars prints a []stkbar for debugging.
   585  func gcPrintStkbars(stkbar []stkbar) {
   586  	print("[")
   587  	for i, s := range stkbar {
   588  		if i > 0 {
   589  			print(" ")
   590  		}
   591  		print("*", hex(s.savedLRPtr), "=", hex(s.savedLRVal))
   592  	}
   593  	print("]")
   594  }
   595  
   596  // gcUnwindBarriers marks all stack barriers up the frame containing
   597  // sp as hit and removes them. This is used during stack unwinding for
   598  // panic/recover and by heapBitsBulkBarrier to force stack re-scanning
   599  // when its destination is on the stack.
   600  //
   601  // This is nosplit to ensure gp's stack does not move.
   602  //
   603  //go:nosplit
   604  func gcUnwindBarriers(gp *g, sp uintptr) {
   605  	// On LR machines, if there is a stack barrier on the return
   606  	// from the frame containing sp, this will mark it as hit even
   607  	// though it isn't, but it's okay to be conservative.
   608  	before := gp.stkbarPos
   609  	for int(gp.stkbarPos) < len(gp.stkbar) && gp.stkbar[gp.stkbarPos].savedLRPtr < sp {
   610  		gcRemoveStackBarrier(gp, gp.stkbar[gp.stkbarPos])
   611  		gp.stkbarPos++
   612  	}
   613  	if debugStackBarrier && gp.stkbarPos != before {
   614  		print("skip barriers below ", hex(sp), " in goid=", gp.goid, ": ")
   615  		gcPrintStkbars(gp.stkbar[before:gp.stkbarPos])
   616  		print("\n")
   617  	}
   618  }
   619  
   620  // nextBarrierPC returns the original return PC of the next stack barrier.
   621  // Used by getcallerpc, so it must be nosplit.
   622  //go:nosplit
   623  func nextBarrierPC() uintptr {
   624  	gp := getg()
   625  	return gp.stkbar[gp.stkbarPos].savedLRVal
   626  }
   627  
   628  // setNextBarrierPC sets the return PC of the next stack barrier.
   629  // Used by setcallerpc, so it must be nosplit.
   630  //go:nosplit
   631  func setNextBarrierPC(pc uintptr) {
   632  	gp := getg()
   633  	gp.stkbar[gp.stkbarPos].savedLRVal = pc
   634  }
   635  
   636  // TODO(austin): Can we consolidate the gcDrain* functions?
   637  
   638  // gcDrain scans objects in work buffers, blackening grey
   639  // objects until all work buffers have been drained.
   640  // If flushScanCredit != -1, gcDrain flushes accumulated scan work
   641  // credit to gcController.bgScanCredit whenever gcw's local scan work
   642  // credit exceeds flushScanCredit.
   643  //go:nowritebarrier
   644  func gcDrain(gcw *gcWork, flushScanCredit int64) {
   645  	if !writeBarrierEnabled {
   646  		throw("gcDrain phase incorrect")
   647  	}
   648  
   649  	var lastScanFlush, nextScanFlush int64
   650  	if flushScanCredit != -1 {
   651  		lastScanFlush = gcw.scanWork
   652  		nextScanFlush = lastScanFlush + flushScanCredit
   653  	} else {
   654  		nextScanFlush = int64(^uint64(0) >> 1)
   655  	}
   656  
   657  	for {
   658  		// If another proc wants a pointer, give it some.
   659  		if work.nwait > 0 && work.full == 0 {
   660  			gcw.balance()
   661  		}
   662  
   663  		b := gcw.get()
   664  		if b == 0 {
   665  			// work barrier reached
   666  			break
   667  		}
   668  		// If the current wbuf is filled by the scan a new wbuf might be
   669  		// returned that could possibly hold only a single object. This
   670  		// could result in each iteration draining only a single object
   671  		// out of the wbuf passed in + a single object placed
   672  		// into an empty wbuf in scanobject so there could be
   673  		// a performance hit as we keep fetching fresh wbufs.
   674  		scanobject(b, gcw)
   675  
   676  		// Flush background scan work credit to the global
   677  		// account if we've accumulated enough locally so
   678  		// mutator assists can draw on it.
   679  		if gcw.scanWork >= nextScanFlush {
   680  			credit := gcw.scanWork - lastScanFlush
   681  			xaddint64(&gcController.bgScanCredit, credit)
   682  			lastScanFlush = gcw.scanWork
   683  			nextScanFlush = lastScanFlush + flushScanCredit
   684  		}
   685  	}
   686  	if flushScanCredit != -1 {
   687  		credit := gcw.scanWork - lastScanFlush
   688  		xaddint64(&gcController.bgScanCredit, credit)
   689  	}
   690  }
   691  
   692  // gcDrainUntilPreempt blackens grey objects until g.preempt is set.
   693  // This is best-effort, so it will return as soon as it is unable to
   694  // get work, even though there may be more work in the system.
   695  //go:nowritebarrier
   696  func gcDrainUntilPreempt(gcw *gcWork, flushScanCredit int64) {
   697  	if !writeBarrierEnabled {
   698  		println("gcphase =", gcphase)
   699  		throw("gcDrainUntilPreempt phase incorrect")
   700  	}
   701  
   702  	var lastScanFlush, nextScanFlush int64
   703  	if flushScanCredit != -1 {
   704  		lastScanFlush = gcw.scanWork
   705  		nextScanFlush = lastScanFlush + flushScanCredit
   706  	} else {
   707  		nextScanFlush = int64(^uint64(0) >> 1)
   708  	}
   709  
   710  	gp := getg()
   711  	for !gp.preempt {
   712  		// If the work queue is empty, balance. During
   713  		// concurrent mark we don't really know if anyone else
   714  		// can make use of this work, but even if we're the
   715  		// only worker, the total cost of this per cycle is
   716  		// only O(_WorkbufSize) pointer copies.
   717  		if work.full == 0 && work.partial == 0 {
   718  			gcw.balance()
   719  		}
   720  
   721  		b := gcw.tryGet()
   722  		if b == 0 {
   723  			// No more work
   724  			break
   725  		}
   726  		scanobject(b, gcw)
   727  
   728  		// Flush background scan work credit to the global
   729  		// account if we've accumulated enough locally so
   730  		// mutator assists can draw on it.
   731  		if gcw.scanWork >= nextScanFlush {
   732  			credit := gcw.scanWork - lastScanFlush
   733  			xaddint64(&gcController.bgScanCredit, credit)
   734  			lastScanFlush = gcw.scanWork
   735  			nextScanFlush = lastScanFlush + flushScanCredit
   736  		}
   737  	}
   738  	if flushScanCredit != -1 {
   739  		credit := gcw.scanWork - lastScanFlush
   740  		xaddint64(&gcController.bgScanCredit, credit)
   741  	}
   742  }
   743  
   744  // gcDrainN blackens grey objects until it has performed roughly
   745  // scanWork units of scan work. This is best-effort, so it may perform
   746  // less work if it fails to get a work buffer. Otherwise, it will
   747  // perform at least n units of work, but may perform more because
   748  // scanning is always done in whole object increments.
   749  //go:nowritebarrier
   750  func gcDrainN(gcw *gcWork, scanWork int64) {
   751  	if !writeBarrierEnabled {
   752  		throw("gcDrainN phase incorrect")
   753  	}
   754  	targetScanWork := gcw.scanWork + scanWork
   755  	for gcw.scanWork < targetScanWork {
   756  		// This might be a good place to add prefetch code...
   757  		// if(wbuf.nobj > 4) {
   758  		//         PREFETCH(wbuf->obj[wbuf.nobj - 3];
   759  		//  }
   760  		b := gcw.tryGet()
   761  		if b == 0 {
   762  			return
   763  		}
   764  		scanobject(b, gcw)
   765  	}
   766  }
   767  
   768  // scanblock scans b as scanobject would, but using an explicit
   769  // pointer bitmap instead of the heap bitmap.
   770  //
   771  // This is used to scan non-heap roots, so it does not update
   772  // gcw.bytesMarked or gcw.scanWork.
   773  //
   774  //go:nowritebarrier
   775  func scanblock(b0, n0 uintptr, ptrmask *uint8, gcw *gcWork) {
   776  	// Use local copies of original parameters, so that a stack trace
   777  	// due to one of the throws below shows the original block
   778  	// base and extent.
   779  	b := b0
   780  	n := n0
   781  
   782  	arena_start := mheap_.arena_start
   783  	arena_used := mheap_.arena_used
   784  
   785  	for i := uintptr(0); i < n; {
   786  		// Find bits for the next word.
   787  		bits := uint32(*addb(ptrmask, i/(ptrSize*8)))
   788  		if bits == 0 {
   789  			i += ptrSize * 8
   790  			continue
   791  		}
   792  		for j := 0; j < 8 && i < n; j++ {
   793  			if bits&1 != 0 {
   794  				// Same work as in scanobject; see comments there.
   795  				obj := *(*uintptr)(unsafe.Pointer(b + i))
   796  				if obj != 0 && arena_start <= obj && obj < arena_used {
   797  					if obj, hbits, span := heapBitsForObject(obj); obj != 0 {
   798  						greyobject(obj, b, i, hbits, span, gcw)
   799  					}
   800  				}
   801  			}
   802  			bits >>= 1
   803  			i += ptrSize
   804  		}
   805  	}
   806  }
   807  
   808  // scanobject scans the object starting at b, adding pointers to gcw.
   809  // b must point to the beginning of a heap object; scanobject consults
   810  // the GC bitmap for the pointer mask and the spans for the size of the
   811  // object (it ignores n).
   812  //go:nowritebarrier
   813  func scanobject(b uintptr, gcw *gcWork) {
   814  	// Note that arena_used may change concurrently during
   815  	// scanobject and hence scanobject may encounter a pointer to
   816  	// a newly allocated heap object that is *not* in
   817  	// [start,used). It will not mark this object; however, we
   818  	// know that it was just installed by a mutator, which means
   819  	// that mutator will execute a write barrier and take care of
   820  	// marking it. This is even more pronounced on relaxed memory
   821  	// architectures since we access arena_used without barriers
   822  	// or synchronization, but the same logic applies.
   823  	arena_start := mheap_.arena_start
   824  	arena_used := mheap_.arena_used
   825  
   826  	// Find bits of the beginning of the object.
   827  	// b must point to the beginning of a heap object, so
   828  	// we can get its bits and span directly.
   829  	hbits := heapBitsForAddr(b)
   830  	s := spanOfUnchecked(b)
   831  	n := s.elemsize
   832  	if n == 0 {
   833  		throw("scanobject n == 0")
   834  	}
   835  
   836  	var i uintptr
   837  	for i = 0; i < n; i += ptrSize {
   838  		// Find bits for this word.
   839  		if i != 0 {
   840  			// Avoid needless hbits.next() on last iteration.
   841  			hbits = hbits.next()
   842  		}
   843  		// During checkmarking, 1-word objects store the checkmark
   844  		// in the type bit for the one word. The only one-word objects
   845  		// are pointers, or else they'd be merged with other non-pointer
   846  		// data into larger allocations.
   847  		bits := hbits.bits()
   848  		if i >= 2*ptrSize && bits&bitMarked == 0 {
   849  			break // no more pointers in this object
   850  		}
   851  		if bits&bitPointer == 0 {
   852  			continue // not a pointer
   853  		}
   854  
   855  		// Work here is duplicated in scanblock and above.
   856  		// If you make changes here, make changes there too.
   857  		obj := *(*uintptr)(unsafe.Pointer(b + i))
   858  
   859  		// At this point we have extracted the next potential pointer.
   860  		// Check if it points into heap and not back at the current object.
   861  		if obj != 0 && arena_start <= obj && obj < arena_used && obj-b >= n {
   862  			// Mark the object.
   863  			if obj, hbits, span := heapBitsForObject(obj); obj != 0 {
   864  				greyobject(obj, b, i, hbits, span, gcw)
   865  			}
   866  		}
   867  	}
   868  	gcw.bytesMarked += uint64(n)
   869  	gcw.scanWork += int64(i)
   870  }
   871  
   872  // Shade the object if it isn't already.
   873  // The object is not nil and known to be in the heap.
   874  // Preemption must be disabled.
   875  //go:nowritebarrier
   876  func shade(b uintptr) {
   877  	if obj, hbits, span := heapBitsForObject(b); obj != 0 {
   878  		gcw := &getg().m.p.ptr().gcw
   879  		greyobject(obj, 0, 0, hbits, span, gcw)
   880  		if gcphase == _GCmarktermination || gcBlackenPromptly {
   881  			// Ps aren't allowed to cache work during mark
   882  			// termination.
   883  			gcw.dispose()
   884  		}
   885  	}
   886  }
   887  
   888  // obj is the start of an object with mark mbits.
   889  // If it isn't already marked, mark it and enqueue into gcw.
   890  // base and off are for debugging only and could be removed.
   891  //go:nowritebarrier
   892  func greyobject(obj, base, off uintptr, hbits heapBits, span *mspan, gcw *gcWork) {
   893  	// obj should be start of allocation, and so must be at least pointer-aligned.
   894  	if obj&(ptrSize-1) != 0 {
   895  		throw("greyobject: obj not pointer-aligned")
   896  	}
   897  
   898  	if useCheckmark {
   899  		if !hbits.isMarked() {
   900  			printlock()
   901  			print("runtime:greyobject: checkmarks finds unexpected unmarked object obj=", hex(obj), "\n")
   902  			print("runtime: found obj at *(", hex(base), "+", hex(off), ")\n")
   903  
   904  			// Dump the source (base) object
   905  			gcDumpObject("base", base, off)
   906  
   907  			// Dump the object
   908  			gcDumpObject("obj", obj, ^uintptr(0))
   909  
   910  			throw("checkmark found unmarked object")
   911  		}
   912  		if hbits.isCheckmarked(span.elemsize) {
   913  			return
   914  		}
   915  		hbits.setCheckmarked(span.elemsize)
   916  		if !hbits.isCheckmarked(span.elemsize) {
   917  			throw("setCheckmarked and isCheckmarked disagree")
   918  		}
   919  	} else {
   920  		// If marked we have nothing to do.
   921  		if hbits.isMarked() {
   922  			return
   923  		}
   924  		hbits.setMarked()
   925  
   926  		// If this is a noscan object, fast-track it to black
   927  		// instead of greying it.
   928  		if !hbits.hasPointers(span.elemsize) {
   929  			gcw.bytesMarked += uint64(span.elemsize)
   930  			return
   931  		}
   932  	}
   933  
   934  	// Queue the obj for scanning. The PREFETCH(obj) logic has been removed but
   935  	// seems like a nice optimization that can be added back in.
   936  	// There needs to be time between the PREFETCH and the use.
   937  	// Previously we put the obj in an 8 element buffer that is drained at a rate
   938  	// to give the PREFETCH time to do its work.
   939  	// Use of PREFETCHNTA might be more appropriate than PREFETCH
   940  
   941  	gcw.put(obj)
   942  }
   943  
   944  // gcDumpObject dumps the contents of obj for debugging and marks the
   945  // field at byte offset off in obj.
   946  func gcDumpObject(label string, obj, off uintptr) {
   947  	if obj < mheap_.arena_start || obj >= mheap_.arena_used {
   948  		print(label, "=", hex(obj), " is not a heap object\n")
   949  		return
   950  	}
   951  	k := obj >> _PageShift
   952  	x := k
   953  	x -= mheap_.arena_start >> _PageShift
   954  	s := h_spans[x]
   955  	print(label, "=", hex(obj), " k=", hex(k))
   956  	if s == nil {
   957  		print(" s=nil\n")
   958  		return
   959  	}
   960  	print(" s.start*_PageSize=", hex(s.start*_PageSize), " s.limit=", hex(s.limit), " s.sizeclass=", s.sizeclass, " s.elemsize=", s.elemsize, "\n")
   961  	for i := uintptr(0); i < s.elemsize; i += ptrSize {
   962  		print(" *(", label, "+", i, ") = ", hex(*(*uintptr)(unsafe.Pointer(obj + uintptr(i)))))
   963  		if i == off {
   964  			print(" <==")
   965  		}
   966  		print("\n")
   967  	}
   968  }
   969  
   970  // If gcBlackenPromptly is true we are in the second mark phase phase so we allocate black.
   971  //go:nowritebarrier
   972  func gcmarknewobject_m(obj, size uintptr) {
   973  	if useCheckmark && !gcBlackenPromptly { // The world should be stopped so this should not happen.
   974  		throw("gcmarknewobject called while doing checkmark")
   975  	}
   976  	heapBitsForAddr(obj).setMarked()
   977  	xadd64(&work.bytesMarked, int64(size))
   978  }
   979  
   980  // Checkmarking
   981  
   982  // To help debug the concurrent GC we remark with the world
   983  // stopped ensuring that any object encountered has their normal
   984  // mark bit set. To do this we use an orthogonal bit
   985  // pattern to indicate the object is marked. The following pattern
   986  // uses the upper two bits in the object's boundary nibble.
   987  // 01: scalar  not marked
   988  // 10: pointer not marked
   989  // 11: pointer     marked
   990  // 00: scalar      marked
   991  // Xoring with 01 will flip the pattern from marked to unmarked and vica versa.
   992  // The higher bit is 1 for pointers and 0 for scalars, whether the object
   993  // is marked or not.
   994  // The first nibble no longer holds the typeDead pattern indicating that the
   995  // there are no more pointers in the object. This information is held
   996  // in the second nibble.
   997  
   998  // If useCheckmark is true, marking of an object uses the
   999  // checkmark bits (encoding above) instead of the standard
  1000  // mark bits.
  1001  var useCheckmark = false
  1002  
  1003  //go:nowritebarrier
  1004  func initCheckmarks() {
  1005  	useCheckmark = true
  1006  	for _, s := range work.spans {
  1007  		if s.state == _MSpanInUse {
  1008  			heapBitsForSpan(s.base()).initCheckmarkSpan(s.layout())
  1009  		}
  1010  	}
  1011  }
  1012  
  1013  func clearCheckmarks() {
  1014  	useCheckmark = false
  1015  	for _, s := range work.spans {
  1016  		if s.state == _MSpanInUse {
  1017  			heapBitsForSpan(s.base()).clearCheckmarkSpan(s.layout())
  1018  		}
  1019  	}
  1020  }