Copyright 2019 The Go Authors. All rights reserved. Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.
Address range data structure. This file contains an implementation of a data structure which manages ordered address ranges.

package runtime

import (
	
	
)
addrRange represents a region of address space. An addrRange must never span a gap in the address space.
base and limit together represent the region of address space [base, limit). That is, base is inclusive, limit is exclusive. These are address over an offset view of the address space on platforms with a segmented address space, that is, on platforms where arenaBaseOffset != 0.
makeAddrRange creates a new address range from two virtual addresses. Throws if the base and limit are not in the same memory segment.
func (,  uintptr) addrRange {
	 := addrRange{offAddr{}, offAddr{}}
	if (-arenaBaseOffset >= ) != (-arenaBaseOffset >= ) {
		throw("addr range base and limit are not in the same memory segment")
	}
	return 
}
size returns the size of the range represented in bytes.
func ( addrRange) () uintptr {
	if !.base.lessThan(.limit) {
		return 0
Subtraction is safe because limit and base must be in the same segment of the address space.
	return .limit.diff(.base)
}
contains returns whether or not the range contains a given address.
func ( addrRange) ( uintptr) bool {
	return .base.lessEqual(offAddr{}) && (offAddr{}).lessThan(.limit)
}
subtract takes the addrRange toPrune and cuts out any overlap with from, then returns the new range. subtract assumes that a and b either don't overlap at all, only overlap on one side, or are equal. If b is strictly contained in a, thus forcing a split, it will throw.
func ( addrRange) ( addrRange) addrRange {
	if .base.lessEqual(.base) && .limit.lessEqual(.limit) {
		return addrRange{}
	} else if .base.lessThan(.base) && .limit.lessThan(.limit) {
		throw("bad prune")
	} else if .limit.lessThan(.limit) && .base.lessThan(.limit) {
		.base = .limit
	} else if .base.lessThan(.base) && .base.lessThan(.limit) {
		.limit = .base
	}
	return 
}
removeGreaterEqual removes all addresses in a greater than or equal to addr and returns the new range.
func ( addrRange) ( uintptr) addrRange {
	if (offAddr{}).lessEqual(.base) {
		return addrRange{}
	}
	if .limit.lessEqual(offAddr{}) {
		return 
	}
	return makeAddrRange(.base.addr(), )
}

minOffAddr is the minimum address in the offset space, and it corresponds to the virtual address arenaBaseOffset.
maxOffAddr is the maximum address in the offset address space. It corresponds to the highest virtual address representable by the page alloc chunk and heap arena maps.
offAddr represents an address in a contiguous view of the address space on systems where the address space is segmented. On other systems, it's just a normal address.
a is just the virtual address, but should never be used directly. Call addr() to get this value instead.
add adds a uintptr offset to the offAddr.
func ( offAddr) ( uintptr) offAddr {
	return offAddr{a: .a + }
}
sub subtracts a uintptr offset from the offAddr.
func ( offAddr) ( uintptr) offAddr {
	return offAddr{a: .a - }
}
diff returns the amount of bytes in between the two offAddrs.
func ( offAddr) ( offAddr) uintptr {
	return .a - .a
}
lessThan returns true if l1 is less than l2 in the offset address space.
func ( offAddr) ( offAddr) bool {
	return (.a - arenaBaseOffset) < (.a - arenaBaseOffset)
}
lessEqual returns true if l1 is less than or equal to l2 in the offset address space.
func ( offAddr) ( offAddr) bool {
	return (.a - arenaBaseOffset) <= (.a - arenaBaseOffset)
}
equal returns true if the two offAddr values are equal.
No need to compare in the offset space, it means the same thing.
	return  == 
}
addr returns the virtual address for this offset address.
func ( offAddr) () uintptr {
	return .a
}
addrRanges is a data structure holding a collection of ranges of address space. The ranges are coalesced eagerly to reduce the number ranges it holds. The slice backing store for this field is persistentalloc'd and thus there is no way to free it. addrRanges is not thread-safe.
ranges is a slice of ranges sorted by base.
totalBytes is the total amount of address space in bytes counted by this addrRanges.
sysStat is the stat to track allocations by this type
	sysStat *sysMemStat
}

func ( *addrRanges) ( *sysMemStat) {
	 := (*notInHeapSlice)(unsafe.Pointer(&.ranges))
	.len = 0
	.cap = 16
	.array = (*notInHeap)(persistentalloc(unsafe.Sizeof(addrRange{})*uintptr(.cap), sys.PtrSize, ))
	.sysStat = 
	.totalBytes = 0
}
findSucc returns the first index in a such that addr is less than the base of the addrRange at that index.
func ( *addrRanges) ( uintptr) int {
	 := offAddr{}
Narrow down the search space via a binary search for large addrRanges until we have at most iterMax candidates left.
	const  = 8
	,  := 0, len(.ranges)
	for - >  {
		 := (( - ) / 2) + 
a.ranges[i] contains base, so its successor is the next index.
			return  + 1
		}
In this case i might actually be the successor, but we can't be sure until we check the ones before it.
			 = 
In this case we know base is greater than or equal to a.ranges[i].limit-1, so i is definitely not the successor. We already checked i, so pick the next one.
			 =  + 1
		}
