Retain atom composition and incremental context validation facts

This commit is contained in:
Kinneyzhang 2026-09-05 11:15:52 +08:00
parent e48af058b5
commit c9de7e6329
4 changed files with 2304 additions and 171 deletions

782
native/src/atom_plan.rs Normal file
View File

@ -0,0 +1,782 @@
use std::cell::Cell;
use std::sync::Arc;
use crate::sequence::{Entry, Measure, Node, NodeView, Sequence, Work};
use super::{Atom, AtomProperties, RegionRole, RegionRoleEntry};
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, serde::Serialize)]
#[serde(rename_all = "kebab-case")]
pub(crate) struct AtomPlanWork {
pub(crate) sequence_nodes_created: u64,
pub(crate) sequence_entries_written: u64,
pub(crate) materialized_atoms: u64,
pub(crate) property_applications: u64,
pub(crate) atom_clones: u64,
pub(crate) operation_block_writes: u64,
}
thread_local! {
static WORK: Cell<AtomPlanWork> = Cell::new(AtomPlanWork::default());
}
pub(crate) fn reset_work() {
WORK.set(AtomPlanWork::default());
}
pub(crate) fn work() -> AtomPlanWork {
WORK.get()
}
fn record_sequence(work: Work) {
WORK.set(WORK.get().checked_add(AtomPlanWork {
sequence_nodes_created: work.nodes_created,
sequence_entries_written: work.entries_written,
materialized_atoms: 0,
property_applications: 0,
atom_clones: 0,
operation_block_writes: 0,
}));
}
fn record_materialized(count: usize) {
let count = u64::try_from(count).expect("validated native atom count fits u64");
WORK.set(WORK.get().checked_add(AtomPlanWork {
materialized_atoms: count,
atom_clones: count,
..AtomPlanWork::default()
}));
}
fn record_atom_clones(count: usize) {
let count = u64::try_from(count).expect("validated native atom count fits u64");
WORK.set(WORK.get().checked_add(AtomPlanWork {
atom_clones: count,
..AtomPlanWork::default()
}));
}
fn record_operation_block_writes(count: usize) {
let count = u64::try_from(count).expect("native atom decoration block fits u64");
WORK.set(WORK.get().checked_add(AtomPlanWork {
operation_block_writes: count,
..AtomPlanWork::default()
}));
}
fn record_property_application() {
WORK.set(WORK.get().checked_add(AtomPlanWork {
property_applications: 1,
..AtomPlanWork::default()
}));
}
impl AtomPlanWork {
pub(crate) fn accumulate(&mut self, other: Self) {
let combined = Self {
sequence_nodes_created: self
.sequence_nodes_created
.checked_add(other.sequence_nodes_created)
.expect("native atom plan node work counter overflow"),
sequence_entries_written: self
.sequence_entries_written
.checked_add(other.sequence_entries_written)
.expect("native atom plan entry work counter overflow"),
materialized_atoms: self
.materialized_atoms
.checked_add(other.materialized_atoms)
.expect("native atom plan materialization counter overflow"),
property_applications: self
.property_applications
.checked_add(other.property_applications)
.expect("native atom plan property work counter overflow"),
atom_clones: self
.atom_clones
.checked_add(other.atom_clones)
.expect("native atom plan clone work counter overflow"),
operation_block_writes: self
.operation_block_writes
.checked_add(other.operation_block_writes)
.expect("native atom plan operation work counter overflow"),
};
*self = combined;
}
fn checked_add(mut self, other: Self) -> Self {
self.accumulate(other);
self
}
}
#[derive(Clone, Copy, Debug, Default)]
struct RunSummary {
prefix: i64,
suffix: i64,
maximum: i64,
all_run: bool,
}
impl RunSummary {
fn atom(atom: &Atom) -> Self {
if atom.wrap_space() {
Self::default()
} else if atom.wrap_cjk() {
Self {
maximum: atom.width(),
..Self::default()
}
} else {
Self {
prefix: atom.width(),
suffix: atom.width(),
maximum: atom.width(),
all_run: true,
}
}
}
fn combine(self, other: Self) -> Self {
let cross = self
.suffix
.checked_add(other.prefix)
.expect("validated native atom widths fit i64");
Self {
prefix: if self.all_run {
self.prefix
.checked_add(other.prefix)
.expect("validated native atom widths fit i64")
} else {
self.prefix
},
suffix: if other.all_run {
self.suffix
.checked_add(other.suffix)
.expect("validated native atom widths fit i64")
} else {
other.suffix
},
maximum: self.maximum.max(other.maximum).max(cross),
all_run: self.all_run && other.all_run,
}
}
}
#[derive(Clone, Debug, Default)]
struct Summary {
atom_count: usize,
any_owner: bool,
any_content: bool,
noncontent: bool,
whitespace: bool,
first_properties: Option<AtomProperties>,
runs: RunSummary,
}
impl Summary {
fn atom(atom: &Atom) -> Self {
let properties = atom.properties();
Self {
atom_count: 1,
any_owner: properties.owner.is_some() || !properties.owners.is_empty(),
any_content: properties.content.is_some(),
noncontent: !properties.style_ids.is_empty()
|| !properties.roles.is_empty()
|| !properties.property_template_ids.is_empty(),
whitespace: match atom {
Atom::Text { text, .. } => text.trim().is_empty(),
Atom::Space { .. } => true,
},
first_properties: Some(properties.clone()),
runs: RunSummary::atom(atom),
}
}
fn combine(self, other: Self) -> Self {
Self {
atom_count: self
.atom_count
.checked_add(other.atom_count)
.expect("validated native atom count fits usize"),
any_owner: self.any_owner || other.any_owner,
any_content: self.any_content || other.any_content,
noncontent: self.noncontent || other.noncontent,
whitespace: self.whitespace && other.whitespace,
first_properties: self.first_properties.or(other.first_properties),
runs: self.runs.combine(other.runs),
}
}
fn atoms(atoms: &[Atom]) -> Self {
let first = atoms.first().expect("nonempty native atom block");
let mut summary = Self {
atom_count: 0,
any_owner: false,
any_content: false,
noncontent: false,
whitespace: true,
first_properties: Some(first.properties().clone()),
runs: RunSummary {
all_run: true,
..RunSummary::default()
},
};
for atom in atoms {
let properties = atom.properties();
summary.atom_count = summary
.atom_count
.checked_add(1)
.expect("validated native atom count fits usize");
summary.any_owner |= properties.owner.is_some() || !properties.owners.is_empty();
summary.any_content |= properties.content.is_some();
summary.noncontent |= !properties.style_ids.is_empty()
|| !properties.roles.is_empty()
|| !properties.property_template_ids.is_empty();
summary.whitespace &= match atom {
Atom::Text { text, .. } => text.trim().is_empty(),
Atom::Space { .. } => true,
};
summary.runs = summary.runs.combine(RunSummary::atom(atom));
}
summary
}
}
#[derive(Clone, Debug)]
enum Decoration {
OwnContent {
region: i64,
index: i64,
had_owner: bool,
had_content: bool,
},
Style(u32),
Template(u32),
Role(RegionRole, i64),
ScrollWindow(i64),
}
#[derive(Clone, Debug)]
enum Part {
Atoms(Box<[Atom]>),
Decorated {
input: Arc<AtomPlan>,
decorations: Box<[Decoration]>,
},
}
#[must_use]
#[derive(Debug, Clone)]
pub(super) struct AtomPlan {
parts: Sequence<Part>,
summary: Summary,
}
impl Default for AtomPlan {
fn default() -> Self {
Self {
parts: Sequence::empty(),
summary: Summary {
whitespace: true,
..Summary::default()
},
}
}
}
impl AtomPlan {
pub(super) fn from_atoms(atoms: &[Atom]) -> Self {
record_atom_clones(atoms.len());
Self::from_owned_atoms(atoms.to_vec())
}
pub(super) fn from_owned_atoms(atoms: Vec<Atom>) -> Self {
if atoms.is_empty() {
return Self::default();
}
let summary = Summary::atoms(&atoms);
let mut sequence_work = Work::default();
let mut entries = Vec::with_capacity(atoms.len().div_ceil(16));
let mut atoms = atoms.into_iter();
loop {
let chunk = atoms.by_ref().take(16).collect::<Vec<_>>();
if chunk.is_empty() {
break;
}
let measure = atoms_measure(&chunk);
entries.push(
Entry::new(Arc::new(Part::Atoms(chunk.into_boxed_slice())), measure)
.expect("validated native atom measure is nonnegative"),
);
}
let parts = Sequence::from_entries(entries, &mut sequence_work)
.expect("validated native atom sequence aggregates fit limits");
record_sequence(sequence_work);
Self { parts, summary }
}
pub(super) fn is_empty(&self) -> bool {
self.parts.is_empty()
}
pub(super) fn append(&self, other: &Self) -> Self {
if self.is_empty() {
return other.clone();
}
if other.is_empty() {
return self.clone();
}
let mut sequence_work = Work::default();
let parts = self
.parts
.concat(&other.parts, &mut sequence_work)
.expect("validated native atom sequence aggregates fit limits");
record_sequence(sequence_work);
Self {
parts,
summary: self.summary.clone().combine(other.summary.clone()),
}
}
pub(super) fn push(&self, atom: Atom) -> Self {
self.append(&Self::from_single(atom))
}
pub(super) fn prepend(&self, atom: Atom) -> Self {
Self::from_single(atom).append(self)
}
pub(super) fn to_vec(&self) -> Vec<Atom> {
let mut output = Vec::with_capacity(self.summary.atom_count);
if let Some(root) = self.parts.root() {
materialize_node(root, &mut output);
}
record_materialized(output.len());
output
}
pub(super) fn first(&self) -> Option<Atom> {
first_node(self.parts.root()?)
}
pub(super) fn whitespace_only(&self) -> bool {
self.summary.whitespace
}
pub(super) fn has_noncontent_properties(&self) -> bool {
self.summary.noncontent
}
pub(super) fn own_content(&self, region: i64, index: i64) -> Self {
if self.is_empty() {
return self.clone();
}
self.decorate(Decoration::OwnContent {
region,
index,
had_owner: self.summary.any_owner,
had_content: self.summary.any_content,
})
}
pub(super) fn apply_style(&self, style: u32) -> Self {
self.decorate(Decoration::Style(style))
}
pub(super) fn apply_template(&self, template: u32) -> Self {
self.decorate(Decoration::Template(template))
}
pub(super) fn apply_role(&self, role: RegionRole, region: i64) -> Self {
self.decorate(Decoration::Role(role, region))
}
pub(super) fn apply_scroll_window(&self, region: i64) -> Self {
self.decorate(Decoration::ScrollWindow(region))
}
pub(super) fn min_content_width(&self) -> i64 {
self.summary.runs.maximum
}
pub(super) fn width(&self) -> i64 {
self.parts.measure().width_sum
}
fn from_single(atom: Atom) -> Self {
let summary = Summary::atom(&atom);
let measure = atom_measure(&atom);
let mut sequence_work = Work::default();
let parts = Sequence::from_entries(
[Entry::new(
Arc::new(Part::Atoms(vec![atom].into_boxed_slice())),
measure,
)
.expect("validated native atom measure is nonnegative")],
&mut sequence_work,
)
.expect("single native atom sequence fits limits");
record_sequence(sequence_work);
Self { parts, summary }
}
fn decorate(&self, decoration: Decoration) -> Self {
if self.is_empty() {
return self.clone();
}
let mut summary = self.summary.clone();
if let Some(properties) = &mut summary.first_properties {
apply_decoration(properties, &decoration);
}
match &decoration {
Decoration::OwnContent { .. } => {
summary.any_owner = true;
summary.any_content = true;
}
Decoration::Style(_) | Decoration::Template(_) | Decoration::Role(_, _) => {
summary.noncontent = true;
}
Decoration::ScrollWindow(_) => {}
}
let (input, decorations) = self
.parts
.get(0)
.filter(|_| self.parts.len() == 1)
.and_then(|entry| match entry.value().as_ref() {
Part::Decorated { input, decorations } if decorations.len() < 16 => {
let mut combined = decorations.to_vec();
combined.push(decoration.clone());
Some((input.clone(), combined.into_boxed_slice()))
}
_ => None,
})
.unwrap_or_else(|| (Arc::new(self.clone()), vec![decoration].into_boxed_slice()));
record_operation_block_writes(decorations.len());
let measure = self.parts.measure();
let mut sequence_work = Work::default();
let parts = Sequence::from_entries(
[
Entry::new(Arc::new(Part::Decorated { input, decorations }), measure)
.expect("validated native atom plan measure is nonnegative"),
],
&mut sequence_work,
)
.expect("decorated native atom sequence fits limits");
record_sequence(sequence_work);
Self { parts, summary }
}
}
fn atom_measure(atom: &Atom) -> Measure {
let chars = match atom {
Atom::Text { text, .. } => text.chars().count() as u64,
Atom::Space { .. } => 1,
};
Measure::new(chars, 0, atom.width(), atom.width())
.expect("validated native atom width is nonnegative")
}
fn atoms_measure(atoms: &[Atom]) -> Measure {
atoms.iter().fold(Measure::default(), |measure, atom| {
measure
.checked_combine(atom_measure(atom))
.expect("validated native atom measures fit limits")
})
}
fn apply_decoration(properties: &mut AtomProperties, decoration: &Decoration) {
record_property_application();
match decoration {
Decoration::OwnContent {
region,
index,
had_owner,
had_content,
} => {
if *had_owner {
let mut owners = properties.owners.clone();
if let Some(owner) = properties.owner {
if !owners.contains(&owner) {
owners.push(owner);
}
}
if !owners.contains(region) {
owners.push(*region);
}
properties.owner = Some(*region);
properties.owners = owners;
} else {
properties.owner = Some(*region);
properties.owners = vec![*region];
}
if !had_content {
properties.content = Some(*region);
properties.content_idx = Some(*index);
}
}
Decoration::Style(style) => properties.style_ids.push(*style),
Decoration::Template(template) => properties.property_template_ids.push(*template),
Decoration::Role(role, region) => properties.roles.push(RegionRoleEntry {
role: *role,
region_id: *region,
}),
Decoration::ScrollWindow(region) => properties.scroll_window = Some(*region),
}
}
fn decorate_atom(mut atom: Atom, decoration: &Decoration) -> Atom {
apply_decoration(atom.properties_mut(), decoration);
atom
}
fn materialize_node(node: &Arc<Node<Part>>, output: &mut Vec<Atom>) {
match node.view() {
NodeView::Leaf { entries, .. } => {
for entry in entries {
match entry.value().as_ref() {
Part::Atoms(atoms) => output.extend(atoms.iter().cloned()),
Part::Decorated { input, decorations } => {
let start = output.len();
if let Some(root) = input.parts.root() {
materialize_node(root, output);
}
for atom in &mut output[start..] {
for decoration in decorations {
apply_decoration(atom.properties_mut(), decoration);
}
}
}
}
}
}
NodeView::Branch { left, right, .. } => {
materialize_node(left, output);
materialize_node(right, output);
}
}
}
fn first_node(node: &Arc<Node<Part>>) -> Option<Atom> {
match node.view() {
NodeView::Leaf { entries, .. } => match entries.first()?.value().as_ref() {
Part::Atoms(atoms) => {
record_materialized(1);
Some(atoms.first()?.clone())
}
Part::Decorated { input, decorations } => input
.first()
.map(|atom| decorations.iter().fold(atom, decorate_atom)),
},
NodeView::Branch { left, .. } => first_node(left),
}
}
#[cfg(test)]
mod tests {
use super::*;
fn text(value: &str, width: i64, cjk: bool, space: bool) -> Atom {
Atom::Text {
text: value.to_owned(),
width,
cjk,
space,
properties: AtomProperties::default(),
}
}
#[test]
fn decoration_is_lazy_ordered_and_new_padding_is_not_retroactive() {
reset_work();
let content = AtomPlan::from_atoms(&[text("x", 1, false, false)])
.apply_style(3)
.own_content(7, 2);
let plan = content.prepend(Atom::Space {
width: 4,
properties: AtomProperties::default(),
});
assert_eq!(work().materialized_atoms, 0);
let atoms = plan.to_vec();
assert!(atoms[0].properties().style_ids.is_empty());
assert_eq!(atoms[1].properties().style_ids, vec![3]);
assert_eq!(atoms[1].properties().content, Some(7));
assert_eq!(atoms[1].properties().content_idx, Some(2));
assert_eq!(work().materialized_atoms, 2);
}
#[test]
fn own_content_uses_whole_line_owner_and_content_branches() {
let mut owned = text("a", 1, false, false);
owned.properties_mut().owner = Some(5);
owned.properties_mut().owners = vec![5];
owned.properties_mut().content = Some(4);
let plan = AtomPlan::from_atoms(&[owned, text("b", 1, false, false)]).own_content(9, 3);
let atoms = plan.to_vec();
assert_eq!(atoms[0].properties().content, Some(4));
assert_eq!(atoms[1].properties().content, None);
assert_eq!(atoms[0].properties().owner, Some(9));
assert_eq!(atoms[0].properties().owners, vec![5, 9]);
assert_eq!(atoms[1].properties().owner, Some(9));
assert_eq!(atoms[1].properties().owners, vec![9]);
}
#[test]
fn min_content_summary_matches_space_and_cjk_breaks() {
let plan = AtomPlan::from_atoms(&[
text("ab", 2, false, false),
text(" ", 1, false, true),
text("", 4, true, false),
text("cd", 3, false, false),
]);
assert_eq!(plan.min_content_width(), 4);
assert!(!plan.whitespace_only());
assert!(!plan.has_noncontent_properties());
assert!(!plan.is_empty());
assert!(AtomPlan::default().first().is_none());
}
#[test]
fn append_shares_parts_and_materializes_once() {
reset_work();
let left = AtomPlan::from_atoms(&[text("a", 1, false, false)]);
let right = AtomPlan::from_owned_atoms(vec![text("b", 2, false, false)]);
let plan = left.append(&right).apply_template(2).apply_scroll_window(8);
assert_eq!(plan.width(), 3);
assert_eq!(work().materialized_atoms, 0);
let atoms = plan.to_vec();
assert_eq!(atoms.len(), 2);
assert_eq!(atoms[0].properties().property_template_ids, vec![2]);
assert_eq!(atoms[1].properties().scroll_window, Some(8));
}
#[test]
fn wide_append_and_decorations_do_no_atom_work_until_materialized() {
for size in [32, 128, 512, 8192] {
let atoms = (0..size)
.map(|_| text("x", 1, false, false))
.collect::<Vec<_>>();
let plan = AtomPlan::from_atoms(&atoms);
reset_work();
let combined = plan
.append(&plan)
.own_content(7, 0)
.apply_style(1)
.apply_template(2)
.apply_role(RegionRole::PaddingLeft, 7)
.apply_scroll_window(7);
let lazy = work();
assert_eq!(lazy.materialized_atoms, 0);
assert_eq!(lazy.sequence_nodes_created, 6);
assert!(lazy.sequence_entries_written <= 21, "{lazy:?}");
assert_eq!(lazy.property_applications, 5);
assert_eq!(lazy.atom_clones, 0);
assert_eq!(lazy.operation_block_writes, 15);
let materialized = combined.to_vec();
assert_eq!(materialized.len(), size * 2);
let eager = work();
assert_eq!(eager.materialized_atoms, (size * 2) as u64);
assert_eq!(eager.property_applications, 5 + (size * 2 * 5) as u64);
}
}
#[test]
fn min_content_randomized_summary_matches_vec_oracle() {
fn oracle(atoms: &[Atom]) -> i64 {
let mut maximum = 0;
let mut run = 0_i64;
for atom in atoms {
if atom.wrap_space() {
maximum = maximum.max(run);
run = 0;
} else if atom.wrap_cjk() {
maximum = maximum.max(run).max(atom.width());
run = 0;
} else {
run += atom.width();
}
}
maximum.max(run)
}
let mut seed = 0x5e91_7ac3_u64;
for size in 0..257 {
let mut atoms = Vec::with_capacity(size);
for _ in 0..size {
seed = seed.wrapping_mul(6364136223846793005).wrapping_add(1);
let width = ((seed >> 32) % 8 + 1) as i64;
atoms.push(match seed % 5 {
0 => text(" ", width, false, true),
1 => text("", width, true, false),
_ => text("x", width, false, false),
});
}
let split = size / 3;
let plan = AtomPlan::default()
.append(&AtomPlan::from_atoms(&atoms[..split]))
.append(&AtomPlan::default())
.append(&AtomPlan::from_atoms(&atoms[split..]));
assert_eq!(plan.min_content_width(), oracle(&atoms));
assert_eq!(plan.is_empty(), atoms.is_empty());
}
}
#[test]
fn first_counts_one_atom_and_each_lazy_property_application() {
let plan = AtomPlan::from_atoms(&[text("a", 1, false, false), text("b", 1, false, false)])
.apply_style(3)
.apply_template(4);
reset_work();
let first = plan.first().unwrap();
assert_eq!(first.properties().style_ids, vec![3]);
assert_eq!(first.properties().property_template_ids, vec![4]);
assert_eq!(work().materialized_atoms, 1);
assert_eq!(work().property_applications, 2);
assert_eq!(work().atom_clones, 1);
}
#[test]
fn decoration_blocks_are_bounded_ordered_and_keep_old_fork() {
let base = AtomPlan::from_owned_atoms(vec![text("x", 1, false, false)]);
let fork = base.clone();
let old_root = Arc::clone(base.parts.root().unwrap());
reset_work();
let decorated = (0..33).fold(base, |plan, style| plan.apply_style(style));
assert!(Arc::ptr_eq(fork.parts.root().unwrap(), &old_root));
assert_eq!(work().materialized_atoms, 0);
assert_eq!(work().operation_block_writes, 273);
let mut block_lengths = Vec::new();
let mut current = &decorated;
loop {
let part = current.parts.get(0).unwrap().value().as_ref();
match part {
Part::Decorated { input, decorations } => {
block_lengths.push(decorations.len());
current = input;
}
Part::Atoms(_) => break,
}
}
assert_eq!(block_lengths, vec![1, 16, 16]);
assert_eq!(
decorated.to_vec()[0].properties().style_ids,
(0..33).collect::<Vec<_>>()
);
assert!(fork.to_vec()[0].properties().style_ids.is_empty());
}
#[test]
fn wide_owned_bootstrap_writes_one_sequence_entry_per_atom_block() {
let atoms = (0..8192)
.map(|_| text("x", 1, false, false))
.collect::<Vec<_>>();
reset_work();
let plan = AtomPlan::from_owned_atoms(atoms);
let bootstrap = work();
assert_eq!(bootstrap.atom_clones, 0);
assert_eq!(bootstrap.sequence_entries_written, 512);
assert_eq!(bootstrap.sequence_nodes_created, 63);
assert_eq!(plan.width(), 8192);
assert_eq!(plan.summary.atom_count, 8192);
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,5 @@
mod layout;
pub mod sequence;
use layout::{
encode_error_tape, DocumentDelta, LayoutContext, LayoutDocument, LayoutTape, RetainedDocument,
@ -468,6 +469,7 @@ struct RenderedJob {
base_renders: u64,
target_renders: u64,
resolver_lookups: u64,
atom_plan_work: layout::AtomPlanWork,
}
#[derive(Default)]
@ -520,6 +522,7 @@ struct RuntimeState {
document_delta_entries_validated: u64,
document_trie_path_nodes_copied: u64,
document_resolver_lookups: u64,
atom_plan_work: layout::AtomPlanWork,
confirmed_baseline: Option<Arc<ConfirmedBaseline>>,
}
@ -580,6 +583,7 @@ struct SessionStats {
document_delta_entries_validated: u64,
document_trie_path_nodes_copied: u64,
document_resolver_lookups: u64,
atom_plan_work: layout::AtomPlanWork,
pending_baselines: usize,
confirmed_baseline: bool,
confirmed_baseline_bytes: usize,
@ -652,6 +656,7 @@ impl Session {
document_delta_entries_validated: 0,
document_trie_path_nodes_copied: 0,
document_resolver_lookups: 0,
atom_plan_work: layout::AtomPlanWork::default(),
confirmed_baseline,
}),
readiness_channel: Mutex::new(None),
@ -1077,6 +1082,7 @@ impl Session {
state.base_renders += output.base_renders;
state.target_renders += output.target_renders;
state.document_resolver_lookups += output.resolver_lookups;
state.atom_plan_work.accumulate(output.atom_plan_work);
state.document_parses += input_stats.parses;
state.document_validations += input_stats.validations;
state.document_reuses += input_stats.reuses;
@ -1225,6 +1231,7 @@ impl Session {
document_delta_entries_validated: state.document_delta_entries_validated,
document_trie_path_nodes_copied: state.document_trie_path_nodes_copied,
document_resolver_lookups: state.document_resolver_lookups,
atom_plan_work: state.atom_plan_work,
pending_baselines,
confirmed_baseline: state.confirmed_baseline.is_some(),
confirmed_baseline_bytes,
@ -1437,6 +1444,7 @@ fn render_layout_payload(
base_renders: 0,
target_renders: 0,
resolver_lookups: 0,
atom_plan_work: layout::AtomPlanWork::default(),
},
JobPayload::Layout {
document,
@ -1494,6 +1502,7 @@ fn render_layout_payload(
String,
>;
layout::reset_resolver_lookups();
layout::reset_atom_plan_work();
let result = catch_unwind(AssertUnwindSafe(|| -> LayoutRenderOutcome {
let target_styles = document.styles()?;
if let Some(base_context) = base_context {
@ -1568,6 +1577,7 @@ fn render_layout_payload(
}));
let resolver_lookups =
validation_resolver_lookups.saturating_add(layout::resolver_lookups());
let atom_plan_work = layout::atom_plan_work();
match result {
Ok(Ok((bytes, tape, styles, baseline_hit, base_renders, target_renders))) => {
RenderedJob {
@ -1583,6 +1593,7 @@ fn render_layout_payload(
base_renders,
target_renders,
resolver_lookups,
atom_plan_work,
}
}
Ok(Err(error)) => RenderedJob {
@ -1592,6 +1603,7 @@ fn render_layout_payload(
base_renders: 0,
target_renders: 0,
resolver_lookups,
atom_plan_work,
},
Err(_) => RenderedJob {
bytes: encode_error_tape(identity, "native layout panicked", max_result_bytes),
@ -1600,6 +1612,7 @@ fn render_layout_payload(
base_renders: 0,
target_renders: 0,
resolver_lookups,
atom_plan_work,
},
}
}
@ -1749,6 +1762,7 @@ fn worker_loop(shared: Arc<Shared>) {
state.base_renders += output.base_renders;
state.target_renders += output.target_renders;
state.document_resolver_lookups += output.resolver_lookups;
state.atom_plan_work.accumulate(output.atom_plan_work);
state.results.insert(
(job.generation, job.key),
ResultEntry {
@ -2573,9 +2587,9 @@ mod tests {
assert_eq!(stats.document_delta_entries_validated, 1);
assert_eq!(stats.document_trie_path_nodes_copied, 17);
assert_eq!(stats.document_delta_input_bytes, delta.len() as u64);
assert!(
stats.document_resolver_lookups >= 3,
"target/base validation and target render lookups must all remain visible"
assert_eq!(
stats.document_resolver_lookups, stats.target_renders,
"each single-owner render resolves its root; retained context validation resolves no nodes"
);
assert!(session.confirm(2, 2, 2).unwrap());

751
native/src/sequence.rs Normal file
View File

@ -0,0 +1,751 @@
use std::sync::Arc;
const LEAF_CAPACITY: usize = 16;
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub struct Measure {
pub chars: u64,
pub lines: u64,
pub width_sum: i64,
pub width_max: i64,
}
impl Measure {
pub fn new(chars: u64, lines: u64, width_sum: i64, width_max: i64) -> Result<Self, Error> {
if width_sum < 0 || width_max < 0 {
return Err(Error::NegativeWidth);
}
Ok(Self {
chars,
lines,
width_sum,
width_max,
})
}
pub fn checked_combine(self, other: Self) -> Result<Self, Error> {
Ok(Self {
chars: self.chars.checked_add(other.chars).ok_or(Error::Overflow)?,
lines: self.lines.checked_add(other.lines).ok_or(Error::Overflow)?,
width_sum: self
.width_sum
.checked_add(other.width_sum)
.ok_or(Error::Overflow)?,
width_max: self.width_max.max(other.width_max),
})
}
}
#[derive(Debug)]
pub struct Entry<T> {
value: Arc<T>,
measure: Measure,
}
impl<T> Clone for Entry<T> {
fn clone(&self) -> Self {
Self {
value: Arc::clone(&self.value),
measure: self.measure,
}
}
}
impl<T> Entry<T> {
pub fn new(value: Arc<T>, measure: Measure) -> Result<Self, Error> {
if measure.width_sum < 0 || measure.width_max < 0 {
return Err(Error::NegativeWidth);
}
Ok(Self { value, measure })
}
pub fn value(&self) -> &Arc<T> {
&self.value
}
pub fn measure(&self) -> Measure {
self.measure
}
}
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub struct Work {
pub nodes_created: u64,
pub entries_written: u64,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum Error {
IndexOutOfBounds,
NegativeWidth,
Overflow,
}
#[derive(Debug)]
pub enum Node<T> {
Leaf {
entries: Box<[Entry<T>]>,
measure: Measure,
},
Branch {
left: Arc<Node<T>>,
right: Arc<Node<T>>,
len: usize,
height: u32,
measure: Measure,
},
}
pub enum NodeView<'a, T> {
Leaf {
entries: &'a [Entry<T>],
measure: Measure,
},
Branch {
left: &'a Arc<Node<T>>,
right: &'a Arc<Node<T>>,
len: usize,
height: u32,
measure: Measure,
},
}
type OptionalRoot<T> = Option<Arc<Node<T>>>;
type SplitRoots<T> = (OptionalRoot<T>, OptionalRoot<T>);
impl<T> Node<T> {
pub fn view(&self) -> NodeView<'_, T> {
match self {
Self::Leaf { entries, measure } => NodeView::Leaf {
entries,
measure: *measure,
},
Self::Branch {
left,
right,
len,
height,
measure,
} => NodeView::Branch {
left,
right,
len: *len,
height: *height,
measure: *measure,
},
}
}
fn len(&self) -> usize {
match self {
Self::Leaf { entries, .. } => entries.len(),
Self::Branch { len, .. } => *len,
}
}
fn height(&self) -> u32 {
match self {
Self::Leaf { .. } => 1,
Self::Branch { height, .. } => *height,
}
}
fn measure(&self) -> Measure {
match self {
Self::Leaf { measure, .. } | Self::Branch { measure, .. } => *measure,
}
}
}
#[derive(Debug)]
pub struct Sequence<T> {
root: Option<Arc<Node<T>>>,
}
impl<T> Clone for Sequence<T> {
fn clone(&self) -> Self {
Self {
root: self.root.as_ref().map(Arc::clone),
}
}
}
impl<T> Default for Sequence<T> {
fn default() -> Self {
Self::empty()
}
}
impl<T> Sequence<T> {
pub fn empty() -> Self {
Self { root: None }
}
pub fn from_entries<I>(entries: I, work: &mut Work) -> Result<Self, Error>
where
I: IntoIterator<Item = Entry<T>>,
{
let entries = entries.into_iter().collect::<Vec<_>>();
let mut leaves = Vec::with_capacity(entries.len().div_ceil(LEAF_CAPACITY));
for chunk in entries.chunks(LEAF_CAPACITY) {
leaves.push(make_leaf(chunk.to_vec(), work)?);
}
fn build<T>(leaves: &[Arc<Node<T>>], work: &mut Work) -> Result<Arc<Node<T>>, Error> {
if leaves.len() == 1 {
return Ok(Arc::clone(&leaves[0]));
}
let middle = leaves.len() / 2;
make_branch(
build(&leaves[..middle], work)?,
build(&leaves[middle..], work)?,
work,
)
}
Ok(Self {
root: if leaves.is_empty() {
None
} else {
Some(build(&leaves, work)?)
},
})
}
pub fn len(&self) -> usize {
self.root.as_ref().map_or(0, |root| root.len())
}
pub fn is_empty(&self) -> bool {
self.root.is_none()
}
pub fn measure(&self) -> Measure {
self.root
.as_ref()
.map_or(Measure::default(), |root| root.measure())
}
pub fn root(&self) -> Option<&Arc<Node<T>>> {
self.root.as_ref()
}
pub fn get(&self, index: usize) -> Option<&Entry<T>> {
fn get_at<T>(node: &Node<T>, index: usize) -> Option<&Entry<T>> {
match node {
Node::Leaf { entries, .. } => entries.get(index),
Node::Branch { left, right, .. } => {
if index < left.len() {
get_at(left, index)
} else {
get_at(right, index - left.len())
}
}
}
}
(index < self.len()).then(|| get_at(self.root.as_deref()?, index))?
}
pub fn prefix_measure(&self, end: usize) -> Result<Measure, Error> {
fn prefix<T>(node: &Node<T>, end: usize) -> Result<Measure, Error> {
match node {
Node::Leaf { entries, .. } => entries[..end]
.iter()
.try_fold(Measure::default(), |sum, entry| {
sum.checked_combine(entry.measure)
}),
Node::Branch { left, right, .. } => {
if end <= left.len() {
prefix(left, end)
} else {
left.measure()
.checked_combine(prefix(right, end - left.len())?)
}
}
}
}
if end > self.len() {
return Err(Error::IndexOutOfBounds);
}
self.root
.as_deref()
.map_or(Ok(Measure::default()), |root| prefix(root, end))
}
pub fn split_at(&self, index: usize, work: &mut Work) -> Result<(Self, Self), Error> {
if index > self.len() {
return Err(Error::IndexOutOfBounds);
}
let (left, right) = split_node(self.root.as_ref(), index, work)?;
Ok((Self { root: left }, Self { root: right }))
}
pub fn concat(&self, other: &Self, work: &mut Work) -> Result<Self, Error> {
Ok(Self {
root: join(self.root.clone(), other.root.clone(), work)?,
})
}
pub fn replace(&self, index: usize, entry: Entry<T>, work: &mut Work) -> Result<Self, Error> {
if index >= self.len() {
return Err(Error::IndexOutOfBounds);
}
Ok(Self {
root: Some(replace_node(
self.root.as_ref().expect("nonempty checked"),
index,
entry,
work,
)?),
})
}
}
fn count_node(work: &mut Work) -> Result<(), Error> {
work.nodes_created = work.nodes_created.checked_add(1).ok_or(Error::Overflow)?;
Ok(())
}
fn make_leaf<T>(entries: Vec<Entry<T>>, work: &mut Work) -> Result<Arc<Node<T>>, Error> {
debug_assert!(!entries.is_empty() && entries.len() <= LEAF_CAPACITY);
let measure = entries.iter().try_fold(Measure::default(), |sum, entry| {
sum.checked_combine(entry.measure)
})?;
let written = u64::try_from(entries.len()).map_err(|_| Error::Overflow)?;
let next_written = work
.entries_written
.checked_add(written)
.ok_or(Error::Overflow)?;
count_node(work)?;
work.entries_written = next_written;
Ok(Arc::new(Node::Leaf {
entries: entries.into_boxed_slice(),
measure,
}))
}
fn make_branch<T>(
left: Arc<Node<T>>,
right: Arc<Node<T>>,
work: &mut Work,
) -> Result<Arc<Node<T>>, Error> {
let len = left.len().checked_add(right.len()).ok_or(Error::Overflow)?;
let height = left
.height()
.max(right.height())
.checked_add(1)
.ok_or(Error::Overflow)?;
let measure = left.measure().checked_combine(right.measure())?;
count_node(work)?;
Ok(Arc::new(Node::Branch {
left,
right,
len,
height,
measure,
}))
}
fn join<T>(
left: Option<Arc<Node<T>>>,
right: Option<Arc<Node<T>>>,
work: &mut Work,
) -> Result<Option<Arc<Node<T>>>, Error> {
let (left, right) = match (left, right) {
(None, right) => return Ok(right),
(left, None) => return Ok(left),
(Some(left), Some(right)) => (left, right),
};
if let (Node::Leaf { entries: a, .. }, Node::Leaf { entries: b, .. }) =
(left.as_ref(), right.as_ref())
{
if a.len() + b.len() <= LEAF_CAPACITY {
let mut entries = Vec::with_capacity(a.len() + b.len());
entries.extend_from_slice(a);
entries.extend_from_slice(b);
return make_leaf(entries, work).map(Some);
}
}
if left.height() > right.height().saturating_add(1) {
let Node::Branch {
left: outer,
right: inner,
..
} = left.as_ref()
else {
unreachable!()
};
let joined = join(Some(Arc::clone(inner)), Some(right), work)?.expect("nonempty join");
return rebalance(Arc::clone(outer), joined, work).map(Some);
}
if right.height() > left.height().saturating_add(1) {
let Node::Branch {
left: inner,
right: outer,
..
} = right.as_ref()
else {
unreachable!()
};
let joined = join(Some(left), Some(Arc::clone(inner)), work)?.expect("nonempty join");
return rebalance(joined, Arc::clone(outer), work).map(Some);
}
make_branch(left, right, work).map(Some)
}
fn rebalance<T>(
left: Arc<Node<T>>,
right: Arc<Node<T>>,
work: &mut Work,
) -> Result<Arc<Node<T>>, Error> {
if left.height() > right.height().saturating_add(1) {
let Node::Branch {
left: ll,
right: lr,
..
} = left.as_ref()
else {
unreachable!()
};
if ll.height() >= lr.height() {
return make_branch(
Arc::clone(ll),
make_branch(Arc::clone(lr), right, work)?,
work,
);
}
let Node::Branch {
left: lrl,
right: lrr,
..
} = lr.as_ref()
else {
unreachable!()
};
return make_branch(
make_branch(Arc::clone(ll), Arc::clone(lrl), work)?,
make_branch(Arc::clone(lrr), right, work)?,
work,
);
}
if right.height() > left.height().saturating_add(1) {
let Node::Branch {
left: rl,
right: rr,
..
} = right.as_ref()
else {
unreachable!()
};
if rr.height() >= rl.height() {
return make_branch(
make_branch(left, Arc::clone(rl), work)?,
Arc::clone(rr),
work,
);
}
let Node::Branch {
left: rll,
right: rlr,
..
} = rl.as_ref()
else {
unreachable!()
};
return make_branch(
make_branch(left, Arc::clone(rll), work)?,
make_branch(Arc::clone(rlr), Arc::clone(rr), work)?,
work,
);
}
make_branch(left, right, work)
}
fn split_node<T>(
node: Option<&Arc<Node<T>>>,
index: usize,
work: &mut Work,
) -> Result<SplitRoots<T>, Error> {
let Some(node) = node else {
return Ok((None, None));
};
if index == 0 {
return Ok((None, Some(Arc::clone(node))));
}
if index == node.len() {
return Ok((Some(Arc::clone(node)), None));
}
match node.as_ref() {
Node::Leaf { entries, .. } => Ok((
Some(make_leaf(entries[..index].to_vec(), work)?),
Some(make_leaf(entries[index..].to_vec(), work)?),
)),
Node::Branch { left, right, .. } => {
if index < left.len() {
let (before, after) = split_node(Some(left), index, work)?;
Ok((before, join(after, Some(Arc::clone(right)), work)?))
} else if index == left.len() {
Ok((Some(Arc::clone(left)), Some(Arc::clone(right))))
} else {
let (before, after) = split_node(Some(right), index - left.len(), work)?;
Ok((join(Some(Arc::clone(left)), before, work)?, after))
}
}
}
}
fn replace_node<T>(
node: &Arc<Node<T>>,
index: usize,
entry: Entry<T>,
work: &mut Work,
) -> Result<Arc<Node<T>>, Error> {
match node.as_ref() {
Node::Leaf { entries, .. } => {
let mut entries = entries.to_vec();
entries[index] = entry;
make_leaf(entries, work)
}
Node::Branch { left, right, .. } => {
if index < left.len() {
make_branch(
replace_node(left, index, entry, work)?,
Arc::clone(right),
work,
)
} else {
make_branch(
Arc::clone(left),
replace_node(right, index - left.len(), entry, work)?,
work,
)
}
}
}
}
#[cfg(test)]
mod tests {
use super::*;
fn entry(value: usize) -> Entry<String> {
let text = if value % 5 == 0 {
format!("{value}")
} else {
value.to_string()
};
Entry::new(
Arc::new(text.clone()),
Measure::new(text.chars().count() as u64, 1, value as i64, value as i64).unwrap(),
)
.unwrap()
}
fn values(sequence: &Sequence<String>) -> Vec<String> {
(0..sequence.len())
.map(|index| sequence.get(index).unwrap().value().as_ref().clone())
.collect()
}
fn height<T>(sequence: &Sequence<T>) -> u32 {
sequence.root().map_or(0, |root| root.height())
}
fn shared_nodes<T>(left: &Arc<Node<T>>, right: &Arc<Node<T>>) -> usize {
if Arc::ptr_eq(left, right) {
return 1;
}
match (left.as_ref(), right.as_ref()) {
(
Node::Branch {
left: ll,
right: lr,
..
},
Node::Branch {
left: rl,
right: rr,
..
},
) => shared_nodes(ll, rl) + shared_nodes(lr, rr),
_ => 0,
}
}
fn assert_valid<T>(node: &Arc<Node<T>>) -> (usize, u32, Measure) {
match node.as_ref() {
Node::Leaf { entries, measure } => {
assert!(!entries.is_empty() && entries.len() <= LEAF_CAPACITY);
let calculated = entries
.iter()
.try_fold(Measure::default(), |sum, entry| {
sum.checked_combine(entry.measure())
})
.unwrap();
assert_eq!(*measure, calculated);
(entries.len(), 1, calculated)
}
Node::Branch {
left,
right,
len,
height,
measure,
} => {
let (left_len, left_height, left_measure) = assert_valid(left);
let (right_len, right_height, right_measure) = assert_valid(right);
assert!(left_height.abs_diff(right_height) <= 1);
assert_eq!(*len, left_len + right_len);
assert_eq!(*height, left_height.max(right_height) + 1);
assert_eq!(
*measure,
left_measure.checked_combine(right_measure).unwrap()
);
(*len, *height, *measure)
}
}
}
#[test]
fn empty_and_unicode_measures_are_exact() {
let empty = Sequence::<String>::empty();
assert!(empty.is_empty());
assert_eq!(empty.measure(), Measure::default());
let mut work = Work::default();
let sequence = Sequence::from_entries([entry(0), entry(12)], &mut work).unwrap();
assert_eq!(sequence.len(), 2);
assert_eq!(sequence.measure().chars, 4);
assert_eq!(sequence.measure().lines, 2);
assert_eq!(sequence.measure().width_sum, 12);
assert_eq!(sequence.measure().width_max, 12);
assert_eq!(sequence.prefix_measure(1).unwrap().chars, 2);
for size in 1..=257 {
let mut work = Work::default();
let varied = Sequence::from_entries((0..size).map(entry), &mut work).unwrap();
assert_eq!(varied.len(), size);
assert_valid(varied.root().unwrap());
}
}
#[test]
fn every_split_point_rejoins_exactly() {
let mut setup = Work::default();
let original = Sequence::from_entries((0..97).map(entry), &mut setup).unwrap();
let oracle = values(&original);
for index in 0..=original.len() {
let mut work = Work::default();
let (left, right) = original.split_at(index, &mut work).unwrap();
assert_eq!(values(&left), oracle[..index]);
assert_eq!(values(&right), oracle[index..]);
let joined = left.concat(&right, &mut work).unwrap();
assert_eq!(values(&joined), oracle);
assert!(height(&joined) <= 8);
assert_valid(joined.root().unwrap());
}
}
#[test]
fn repeated_left_and_right_concat_remain_balanced() {
let mut left = Sequence::empty();
let mut right = Sequence::empty();
let mut work = Work::default();
for index in 0..2048 {
let one = Sequence::from_entries([entry(index)], &mut work).unwrap();
left = left.concat(&one, &mut work).unwrap();
right = one.concat(&right, &mut work).unwrap();
}
assert_eq!(left.len(), 2048);
assert_eq!(right.len(), 2048);
assert!(height(&left) <= 16, "left height={}", height(&left));
assert!(height(&right) <= 16, "right height={}", height(&right));
assert_valid(left.root().unwrap());
assert_valid(right.root().unwrap());
}
#[test]
fn deterministic_random_operations_match_vec_oracle() {
let mut seed = 0x91e1_0da5_u64;
let mut oracle = (0..64).collect::<Vec<_>>();
let mut setup = Work::default();
let mut sequence =
Sequence::from_entries(oracle.iter().copied().map(entry), &mut setup).unwrap();
for _ in 0..1000 {
seed = seed.wrapping_mul(6364136223846793005).wrapping_add(1);
let index = (seed as usize) % oracle.len();
seed = seed.wrapping_mul(6364136223846793005).wrapping_add(1);
let value = (seed >> 16) as usize % 10_000;
oracle[index] = value;
let mut work = Work::default();
sequence = sequence.replace(index, entry(value), &mut work).unwrap();
assert!(work.entries_written <= LEAF_CAPACITY as u64);
}
assert_eq!(
values(&sequence),
oracle
.iter()
.map(|value| entry(*value).value().as_ref().clone())
.collect::<Vec<_>>()
);
assert_valid(sequence.root().unwrap());
}
#[test]
fn single_replace_is_logarithmic_and_preserves_old_fork() {
for size in [32, 128, 512, 8192] {
let mut setup = Work::default();
let original = Sequence::from_entries((0..size).map(entry), &mut setup).unwrap();
let fork = original.clone();
let old_value = original.get(1).unwrap().value().clone();
let mut work = Work::default();
let updated = original.replace(1, entry(99_999), &mut work).unwrap();
assert!(work.nodes_created <= u64::from(height(&original)) + 1);
assert!(work.entries_written <= LEAF_CAPACITY as u64);
assert!(shared_nodes(original.root().unwrap(), updated.root().unwrap()) > 0);
assert!(Arc::ptr_eq(fork.get(1).unwrap().value(), &old_value));
assert_eq!(fork.get(1).unwrap().value().as_str(), "1");
assert_eq!(updated.get(1).unwrap().value().as_str(), "99999");
assert_valid(updated.root().unwrap());
}
}
#[test]
fn large_split_and_rejoin_touch_only_logarithmic_paths() {
let mut setup = Work::default();
let original = Sequence::from_entries((0..8192).map(entry), &mut setup).unwrap();
let mut split_work = Work::default();
let (left, right) = original.split_at(4097, &mut split_work).unwrap();
assert!(split_work.nodes_created <= 32, "{split_work:?}");
assert!(split_work.entries_written <= 32, "{split_work:?}");
let mut concat_work = Work::default();
let rejoined = left.concat(&right, &mut concat_work).unwrap();
assert!(concat_work.nodes_created <= 32, "{concat_work:?}");
assert_eq!(values(&rejoined), values(&original));
assert_valid(rejoined.root().unwrap());
}
#[test]
fn overflow_and_invalid_updates_leave_the_old_root_unchanged() {
let huge = Entry::new(
Arc::new("x".to_owned()),
Measure::new(u64::MAX, 0, i64::MAX, i64::MAX).unwrap(),
)
.unwrap();
let one = Entry::new(Arc::new("y".to_owned()), Measure::new(1, 0, 1, 1).unwrap()).unwrap();
let mut work = Work::default();
let base = Sequence::from_entries([huge], &mut work).unwrap();
let old_root = Arc::clone(base.root().unwrap());
let mut failed_work = Work::default();
assert!(matches!(
base.concat(
&Sequence::from_entries([one], &mut Work::default()).unwrap(),
&mut failed_work
),
Err(Error::Overflow)
));
assert!(Arc::ptr_eq(base.root().unwrap(), &old_root));
assert!(matches!(
base.replace(2, entry(2), &mut failed_work),
Err(Error::IndexOutOfBounds)
));
assert!(Measure::new(0, 0, -1, 0).is_err());
assert!(Arc::ptr_eq(base.root().unwrap(), &old_root));
}
}