github.com/erikdubbelboer/gopher-lua@v0.0.0-20160512044044-e68f0dc85040/alloc.go (about)

     1  package lua
     2  
     3  import (
     4  	"reflect"
     5  	"unsafe"
     6  )
     7  
     8  // iface is an internal representation of the go-interface.
     9  type iface struct {
    10  	itab unsafe.Pointer
    11  	word unsafe.Pointer
    12  }
    13  
    14  const preloadLimit LNumber = 128
    15  
    16  var _fv float64
    17  var _uv uintptr
    18  
    19  // allocator is a fast bulk memory allocator for the LValue.
    20  type allocator struct {
    21  	top         int
    22  	size        int
    23  	nptrs       []LValue
    24  	nheader     *reflect.SliceHeader
    25  	fptrs       []float64
    26  	fheader     *reflect.SliceHeader
    27  	itabLNumber unsafe.Pointer
    28  	preloads    [int(preloadLimit)]LValue
    29  }
    30  
    31  func newAllocator(size int) *allocator {
    32  	al := &allocator{
    33  		top:         0,
    34  		size:        size,
    35  		nptrs:       make([]LValue, size),
    36  		nheader:     nil,
    37  		fptrs:       make([]float64, size),
    38  		fheader:     nil,
    39  		itabLNumber: unsafe.Pointer(nil),
    40  	}
    41  	al.nheader = (*reflect.SliceHeader)(unsafe.Pointer(&al.nptrs))
    42  	al.fheader = (*reflect.SliceHeader)(unsafe.Pointer(&al.fptrs))
    43  
    44  	var v LValue = LNumber(0)
    45  	vp := (*iface)(unsafe.Pointer(&v))
    46  	al.itabLNumber = vp.itab
    47  	for i := 0; i < int(preloadLimit); i++ {
    48  		al.preloads[i] = LNumber(i)
    49  	}
    50  	return al
    51  }
    52  
    53  func (al *allocator) LNumber2I(v LNumber) LValue {
    54  	if v >= 0 && v < preloadLimit && float64(v) == float64(int64(v)) {
    55  		return al.preloads[int(v)]
    56  	}
    57  	if al.top == len(al.nptrs)-1 {
    58  		al.top = 0
    59  		al.nptrs = make([]LValue, al.size)
    60  		al.nheader = (*reflect.SliceHeader)(unsafe.Pointer(&al.nptrs))
    61  		al.fptrs = make([]float64, al.size)
    62  		al.fheader = (*reflect.SliceHeader)(unsafe.Pointer(&al.fptrs))
    63  	}
    64  	fptr := (*float64)(unsafe.Pointer(al.fheader.Data + uintptr(al.top)*unsafe.Sizeof(_fv)))
    65  	e := *(*LValue)(unsafe.Pointer(al.nheader.Data + uintptr(al.top)*unsafe.Sizeof(_uv)))
    66  	al.top++
    67  
    68  	ep := (*iface)(unsafe.Pointer(&e))
    69  	ep.itab = al.itabLNumber
    70  	*fptr = float64(v)
    71  	ep.word = unsafe.Pointer(fptr)
    72  	return e
    73  }