ensure '\0' atom is static & never inlined (#2880)

This commit is contained in:
Mark Thom
2025-04-12 18:48:47 -07:00
committed by Mark Thom
parent 907e64e185
commit 1297a24469
2 changed files with 16 additions and 16 deletions

View File

@@ -87,7 +87,7 @@ impl<'ast> Visit<'ast> for StaticStrVisitor {
const INLINED_ATOM_MAX_LEN: usize = 6;
fn static_string_index(string: &str, index: usize) -> u64 {
if 0 < string.len() && string.len() <= INLINED_ATOM_MAX_LEN {
if !string.is_empty() && string.len() <= INLINED_ATOM_MAX_LEN && !string.contains('\u{0}') {
let mut string_buf: [u8; 8] = [0u8; 8];
string_buf[..string.len()].copy_from_slice(string.as_bytes());
(u64::from_le_bytes(string_buf) << 1) | 1
@@ -183,8 +183,7 @@ pub fn index_static_strings(instruction_rs_path: &std::path::Path) -> TokenStrea
})
.collect();
let static_strs_len = static_strs.len(); // visitor.static_strs.len();
//let static_strs: &Vec<_> = &visitor.static_strs.into_iter().collect();
let static_strs_len = static_strs.len();
quote! {
static STRINGS: [&str; #static_strs_len] = [

View File

@@ -49,9 +49,9 @@ const_assert!(mem::size_of::<Atom>() == 8);
impl AtomCell {
#[inline]
pub fn new_static(index: u64) -> Self {
fn new_static(index: u64) -> Self {
// upper 23 bits of index must be 0
debug_assert!(index & !((1 << 49) - 1) == 0);
debug_assert_eq!(index & !((1 << 49) - 1), 0);
AtomCell::new()
.with_name(index)
.with_arity(0u8)
@@ -62,7 +62,7 @@ impl AtomCell {
}
#[inline]
pub fn new_inlined(string: &str, arity: u8) -> Self {
fn new_inlined(string: &str, arity: u8) -> Self {
debug_assert!(string.len() <= INLINED_ATOM_MAX_LEN);
let mut string_buf: [u8; 8] = [0u8; 8];
@@ -80,6 +80,10 @@ impl AtomCell {
#[inline]
pub fn new_char_inlined(c: char) -> Self {
if c == '\u{0}' {
return Self::new_static(NULL_ATOM.flat_index());
}
let mut char_buf = [0u8; 8];
c.encode_utf8(&mut char_buf);
@@ -135,6 +139,7 @@ include!(concat!(env!("OUT_DIR"), "/static_atoms.rs"));
// populate these in STRINGS so they can be used from build_functor
const _: Atom = atom!(".");
const _: Atom = atom!("[]");
const NULL_ATOM: Atom = atom!("\0");
impl<'a> From<&'a Atom> for Atom {
#[inline]
@@ -222,16 +227,12 @@ pub enum AtomString<'a> {
Dynamic(AtomTableRef<str>),
}
#[inline(always)]
fn inlined_to_str(bytes: &[u8; 8]) -> &str {
// allow the '\0\' atom to be represented as the 0-valued inlined atom
let slice_len = if bytes[0] == 0 {
1
} else {
bytes
let slice_len = bytes
.iter()
.position(|&b| b == 0u8)
.unwrap_or(INLINED_ATOM_MAX_LEN)
};
.unwrap_or(INLINED_ATOM_MAX_LEN);
unsafe { str::from_utf8_unchecked(&bytes[..slice_len]) }
}
@@ -467,7 +468,7 @@ impl AtomTable {
}
pub fn build_with(atom_table: &AtomTable, string: &str) -> Atom {
if 0 < string.len() && string.len() <= INLINED_ATOM_MAX_LEN && !string.contains('\u{0}') {
if !string.is_empty() && string.len() <= INLINED_ATOM_MAX_LEN && !string.contains('\u{0}') {
return Atom::new_inlined(string);
}