74 lines
1.8 KiB
Go
74 lines
1.8 KiB
Go
package lua
|
|
|
|
import (
|
|
"reflect"
|
|
"unsafe"
|
|
)
|
|
|
|
// iface is an internal representation of the go-interface.
|
|
type iface struct {
|
|
itab unsafe.Pointer
|
|
word unsafe.Pointer
|
|
}
|
|
|
|
const preloadLimit LNumber = 128
|
|
|
|
var _fv float64
|
|
var _uv uintptr
|
|
|
|
// allocator is a fast bulk memory allocator for the LValue.
|
|
type allocator struct {
|
|
top int
|
|
size int
|
|
nptrs []LValue
|
|
nheader *reflect.SliceHeader
|
|
fptrs []float64
|
|
fheader *reflect.SliceHeader
|
|
itabLNumber unsafe.Pointer
|
|
preloads [int(preloadLimit)]LValue
|
|
}
|
|
|
|
func newAllocator(size int) *allocator {
|
|
al := &allocator{
|
|
top: 0,
|
|
size: size,
|
|
nptrs: make([]LValue, size),
|
|
nheader: nil,
|
|
fptrs: make([]float64, size),
|
|
fheader: nil,
|
|
itabLNumber: unsafe.Pointer(nil),
|
|
}
|
|
al.nheader = (*reflect.SliceHeader)(unsafe.Pointer(&al.nptrs))
|
|
al.fheader = (*reflect.SliceHeader)(unsafe.Pointer(&al.fptrs))
|
|
|
|
var v LValue = LNumber(0)
|
|
vp := (*iface)(unsafe.Pointer(&v))
|
|
al.itabLNumber = vp.itab
|
|
for i := 0; i < int(preloadLimit); i++ {
|
|
al.preloads[i] = LNumber(i)
|
|
}
|
|
return al
|
|
}
|
|
|
|
func (al *allocator) LNumber2I(v LNumber) LValue {
|
|
if v >= 0 && v < preloadLimit && float64(v) == float64(int64(v)) {
|
|
return al.preloads[int(v)]
|
|
}
|
|
if al.top == len(al.nptrs)-1 {
|
|
al.top = 0
|
|
al.nptrs = make([]LValue, al.size)
|
|
al.nheader = (*reflect.SliceHeader)(unsafe.Pointer(&al.nptrs))
|
|
al.fptrs = make([]float64, al.size)
|
|
al.fheader = (*reflect.SliceHeader)(unsafe.Pointer(&al.fptrs))
|
|
}
|
|
fptr := (*float64)(unsafe.Pointer(al.fheader.Data + uintptr(al.top)*unsafe.Sizeof(_fv)))
|
|
e := *(*LValue)(unsafe.Pointer(al.nheader.Data + uintptr(al.top)*unsafe.Sizeof(_uv)))
|
|
al.top++
|
|
|
|
ep := (*iface)(unsafe.Pointer(&e))
|
|
ep.itab = al.itabLNumber
|
|
*fptr = float64(v)
|
|
ep.word = unsafe.Pointer(fptr)
|
|
return e
|
|
}
|