difftreelog
perf mutate context if operating on only strong ref
in: master
4 files changed
crates/jrsonnet-evaluator/src/ctx.rsdiffbeforeafterboth75 ctx.unwrap()75 ctx.unwrap()76 }76 }777778 pub fn with_var(&self, name: Rc<str>, value: Val) -> Result<Context> {78 pub fn with_var(self, name: Rc<str>, value: Val) -> Context {79 let mut new_bindings = HashMap::with_capacity(1);79 let mut new_bindings = HashMap::with_capacity(1);80 new_bindings.insert(name, resolved_lazy_val!(value));80 new_bindings.insert(name, resolved_lazy_val!(value));81 self.extend(new_bindings, None, None, None)81 self.extend(new_bindings, None, None, None)82 }82 }838384 pub fn extend(84 pub fn extend(85 &self,85 self,86 new_bindings: HashMap<Rc<str>, LazyVal>,86 new_bindings: HashMap<Rc<str>, LazyVal>,87 new_dollar: Option<ObjValue>,87 new_dollar: Option<ObjValue>,88 new_this: Option<ObjValue>,88 new_this: Option<ObjValue>,89 new_super_obj: Option<ObjValue>,89 new_super_obj: Option<ObjValue>,90 ) -> Result<Context> {90 ) -> Context {91 match Rc::try_unwrap(self.0) {92 Ok(mut ctx) => {93 // Extended context aren't used by anything else, we can freely mutate it without cloning94 if let Some(dollar) = new_dollar {95 ctx.dollar = Some(dollar);96 }97 if let Some(this) = new_this {98 ctx.this = Some(this);99 }100 if let Some(super_obj) = new_super_obj {101 ctx.super_obj = Some(super_obj);102 }103 if !new_bindings.is_empty() {104 ctx.bindings = ctx.bindings.extend(new_bindings);105 }106 Context(Rc::new(ctx))107 }108 Err(ctx) => {91 let dollar = new_dollar.or_else(|| self.0.dollar.clone());109 let dollar = new_dollar.or_else(|| ctx.dollar.clone());92 let this = new_this.or_else(|| self.0.this.clone());110 let this = new_this.or_else(|| ctx.this.clone());93 let super_obj = new_super_obj.or_else(|| self.0.super_obj.clone());111 let super_obj = new_super_obj.or_else(|| ctx.super_obj.clone());94 let bindings = if new_bindings.is_empty() {112 let bindings = if new_bindings.is_empty() {95 self.0.bindings.clone()113 ctx.bindings.clone()96 } else {114 } else {97 self.0.bindings.extend(new_bindings)115 ctx.bindings.clone().extend(new_bindings)98 };116 };99 Ok(Context(Rc::new(ContextInternals {117 Context(Rc::new(ContextInternals {100 dollar,118 dollar,101 this,119 this,102 super_obj,120 super_obj,103 bindings,121 bindings,104 })))122 }))105 }123 }124 }125 }106 pub fn extend_unbound(126 pub fn extend_unbound(107 &self,127 self,108 new_bindings: HashMap<Rc<str>, LazyBinding>,128 new_bindings: HashMap<Rc<str>, LazyBinding>,109 new_dollar: Option<ObjValue>,129 new_dollar: Option<ObjValue>,110 new_this: Option<ObjValue>,130 new_this: Option<ObjValue>,116 for (k, v) in new_bindings.into_iter() {136 for (k, v) in new_bindings.into_iter() {117 new.insert(k, v.evaluate(this.clone(), super_obj.clone())?);137 new.insert(k, v.evaluate(this.clone(), super_obj.clone())?);118 }138 }119 self.extend(new, new_dollar, this, super_obj)139 Ok(self.extend(new, new_dollar, this, super_obj))120 }140 }121 pub fn into_weak(self) -> WeakContext {141 pub fn into_weak(self) -> WeakContext {122 WeakContext(Rc::downgrade(&self.0))142 WeakContext(Rc::downgrade(&self.0))crates/jrsonnet-evaluator/src/evaluate.rsdiffbeforeafterboth209 for item in list.iter() {209 for item in list.iter() {210 let item = item.unwrap_if_lazy()?;210 let item = item.unwrap_if_lazy()?;211 out.push(evaluate_comp(211 out.push(evaluate_comp(212 context.with_var(var.clone(), item.clone())?,212 context.clone().with_var(var.clone(), item.clone()),213 value,213 value,214 &specs[1..],214 &specs[1..],215 )?);215 )?);227 let future_this = FutureObjValue::new();227 let future_this = FutureObjValue::new();228 let context_creator = context_creator!(228 let context_creator = context_creator!(229 closure!(clone context, clone new_bindings, |this: Option<ObjValue>, super_obj: Option<ObjValue>| {229 closure!(clone context, clone new_bindings, |this: Option<ObjValue>, super_obj: Option<ObjValue>| {230 Ok(context.extend_unbound(230 Ok(context.clone().extend_unbound(231 new_bindings.clone().unwrap(),231 new_bindings.clone().unwrap(),232 context.dollar().clone().or_else(||this.clone()),232 context.dollar().clone().or_else(||this.clone()),233 Some(this.unwrap()),233 Some(this.unwrap()),332 let new_bindings = FutureNewBindings::new();332 let new_bindings = FutureNewBindings::new();333 let context_creator = context_creator!(333 let context_creator = context_creator!(334 closure!(clone context, clone new_bindings, |this: Option<ObjValue>, super_obj: Option<ObjValue>| {334 closure!(clone context, clone new_bindings, |this: Option<ObjValue>, super_obj: Option<ObjValue>| {335 Ok(context.extend_unbound(335 Ok(context.clone().extend_unbound(336 new_bindings.clone().unwrap(),336 new_bindings.clone().unwrap(),337 context.dollar().clone().or_else(||this.clone()),337 context.dollar().clone().or_else(||this.clone()),338 None,338 None,354 let key = evaluate(ctx.clone(), &obj.key)?;354 let key = evaluate(ctx.clone(), &obj.key)?;355 let value = LazyBinding::Bindable(Rc::new(355 let value = LazyBinding::Bindable(Rc::new(356 closure!(clone ctx, clone obj.value, |this, _super_obj| {356 closure!(clone ctx, clone obj.value, |this, _super_obj| {357 Ok(LazyVal::new_resolved(evaluate(ctx.extend(HashMap::new(), None, this, None)?, &value)?))357 Ok(LazyVal::new_resolved(evaluate(ctx.clone().extend(HashMap::new(), None, this, None), &value)?))358 }),358 }),359 ));359 ));360360crates/jrsonnet-evaluator/src/function.rsdiffbeforeafterboth57 out.insert(p.0.clone(), val);57 out.insert(p.0.clone(), val);58 }58 }595960 Ok(body_ctx.unwrap_or(ctx).extend(out, None, None, None)?)60 Ok(body_ctx.unwrap_or(ctx).extend(out, None, None, None))61}61}626263pub fn parse_function_call_map(63pub fn parse_function_call_map(106 out.insert(p.0.clone(), val);106 out.insert(p.0.clone(), val);107 }107 }108108109 Ok(body_ctx.unwrap_or(ctx).extend(out, None, None, None)?)109 Ok(body_ctx.unwrap_or(ctx).extend(out, None, None, None))110}110}111111112pub(crate) fn place_args(112pub(crate) fn place_args(135 out.insert(p.0.clone(), resolved_lazy_val!(val));135 out.insert(p.0.clone(), resolved_lazy_val!(val));136 }136 }137137138 Ok(body_ctx.unwrap_or(ctx).extend(out, None, None, None)?)138 Ok(body_ctx.unwrap_or(ctx).extend(out, None, None, None))139}139}140140141#[macro_export]141#[macro_export]crates/jrsonnet-evaluator/src/map.rsdiffbeforeafterboth10pub struct LayeredHashMap<K: Hash, V>(Rc<LayeredHashMapInternals<K, V>>);10pub struct LayeredHashMap<K: Hash, V>(Rc<LayeredHashMapInternals<K, V>>);111112impl<K: Hash + Eq, V> LayeredHashMap<K, V> {12impl<K: Hash + Eq, V> LayeredHashMap<K, V> {13 pub fn extend(&self, new_layer: HashMap<K, V>) -> Self {13 pub fn extend(self, new_layer: HashMap<K, V>) -> Self {14 let super_map = self.clone();14 match Rc::try_unwrap(self.0) {15 Ok(mut map) => {16 map.current.extend(new_layer);17 LayeredHashMap(Rc::new(map))18 }15 LayeredHashMap(Rc::new(LayeredHashMapInternals {19 Err(this) => LayeredHashMap(Rc::new(LayeredHashMapInternals {16 parent: Some(super_map),20 parent: Some(LayeredHashMap(this)),17 current: new_layer,21 current: new_layer,18 }))22 })),23 }19 }24 }202521 pub fn get<Q: ?Sized>(&self, key: &Q) -> Option<&V>26 pub fn get<Q: ?Sized>(&self, key: &Q) -> Option<&V>