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