vendor tsgo
This commit is contained in:
66
tools/tsgo/internal/core/arena.go
Normal file
66
tools/tsgo/internal/core/arena.go
Normal file
@@ -0,0 +1,66 @@
|
||||
package core
|
||||
|
||||
import "slices"
|
||||
|
||||
// Arena allocator
|
||||
|
||||
type Arena[T any] struct {
|
||||
data []T
|
||||
}
|
||||
|
||||
// Allocate a single element in the arena and return a pointer to the element. If the arena is at capacity,
|
||||
// a new arena of the next size up is allocated.
|
||||
func (a *Arena[T]) New() *T {
|
||||
if len(a.data) == cap(a.data) {
|
||||
nextSize := nextArenaSize(len(a.data))
|
||||
// Use the same trick as slices.Concat; Grow rounds up to the next size class.
|
||||
a.data = slices.Grow[[]T](nil, nextSize)
|
||||
}
|
||||
index := len(a.data)
|
||||
a.data = a.data[:index+1]
|
||||
return &a.data[index]
|
||||
}
|
||||
|
||||
// Allocate a slice of the given size in the arena. If the requested size is beyond the capacity of the arena
|
||||
// and an arena of the next size up still wouldn't fit the slice, make a separate memory allocation for the slice.
|
||||
// Otherwise, grow the arena if necessary and allocate a slice out of it. The length and capacity of the resulting
|
||||
// slice are equal to the given size.
|
||||
func (a *Arena[T]) NewSlice(size int) []T {
|
||||
if size == 0 {
|
||||
return nil
|
||||
}
|
||||
if len(a.data)+size > cap(a.data) {
|
||||
nextSize := nextArenaSize(len(a.data))
|
||||
if size > nextSize {
|
||||
return make([]T, size)
|
||||
}
|
||||
// Use the same trick as slices.Concat; Grow rounds up to the next size class.
|
||||
a.data = slices.Grow[[]T](nil, nextSize)
|
||||
}
|
||||
newLen := len(a.data) + size
|
||||
slice := a.data[len(a.data):newLen:newLen]
|
||||
a.data = a.data[:newLen]
|
||||
return slice
|
||||
}
|
||||
|
||||
func (a *Arena[T]) NewSlice1(t T) []T {
|
||||
slice := a.NewSlice(1)
|
||||
slice[0] = t
|
||||
return slice
|
||||
}
|
||||
|
||||
func (a *Arena[T]) Clone(t []T) []T {
|
||||
if len(t) == 0 {
|
||||
return nil
|
||||
}
|
||||
slice := a.NewSlice(len(t))
|
||||
copy(slice, t)
|
||||
return slice
|
||||
}
|
||||
|
||||
func nextArenaSize(size int) int {
|
||||
// This compiles down branch-free.
|
||||
size = max(size, 1)
|
||||
size = min(size*2, 256)
|
||||
return size
|
||||
}
|
||||
Reference in New Issue
Block a user