github.com/hbdrawn/golang@v0.0.0-20141214014649-6b835209aba2/src/runtime/malloc.go (about)

     1  // Copyright 2014 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  	debugMalloc = false
    11  
    12  	flagNoScan = _FlagNoScan
    13  	flagNoZero = _FlagNoZero
    14  
    15  	maxTinySize   = _TinySize
    16  	tinySizeClass = _TinySizeClass
    17  	maxSmallSize  = _MaxSmallSize
    18  
    19  	pageShift = _PageShift
    20  	pageSize  = _PageSize
    21  	pageMask  = _PageMask
    22  
    23  	bitsPerPointer  = _BitsPerPointer
    24  	bitsMask        = _BitsMask
    25  	pointersPerByte = _PointersPerByte
    26  	maxGCMask       = _MaxGCMask
    27  	bitsDead        = _BitsDead
    28  	bitsPointer     = _BitsPointer
    29  	bitsScalar      = _BitsScalar
    30  
    31  	mSpanInUse = _MSpanInUse
    32  
    33  	concurrentSweep = _ConcurrentSweep
    34  )
    35  
    36  // Page number (address>>pageShift)
    37  type pageID uintptr
    38  
    39  // base address for all 0-byte allocations
    40  var zerobase uintptr
    41  
    42  // Allocate an object of size bytes.
    43  // Small objects are allocated from the per-P cache's free lists.
    44  // Large objects (> 32 kB) are allocated straight from the heap.
    45  func mallocgc(size uintptr, typ *_type, flags uint32) unsafe.Pointer {
    46  	if size == 0 {
    47  		return unsafe.Pointer(&zerobase)
    48  	}
    49  	size0 := size
    50  
    51  	if flags&flagNoScan == 0 && typ == nil {
    52  		gothrow("malloc missing type")
    53  	}
    54  
    55  	// This function must be atomic wrt GC, but for performance reasons
    56  	// we don't acquirem/releasem on fast path. The code below does not have
    57  	// split stack checks, so it can't be preempted by GC.
    58  	// Functions like roundup/add are inlined. And systemstack/racemalloc are nosplit.
    59  	// If debugMalloc = true, these assumptions are checked below.
    60  	if debugMalloc {
    61  		mp := acquirem()
    62  		if mp.mallocing != 0 {
    63  			gothrow("malloc deadlock")
    64  		}
    65  		mp.mallocing = 1
    66  		if mp.curg != nil {
    67  			mp.curg.stackguard0 = ^uintptr(0xfff) | 0xbad
    68  		}
    69  	}
    70  
    71  	c := gomcache()
    72  	var s *mspan
    73  	var x unsafe.Pointer
    74  	if size <= maxSmallSize {
    75  		if flags&flagNoScan != 0 && size < maxTinySize {
    76  			// Tiny allocator.
    77  			//
    78  			// Tiny allocator combines several tiny allocation requests
    79  			// into a single memory block. The resulting memory block
    80  			// is freed when all subobjects are unreachable. The subobjects
    81  			// must be FlagNoScan (don't have pointers), this ensures that
    82  			// the amount of potentially wasted memory is bounded.
    83  			//
    84  			// Size of the memory block used for combining (maxTinySize) is tunable.
    85  			// Current setting is 16 bytes, which relates to 2x worst case memory
    86  			// wastage (when all but one subobjects are unreachable).
    87  			// 8 bytes would result in no wastage at all, but provides less
    88  			// opportunities for combining.
    89  			// 32 bytes provides more opportunities for combining,
    90  			// but can lead to 4x worst case wastage.
    91  			// The best case winning is 8x regardless of block size.
    92  			//
    93  			// Objects obtained from tiny allocator must not be freed explicitly.
    94  			// So when an object will be freed explicitly, we ensure that
    95  			// its size >= maxTinySize.
    96  			//
    97  			// SetFinalizer has a special case for objects potentially coming
    98  			// from tiny allocator, it such case it allows to set finalizers
    99  			// for an inner byte of a memory block.
   100  			//
   101  			// The main targets of tiny allocator are small strings and
   102  			// standalone escaping variables. On a json benchmark
   103  			// the allocator reduces number of allocations by ~12% and
   104  			// reduces heap size by ~20%.
   105  			tinysize := uintptr(c.tinysize)
   106  			if size <= tinysize {
   107  				tiny := unsafe.Pointer(c.tiny)
   108  				// Align tiny pointer for required (conservative) alignment.
   109  				if size&7 == 0 {
   110  					tiny = roundup(tiny, 8)
   111  				} else if size&3 == 0 {
   112  					tiny = roundup(tiny, 4)
   113  				} else if size&1 == 0 {
   114  					tiny = roundup(tiny, 2)
   115  				}
   116  				size1 := size + (uintptr(tiny) - uintptr(unsafe.Pointer(c.tiny)))
   117  				if size1 <= tinysize {
   118  					// The object fits into existing tiny block.
   119  					x = tiny
   120  					c.tiny = (*byte)(add(x, size))
   121  					c.tinysize -= uintptr(size1)
   122  					c.local_tinyallocs++
   123  					if debugMalloc {
   124  						mp := acquirem()
   125  						if mp.mallocing == 0 {
   126  							gothrow("bad malloc")
   127  						}
   128  						mp.mallocing = 0
   129  						if mp.curg != nil {
   130  							mp.curg.stackguard0 = mp.curg.stack.lo + _StackGuard
   131  						}
   132  						// Note: one releasem for the acquirem just above.
   133  						// The other for the acquirem at start of malloc.
   134  						releasem(mp)
   135  						releasem(mp)
   136  					}
   137  					return x
   138  				}
   139  			}
   140  			// Allocate a new maxTinySize block.
   141  			s = c.alloc[tinySizeClass]
   142  			v := s.freelist
   143  			if v.ptr() == nil {
   144  				systemstack(func() {
   145  					mCache_Refill(c, tinySizeClass)
   146  				})
   147  				s = c.alloc[tinySizeClass]
   148  				v = s.freelist
   149  			}
   150  			s.freelist = v.ptr().next
   151  			s.ref++
   152  			//TODO: prefetch v.next
   153  			x = unsafe.Pointer(v)
   154  			(*[2]uint64)(x)[0] = 0
   155  			(*[2]uint64)(x)[1] = 0
   156  			// See if we need to replace the existing tiny block with the new one
   157  			// based on amount of remaining free space.
   158  			if maxTinySize-size > tinysize {
   159  				c.tiny = (*byte)(add(x, size))
   160  				c.tinysize = uintptr(maxTinySize - size)
   161  			}
   162  			size = maxTinySize
   163  		} else {
   164  			var sizeclass int8
   165  			if size <= 1024-8 {
   166  				sizeclass = size_to_class8[(size+7)>>3]
   167  			} else {
   168  				sizeclass = size_to_class128[(size-1024+127)>>7]
   169  			}
   170  			size = uintptr(class_to_size[sizeclass])
   171  			s = c.alloc[sizeclass]
   172  			v := s.freelist
   173  			if v.ptr() == nil {
   174  				systemstack(func() {
   175  					mCache_Refill(c, int32(sizeclass))
   176  				})
   177  				s = c.alloc[sizeclass]
   178  				v = s.freelist
   179  			}
   180  			s.freelist = v.ptr().next
   181  			s.ref++
   182  			//TODO: prefetch
   183  			x = unsafe.Pointer(v)
   184  			if flags&flagNoZero == 0 {
   185  				v.ptr().next = 0
   186  				if size > 2*ptrSize && ((*[2]uintptr)(x))[1] != 0 {
   187  					memclr(unsafe.Pointer(v), size)
   188  				}
   189  			}
   190  		}
   191  		c.local_cachealloc += intptr(size)
   192  	} else {
   193  		var s *mspan
   194  		systemstack(func() {
   195  			s = largeAlloc(size, uint32(flags))
   196  		})
   197  		x = unsafe.Pointer(uintptr(s.start << pageShift))
   198  		size = uintptr(s.elemsize)
   199  	}
   200  
   201  	if flags&flagNoScan != 0 {
   202  		// All objects are pre-marked as noscan.
   203  		goto marked
   204  	}
   205  
   206  	// If allocating a defer+arg block, now that we've picked a malloc size
   207  	// large enough to hold everything, cut the "asked for" size down to
   208  	// just the defer header, so that the GC bitmap will record the arg block
   209  	// as containing nothing at all (as if it were unused space at the end of
   210  	// a malloc block caused by size rounding).
   211  	// The defer arg areas are scanned as part of scanstack.
   212  	if typ == deferType {
   213  		size0 = unsafe.Sizeof(_defer{})
   214  	}
   215  
   216  	// From here till marked label marking the object as allocated
   217  	// and storing type info in the GC bitmap.
   218  	{
   219  		arena_start := uintptr(unsafe.Pointer(mheap_.arena_start))
   220  		off := (uintptr(x) - arena_start) / ptrSize
   221  		xbits := (*uint8)(unsafe.Pointer(arena_start - off/wordsPerBitmapByte - 1))
   222  		shift := (off % wordsPerBitmapByte) * gcBits
   223  		if debugMalloc && ((*xbits>>shift)&(bitMask|bitPtrMask)) != bitBoundary {
   224  			println("runtime: bits =", (*xbits>>shift)&(bitMask|bitPtrMask))
   225  			gothrow("bad bits in markallocated")
   226  		}
   227  
   228  		var ti, te uintptr
   229  		var ptrmask *uint8
   230  		if size == ptrSize {
   231  			// It's one word and it has pointers, it must be a pointer.
   232  			*xbits |= (bitsPointer << 2) << shift
   233  			goto marked
   234  		}
   235  		if typ.kind&kindGCProg != 0 {
   236  			nptr := (uintptr(typ.size) + ptrSize - 1) / ptrSize
   237  			masksize := nptr
   238  			if masksize%2 != 0 {
   239  				masksize *= 2 // repeated
   240  			}
   241  			masksize = masksize * pointersPerByte / 8 // 4 bits per word
   242  			masksize++                                // unroll flag in the beginning
   243  			if masksize > maxGCMask && typ.gc[1] != 0 {
   244  				// write barriers have not been updated to deal with this case yet.
   245  				gothrow("maxGCMask too small for now")
   246  				// If the mask is too large, unroll the program directly
   247  				// into the GC bitmap. It's 7 times slower than copying
   248  				// from the pre-unrolled mask, but saves 1/16 of type size
   249  				// memory for the mask.
   250  				systemstack(func() {
   251  					unrollgcproginplace_m(x, typ, size, size0)
   252  				})
   253  				goto marked
   254  			}
   255  			ptrmask = (*uint8)(unsafe.Pointer(uintptr(typ.gc[0])))
   256  			// Check whether the program is already unrolled
   257  			// by checking if the unroll flag byte is set
   258  			maskword := uintptr(atomicloadp(unsafe.Pointer(ptrmask)))
   259  			if *(*uint8)(unsafe.Pointer(&maskword)) == 0 {
   260  				systemstack(func() {
   261  					unrollgcprog_m(typ)
   262  				})
   263  			}
   264  			ptrmask = (*uint8)(add(unsafe.Pointer(ptrmask), 1)) // skip the unroll flag byte
   265  		} else {
   266  			ptrmask = (*uint8)(unsafe.Pointer(typ.gc[0])) // pointer to unrolled mask
   267  		}
   268  		if size == 2*ptrSize {
   269  			*xbits = *ptrmask | bitBoundary
   270  			goto marked
   271  		}
   272  		te = uintptr(typ.size) / ptrSize
   273  		// If the type occupies odd number of words, its mask is repeated.
   274  		if te%2 == 0 {
   275  			te /= 2
   276  		}
   277  		// Copy pointer bitmask into the bitmap.
   278  		for i := uintptr(0); i < size0; i += 2 * ptrSize {
   279  			v := *(*uint8)(add(unsafe.Pointer(ptrmask), ti))
   280  			ti++
   281  			if ti == te {
   282  				ti = 0
   283  			}
   284  			if i == 0 {
   285  				v |= bitBoundary
   286  			}
   287  			if i+ptrSize == size0 {
   288  				v &^= uint8(bitPtrMask << 4)
   289  			}
   290  
   291  			*xbits = v
   292  			xbits = (*byte)(add(unsafe.Pointer(xbits), ^uintptr(0)))
   293  		}
   294  		if size0%(2*ptrSize) == 0 && size0 < size {
   295  			// Mark the word after last object's word as bitsDead.
   296  			*xbits = bitsDead << 2
   297  		}
   298  	}
   299  marked:
   300  
   301  	// GCmarkterminate allocates black
   302  	// All slots hold nil so no scanning is needed.
   303  	// This may be racing with GC so do it atomically if there can be
   304  	// a race marking the bit.
   305  	if gcphase == _GCmarktermination {
   306  		systemstack(func() {
   307  			gcmarknewobject_m(uintptr(x))
   308  		})
   309  	}
   310  
   311  	if raceenabled {
   312  		racemalloc(x, size)
   313  	}
   314  
   315  	if debugMalloc {
   316  		mp := acquirem()
   317  		if mp.mallocing == 0 {
   318  			gothrow("bad malloc")
   319  		}
   320  		mp.mallocing = 0
   321  		if mp.curg != nil {
   322  			mp.curg.stackguard0 = mp.curg.stack.lo + _StackGuard
   323  		}
   324  		// Note: one releasem for the acquirem just above.
   325  		// The other for the acquirem at start of malloc.
   326  		releasem(mp)
   327  		releasem(mp)
   328  	}
   329  
   330  	if debug.allocfreetrace != 0 {
   331  		tracealloc(x, size, typ)
   332  	}
   333  
   334  	if rate := MemProfileRate; rate > 0 {
   335  		if size < uintptr(rate) && int32(size) < c.next_sample {
   336  			c.next_sample -= int32(size)
   337  		} else {
   338  			mp := acquirem()
   339  			profilealloc(mp, x, size)
   340  			releasem(mp)
   341  		}
   342  	}
   343  
   344  	if memstats.heap_alloc >= memstats.next_gc/2 {
   345  		gogc(0)
   346  	}
   347  
   348  	return x
   349  }
   350  
   351  func loadPtrMask(typ *_type) []uint8 {
   352  	var ptrmask *uint8
   353  	nptr := (uintptr(typ.size) + ptrSize - 1) / ptrSize
   354  	if typ.kind&kindGCProg != 0 {
   355  		masksize := nptr
   356  		if masksize%2 != 0 {
   357  			masksize *= 2 // repeated
   358  		}
   359  		masksize = masksize * pointersPerByte / 8 // 4 bits per word
   360  		masksize++                                // unroll flag in the beginning
   361  		if masksize > maxGCMask && typ.gc[1] != 0 {
   362  			// write barriers have not been updated to deal with this case yet.
   363  			gothrow("maxGCMask too small for now")
   364  		}
   365  		ptrmask = (*uint8)(unsafe.Pointer(uintptr(typ.gc[0])))
   366  		// Check whether the program is already unrolled
   367  		// by checking if the unroll flag byte is set
   368  		maskword := uintptr(atomicloadp(unsafe.Pointer(ptrmask)))
   369  		if *(*uint8)(unsafe.Pointer(&maskword)) == 0 {
   370  			systemstack(func() {
   371  				unrollgcprog_m(typ)
   372  			})
   373  		}
   374  		ptrmask = (*uint8)(add(unsafe.Pointer(ptrmask), 1)) // skip the unroll flag byte
   375  	} else {
   376  		ptrmask = (*uint8)(unsafe.Pointer(typ.gc[0])) // pointer to unrolled mask
   377  	}
   378  	return (*[1 << 30]byte)(unsafe.Pointer(ptrmask))[:(nptr+1)/2]
   379  }
   380  
   381  // implementation of new builtin
   382  func newobject(typ *_type) unsafe.Pointer {
   383  	flags := uint32(0)
   384  	if typ.kind&kindNoPointers != 0 {
   385  		flags |= flagNoScan
   386  	}
   387  	return mallocgc(uintptr(typ.size), typ, flags)
   388  }
   389  
   390  // implementation of make builtin for slices
   391  func newarray(typ *_type, n uintptr) unsafe.Pointer {
   392  	flags := uint32(0)
   393  	if typ.kind&kindNoPointers != 0 {
   394  		flags |= flagNoScan
   395  	}
   396  	if int(n) < 0 || (typ.size > 0 && n > _MaxMem/uintptr(typ.size)) {
   397  		panic("runtime: allocation size out of range")
   398  	}
   399  	return mallocgc(uintptr(typ.size)*n, typ, flags)
   400  }
   401  
   402  // rawmem returns a chunk of pointerless memory.  It is
   403  // not zeroed.
   404  func rawmem(size uintptr) unsafe.Pointer {
   405  	return mallocgc(size, nil, flagNoScan|flagNoZero)
   406  }
   407  
   408  // round size up to next size class
   409  func goroundupsize(size uintptr) uintptr {
   410  	if size < maxSmallSize {
   411  		if size <= 1024-8 {
   412  			return uintptr(class_to_size[size_to_class8[(size+7)>>3]])
   413  		}
   414  		return uintptr(class_to_size[size_to_class128[(size-1024+127)>>7]])
   415  	}
   416  	if size+pageSize < size {
   417  		return size
   418  	}
   419  	return (size + pageSize - 1) &^ pageMask
   420  }
   421  
   422  func profilealloc(mp *m, x unsafe.Pointer, size uintptr) {
   423  	c := mp.mcache
   424  	rate := MemProfileRate
   425  	if size < uintptr(rate) {
   426  		// pick next profile time
   427  		// If you change this, also change allocmcache.
   428  		if rate > 0x3fffffff { // make 2*rate not overflow
   429  			rate = 0x3fffffff
   430  		}
   431  		next := int32(fastrand1()) % (2 * int32(rate))
   432  		// Subtract the "remainder" of the current allocation.
   433  		// Otherwise objects that are close in size to sampling rate
   434  		// will be under-sampled, because we consistently discard this remainder.
   435  		next -= (int32(size) - c.next_sample)
   436  		if next < 0 {
   437  			next = 0
   438  		}
   439  		c.next_sample = next
   440  	}
   441  
   442  	mProf_Malloc(x, size)
   443  }
   444  
   445  // force = 1 - do GC regardless of current heap usage
   446  // force = 2 - go GC and eager sweep
   447  func gogc(force int32) {
   448  	// The gc is turned off (via enablegc) until the bootstrap has completed.
   449  	// Also, malloc gets called in the guts of a number of libraries that might be
   450  	// holding locks. To avoid deadlocks during stoptheworld, don't bother
   451  	// trying to run gc while holding a lock. The next mallocgc without a lock
   452  	// will do the gc instead.
   453  	mp := acquirem()
   454  	if gp := getg(); gp == mp.g0 || mp.locks > 1 || !memstats.enablegc || panicking != 0 || gcpercent < 0 {
   455  		releasem(mp)
   456  		return
   457  	}
   458  	releasem(mp)
   459  	mp = nil
   460  
   461  	semacquire(&worldsema, false)
   462  
   463  	if force == 0 && memstats.heap_alloc < memstats.next_gc {
   464  		// typically threads which lost the race to grab
   465  		// worldsema exit here when gc is done.
   466  		semrelease(&worldsema)
   467  		return
   468  	}
   469  
   470  	// Ok, we're doing it!  Stop everybody else
   471  	startTime := nanotime()
   472  	mp = acquirem()
   473  	mp.gcing = 1
   474  	releasem(mp)
   475  
   476  	systemstack(stoptheworld)
   477  	systemstack(finishsweep_m) // finish sweep before we start concurrent scan.
   478  	if true {                  // To turn on concurrent scan and mark set to true...
   479  		systemstack(starttheworld)
   480  		// Do a concurrent heap scan before we stop the world.
   481  		systemstack(gcscan_m)
   482  		systemstack(stoptheworld)
   483  		systemstack(gcinstallmarkwb_m)
   484  		systemstack(starttheworld)
   485  		systemstack(gcmark_m)
   486  		systemstack(stoptheworld)
   487  		systemstack(gcinstalloffwb_m)
   488  	}
   489  
   490  	if mp != acquirem() {
   491  		gothrow("gogc: rescheduled")
   492  	}
   493  
   494  	clearpools()
   495  
   496  	// Run gc on the g0 stack.  We do this so that the g stack
   497  	// we're currently running on will no longer change.  Cuts
   498  	// the root set down a bit (g0 stacks are not scanned, and
   499  	// we don't need to scan gc's internal state).  We also
   500  	// need to switch to g0 so we can shrink the stack.
   501  	n := 1
   502  	if debug.gctrace > 1 {
   503  		n = 2
   504  	}
   505  	eagersweep := force >= 2
   506  	for i := 0; i < n; i++ {
   507  		if i > 0 {
   508  			startTime = nanotime()
   509  		}
   510  		// switch to g0, call gc, then switch back
   511  		systemstack(func() {
   512  			gc_m(startTime, eagersweep)
   513  		})
   514  	}
   515  
   516  	systemstack(func() {
   517  		gccheckmark_m(startTime, eagersweep)
   518  	})
   519  
   520  	// all done
   521  	mp.gcing = 0
   522  	semrelease(&worldsema)
   523  	systemstack(starttheworld)
   524  	releasem(mp)
   525  	mp = nil
   526  
   527  	// now that gc is done, kick off finalizer thread if needed
   528  	if !concurrentSweep {
   529  		// give the queued finalizers, if any, a chance to run
   530  		Gosched()
   531  	}
   532  }
   533  
   534  func GCcheckmarkenable() {
   535  	systemstack(gccheckmarkenable_m)
   536  }
   537  
   538  func GCcheckmarkdisable() {
   539  	systemstack(gccheckmarkdisable_m)
   540  }
   541  
   542  // GC runs a garbage collection.
   543  func GC() {
   544  	gogc(2)
   545  }
   546  
   547  // linker-provided
   548  var noptrdata struct{}
   549  var enoptrdata struct{}
   550  var noptrbss struct{}
   551  var enoptrbss struct{}
   552  
   553  // SetFinalizer sets the finalizer associated with x to f.
   554  // When the garbage collector finds an unreachable block
   555  // with an associated finalizer, it clears the association and runs
   556  // f(x) in a separate goroutine.  This makes x reachable again, but
   557  // now without an associated finalizer.  Assuming that SetFinalizer
   558  // is not called again, the next time the garbage collector sees
   559  // that x is unreachable, it will free x.
   560  //
   561  // SetFinalizer(x, nil) clears any finalizer associated with x.
   562  //
   563  // The argument x must be a pointer to an object allocated by
   564  // calling new or by taking the address of a composite literal.
   565  // The argument f must be a function that takes a single argument
   566  // to which x's type can be assigned, and can have arbitrary ignored return
   567  // values. If either of these is not true, SetFinalizer aborts the
   568  // program.
   569  //
   570  // Finalizers are run in dependency order: if A points at B, both have
   571  // finalizers, and they are otherwise unreachable, only the finalizer
   572  // for A runs; once A is freed, the finalizer for B can run.
   573  // If a cyclic structure includes a block with a finalizer, that
   574  // cycle is not guaranteed to be garbage collected and the finalizer
   575  // is not guaranteed to run, because there is no ordering that
   576  // respects the dependencies.
   577  //
   578  // The finalizer for x is scheduled to run at some arbitrary time after
   579  // x becomes unreachable.
   580  // There is no guarantee that finalizers will run before a program exits,
   581  // so typically they are useful only for releasing non-memory resources
   582  // associated with an object during a long-running program.
   583  // For example, an os.File object could use a finalizer to close the
   584  // associated operating system file descriptor when a program discards
   585  // an os.File without calling Close, but it would be a mistake
   586  // to depend on a finalizer to flush an in-memory I/O buffer such as a
   587  // bufio.Writer, because the buffer would not be flushed at program exit.
   588  //
   589  // It is not guaranteed that a finalizer will run if the size of *x is
   590  // zero bytes.
   591  //
   592  // It is not guaranteed that a finalizer will run for objects allocated
   593  // in initializers for package-level variables. Such objects may be
   594  // linker-allocated, not heap-allocated.
   595  //
   596  // A single goroutine runs all finalizers for a program, sequentially.
   597  // If a finalizer must run for a long time, it should do so by starting
   598  // a new goroutine.
   599  func SetFinalizer(obj interface{}, finalizer interface{}) {
   600  	e := (*eface)(unsafe.Pointer(&obj))
   601  	etyp := e._type
   602  	if etyp == nil {
   603  		gothrow("runtime.SetFinalizer: first argument is nil")
   604  	}
   605  	if etyp.kind&kindMask != kindPtr {
   606  		gothrow("runtime.SetFinalizer: first argument is " + *etyp._string + ", not pointer")
   607  	}
   608  	ot := (*ptrtype)(unsafe.Pointer(etyp))
   609  	if ot.elem == nil {
   610  		gothrow("nil elem type!")
   611  	}
   612  
   613  	// find the containing object
   614  	_, base, _ := findObject(e.data)
   615  
   616  	if base == nil {
   617  		// 0-length objects are okay.
   618  		if e.data == unsafe.Pointer(&zerobase) {
   619  			return
   620  		}
   621  
   622  		// Global initializers might be linker-allocated.
   623  		//	var Foo = &Object{}
   624  		//	func main() {
   625  		//		runtime.SetFinalizer(Foo, nil)
   626  		//	}
   627  		// The relevant segments are: noptrdata, data, bss, noptrbss.
   628  		// We cannot assume they are in any order or even contiguous,
   629  		// due to external linking.
   630  		if uintptr(unsafe.Pointer(&noptrdata)) <= uintptr(e.data) && uintptr(e.data) < uintptr(unsafe.Pointer(&enoptrdata)) ||
   631  			uintptr(unsafe.Pointer(&data)) <= uintptr(e.data) && uintptr(e.data) < uintptr(unsafe.Pointer(&edata)) ||
   632  			uintptr(unsafe.Pointer(&bss)) <= uintptr(e.data) && uintptr(e.data) < uintptr(unsafe.Pointer(&ebss)) ||
   633  			uintptr(unsafe.Pointer(&noptrbss)) <= uintptr(e.data) && uintptr(e.data) < uintptr(unsafe.Pointer(&enoptrbss)) {
   634  			return
   635  		}
   636  		gothrow("runtime.SetFinalizer: pointer not in allocated block")
   637  	}
   638  
   639  	if e.data != base {
   640  		// As an implementation detail we allow to set finalizers for an inner byte
   641  		// of an object if it could come from tiny alloc (see mallocgc for details).
   642  		if ot.elem == nil || ot.elem.kind&kindNoPointers == 0 || ot.elem.size >= maxTinySize {
   643  			gothrow("runtime.SetFinalizer: pointer not at beginning of allocated block")
   644  		}
   645  	}
   646  
   647  	f := (*eface)(unsafe.Pointer(&finalizer))
   648  	ftyp := f._type
   649  	if ftyp == nil {
   650  		// switch to system stack and remove finalizer
   651  		systemstack(func() {
   652  			removefinalizer(e.data)
   653  		})
   654  		return
   655  	}
   656  
   657  	if ftyp.kind&kindMask != kindFunc {
   658  		gothrow("runtime.SetFinalizer: second argument is " + *ftyp._string + ", not a function")
   659  	}
   660  	ft := (*functype)(unsafe.Pointer(ftyp))
   661  	ins := *(*[]*_type)(unsafe.Pointer(&ft.in))
   662  	if ft.dotdotdot || len(ins) != 1 {
   663  		gothrow("runtime.SetFinalizer: cannot pass " + *etyp._string + " to finalizer " + *ftyp._string)
   664  	}
   665  	fint := ins[0]
   666  	switch {
   667  	case fint == etyp:
   668  		// ok - same type
   669  		goto okarg
   670  	case fint.kind&kindMask == kindPtr:
   671  		if (fint.x == nil || fint.x.name == nil || etyp.x == nil || etyp.x.name == nil) && (*ptrtype)(unsafe.Pointer(fint)).elem == ot.elem {
   672  			// ok - not same type, but both pointers,
   673  			// one or the other is unnamed, and same element type, so assignable.
   674  			goto okarg
   675  		}
   676  	case fint.kind&kindMask == kindInterface:
   677  		ityp := (*interfacetype)(unsafe.Pointer(fint))
   678  		if len(ityp.mhdr) == 0 {
   679  			// ok - satisfies empty interface
   680  			goto okarg
   681  		}
   682  		if _, ok := assertE2I2(ityp, obj); ok {
   683  			goto okarg
   684  		}
   685  	}
   686  	gothrow("runtime.SetFinalizer: cannot pass " + *etyp._string + " to finalizer " + *ftyp._string)
   687  okarg:
   688  	// compute size needed for return parameters
   689  	nret := uintptr(0)
   690  	for _, t := range *(*[]*_type)(unsafe.Pointer(&ft.out)) {
   691  		nret = round(nret, uintptr(t.align)) + uintptr(t.size)
   692  	}
   693  	nret = round(nret, ptrSize)
   694  
   695  	// make sure we have a finalizer goroutine
   696  	createfing()
   697  
   698  	systemstack(func() {
   699  		if !addfinalizer(e.data, (*funcval)(f.data), nret, fint, ot) {
   700  			gothrow("runtime.SetFinalizer: finalizer already set")
   701  		}
   702  	})
   703  }
   704  
   705  // round n up to a multiple of a.  a must be a power of 2.
   706  func round(n, a uintptr) uintptr {
   707  	return (n + a - 1) &^ (a - 1)
   708  }
   709  
   710  // Look up pointer v in heap.  Return the span containing the object,
   711  // the start of the object, and the size of the object.  If the object
   712  // does not exist, return nil, nil, 0.
   713  func findObject(v unsafe.Pointer) (s *mspan, x unsafe.Pointer, n uintptr) {
   714  	c := gomcache()
   715  	c.local_nlookup++
   716  	if ptrSize == 4 && c.local_nlookup >= 1<<30 {
   717  		// purge cache stats to prevent overflow
   718  		lock(&mheap_.lock)
   719  		purgecachedstats(c)
   720  		unlock(&mheap_.lock)
   721  	}
   722  
   723  	// find span
   724  	arena_start := uintptr(unsafe.Pointer(mheap_.arena_start))
   725  	arena_used := uintptr(unsafe.Pointer(mheap_.arena_used))
   726  	if uintptr(v) < arena_start || uintptr(v) >= arena_used {
   727  		return
   728  	}
   729  	p := uintptr(v) >> pageShift
   730  	q := p - arena_start>>pageShift
   731  	s = *(**mspan)(add(unsafe.Pointer(mheap_.spans), q*ptrSize))
   732  	if s == nil {
   733  		return
   734  	}
   735  	x = unsafe.Pointer(uintptr(s.start) << pageShift)
   736  
   737  	if uintptr(v) < uintptr(x) || uintptr(v) >= uintptr(unsafe.Pointer(s.limit)) || s.state != mSpanInUse {
   738  		s = nil
   739  		x = nil
   740  		return
   741  	}
   742  
   743  	n = uintptr(s.elemsize)
   744  	if s.sizeclass != 0 {
   745  		x = add(x, (uintptr(v)-uintptr(x))/n*n)
   746  	}
   747  	return
   748  }
   749  
   750  var fingCreate uint32
   751  
   752  func createfing() {
   753  	// start the finalizer goroutine exactly once
   754  	if fingCreate == 0 && cas(&fingCreate, 0, 1) {
   755  		go runfinq()
   756  	}
   757  }
   758  
   759  // This is the goroutine that runs all of the finalizers
   760  func runfinq() {
   761  	var (
   762  		frame    unsafe.Pointer
   763  		framecap uintptr
   764  	)
   765  
   766  	for {
   767  		lock(&finlock)
   768  		fb := finq
   769  		finq = nil
   770  		if fb == nil {
   771  			gp := getg()
   772  			fing = gp
   773  			fingwait = true
   774  			gp.issystem = true
   775  			goparkunlock(&finlock, "finalizer wait")
   776  			gp.issystem = false
   777  			continue
   778  		}
   779  		unlock(&finlock)
   780  		if raceenabled {
   781  			racefingo()
   782  		}
   783  		for fb != nil {
   784  			for i := int32(0); i < fb.cnt; i++ {
   785  				f := (*finalizer)(add(unsafe.Pointer(&fb.fin), uintptr(i)*unsafe.Sizeof(finalizer{})))
   786  
   787  				framesz := unsafe.Sizeof((interface{})(nil)) + uintptr(f.nret)
   788  				if framecap < framesz {
   789  					// The frame does not contain pointers interesting for GC,
   790  					// all not yet finalized objects are stored in finq.
   791  					// If we do not mark it as FlagNoScan,
   792  					// the last finalized object is not collected.
   793  					frame = mallocgc(framesz, nil, flagNoScan)
   794  					framecap = framesz
   795  				}
   796  
   797  				if f.fint == nil {
   798  					gothrow("missing type in runfinq")
   799  				}
   800  				switch f.fint.kind & kindMask {
   801  				case kindPtr:
   802  					// direct use of pointer
   803  					*(*unsafe.Pointer)(frame) = f.arg
   804  				case kindInterface:
   805  					ityp := (*interfacetype)(unsafe.Pointer(f.fint))
   806  					// set up with empty interface
   807  					(*eface)(frame)._type = &f.ot.typ
   808  					(*eface)(frame).data = f.arg
   809  					if len(ityp.mhdr) != 0 {
   810  						// convert to interface with methods
   811  						// this conversion is guaranteed to succeed - we checked in SetFinalizer
   812  						*(*fInterface)(frame) = assertE2I(ityp, *(*interface{})(frame))
   813  					}
   814  				default:
   815  					gothrow("bad kind in runfinq")
   816  				}
   817  				reflectcall(unsafe.Pointer(f.fn), frame, uint32(framesz), uint32(framesz))
   818  
   819  				// drop finalizer queue references to finalized object
   820  				f.fn = nil
   821  				f.arg = nil
   822  				f.ot = nil
   823  			}
   824  			fb.cnt = 0
   825  			next := fb.next
   826  			lock(&finlock)
   827  			fb.next = finc
   828  			finc = fb
   829  			unlock(&finlock)
   830  			fb = next
   831  		}
   832  	}
   833  }
   834  
   835  var persistent struct {
   836  	lock mutex
   837  	pos  unsafe.Pointer
   838  	end  unsafe.Pointer
   839  }
   840  
   841  // Wrapper around sysAlloc that can allocate small chunks.
   842  // There is no associated free operation.
   843  // Intended for things like function/type/debug-related persistent data.
   844  // If align is 0, uses default align (currently 8).
   845  func persistentalloc(size, align uintptr, stat *uint64) unsafe.Pointer {
   846  	const (
   847  		chunk    = 256 << 10
   848  		maxBlock = 64 << 10 // VM reservation granularity is 64K on windows
   849  	)
   850  
   851  	if align != 0 {
   852  		if align&(align-1) != 0 {
   853  			gothrow("persistentalloc: align is not a power of 2")
   854  		}
   855  		if align > _PageSize {
   856  			gothrow("persistentalloc: align is too large")
   857  		}
   858  	} else {
   859  		align = 8
   860  	}
   861  
   862  	if size >= maxBlock {
   863  		return sysAlloc(size, stat)
   864  	}
   865  
   866  	lock(&persistent.lock)
   867  	persistent.pos = roundup(persistent.pos, align)
   868  	if uintptr(persistent.pos)+size > uintptr(persistent.end) {
   869  		persistent.pos = sysAlloc(chunk, &memstats.other_sys)
   870  		if persistent.pos == nil {
   871  			unlock(&persistent.lock)
   872  			gothrow("runtime: cannot allocate memory")
   873  		}
   874  		persistent.end = add(persistent.pos, chunk)
   875  	}
   876  	p := persistent.pos
   877  	persistent.pos = add(persistent.pos, size)
   878  	unlock(&persistent.lock)
   879  
   880  	if stat != &memstats.other_sys {
   881  		xadd64(stat, int64(size))
   882  		xadd64(&memstats.other_sys, -int64(size))
   883  	}
   884  	return p
   885  }