package runtime
import (
"internal/abi"
"internal/goarch"
"runtime/internal/math"
"runtime/internal/sys"
"unsafe"
)
type slice struct {
array unsafe .Pointer
len int
cap int
}
type notInHeapSlice struct {
array *notInHeap
len int
cap int
}
func panicmakeslicelen() {
panic (errorString ("makeslice: len out of range" ))
}
func panicmakeslicecap() {
panic (errorString ("makeslice: cap out of range" ))
}
func makeslicecopy(et *_type , tolen int , fromlen int , from unsafe .Pointer ) unsafe .Pointer {
var tomem , copymem uintptr
if uintptr (tolen ) > uintptr (fromlen ) {
var overflow bool
tomem , overflow = math .MulUintptr (et .size , uintptr (tolen ))
if overflow || tomem > maxAlloc || tolen < 0 {
panicmakeslicelen ()
}
copymem = et .size * uintptr (fromlen )
} else {
tomem = et .size * uintptr (tolen )
copymem = tomem
}
var to unsafe .Pointer
if et .ptrdata == 0 {
to = mallocgc (tomem , nil , false )
if copymem < tomem {
memclrNoHeapPointers (add (to , copymem ), tomem -copymem )
}
} else {
to = mallocgc (tomem , et , true )
if copymem > 0 && writeBarrier .enabled {
bulkBarrierPreWriteSrcOnly (uintptr (to ), uintptr (from ), copymem )
}
}
if raceenabled {
callerpc := getcallerpc ()
pc := abi .FuncPCABIInternal (makeslicecopy )
racereadrangepc (from , copymem , callerpc , pc )
}
if msanenabled {
msanread (from , copymem )
}
if asanenabled {
asanread (from , copymem )
}
memmove (to , from , copymem )
return to
}
func makeslice(et *_type , len , cap int ) unsafe .Pointer {
mem , overflow := math .MulUintptr (et .size , uintptr (cap ))
if overflow || mem > maxAlloc || len < 0 || len > cap {
mem , overflow := math .MulUintptr (et .size , uintptr (len ))
if overflow || mem > maxAlloc || len < 0 {
panicmakeslicelen ()
}
panicmakeslicecap ()
}
return mallocgc (mem , et , true )
}
func makeslice64(et *_type , len64 , cap64 int64 ) unsafe .Pointer {
len := int (len64 )
if int64 (len ) != len64 {
panicmakeslicelen ()
}
cap := int (cap64 )
if int64 (cap ) != cap64 {
panicmakeslicecap ()
}
return makeslice (et , len , cap )
}
func unsafeslice(et *_type , ptr unsafe .Pointer , len int ) {
if len < 0 {
panicunsafeslicelen ()
}
mem , overflow := math .MulUintptr (et .size , uintptr (len ))
if overflow || mem > -uintptr (ptr ) {
if ptr == nil {
panic (errorString ("unsafe.Slice: ptr is nil and len is not zero" ))
}
panicunsafeslicelen ()
}
}
func unsafeslice64(et *_type , ptr unsafe .Pointer , len64 int64 ) {
len := int (len64 )
if int64 (len ) != len64 {
panicunsafeslicelen ()
}
unsafeslice (et , ptr , len )
}
func unsafeslicecheckptr(et *_type , ptr unsafe .Pointer , len64 int64 ) {
unsafeslice64 (et , ptr , len64 )
if checkptrStraddles (ptr , uintptr (len64 )*et .size ) {
throw ("checkptr: unsafe.Slice result straddles multiple allocations" )
}
}
func panicunsafeslicelen() {
panic (errorString ("unsafe.Slice: len out of range" ))
}
func growslice(et *_type , old slice , cap int ) slice {
if raceenabled {
callerpc := getcallerpc ()
racereadrangepc (old .array , uintptr (old .len *int (et .size )), callerpc , abi .FuncPCABIInternal (growslice ))
}
if msanenabled {
msanread (old .array , uintptr (old .len *int (et .size )))
}
if asanenabled {
asanread (old .array , uintptr (old .len *int (et .size )))
}
if cap < old .cap {
panic (errorString ("growslice: cap out of range" ))
}
if et .size == 0 {
return slice {unsafe .Pointer (&zerobase ), old .len , cap }
}
newcap := old .cap
doublecap := newcap + newcap
if cap > doublecap {
newcap = cap
} else {
const threshold = 256
if old .cap < threshold {
newcap = doublecap
} else {
for 0 < newcap && newcap < cap {
newcap += (newcap + 3 *threshold ) / 4
}
if newcap <= 0 {
newcap = cap
}
}
}
var overflow bool
var lenmem , newlenmem , capmem uintptr
switch {
case et .size == 1 :
lenmem = uintptr (old .len )
newlenmem = uintptr (cap )
capmem = roundupsize (uintptr (newcap ))
overflow = uintptr (newcap ) > maxAlloc
newcap = int (capmem )
case et .size == goarch .PtrSize :
lenmem = uintptr (old .len ) * goarch .PtrSize
newlenmem = uintptr (cap ) * goarch .PtrSize
capmem = roundupsize (uintptr (newcap ) * goarch .PtrSize )
overflow = uintptr (newcap ) > maxAlloc /goarch .PtrSize
newcap = int (capmem / goarch .PtrSize )
case isPowerOfTwo (et .size ):
var shift uintptr
if goarch .PtrSize == 8 {
shift = uintptr (sys .Ctz64 (uint64 (et .size ))) & 63
} else {
shift = uintptr (sys .Ctz32 (uint32 (et .size ))) & 31
}
lenmem = uintptr (old .len ) << shift
newlenmem = uintptr (cap ) << shift
capmem = roundupsize (uintptr (newcap ) << shift )
overflow = uintptr (newcap ) > (maxAlloc >> shift )
newcap = int (capmem >> shift )
default :
lenmem = uintptr (old .len ) * et .size
newlenmem = uintptr (cap ) * et .size
capmem , overflow = math .MulUintptr (et .size , uintptr (newcap ))
capmem = roundupsize (capmem )
newcap = int (capmem / et .size )
}
if overflow || capmem > maxAlloc {
panic (errorString ("growslice: cap out of range" ))
}
var p unsafe .Pointer
if et .ptrdata == 0 {
p = mallocgc (capmem , nil , false )
memclrNoHeapPointers (add (p , newlenmem ), capmem -newlenmem )
} else {
p = mallocgc (capmem , et , true )
if lenmem > 0 && writeBarrier .enabled {
bulkBarrierPreWriteSrcOnly (uintptr (p ), uintptr (old .array ), lenmem -et .size +et .ptrdata )
}
}
memmove (p , old .array , lenmem )
return slice {p , old .len , newcap }
}
func isPowerOfTwo(x uintptr ) bool {
return x &(x -1 ) == 0
}
func slicecopy(toPtr unsafe .Pointer , toLen int , fromPtr unsafe .Pointer , fromLen int , width uintptr ) int {
if fromLen == 0 || toLen == 0 {
return 0
}
n := fromLen
if toLen < n {
n = toLen
}
if width == 0 {
return n
}
size := uintptr (n ) * width
if raceenabled {
callerpc := getcallerpc ()
pc := abi .FuncPCABIInternal (slicecopy )
racereadrangepc (fromPtr , size , callerpc , pc )
racewriterangepc (toPtr , size , callerpc , pc )
}
if msanenabled {
msanread (fromPtr , size )
msanwrite (toPtr , size )
}
if asanenabled {
asanread (fromPtr , size )
asanwrite (toPtr , size )
}
if size == 1 {
*(*byte )(toPtr ) = *(*byte )(fromPtr )
} else {
memmove (toPtr , fromPtr , size )
}
return n
}
The pages are generated with Golds v0.4.5 . (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu .
PR and bug reports are welcome and can be submitted to the issue list .
Please follow @Go100and1 (reachable from the left QR code) to get the latest news of Golds .