diff --git a/src/bytecode.rs b/src/bytecode.rs index 6ee9227..90b45db 100644 --- a/src/bytecode.rs +++ b/src/bytecode.rs @@ -38,7 +38,7 @@ pub enum OpCode { JmpIfFalse { step: usize }, /// push an empty attribute set onto stack - AttrSet, + AttrSet { cap: usize }, /// finalize the recursive attribute set at TOS FinalizeRec, /// [ .. set value ] consume 1 element, push a static kv pair (`name`, `value`) into `set` diff --git a/src/compile.rs b/src/compile.rs index 1000701..5b41b0f 100644 --- a/src/compile.rs +++ b/src/compile.rs @@ -97,7 +97,7 @@ impl Compile for ir::Thunk { impl Compile for ir::Attrs { fn compile(self, comp: &mut Compiler) { - comp.push(OpCode::AttrSet); + comp.push(OpCode::AttrSet { cap: self.stcs.len() + self.dyns.len() }); for stc in self.stcs { stc.1.compile(comp); if !self.rec { @@ -250,17 +250,17 @@ impl Compile for ir::HasAttr { for attr in self.rhs { match attr { ir::Attr::Str(sym) => { - comp.push(OpCode::AttrSet); + comp.push(OpCode::AttrSet { cap: 0 }); comp.push(OpCode::SelectOrDefault { sym }) } ir::Attr::Dynamic(dynamic) => { dynamic.compile(comp); - comp.push(OpCode::AttrSet); + comp.push(OpCode::AttrSet { cap: 0 }); comp.push(OpCode::SelectDynamicOrDefault); } ir::Attr::Strs(string) => { string.compile(comp); - comp.push(OpCode::AttrSet); + comp.push(OpCode::AttrSet { cap: 0 }); comp.push(OpCode::SelectDynamicOrDefault); } } @@ -281,17 +281,17 @@ impl Compile for ir::Select { for attr in self.attrpath { match attr { ir::Attr::Str(sym) => { - comp.push(OpCode::AttrSet); + comp.push(OpCode::AttrSet { cap: 0 }); comp.push(OpCode::SelectOrDefault { sym }) } ir::Attr::Dynamic(dynamic) => { dynamic.compile(comp); - comp.push(OpCode::AttrSet); + comp.push(OpCode::AttrSet { cap: 0 }); comp.push(OpCode::SelectDynamicOrDefault); } ir::Attr::Strs(string) => { string.compile(comp); - comp.push(OpCode::AttrSet); + comp.push(OpCode::AttrSet { cap: 0 }); comp.push(OpCode::SelectDynamicOrDefault); } } diff --git a/src/ty/internal/attrset.rs b/src/ty/internal/attrset.rs index 498f546..dca7d84 100644 --- a/src/ty/internal/attrset.rs +++ b/src/ty/internal/attrset.rs @@ -1,3 +1,5 @@ +use std::hash::Hash; + use hashbrown::{HashMap, HashSet}; use derive_more::Constructor; @@ -22,6 +24,10 @@ impl<'vm> AttrSet<'vm> { } } + pub fn with_capacity(cap: usize) -> Self { + AttrSet { data: HashMap::with_capacity(cap) } + } + pub fn push_attr_force(&mut self, sym: usize, val: Value<'vm>) { self.data.insert(sym, val); } diff --git a/src/vm/mod.rs b/src/vm/mod.rs index a18e2c8..70c8bfb 100644 --- a/src/vm/mod.rs +++ b/src/vm/mod.rs @@ -182,8 +182,8 @@ impl<'vm, 'jit: 'vm> VM<'jit> { let elem = stack.pop(); stack.tos_mut()?.push(elem); } - OpCode::AttrSet => { - stack.push(Value::AttrSet(AttrSet::empty().into()))?; + OpCode::AttrSet { cap } => { + stack.push(Value::AttrSet(AttrSet::with_capacity(cap).into()))?; } OpCode::FinalizeRec => { let env = env.clone().enter(