github.com/primecitizens/pcz/std@v0.2.1/core/mark/noescape.go (about)

     1  // SPDX-License-Identifier: Apache-2.0
     2  // Copyright 2023 The Prime Citizens
     3  
     4  package mark
     5  
     6  import (
     7  	"unsafe"
     8  	_ "unsafe" // for go:linkname
     9  
    10  	_ "github.com/primecitizens/pcz/std/core/mark/internal/reflect" // import reflect.noescape
    11  )
    12  
    13  // NoEscape hides a pointer from escape analysis. USE CAREFULLY!
    14  //
    15  // It is the identity function but escape analysis doesn't think the output
    16  // depends on the input.
    17  //
    18  // It is inlined and currently compiles down to zero instructions.
    19  //
    20  //go:nosplit
    21  func NoEscape[T any](p *T) *T {
    22  	return (*T)(NoEscapeUnsafePointer(unsafe.Pointer(p)))
    23  }
    24  
    25  //go:linkname NoEscapeUnsafePointer reflect.noescape
    26  //go:noescape
    27  func NoEscapeUnsafePointer(p unsafe.Pointer) unsafe.Pointer
    28  
    29  // NoEscapePointer is [NoEscape] but returns unsafe.Pointer.
    30  //
    31  //go:nosplit
    32  func NoEscapePointer[T any](p *T) unsafe.Pointer {
    33  	return NoEscapeUnsafePointer(unsafe.Pointer(p))
    34  }
    35  
    36  // NoEscapeSlice is [NoEscape] for slices.
    37  //
    38  //go:nosplit
    39  func NoEscapeSlice[T any](p []T) []T {
    40  	return unsafe.Slice(NoEscape(unsafe.SliceData(p)), cap(p))[:len(p)]
    41  }
    42  
    43  // NoEscapeSliceData is [NoEscapeSlice] but returns the pointer
    44  // to the underlay array.
    45  //
    46  //go:nosplit
    47  func NoEscapeSliceData[T any](p []T) *T {
    48  	return NoEscape(unsafe.SliceData(p))
    49  }
    50  
    51  // NoEscapeSliceDataPointer is [NoEscapeSliceData] but returns an
    52  // unsafe.Pointer.
    53  //
    54  //go:nosplit
    55  func NoEscapeSliceDataPointer[T any](p []T) unsafe.Pointer {
    56  	return NoEscapeUnsafePointer(unsafe.Pointer(unsafe.SliceData(p)))
    57  }
    58  
    59  // NoEscapeString is [NoEscape] for string.
    60  //
    61  //go:nosplit
    62  func NoEscapeString[String ~string](s String) String {
    63  	return String(
    64  		unsafe.String(
    65  			NoEscape(unsafe.StringData(string(s))),
    66  			len(s),
    67  		),
    68  	)
    69  }
    70  
    71  // NoEscapeStringData is [NoEscapeString] but returns the pointer to
    72  // the underlay byte array.
    73  //
    74  //go:nosplit
    75  func NoEscapeStringData[String ~string](s String) *byte {
    76  	return NoEscape(unsafe.StringData(string(s)))
    77  }
    78  
    79  // NoEscapeStringDataPointer is [NoEscapeStringData] but returns an
    80  // unsafe.Pointer.
    81  //
    82  //go:nosplit
    83  func NoEscapeStringDataPointer[String ~string](s String) unsafe.Pointer {
    84  	return NoEscapeUnsafePointer(unsafe.Pointer(unsafe.StringData(string(s))))
    85  }
    86  
    87  // NoEscapeBytesString is [NoEscapeString] but taking bytes as the argument.
    88  func NoEscapeBytesString[T ~byte](s []T) string {
    89  	return unsafe.String(
    90  		(*byte)(NoEscapeUnsafePointer(unsafe.Pointer(unsafe.SliceData(s)))),
    91  		len(s),
    92  	)
    93  }