git.delta.rocks / jrsonnet / refs/commits / e4a890bf0c31

difftreelog

perf mutate context if operating on only strong ref

Лач2020-07-21parent: #84f648e.patch.diff
in: master

4 files changed

modifiedcrates/jrsonnet-evaluator/src/ctx.rsdiffbeforeafterboth
75 ctx.unwrap()75 ctx.unwrap()
76 }76 }
7777
78 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 }
8383
84 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 cloning
94 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))
modifiedcrates/jrsonnet-evaluator/src/evaluate.rsdiffbeforeafterboth
209 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 ));
360360
modifiedcrates/jrsonnet-evaluator/src/function.rsdiffbeforeafterboth
57 out.insert(p.0.clone(), val);57 out.insert(p.0.clone(), val);
58 }58 }
5959
60 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}
6262
63pub 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 }
108108
109 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}
111111
112pub(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 }
137137
138 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}
140140
141#[macro_export]141#[macro_export]
modifiedcrates/jrsonnet-evaluator/src/map.rsdiffbeforeafterboth
10pub struct LayeredHashMap<K: Hash, V>(Rc<LayeredHashMapInternals<K, V>>);10pub struct LayeredHashMap<K: Hash, V>(Rc<LayeredHashMapInternals<K, V>>);
1111
12impl<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 }
2025
21 pub fn get<Q: ?Sized>(&self, key: &Q) -> Option<&V>26 pub fn get<Q: ?Sized>(&self, key: &Q) -> Option<&V>