diff --git a/src/typeref.rs b/src/typeref.rs index ff9e401d..fc78bcef 100644 --- a/src/typeref.rs +++ b/src/typeref.rs @@ -4,6 +4,8 @@ use crate::ffi::orjson_fragmenttype_new; use ahash::RandomState; use once_cell::race::OnceBox; use pyo3_ffi::*; +use std::cell::UnsafeCell; +use std::mem::MaybeUninit; use std::os::raw::c_char; use std::ptr::{null_mut, NonNull}; use std::sync::Once; @@ -88,16 +90,28 @@ pub fn ahash_init() -> Box { pub const YYJSON_BUFFER_SIZE: usize = 1024 * 1024 * 8; #[cfg(feature = "yyjson")] -pub static mut YYJSON_ALLOC: OnceBox<[u8; YYJSON_BUFFER_SIZE]> = OnceBox::new(); +#[repr(align(64))] +pub struct YYJSONBuffer(UnsafeCell>); #[cfg(feature = "yyjson")] -pub fn yyjson_init() -> Box<[u8; YYJSON_BUFFER_SIZE]> { +impl YYJSONBuffer { + pub(crate) fn as_ptr(&self) -> *mut u8 { + self.0.get().cast::() + } +} + +#[cfg(feature = "yyjson")] +pub static mut YYJSON_ALLOC: OnceBox = OnceBox::new(); + +#[cfg(feature = "yyjson")] +pub fn yyjson_init() -> Box { + // Using unsafe to ensure allocation happens on the heap without going through the stack + // so we don't stack overflow in debug mode. Once rust-lang/rust#63291 is stable (Box::new_uninit) + // we can use that instead. + let layout = std::alloc::Layout::new::(); unsafe { - let buffer = std::alloc::alloc(std::alloc::Layout::from_size_align_unchecked( - YYJSON_BUFFER_SIZE, - 64, - )) as *mut [u8; YYJSON_BUFFER_SIZE]; - Box::new(*buffer) + let buffer = std::alloc::alloc(layout); + Box::from_raw(buffer.cast::()) } }