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.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/evaluate.rs
+++ b/crates/jrsonnet-evaluator/src/evaluate.rs
@@ -209,7 +209,7 @@
for item in list.iter() {
let item = item.unwrap_if_lazy()?;
out.push(evaluate_comp(
- context.with_var(var.clone(), item.clone())?,
+ context.clone().with_var(var.clone(), item.clone()),
value,
&specs[1..],
)?);
@@ -227,7 +227,7 @@
let future_this = FutureObjValue::new();
let context_creator = context_creator!(
closure!(clone context, clone new_bindings, |this: Option<ObjValue>, super_obj: Option<ObjValue>| {
- Ok(context.extend_unbound(
+ Ok(context.clone().extend_unbound(
new_bindings.clone().unwrap(),
context.dollar().clone().or_else(||this.clone()),
Some(this.unwrap()),
@@ -332,7 +332,7 @@
let new_bindings = FutureNewBindings::new();
let context_creator = context_creator!(
closure!(clone context, clone new_bindings, |this: Option<ObjValue>, super_obj: Option<ObjValue>| {
- Ok(context.extend_unbound(
+ Ok(context.clone().extend_unbound(
new_bindings.clone().unwrap(),
context.dollar().clone().or_else(||this.clone()),
None,
@@ -354,7 +354,7 @@
let key = evaluate(ctx.clone(), &obj.key)?;
let value = LazyBinding::Bindable(Rc::new(
closure!(clone ctx, clone obj.value, |this, _super_obj| {
- Ok(LazyVal::new_resolved(evaluate(ctx.extend(HashMap::new(), None, this, None)?, &value)?))
+ Ok(LazyVal::new_resolved(evaluate(ctx.clone().extend(HashMap::new(), None, this, None), &value)?))
}),
));
crates/jrsonnet-evaluator/src/function.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/function.rs
+++ b/crates/jrsonnet-evaluator/src/function.rs
@@ -57,7 +57,7 @@
out.insert(p.0.clone(), val);
}
- Ok(body_ctx.unwrap_or(ctx).extend(out, None, None, None)?)
+ Ok(body_ctx.unwrap_or(ctx).extend(out, None, None, None))
}
pub fn parse_function_call_map(
@@ -106,7 +106,7 @@
out.insert(p.0.clone(), val);
}
- Ok(body_ctx.unwrap_or(ctx).extend(out, None, None, None)?)
+ Ok(body_ctx.unwrap_or(ctx).extend(out, None, None, None))
}
pub(crate) fn place_args(
@@ -135,7 +135,7 @@
out.insert(p.0.clone(), resolved_lazy_val!(val));
}
- Ok(body_ctx.unwrap_or(ctx).extend(out, None, None, None)?)
+ Ok(body_ctx.unwrap_or(ctx).extend(out, None, None, None))
}
#[macro_export]
crates/jrsonnet-evaluator/src/map.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/map.rs
+++ b/crates/jrsonnet-evaluator/src/map.rs
@@ -10,12 +10,17 @@
pub struct LayeredHashMap<K: Hash, V>(Rc<LayeredHashMapInternals<K, V>>);
impl<K: Hash + Eq, V> LayeredHashMap<K, V> {
- pub fn extend(&self, new_layer: HashMap<K, V>) -> Self {
- let super_map = self.clone();
- LayeredHashMap(Rc::new(LayeredHashMapInternals {
- parent: Some(super_map),
- current: new_layer,
- }))
+ pub fn extend(self, new_layer: HashMap<K, V>) -> Self {
+ match Rc::try_unwrap(self.0) {
+ Ok(mut map) => {
+ map.current.extend(new_layer);
+ LayeredHashMap(Rc::new(map))
+ }
+ Err(this) => LayeredHashMap(Rc::new(LayeredHashMapInternals {
+ parent: Some(LayeredHashMap(this)),
+ current: new_layer,
+ })),
+ }
}
pub fn get<Q: ?Sized>(&self, key: &Q) -> Option<&V>