github.com/qiniu/gopher-lua@v0.2017.11/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 }