github.com/insolar/vanilla@v0.0.0-20201023172447-248fdf805322/reflectkit/func_code.go (about)

     1  // Copyright 2020 Insolar Network Ltd.
     2  // All rights reserved.
     3  // This material is licensed under the Insolar License version 1.0,
     4  // available at https://github.com/insolar/assured-ledger/blob/master/LICENSE.md.
     5  
     6  package reflectkit
     7  
     8  import (
     9  	"reflect"
    10  	"unsafe"
    11  )
    12  
    13  // A faster version (25-35%) to get comparable identity of function's code.
    14  // Same to reflect.ValueOf(<func>).Pointer(), but doesn't force heap-escape of the argument.
    15  // NB! ONLY works for hard-coded functions. Functions created with reflect will have same code identity.
    16  func CodeOf(v interface{}) uintptr {
    17  	if v == nil {
    18  		panic("illegal value")
    19  	}
    20  
    21  	ptr, kind := unwrapIface(v)
    22  	if kind != uint8(reflect.Func)|kindDirectIface {
    23  		panic("illegal value")
    24  	}
    25  	if ptr == nil {
    26  		return 0
    27  	}
    28  
    29  	// Non-nil func value points at data block.
    30  	// First word of data block is actual code.
    31  	return *(*uintptr)(ptr)
    32  }
    33  
    34  // const kindMask = (1 << 5) - 1
    35  const kindDirectIface = 1 << 5
    36  
    37  func unwrapIface(v interface{}) (word unsafe.Pointer, kind uint8) {
    38  	type rtype struct {
    39  		_, _    uintptr
    40  		_       uint32
    41  		_, _, _ uint8
    42  		kind    uint8
    43  	}
    44  
    45  	type emptyInterface struct {
    46  		typ  *rtype
    47  		word unsafe.Pointer
    48  	}
    49  
    50  	iface := (*emptyInterface)(unsafe.Pointer(&v))
    51  	return iface.word, iface.typ.kind
    52  }
    53  
    54  // A faster version (25-35%) to check for interface nil
    55  func IsNil(v interface{}) bool {
    56  	if v == nil {
    57  		return true
    58  	}
    59  	ptr, kind := unwrapIface(v)
    60  	return ptr == nil && kind&kindDirectIface != 0
    61  }
    62  
    63