LNumber2I takes a number value and returns an interface LValue representing the same number. Converting an LNumber to a LValue naively, by doing: `var val LValue = myLNumber` will result in an individual heap alloc of 8 bytes for the float value. LNumber2I amortizes the cost and memory overhead of t
(v LNumber)
| 55 | // The downside of this is that all of the floats on a given block have to become eligible for gc before the block |
| 56 | // as a whole can be gc-ed. |
| 57 | func (al *allocator) LNumber2I(v LNumber) LValue { |
| 58 | // first check for shared preloaded numbers |
| 59 | if v >= 0 && v < preloadLimit && float64(v) == float64(int64(v)) { |
| 60 | return preloads[int(v)] |
| 61 | } |
| 62 | |
| 63 | // check if we need a new alloc page |
| 64 | if cap(al.fptrs) == len(al.fptrs) { |
| 65 | al.fptrs = make([]float64, 0, al.size) |
| 66 | al.fheader = (*reflect.SliceHeader)(unsafe.Pointer(&al.fptrs)) |
| 67 | } |
| 68 | |
| 69 | // alloc a new float, and store our value into it |
| 70 | al.fptrs = append(al.fptrs, float64(v)) |
| 71 | fptr := &al.fptrs[len(al.fptrs)-1] |
| 72 | |
| 73 | // hack our scratch LValue to point to our allocated value |
| 74 | // this scratch lvalue is copied when this function returns meaning the scratch value can be reused |
| 75 | // on the next call |
| 76 | al.scratchValueP.word = unsafe.Pointer(fptr) |
| 77 | |
| 78 | return al.scratchValue |
| 79 | } |