libgo: update to Go1.14beta1
[platform/upstream/gcc.git] / libgo / go / runtime / malloc.go
index 0eee55e..fda2273 100644 (file)
@@ -19,7 +19,7 @@
 //     fixalloc: a free-list allocator for fixed-size off-heap objects,
 //             used to manage storage used by the allocator.
 //     mheap: the malloc heap, managed at page (8192-byte) granularity.
-//     mspan: a run of pages managed by the mheap.
+//     mspan: a run of in-use pages managed by the mheap.
 //     mcentral: collects all spans of a given size class.
 //     mcache: a per-P cache of mspans with free space.
 //     mstats: allocation statistics.
 //        it is placed on the mcentral free list for the mspan's size
 //        class.
 //
-//     3. Otherwise, if all objects in the mspan are free, the mspan
-//        is now "idle", so it is returned to the mheap and no longer
-//        has a size class.
-//        This may coalesce it with adjacent idle mspans.
-//
-//     4. If an mspan remains idle for long enough, return its pages
-//        to the operating system.
+//     3. Otherwise, if all objects in the mspan are free, the mspan's
+//        pages are returned to the mheap and the mspan is now dead.
 //
 // Allocating and freeing a large object uses the mheap
 // directly, bypassing the mcache and mcentral.
@@ -207,17 +202,21 @@ const (
        // exceed Go's 48 bit limit, it's extremely unlikely in
        // practice.
        //
-       // On aix/ppc64, the limits is increased to 1<<60 to accept addresses
-       // returned by mmap syscall. These are in range:
-       //  0x0a00000000000000 - 0x0afffffffffffff
-       //
        // On 32-bit platforms, we accept the full 32-bit address
        // space because doing so is cheap.
        // mips32 only has access to the low 2GB of virtual memory, so
        // we further limit it to 31 bits.
        //
+       // On darwin/arm64, although 64-bit pointers are presumably
+       // available, pointers are truncated to 33 bits. Furthermore,
+       // only the top 4 GiB of the address space are actually available
+       // to the application, but we allow the whole 33 bits anyway for
+       // simplicity.
+       // TODO(mknyszek): Consider limiting it to 32 bits and using
+       // arenaBaseOffset to offset into the top 4 GiB.
+       //
        // WebAssembly currently has a limit of 4GB linear memory.
-       heapAddrBits = (_64bit*(1-sys.GoarchWasm)*(1-sys.GoosAix))*48 + (1-_64bit+sys.GoarchWasm)*(32-(sys.GoarchMips+sys.GoarchMipsle)) + 60*(sys.GoosAix*_64bit)
+       heapAddrBits = (_64bit*(1-sys.GoarchWasm)*(1-sys.GoosDarwin*sys.GoarchArm64))*48 + (1-_64bit+sys.GoarchWasm)*(32-(sys.GoarchMips+sys.GoarchMipsle)) + 33*sys.GoosDarwin*sys.GoarchArm64
 
        // maxAlloc is the maximum size of an allocation. On 64-bit,
        // it's theoretically possible to allocate 1<<heapAddrBits bytes. On
@@ -236,7 +235,6 @@ const (
        //       Platform  Addr bits  Arena size  L1 entries   L2 entries
        // --------------  ---------  ----------  ----------  -----------
        //       */64-bit         48        64MB           1    4M (32MB)
-       //     aix/64-bit         60       256MB        4096    4M (32MB)
        // windows/64-bit         48         4MB          64    1M  (8MB)
        //       */32-bit         32         4MB           1  1024  (4KB)
        //     */mips(le)         31         4MB           1   512  (2KB)
@@ -258,7 +256,7 @@ const (
        // logHeapArenaBytes is log_2 of heapArenaBytes. For clarity,
        // prefer using heapArenaBytes where possible (we need the
        // constant to compute some other constants).
-       logHeapArenaBytes = (6+20)*(_64bit*(1-sys.GoosWindows)*(1-sys.GoosAix)) + (2+20)*(_64bit*sys.GoosWindows) + (2+20)*(1-_64bit) + (8+20)*(sys.GoosAix*_64bit)
+       logHeapArenaBytes = (6+20)*(_64bit*(1-sys.GoosWindows)*(1-sys.GoarchWasm)) + (2+20)*(_64bit*sys.GoosWindows) + (2+20)*(1-_64bit) + (2+20)*sys.GoarchWasm
 
        // heapArenaBitmapBytes is the size of each heap arena's bitmap.
        heapArenaBitmapBytes = heapArenaBytes / (sys.PtrSize * 8 / 2)
@@ -278,10 +276,7 @@ const (
        // We use the L1 map on 64-bit Windows because the arena size
        // is small, but the address space is still 48 bits, and
        // there's a high cost to having a large L2.
-       //
-       // We use the L1 map on aix/ppc64 to keep the same L2 value
-       // as on Linux.
-       arenaL1Bits = 6*(_64bit*sys.GoosWindows) + 12*(sys.GoosAix*_64bit)
+       arenaL1Bits = 6 * (_64bit * sys.GoosWindows)
 
        // arenaL2Bits is the number of bits of the arena number
        // covered by the second level arena index.
@@ -308,9 +303,15 @@ const (
        // bits. This offset lets us handle "negative" addresses (or
        // high addresses if viewed as unsigned).
        //
+       // On aix/ppc64, this offset allows to keep the heapAddrBits to
+       // 48. Otherwize, it would be 60 in order to handle mmap addresses
+       // (in range 0x0a00000000000000 - 0x0afffffffffffff). But in this
+       // case, the memory reserved in (s *pageAlloc).init for chunks
+       // is causing important slowdowns.
+       //
        // On other platforms, the user address space is contiguous
        // and starts at 0, so no offset is necessary.
-       arenaBaseOffset uintptr = sys.GoarchAmd64 * (1 << 47)
+       arenaBaseOffset = sys.GoarchAmd64*(1<<47) + (^0x0a00000000000000+1)&uintptrMask*sys.GoosAix
 
        // Max number of threads to run garbage collection.
        // 2, 3, and 4 are all plausible maximums depending
@@ -444,6 +445,10 @@ func mallocinit() {
                // The OS init code failed to fetch the physical page size.
                throw("failed to get system page size")
        }
+       if physPageSize > maxPhysPageSize {
+               print("system page size (", physPageSize, ") is larger than maximum page size (", maxPhysPageSize, ")\n")
+               throw("bad system page size")
+       }
        if physPageSize < minPhysPageSize {
                print("system page size (", physPageSize, ") is smaller than minimum page size (", minPhysPageSize, ")\n")
                throw("bad system page size")
@@ -456,6 +461,13 @@ func mallocinit() {
                print("system huge page size (", physHugePageSize, ") must be a power of 2\n")
                throw("bad system huge page size")
        }
+       if physHugePageSize > maxPhysHugePageSize {
+               // physHugePageSize is greater than the maximum supported huge page size.
+               // Don't throw here, like in the other cases, since a system configured
+               // in this way isn't wrong, we just don't have the code to support them.
+               // Instead, silently set the huge page size to zero.
+               physHugePageSize = 0
+       }
        if physHugePageSize != 0 {
                // Since physHugePageSize is a power of 2, it suffices to increase
                // physHugePageShift until 1<<physHugePageShift == physHugePageSize.
@@ -579,7 +591,7 @@ func mallocinit() {
                if mheap_.heapArenaAlloc.next <= p && p < mheap_.heapArenaAlloc.end {
                        p = mheap_.heapArenaAlloc.end
                }
-               p = round(p+(256<<10), heapArenaBytes)
+               p = alignUp(p+(256<<10), heapArenaBytes)
                // Because we're worried about fragmentation on
                // 32-bit, we try to make a large initial reservation.
                arenaSizes := [...]uintptr{
@@ -612,7 +624,7 @@ func mallocinit() {
 //
 // h must be locked.
 func (h *mheap) sysAlloc(n uintptr) (v unsafe.Pointer, size uintptr) {
-       n = round(n, heapArenaBytes)
+       n = alignUp(n, heapArenaBytes)
 
        // First, try the arena pre-reservation.
        v = h.arena.alloc(n, heapArenaBytes, &memstats.heap_sys)
@@ -795,7 +807,7 @@ retry:
                // re-reserve the aligned sub-region. This may race,
                // so we may have to try again.
                sysFree(unsafe.Pointer(p), size+align, nil)
-               p = round(p, align)
+               p = alignUp(p, align)
                p2 := sysReserve(unsafe.Pointer(p), size)
                if p != uintptr(p2) {
                        // Must have raced. Try again.
@@ -809,7 +821,7 @@ retry:
                return p2, size
        default:
                // Trim off the unaligned parts.
-               pAligned := round(p, align)
+               pAligned := alignUp(p, align)
                sysFree(unsafe.Pointer(p), pAligned-p, nil)
                end := pAligned + size
                endLen := (p + size + align) - end
@@ -998,11 +1010,11 @@ func mallocgc(size uintptr, typ *_type, needzero bool) unsafe.Pointer {
                        off := c.tinyoffset
                        // Align tiny pointer for required (conservative) alignment.
                        if size&7 == 0 {
-                               off = round(off, 8)
+                               off = alignUp(off, 8)
                        } else if size&3 == 0 {
-                               off = round(off, 4)
+                               off = alignUp(off, 4)
                        } else if size&1 == 0 {
-                               off = round(off, 2)
+                               off = alignUp(off, 2)
                        }
                        if off+size <= maxTinySize && c.tiny != 0 {
                                // The object fits into existing tiny block.
@@ -1160,7 +1172,7 @@ func largeAlloc(size uintptr, needzero bool, noscan bool) *mspan {
        // pays the debt down to npage pages.
        deductSweepCredit(npages*_PageSize, npages)
 
-       s := mheap_.alloc(npages, makeSpanClass(0, noscan), true, needzero)
+       s := mheap_.alloc(npages, makeSpanClass(0, noscan), needzero)
        if s == nil {
                throw("out of memory")
        }
@@ -1338,7 +1350,7 @@ func persistentalloc1(size, align uintptr, sysStat *uint64) *notInHeap {
                lock(&globalAlloc.mutex)
                persistent = &globalAlloc.persistentAlloc
        }
-       persistent.off = round(persistent.off, align)
+       persistent.off = alignUp(persistent.off, align)
        if persistent.off+size > persistentChunkSize || persistent.base == nil {
                persistent.base = (*notInHeap)(sysAlloc(persistentChunkSize, &memstats.other_sys))
                if persistent.base == nil {
@@ -1356,7 +1368,7 @@ func persistentalloc1(size, align uintptr, sysStat *uint64) *notInHeap {
                                break
                        }
                }
-               persistent.off = round(sys.PtrSize, align)
+               persistent.off = alignUp(sys.PtrSize, align)
        }
        p := persistent.base.add(persistent.off)
        persistent.off += size
@@ -1402,12 +1414,12 @@ func (l *linearAlloc) init(base, size uintptr) {
 }
 
 func (l *linearAlloc) alloc(size, align uintptr, sysStat *uint64) unsafe.Pointer {
-       p := round(l.next, align)
+       p := alignUp(l.next, align)
        if p+size > l.end {
                return nil
        }
        l.next = p + size
-       if pEnd := round(l.next-1, physPageSize); pEnd > l.mapped {
+       if pEnd := alignUp(l.next-1, physPageSize); pEnd > l.mapped {
                // Transition from Reserved to Prepared to Ready.
                sysMap(unsafe.Pointer(l.mapped), pEnd-l.mapped, sysStat)
                sysUsed(unsafe.Pointer(l.mapped), pEnd-l.mapped)