difftreelog
perf use weak objvalue as cache key
in: master
4 files changed
crates/jrsonnet-evaluator/Cargo.tomldiffbeforeafterboth1[package]2name = "jrsonnet-evaluator"3description = "jsonnet interpreter"4version = "0.4.2"5authors = ["Yaroslav Bolyukin <iam@lach.pw>"]6license = "MIT"7edition = "2021"89[features]10default = ["serialized-stdlib", "explaining-traces"]11# Serializes standard library AST instead of parsing them every run12serialized-stdlib = ["bincode", "jrsonnet-parser/deserialize"]13# Rustc-like trace visualization14explaining-traces = ["annotate-snippets"]15# Allows library authors to throw custom errors16anyhow-error = ["anyhow"]1718# Unlocks extra features, but works only on unstable19unstable = []2021[dependencies]22jrsonnet-interner = { path = "../jrsonnet-interner", version = "0.4.2" }23jrsonnet-parser = { path = "../jrsonnet-parser", version = "0.4.2" }24jrsonnet-stdlib = { path = "../jrsonnet-stdlib", version = "0.4.2" }25jrsonnet-types = { path = "../jrsonnet-types", version = "0.4.2" }26jrsonnet-macros = { path = "../jrsonnet-macros", version = "0.4.2" }27pathdiff = "0.2.0"2829md5 = "0.7.0"30base64 = "0.13.0"31rustc-hash = "1.1.0"3233thiserror = "1.0"34gcmodule = { git = "https://github.com/CertainLach/gcmodule", branch = "jrsonnet" }3536serde = "1.0"37serde_json = "1.0"38serde_yaml = { git = "https://github.com/CertainLach/serde-yaml", branch = "feature/old-octals-quirk" }3940[dependencies.anyhow]41version = "1.0"42optional = true4344# Serialized stdlib45[dependencies.bincode]46version = "1.3.1"47optional = true4849# Explaining traces50[dependencies.annotate-snippets]51version = "0.9.1"52features = ["color"]53optional = true5455[build-dependencies]56jrsonnet-parser = { path = "../jrsonnet-parser", features = [57 "serialize",58 "deserialize",59], version = "0.4.2" }60jrsonnet-stdlib = { path = "../jrsonnet-stdlib", version = "0.4.2" }61serde = "1.0"62bincode = "1.3.1"1[package]2name = "jrsonnet-evaluator"3description = "jsonnet interpreter"4version = "0.4.2"5authors = ["Yaroslav Bolyukin <iam@lach.pw>"]6license = "MIT"7edition = "2021"89[features]10default = ["serialized-stdlib", "explaining-traces"]11# Serializes standard library AST instead of parsing them every run12serialized-stdlib = ["bincode", "jrsonnet-parser/deserialize"]13# Rustc-like trace visualization14explaining-traces = ["annotate-snippets"]15# Allows library authors to throw custom errors16anyhow-error = ["anyhow"]1718[dependencies]19jrsonnet-interner = { path = "../jrsonnet-interner", version = "0.4.2" }20jrsonnet-parser = { path = "../jrsonnet-parser", version = "0.4.2" }21jrsonnet-stdlib = { path = "../jrsonnet-stdlib", version = "0.4.2" }22jrsonnet-types = { path = "../jrsonnet-types", version = "0.4.2" }23jrsonnet-macros = { path = "../jrsonnet-macros", version = "0.4.2" }24pathdiff = "0.2.0"2526md5 = "0.7.0"27base64 = "0.13.0"28rustc-hash = "1.1.0"2930thiserror = "1.0"31gcmodule = { git = "https://github.com/CertainLach/gcmodule", branch = "jrsonnet" }3233serde = "1.0"34serde_json = "1.0"35serde_yaml = { git = "https://github.com/CertainLach/serde-yaml", branch = "feature/old-octals-quirk" }3637[dependencies.anyhow]38version = "1.0"39optional = true4041# Serialized stdlib42[dependencies.bincode]43version = "1.3.1"44optional = true4546# Explaining traces47[dependencies.annotate-snippets]48version = "0.9.1"49features = ["color"]50optional = true5152[build-dependencies]53jrsonnet-parser = { path = "../jrsonnet-parser", features = [54 "serialize",55 "deserialize",56], version = "0.4.2" }57jrsonnet-stdlib = { path = "../jrsonnet-stdlib", version = "0.4.2" }58serde = "1.0"59bincode = "1.3.1"crates/jrsonnet-evaluator/src/ctx.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/ctx.rs
+++ b/crates/jrsonnet-evaluator/src/ctx.rs
@@ -133,10 +133,6 @@
}
Ok(self.extend(new, new_dollar, this, super_obj))
}
- #[cfg(feature = "unstable")]
- pub fn into_weak(self) -> WeakContext {
- WeakContext(Rc::downgrade(&self.0))
- }
}
impl Default for Context {
crates/jrsonnet-evaluator/src/lib.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/lib.rs
+++ b/crates/jrsonnet-evaluator/src/lib.rs
@@ -1,4 +1,3 @@
-#![cfg_attr(feature = "unstable", feature(stmt_expr_attributes))]
#![warn(clippy::all, clippy::nursery)]
#![allow(
macro_expanded_macro_exports_accessed_by_absolute_paths,
@@ -31,7 +30,7 @@
pub use evaluate::*;
use function::{Builtin, TlaArg};
use gc::{GcHashMap, TraceBox};
-use gcmodule::{Cc, Trace};
+use gcmodule::{Cc, Trace, Weak};
pub use import::*;
pub use jrsonnet_interner::IStr;
use jrsonnet_parser::*;
@@ -653,6 +652,28 @@
std::ptr::eq(a, b)
}
+fn weak_raw<T>(a: Weak<T>) -> *const () {
+ unsafe { std::mem::transmute(a) }
+}
+fn weak_ptr_eq<T>(a: Weak<T>, b: Weak<T>) -> bool {
+ std::ptr::eq(weak_raw(a), weak_raw(b))
+}
+
+#[test]
+fn weak_unsafe() {
+ let a = Cc::new(1);
+ let b = Cc::new(2);
+
+ let aw1 = a.clone().downgrade();
+ let aw2 = a.clone().downgrade();
+ let aw3 = a.clone().downgrade();
+
+ let bw = b.clone().downgrade();
+
+ assert!(weak_ptr_eq(aw1, aw2));
+ assert!(!weak_ptr_eq(aw3, bw));
+}
+
#[cfg(test)]
pub mod tests {
use super::Val;
crates/jrsonnet-evaluator/src/obj.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/obj.rs
+++ b/crates/jrsonnet-evaluator/src/obj.rs
@@ -1,7 +1,7 @@
use crate::gc::{GcHashMap, GcHashSet, TraceBox};
use crate::operator::evaluate_add_op;
-use crate::{cc_ptr_eq, Bindable, LazyBinding, LazyVal, Result, Val};
-use gcmodule::{Cc, Trace};
+use crate::{cc_ptr_eq, weak_ptr_eq, weak_raw, Bindable, LazyBinding, LazyVal, Result, Val};
+use gcmodule::{Cc, Trace, Weak};
use jrsonnet_interner::IStr;
use jrsonnet_parser::{ExprLocation, Visibility};
use rustc_hash::FxHashMap;
@@ -22,7 +22,7 @@
}
// Field => This
-type CacheKey = (IStr, ObjValue);
+type CacheKey = (IStr, WeakObjValue);
#[derive(Trace)]
#[force_tracking]
pub struct ObjValueInternals {
@@ -35,6 +35,22 @@
}
#[derive(Clone, Trace)]
+pub struct WeakObjValue(#[skip_trace] pub(crate) Weak<ObjValueInternals>);
+
+impl PartialEq for WeakObjValue {
+ fn eq(&self, other: &Self) -> bool {
+ weak_ptr_eq(self.0.clone(), other.0.clone())
+ }
+}
+
+impl Eq for WeakObjValue {}
+impl Hash for WeakObjValue {
+ fn hash<H: Hasher>(&self, hasher: &mut H) {
+ hasher.write_usize(weak_raw(self.0.clone()) as usize)
+ }
+}
+
+#[derive(Clone, Trace)]
pub struct ObjValue(pub(crate) Cc<ObjValueInternals>);
impl Debug for ObjValue {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
@@ -50,14 +66,7 @@
for (name, member) in self.0.this_entries.iter() {
debug.field(name, member);
}
- #[cfg(feature = "unstable")]
- {
- debug.finish_non_exhaustive()
- }
- #[cfg(not(feature = "unstable"))]
- {
- debug.finish()
- }
+ debug.finish_non_exhaustive()
}
}
@@ -217,7 +226,7 @@
fn get_raw(&self, key: IStr, real_this: Option<&Self>) -> Result<Option<Val>> {
let real_this = real_this.unwrap_or(self);
- let cache_key = (key.clone(), real_this.clone());
+ let cache_key = (key.clone(), WeakObjValue(real_this.0.downgrade()));
if let Some(v) = self.0.value_cache.borrow().get(&cache_key) {
return Ok(v.clone());