Use Arc for environment variables on the stack

This commit is contained in:
Devyn Cairns 2024-07-10 01:44:43 -07:00
parent 0178295363
commit 2758c325cf
3 changed files with 19 additions and 17 deletions

View File

@ -62,8 +62,8 @@ pub struct ClosureEval {
stack: Stack, stack: Stack,
block: Arc<Block>, block: Arc<Block>,
arg_index: usize, arg_index: usize,
env_vars: Vec<EnvVars>, env_vars: Vec<Arc<EnvVars>>,
env_hidden: HashMap<String, HashSet<String>>, env_hidden: Arc<HashMap<String, HashSet<String>>>,
eval: EvalBlockWithEarlyReturnFn, eval: EvalBlockWithEarlyReturnFn,
} }

View File

@ -304,7 +304,7 @@ impl EngineState {
let mut config_updated = false; let mut config_updated = false;
for mut scope in stack.env_vars.drain(..) { for mut scope in stack.env_vars.drain(..) {
for (overlay_name, mut env) in scope.drain() { for (overlay_name, mut env) in Arc::make_mut(&mut scope).drain() {
if let Some(env_vars) = Arc::make_mut(&mut self.env_vars).get_mut(&overlay_name) { if let Some(env_vars) = Arc::make_mut(&mut self.env_vars).get_mut(&overlay_name) {
// Updating existing overlay // Updating existing overlay
for (k, v) in env.drain() { for (k, v) in env.drain() {

View File

@ -36,9 +36,9 @@ pub struct Stack {
/// Variables /// Variables
pub vars: Vec<(VarId, Value)>, pub vars: Vec<(VarId, Value)>,
/// Environment variables arranged as a stack to be able to recover values from parent scopes /// Environment variables arranged as a stack to be able to recover values from parent scopes
pub env_vars: Vec<EnvVars>, pub env_vars: Vec<Arc<EnvVars>>,
/// Tells which environment variables from engine state are hidden, per overlay. /// Tells which environment variables from engine state are hidden, per overlay.
pub env_hidden: HashMap<String, HashSet<String>>, pub env_hidden: Arc<HashMap<String, HashSet<String>>>,
/// List of active overlays /// List of active overlays
pub active_overlays: Vec<String>, pub active_overlays: Vec<String>,
pub recursion_count: u64, pub recursion_count: u64,
@ -66,7 +66,7 @@ impl Stack {
Self { Self {
vars: Vec::new(), vars: Vec::new(),
env_vars: Vec::new(), env_vars: Vec::new(),
env_hidden: HashMap::new(), env_hidden: Arc::new(HashMap::new()),
active_overlays: vec![DEFAULT_OVERLAY_NAME.to_string()], active_overlays: vec![DEFAULT_OVERLAY_NAME.to_string()],
recursion_count: 0, recursion_count: 0,
parent_stack: None, parent_stack: None,
@ -119,8 +119,8 @@ impl Stack {
pub fn with_env( pub fn with_env(
&mut self, &mut self,
env_vars: &[EnvVars], env_vars: &[Arc<EnvVars>],
env_hidden: &HashMap<String, HashSet<String>>, env_hidden: &Arc<HashMap<String, HashSet<String>>>,
) { ) {
// Do not clone the environment if it hasn't changed // Do not clone the environment if it hasn't changed
if self.env_vars.iter().any(|scope| !scope.is_empty()) { if self.env_vars.iter().any(|scope| !scope.is_empty()) {
@ -207,23 +207,24 @@ impl Stack {
pub fn add_env_var(&mut self, var: String, value: Value) { pub fn add_env_var(&mut self, var: String, value: Value) {
if let Some(last_overlay) = self.active_overlays.last() { if let Some(last_overlay) = self.active_overlays.last() {
if let Some(env_hidden) = self.env_hidden.get_mut(last_overlay) { if let Some(env_hidden) = Arc::make_mut(&mut self.env_hidden).get_mut(last_overlay) {
// if the env var was hidden, let's activate it again // if the env var was hidden, let's activate it again
env_hidden.remove(&var); env_hidden.remove(&var);
} }
if let Some(scope) = self.env_vars.last_mut() { if let Some(scope) = self.env_vars.last_mut() {
let scope = Arc::make_mut(scope);
if let Some(env_vars) = scope.get_mut(last_overlay) { if let Some(env_vars) = scope.get_mut(last_overlay) {
env_vars.insert(var, value); env_vars.insert(var, value);
} else { } else {
scope.insert(last_overlay.into(), [(var, value)].into_iter().collect()); scope.insert(last_overlay.into(), [(var, value)].into_iter().collect());
} }
} else { } else {
self.env_vars.push( self.env_vars.push(Arc::new(
[(last_overlay.into(), [(var, value)].into_iter().collect())] [(last_overlay.into(), [(var, value)].into_iter().collect())]
.into_iter() .into_iter()
.collect(), .collect(),
); ));
} }
} else { } else {
// TODO: Remove panic // TODO: Remove panic
@ -245,9 +246,8 @@ impl Stack {
} }
pub fn captures_to_stack_preserve_out_dest(&self, captures: Vec<(VarId, Value)>) -> Stack { pub fn captures_to_stack_preserve_out_dest(&self, captures: Vec<(VarId, Value)>) -> Stack {
// FIXME: this is probably slow
let mut env_vars = self.env_vars.clone(); let mut env_vars = self.env_vars.clone();
env_vars.push(HashMap::new()); env_vars.push(Arc::new(HashMap::new()));
Stack { Stack {
vars: captures, vars: captures,
@ -277,7 +277,7 @@ impl Stack {
} }
let mut env_vars = self.env_vars.clone(); let mut env_vars = self.env_vars.clone();
env_vars.push(HashMap::new()); env_vars.push(Arc::new(HashMap::new()));
Stack { Stack {
vars, vars,
@ -444,6 +444,7 @@ impl Stack {
pub fn remove_env_var(&mut self, engine_state: &EngineState, name: &str) -> bool { pub fn remove_env_var(&mut self, engine_state: &EngineState, name: &str) -> bool {
for scope in self.env_vars.iter_mut().rev() { for scope in self.env_vars.iter_mut().rev() {
let scope = Arc::make_mut(scope);
for active_overlay in self.active_overlays.iter().rev() { for active_overlay in self.active_overlays.iter().rev() {
if let Some(env_vars) = scope.get_mut(active_overlay) { if let Some(env_vars) = scope.get_mut(active_overlay) {
if env_vars.remove(name).is_some() { if env_vars.remove(name).is_some() {
@ -456,10 +457,11 @@ impl Stack {
for active_overlay in self.active_overlays.iter().rev() { for active_overlay in self.active_overlays.iter().rev() {
if let Some(env_vars) = engine_state.env_vars.get(active_overlay) { if let Some(env_vars) = engine_state.env_vars.get(active_overlay) {
if env_vars.get(name).is_some() { if env_vars.get(name).is_some() {
if let Some(env_hidden) = self.env_hidden.get_mut(active_overlay) { let env_hidden = Arc::make_mut(&mut self.env_hidden);
env_hidden.insert(name.into()); if let Some(env_hidden_in_overlay) = env_hidden.get_mut(active_overlay) {
env_hidden_in_overlay.insert(name.into());
} else { } else {
self.env_hidden env_hidden
.insert(active_overlay.into(), [name.into()].into_iter().collect()); .insert(active_overlay.into(), [name.into()].into_iter().collect());
} }