use alloc::alloc::{Layout, alloc, alloc_zeroed, dealloc, handle_alloc_error};
use alloc::vec::Vec;
use core::mem::{align_of, size_of};
use core::ptr::NonNull;
pub(crate) const ALIGN: usize = 64;
pub(crate) const fn region_bytes<T>(count: usize) -> usize {
let Some(bytes) = count.checked_mul(size_of::<T>()) else {
panic!("workspace region size overflows usize");
};
let Some(padded) = bytes.checked_add(ALIGN - 1) else {
panic!("workspace region size overflows usize");
};
padded & !(ALIGN - 1)
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub(crate) enum IngestPlan {
Raw,
Slice(usize),
Stream,
PledgedStream(usize),
}
impl IngestPlan {
pub(crate) fn exact_len(self) -> Option<usize> {
match self {
Self::Slice(len) | Self::PledgedStream(len) => Some(len),
Self::Raw | Self::Stream => None,
}
}
}
pub struct Workspace {
ptr: NonNull<u8>,
base: NonNull<u8>,
capacity: usize,
generation: u64,
front: usize,
history_front: usize,
leading: usize,
back: usize,
retired: Option<(NonNull<u8>, usize)>,
block_target: usize,
trailing_for: fn(usize) -> usize,
ingest: IngestPlan,
block_capacity: usize,
open: bool,
oversized_layouts: u32,
sparse_table_bytes: usize,
zeroed: bool,
fresh_pages: bool,
}
const TOO_LARGE_FACTOR: usize = 3;
const TOO_LARGE_MAX_LAYOUTS: u32 = 128;
#[cfg(target_env = "musl")]
const FRESH_PAGES_FROM: usize = 128 * 1024;
#[cfg(all(not(target_env = "musl"), target_pointer_width = "32"))]
const FRESH_PAGES_FROM: usize = 512 * 1024;
#[cfg(all(not(target_env = "musl"), not(target_pointer_width = "32")))]
const FRESH_PAGES_FROM: usize = 32 * 1024 * 1024;
const SYSTEM_ALLOCATOR: bool = cfg!(feature = "std");
unsafe impl Send for Workspace {}
unsafe impl Sync for Workspace {}
impl Workspace {
pub(crate) const fn new() -> Self {
Self {
ptr: NonNull::<Aligned>::dangling().cast(),
base: NonNull::dangling(),
capacity: 0,
generation: 0,
front: 0,
history_front: 0,
leading: 0,
back: 0,
retired: None,
block_target: 0,
trailing_for: no_trailing,
ingest: IngestPlan::Stream,
block_capacity: 0,
open: false,
oversized_layouts: 0,
sparse_table_bytes: 0,
zeroed: false,
fresh_pages: false,
}
}
#[cfg(test)]
pub(crate) fn capacity(&self) -> usize {
self.capacity
}
pub(crate) fn on_fresh_pages(&self) -> bool {
self.fresh_pages
}
pub(crate) fn heap_bytes(&self) -> usize {
let allocated = |capacity: usize| {
if capacity == 0 {
0
} else {
allocation_layout(capacity).size()
}
};
allocated(self.capacity) + self.retired.map_or(0, |(_, capacity)| allocated(capacity))
}
pub(crate) fn begin_layout(
&mut self,
block_target: usize,
trailing_for: fn(usize) -> usize,
ingest: IngestPlan,
) {
self.release_retired();
self.block_target = block_target;
self.trailing_for = trailing_for;
self.ingest = ingest;
self.sparse_table_bytes = 0;
self.open = false;
}
pub(crate) fn open_for_match_finder(
&mut self,
leading: usize,
zero_tables: usize,
window: usize,
expected_input: usize,
) {
self.sparse_table_bytes = if zero_tables > expected_input {
zero_tables
} else {
0
};
self.open(leading, window);
}
pub(crate) fn is_open(&self) -> bool {
self.open
}
pub(crate) fn ingest(&self) -> IngestPlan {
self.ingest
}
pub(crate) fn block_for_window(&self, window: usize) -> usize {
self.block_target
.min(window)
.min(self.ingest.exact_len().unwrap_or(usize::MAX))
.max(1)
}
pub(crate) fn block_capacity(&self) -> usize {
self.block_capacity
}
pub(crate) fn open(&mut self, leading: usize, window: usize) {
assert!(!self.open, "a workspace layout opens once per frame");
self.block_capacity = self.block_for_window(window);
let total = leading
.checked_add((self.trailing_for)(self.block_capacity))
.expect("workspace size overflows usize");
let reallocate = if total > self.capacity {
true
} else {
let too_large = total
.checked_mul(TOO_LARGE_FACTOR)
.is_some_and(|wasted| self.capacity - total >= wasted);
self.oversized_layouts = if too_large {
self.oversized_layouts.saturating_add(1)
} else {
0
};
self.oversized_layouts > TOO_LARGE_MAX_LAYOUTS
};
debug_assert!(
self.sparse_table_bytes <= leading,
"zero tables are part of the leading bytes"
);
let zero_all = (SYSTEM_ALLOCATOR && total >= FRESH_PAGES_FROM)
|| (self.sparse_table_bytes > 0
&& total - self.sparse_table_bytes <= self.sparse_table_bytes / 3);
if reallocate {
self.grow(total, zero_all);
}
self.zeroed = reallocate && zero_all;
self.fresh_pages = SYSTEM_ALLOCATOR && self.zeroed && self.capacity >= FRESH_PAGES_FROM;
self.front = 0;
self.leading = leading;
self.history_front = leading;
self.back = self.capacity;
self.open = true;
}
pub(crate) fn table_after<T: TableValue>(
&mut self,
count: usize,
previous: &Region<T>,
empty: T,
) -> (Region<T>, bool) {
let offset = self.carve_front(region_bytes::<T>(count));
let mut region = self.region_at::<T>(offset, count);
let kept = count > 0
&& previous.generation == region.generation
&& previous.ptr == region.ptr
&& previous.len == count;
if !kept && !(self.zeroed && empty.is_zero()) {
region.fill(empty);
}
(region, kept)
}
#[cfg(test)]
pub(crate) fn table<T: TableValue>(&mut self, count: usize, value: T) -> Region<T> {
self.table_after(count, &Region::empty(), value).0
}
pub(crate) fn buffer<T: Copy>(&mut self, capacity: usize) -> RegionVec<T> {
assert!(
self.open,
"carving from a workspace layout that is not open"
);
let bytes = region_bytes::<T>(capacity);
assert!(
bytes <= self.back - self.leading,
"workspace sized below its layout"
);
self.back -= bytes;
RegionVec {
region: self.region_at::<T>(self.back, capacity),
len: 0,
}
}
fn history_room(&mut self, capacity: usize) -> Region<u8> {
assert!(
self.open,
"carving from a workspace layout that is not open"
);
let bytes = region_bytes::<u8>(capacity);
assert!(
bytes <= self.history_front - self.front,
"workspace sized below its layout"
);
self.history_front -= bytes;
self.region_at::<u8>(self.history_front, capacity)
}
fn carve_front(&mut self, bytes: usize) -> usize {
assert!(
self.open,
"carving from a workspace layout that is not open"
);
assert!(
bytes <= self.history_front - self.front,
"workspace sized below its layout"
);
let offset = self.front;
self.front += bytes;
offset
}
fn region_at<T>(&self, offset: usize, count: usize) -> Region<T> {
const {
assert!(
align_of::<T>() <= ALIGN,
"a region is aligned to ALIGN at most"
);
}
let ptr = unsafe { self.ptr.as_ptr().add(offset) };
Region {
ptr: unsafe { NonNull::new_unchecked(ptr.cast::<T>()) },
len: count,
generation: self.generation,
}
}
fn grow(&mut self, bytes: usize, zeroed: bool) {
self.release_retired();
if self.capacity != 0 {
self.retired = Some((self.base, self.capacity));
self.base = NonNull::dangling();
self.ptr = NonNull::<Aligned>::dangling().cast();
self.capacity = 0;
}
self.generation += 1;
self.oversized_layouts = 0;
if bytes == 0 {
return;
}
let layout = allocation_layout(bytes);
let raw = unsafe {
if zeroed {
alloc_zeroed(layout)
} else {
alloc(layout)
}
};
let Some(base) = NonNull::new(raw) else {
handle_alloc_error(layout);
};
let offset = raw.align_offset(ALIGN);
debug_assert!(offset < ALIGN, "a byte pointer aligns within ALIGN bytes");
self.base = base;
self.ptr = unsafe { NonNull::new_unchecked(raw.add(offset)) };
self.capacity = bytes;
}
pub(crate) fn release_retired(&mut self) {
if let Some((base, capacity)) = self.retired.take() {
unsafe { free(base, capacity) };
}
}
fn release(&mut self) {
self.release_retired();
if self.capacity == 0 {
return;
}
unsafe { free(self.base, self.capacity) };
self.base = NonNull::dangling();
self.ptr = NonNull::<Aligned>::dangling().cast();
self.capacity = 0;
}
}
fn allocation_layout(capacity: usize) -> Layout {
let bytes = capacity
.checked_add(ALIGN - 1)
.expect("workspace size overflows usize");
Layout::from_size_align(bytes, 1).expect("workspace size overflows isize")
}
unsafe fn free(base: NonNull<u8>, capacity: usize) {
unsafe { dealloc(base.as_ptr(), allocation_layout(capacity)) };
}
impl Default for Workspace {
fn default() -> Self {
Self::new()
}
}
impl Drop for Workspace {
fn drop(&mut self) {
self.release();
}
}
pub(crate) fn no_trailing(_block: usize) -> usize {
0
}
#[repr(align(64))]
struct Aligned;
const _: () = assert!(align_of::<Aligned>() == ALIGN);
pub(crate) trait TableValue: Copy {
fn is_zero(self) -> bool;
}
macro_rules! table_value {
($($int:ty),*) => {$(
impl TableValue for $int {
fn is_zero(self) -> bool {
self == 0
}
}
)*};
}
table_value!(u8, u32, u64);
pub(crate) struct Region<T> {
ptr: NonNull<T>,
len: usize,
generation: u64,
}
unsafe impl<T: Send> Send for Region<T> {}
unsafe impl<T: Sync> Sync for Region<T> {}
impl<T> Region<T> {
pub(crate) const fn empty() -> Self {
Self {
ptr: NonNull::dangling(),
len: 0,
generation: 0,
}
}
#[cfg(test)]
pub(crate) fn len(&self) -> usize {
self.len
}
pub(crate) fn as_mut_ptr(&mut self) -> *mut T {
self.ptr.as_ptr()
}
pub(crate) fn as_ptr(&self) -> *const T {
self.ptr.as_ptr()
}
}
impl<T: Copy> Region<T> {
pub(crate) fn as_slice(&self) -> &[T] {
unsafe { core::slice::from_raw_parts(self.ptr.as_ptr(), self.len) }
}
pub(crate) fn as_mut_slice(&mut self) -> &mut [T] {
unsafe { core::slice::from_raw_parts_mut(self.ptr.as_ptr(), self.len) }
}
fn fill(&mut self, value: T) {
let base = self.ptr.as_ptr();
for i in 0..self.len {
unsafe { base.add(i).write(value) };
}
}
}
pub(crate) struct Table<T: Copy> {
view: Region<T>,
own: Vec<T>,
}
impl<T: Copy> Table<T> {
pub(crate) const fn empty() -> Self {
Self {
view: Region::empty(),
own: Vec::new(),
}
}
pub(crate) fn owned(mut values: Vec<T>) -> Self {
let view = Region {
ptr: unsafe { NonNull::new_unchecked(values.as_mut_ptr()) },
len: values.len(),
generation: 0,
};
Self { view, own: values }
}
pub(crate) fn bind(&mut self, workspace: &mut Workspace, count: usize, empty: T) -> bool
where
T: TableValue,
{
let (view, kept) = workspace.table_after(count, &self.view, empty);
self.view = view;
self.own = Vec::new();
kept
}
pub(crate) fn len(&self) -> usize {
self.view.len
}
pub(crate) fn is_empty(&self) -> bool {
self.view.len == 0
}
pub(crate) fn as_slice(&self) -> &[T] {
self.view.as_slice()
}
pub(crate) fn as_mut_slice(&mut self) -> &mut [T] {
self.view.as_mut_slice()
}
pub(crate) fn as_ptr(&self) -> *const T {
self.view.as_ptr()
}
pub(crate) fn as_mut_ptr(&mut self) -> *mut T {
self.view.as_mut_ptr()
}
pub(crate) fn owned_bytes(&self) -> usize {
self.own.capacity() * size_of::<T>()
}
pub(crate) fn leave_workspace(&mut self) {
if self.own.is_empty() && !self.is_empty() {
*self = self.clone();
}
}
}
impl<T: Copy> Clone for Table<T> {
fn clone(&self) -> Self {
Self::owned(self.as_slice().to_vec())
}
fn clone_from(&mut self, source: &Self) {
if self.len() == source.len() {
self.as_mut_slice().copy_from_slice(source.as_slice());
} else {
*self = source.clone();
}
}
}
impl<T: Copy> Default for Table<T> {
fn default() -> Self {
Self::empty()
}
}
impl<T: Copy> core::ops::Deref for Table<T> {
type Target = [T];
fn deref(&self) -> &[T] {
self.as_slice()
}
}
impl<T: Copy> core::ops::DerefMut for Table<T> {
fn deref_mut(&mut self) -> &mut [T] {
self.as_mut_slice()
}
}
pub struct HistoryBuf {
ptr: NonNull<u8>,
capacity: usize,
len: usize,
own: Vec<u8>,
}
unsafe impl Send for HistoryBuf {}
unsafe impl Sync for HistoryBuf {}
impl HistoryBuf {
pub const fn new() -> Self {
Self {
ptr: NonNull::dangling(),
capacity: 0,
len: 0,
own: Vec::new(),
}
}
pub(crate) fn workspace_bytes(&self, capacity: usize) -> usize {
region_bytes::<u8>(capacity.max(self.len))
}
pub(crate) fn bind(&mut self, workspace: &mut Workspace, capacity: usize) {
let capacity = capacity.max(self.len);
let room = workspace.history_room(capacity);
if self.ptr != room.ptr {
unsafe { core::ptr::copy(self.ptr.as_ptr(), room.ptr.as_ptr(), self.len) };
}
self.ptr = room.ptr;
self.capacity = capacity;
self.own = Vec::new();
workspace.release_retired();
}
pub(crate) fn leave_workspace(&mut self) {
if self.own.capacity() == 0 && self.capacity != 0 {
self.move_room(self.len);
}
}
pub fn len(&self) -> usize {
self.len
}
pub fn is_empty(&self) -> bool {
self.len == 0
}
pub fn capacity(&self) -> usize {
self.capacity
}
pub(crate) fn owned_bytes(&self) -> usize {
self.own.capacity()
}
pub fn clear(&mut self) {
self.len = 0;
}
pub fn truncate(&mut self, len: usize) {
self.len = self.len.min(len);
}
pub fn reserve(&mut self, additional: usize) {
let needed = self
.len
.checked_add(additional)
.expect("history length overflows usize");
if needed > self.capacity {
let doubled = self.capacity.checked_mul(2).unwrap_or(needed);
self.move_room(needed.max(doubled));
}
}
pub(crate) fn reserve_exact(&mut self, additional: usize) {
let needed = self
.len
.checked_add(additional)
.expect("history length overflows usize");
if needed > self.capacity {
self.move_room(needed);
}
}
pub fn extend_from_slice(&mut self, bytes: &[u8]) {
self.reserve(bytes.len());
unsafe {
core::ptr::copy_nonoverlapping(
bytes.as_ptr(),
self.ptr.as_ptr().add(self.len),
bytes.len(),
);
}
self.len += bytes.len();
}
pub(crate) fn push(&mut self, byte: u8) {
self.reserve(1);
unsafe { self.ptr.as_ptr().add(self.len).write(byte) };
self.len += 1;
}
pub(crate) fn resize(&mut self, len: usize, value: u8) {
if len > self.len {
self.reserve(len - self.len);
unsafe {
core::ptr::write_bytes(self.ptr.as_ptr().add(self.len), value, len - self.len);
}
}
self.len = len;
}
pub fn drain_front(&mut self, count: usize) {
assert!(count <= self.len, "draining past the history's end");
unsafe {
core::ptr::copy(
self.ptr.as_ptr().add(count),
self.ptr.as_ptr(),
self.len - count,
);
}
self.len -= count;
}
fn move_room(&mut self, capacity: usize) {
let mut own: Vec<u8> = Vec::with_capacity(capacity);
unsafe { core::ptr::copy_nonoverlapping(self.ptr.as_ptr(), own.as_mut_ptr(), self.len) };
self.ptr = unsafe { NonNull::new_unchecked(own.as_mut_ptr()) };
self.capacity = own.capacity();
self.own = own;
}
}
impl Default for HistoryBuf {
fn default() -> Self {
Self::new()
}
}
impl Clone for HistoryBuf {
fn clone(&self) -> Self {
let mut copy = Self::new();
copy.extend_from_slice(self);
copy
}
fn clone_from(&mut self, source: &Self) {
self.clear();
self.extend_from_slice(source);
}
}
#[cfg(test)]
impl From<Vec<u8>> for HistoryBuf {
fn from(mut bytes: Vec<u8>) -> Self {
let len = bytes.len();
unsafe { bytes.set_len(0) };
Self {
ptr: unsafe { NonNull::new_unchecked(bytes.as_mut_ptr()) },
capacity: bytes.capacity(),
len,
own: bytes,
}
}
}
impl core::ops::Deref for HistoryBuf {
type Target = [u8];
fn deref(&self) -> &[u8] {
unsafe { core::slice::from_raw_parts(self.ptr.as_ptr(), self.len) }
}
}
impl core::ops::DerefMut for HistoryBuf {
fn deref_mut(&mut self) -> &mut [u8] {
unsafe { core::slice::from_raw_parts_mut(self.ptr.as_ptr(), self.len) }
}
}
impl core::fmt::Debug for HistoryBuf {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("HistoryBuf")
.field("len", &self.len)
.field("capacity", &self.capacity)
.finish()
}
}
#[derive(Clone, Copy, Debug)]
pub(crate) struct RetiredHistory {
pub(crate) next_floor: usize,
pub(crate) kept: Option<usize>,
}
pub(crate) trait IngestBuffer: core::ops::DerefMut<Target = [u8]> {
fn extend_from_slice(&mut self, bytes: &[u8]);
fn resize(&mut self, len: usize, value: u8);
fn truncate(&mut self, len: usize);
fn push(&mut self, byte: u8);
}
impl IngestBuffer for Vec<u8> {
fn extend_from_slice(&mut self, bytes: &[u8]) {
Vec::extend_from_slice(self, bytes);
}
fn resize(&mut self, len: usize, value: u8) {
Vec::resize(self, len, value);
}
fn truncate(&mut self, len: usize) {
Vec::truncate(self, len);
}
fn push(&mut self, byte: u8) {
Vec::push(self, byte);
}
}
impl IngestBuffer for HistoryBuf {
fn extend_from_slice(&mut self, bytes: &[u8]) {
HistoryBuf::extend_from_slice(self, bytes);
}
fn resize(&mut self, len: usize, value: u8) {
HistoryBuf::resize(self, len, value);
}
fn truncate(&mut self, len: usize) {
HistoryBuf::truncate(self, len);
}
fn push(&mut self, byte: u8) {
HistoryBuf::push(self, byte);
}
}
pub(crate) struct RegionVec<T> {
region: Region<T>,
len: usize,
}
impl<T: Copy> RegionVec<T> {
pub(crate) const fn empty() -> Self {
Self {
region: Region::empty(),
len: 0,
}
}
pub(crate) fn capacity(&self) -> usize {
self.region.len
}
pub(crate) fn clear(&mut self) {
self.len = 0;
}
#[inline]
pub(crate) fn push(&mut self, value: T) {
if self.len == self.region.len {
capacity_exhausted();
}
unsafe { self.region.as_mut_ptr().add(self.len).write(value) };
self.len += 1;
}
pub(crate) fn as_mut_ptr(&mut self) -> *mut T {
self.region.as_mut_ptr()
}
pub(crate) unsafe fn set_len(&mut self, len: usize) {
debug_assert!(len <= self.region.len);
self.len = len;
}
}
impl<T: Copy> core::ops::Deref for RegionVec<T> {
type Target = [T];
fn deref(&self) -> &[T] {
unsafe { core::slice::from_raw_parts(self.region.as_ptr(), self.len) }
}
}
impl<T: Copy> core::ops::DerefMut for RegionVec<T> {
fn deref_mut(&mut self) -> &mut [T] {
unsafe { core::slice::from_raw_parts_mut(self.region.as_mut_ptr(), self.len) }
}
}
impl<T: Copy> Default for RegionVec<T> {
fn default() -> Self {
Self::empty()
}
}
#[cold]
#[inline(never)]
pub(crate) fn capacity_exhausted() -> ! {
panic!("workspace buffer sized below what the frame put in it")
}
#[cfg(test)]
mod tests;