There are top-bot candidates left, so iterate over them and find the first that base is strictly less than.
	for  := ;  < ; ++ {
		if .lessThan(.ranges[].base) {
			return 
		}
	}
	return 
}
findAddrGreaterEqual returns the smallest address represented by a that is >= addr. Thus, if the address is represented by a, then it returns addr. The second return value indicates whether such an address exists for addr in a. That is, if addr is larger than any address known to a, the second return value will be false.
func ( *addrRanges) ( uintptr) (uintptr, bool) {
	 := .findSucc()
	if  == 0 {
		return .ranges[0].base.addr(), true
	}
	if .ranges[-1].contains() {
		return , true
	}
	if  < len(.ranges) {
		return .ranges[].base.addr(), true
	}
	return 0, false
}
contains returns true if a covers the address addr.
func ( *addrRanges) ( uintptr) bool {
	 := .findSucc()
	if  == 0 {
		return false
	}
	return .ranges[-1].contains()
}
add inserts a new address range to a. r must not overlap with any address range in a and r.size() must be > 0.
The copies in this function are potentially expensive, but this data structure is meant to represent the Go heap. At worst, copying this would take ~160µs assuming a conservative copying rate of 25 GiB/s (the copy will almost never trigger a page fault) for a 1 TiB heap with 4 MiB arenas which is completely discontiguous. ~160µs is still a lot, but in practice most platforms have 64 MiB arenas (which cuts this by a factor of 16) and Go heaps are usually mostly contiguous, so the chance that an addrRanges even grows to that size is extremely low.
An empty range has no effect on the set of addresses represented by a, but passing a zero-sized range is almost always a bug.
	if .size() == 0 {
		print("runtime: range = {", hex(.base.addr()), ", ", hex(.limit.addr()), "}\n")
		throw("attempted to add zero-sized address range")
Because we assume r is not currently represented in a, findSucc gives us our insertion index.
	 := .findSucc(.base.addr())
	 :=  > 0 && .ranges[-1].limit.equal(.base)
	 :=  < len(.ranges) && .limit.equal(.ranges[].base)
We have neighbors and they both border us. Merge a.ranges[i-1], r, and a.ranges[i] together into a.ranges[i-1].
		.ranges[-1].limit = .ranges[].limit
Delete a.ranges[i].
		copy(.ranges[:], .ranges[+1:])
		.ranges = .ranges[:len(.ranges)-1]
We have a neighbor at a lower address only and it borders us. Merge the new space into a.ranges[i-1].
		.ranges[-1].limit = .limit
We have a neighbor at a higher address only and it borders us. Merge the new space into a.ranges[i].
		.ranges[].base = .base
We may or may not have neighbors which don't border us. Add the new range.
Grow the array. Note that this leaks the old array, but since we're doubling we have at most 2x waste. For a 1 TiB heap and 4 MiB arenas which are all discontiguous (both very conservative assumptions), this would waste at most 4 MiB of memory.
			 := .ranges
			 := (*notInHeapSlice)(unsafe.Pointer(&.ranges))
			.len = len() + 1
			.cap = cap() * 2
			.array = (*notInHeap)(persistentalloc(unsafe.Sizeof(addrRange{})*uintptr(.cap), sys.PtrSize, .sysStat))
Copy in the old array, but make space for the new range.
			copy(.ranges[:], [:])
			copy(.ranges[+1:], [:])
		} else {
			.ranges = .ranges[:len(.ranges)+1]
			copy(.ranges[+1:], .ranges[:])
		}
		.ranges[] = 
	}
	.totalBytes += .size()
}
removeLast removes and returns the highest-addressed contiguous range of a, or the last nBytes of that range, whichever is smaller. If a is empty, it returns an empty range.
func ( *addrRanges) ( uintptr) addrRange {
	if len(.ranges) == 0 {
		return addrRange{}
	}
	 := .ranges[len(.ranges)-1]
	 := .size()
	if  >  {
		 := .limit.sub()
		.ranges[len(.ranges)-1].limit = 
		.totalBytes -= 
		return addrRange{, .limit}
	}
	.ranges = .ranges[:len(.ranges)-1]
	.totalBytes -= 
	return 
}
removeGreaterEqual removes the ranges of a which are above addr, and additionally splits any range containing addr.
func ( *addrRanges) ( uintptr) {
	 := .findSucc()
addr is before all ranges in a.
		.totalBytes = 0
		.ranges = .ranges[:0]
		return
	}
	 := uintptr(0)
	for ,  := range .ranges[:] {
		 += .size()
	}
	if  := .ranges[-1]; .contains() {
		 += .size()
		 = .removeGreaterEqual()
		if .size() == 0 {
			--
		} else {
			 -= .size()
			.ranges[-1] = 
		}
	}
	.ranges = .ranges[:]
	.totalBytes -= 
}
cloneInto makes a deep clone of a's state into b, re-using b's ranges if able.
Grow the array.
		 := (*notInHeapSlice)(unsafe.Pointer(&.ranges))
		.len = 0
		.cap = cap(.ranges)
		.array = (*notInHeap)(persistentalloc(unsafe.Sizeof(addrRange{})*uintptr(.cap), sys.PtrSize, .sysStat))
	}
	.ranges = .ranges[:len(.ranges)]
	.totalBytes = .totalBytes
	copy(.ranges, .ranges)