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

difftreelog

refactor for loop-invariant compspecs, reanalyze overs in outer

ssovpxyoYaroslav Bolyukin2026-05-14parent: #da47272.patch.diff
in: master

1 file changed

modifiedcrates/jrsonnet-evaluator/src/analyze.rsdiffbeforeafterboth
1027 }1027 }
1028 }1028 }
1029
1030 /// Temporarily detach closure frames above `keep_len` so an expression
1031 /// can be re-analyzed as if it lived in the outer closure context.
1032 fn reanalyze_in_outer_closure<T>(
1033 &mut self,
1034 keep_len: usize,
1035 inner: impl FnOnce(&mut AnalysisStack) -> T,
1036 ) -> T {
1037 let saved: Vec<ClosureFrame> = self.closure_stack.split_off(keep_len);
1038 let diag_len = self.diagnostics.len();
1039 let prev_errored = self.errored;
1040 let v = inner(self);
1041 self.diagnostics.truncate(diag_len);
1042 self.errored = prev_errored;
1043 self.closure_stack.extend(saved);
1044 v
1045 }
10291046
1030 /// Resolve a `LocalId` reference to an `LSlot` against the innermost1047 /// Resolve a `LocalId` reference to an `LSlot` against the innermost
1031 /// closure frame. May insert capture entries up the closure stack as1048 /// closure frame. May insert capture entries up the closure stack as
1934 }))1951 }))
1935}1952}
19361953
1954#[allow(clippy::too_many_lines)]
1937fn analyze_comp_specs<R>(1955fn analyze_comp_specs<R>(
1938 specs: &[CompSpec],1956 specs: &[CompSpec],
1939 stack: &mut AnalysisStack,1957 stack: &mut AnalysisStack,
1940 taint: &mut AnalysisResult,1958 taint: &mut AnalysisResult,
1941 inside: impl FnOnce(&mut AnalysisStack, &mut AnalysisResult) -> R,1959 inside: impl FnOnce(&mut AnalysisStack, &mut AnalysisResult) -> R,
1942) -> CompSpecResult<R> {1960) -> CompSpecResult<R> {
1961 #[allow(clippy::too_many_lines)]
1943 fn go<R>(1962 fn go<R>(
1944 idx: usize,1963 idx: usize,
1945 specs: &[CompSpec],1964 specs: &[CompSpec],
1946 outer_depth: u32,1965 outer_depth: u32,
1966 outer_closure_depth: usize,
1947 stack: &mut AnalysisStack,1967 stack: &mut AnalysisStack,
1948 taint: &mut AnalysisResult,1968 taint: &mut AnalysisResult,
1949 inside: impl FnOnce(&mut AnalysisStack, &mut AnalysisResult) -> R,1969 inside: impl FnOnce(&mut AnalysisStack, &mut AnalysisResult) -> R,
1978 idx + 1,
1979 specs,
1980 outer_depth,
1981 outer_closure_depth,
1982 stack,
1983 taint,
1984 inside,
1985 );
1958 rest.insert(0, LCompSpec::If(cond_l));1986 rest.insert(0, LCompSpec::If(cond_l));
1959 (r, rest)1987 (r, rest)
1960 }1988 }
1961 CompSpec::ForSpec(ForSpecData { destruct, over }) => {1989 CompSpec::ForSpec(ForSpecData { destruct, over }) => {
1962 let mut over_taint = AnalysisResult::default();1990 let mut over_taint = AnalysisResult::default();
1963 let over_l = analyze(over, stack, &mut over_taint);1991 let mut over_l = analyze(over, stack, &mut over_taint);
1964 let loop_invariant = !over_taint.has_local_deps()1992 let loop_invariant = !over_taint.has_local_deps()
1965 || over_taint.local_dependent_depth_max < outer_depth;1993 || over_taint.local_dependent_depth_max < outer_depth;
1966 taint.taint_by(over_taint);1994 taint.taint_by(over_taint);
1995
1996 if loop_invariant && stack.closure_stack.len() > outer_closure_depth {
1997 over_l = stack.reanalyze_in_outer_closure(outer_closure_depth, |stack| {
1998 let mut t = AnalysisResult::default();
1999 analyze(over, stack, &mut t)
2000 });
2001 }
19672002
1968 let mut alloc = FrameAlloc::new(stack);2003 let mut alloc = FrameAlloc::new(stack);
1969 let closure = alloc.push_locals_closure();2004 let closure = alloc.push_locals_closure();
1970 let Some(l_destruct) = alloc.alloc_destruct(destruct) else {2005 let Some(l_destruct) = alloc.alloc_destruct(destruct) else {
1971 stack.pop_closure(closure);2006 stack.pop_closure(closure);
1972 return go(idx + 1, specs, outer_depth, stack, taint, inside);2007 return go(
2008 idx + 1,
2009 specs,
2010 outer_depth,
2011 outer_closure_depth,
2012 stack,
2013 taint,
2014 inside,
2015 );
1973 };2016 };
1974 let mut pending = alloc.finish();2017 let mut pending = alloc.finish();
1982 go(idx + 1, specs, outer_depth, body_frame.stack, taint, inside);2025 idx + 1,
2026 specs,
2027 outer_depth,
2028 outer_closure_depth,
2029 body_frame.stack,
2030 taint,
2031 inside,
2032 );
1983 body_frame.finish();2033 body_frame.finish();
1984 let frame_shape = stack.pop_closure(closure);2034 let frame_shape = stack.pop_closure(closure);
1997 #[cfg(feature = "exp-object-iteration")]2047 #[cfg(feature = "exp-object-iteration")]
1998 CompSpec::ForObjSpec(data) => {2048 CompSpec::ForObjSpec(data) => {
1999 let mut over_taint = AnalysisResult::default();2049 let mut over_taint = AnalysisResult::default();
2000 let over_l = analyze(&data.over, stack, &mut over_taint);2050 let mut over_l = analyze(&data.over, stack, &mut over_taint);
2001 let loop_invariant = !over_taint.has_local_deps()2051 let loop_invariant = !over_taint.has_local_deps()
2002 || over_taint.local_dependent_depth_max < outer_depth;2052 || over_taint.local_dependent_depth_max < outer_depth;
2003 taint.taint_by(over_taint);2053 taint.taint_by(over_taint);
2054
2055 if loop_invariant && stack.closure_stack.len() > outer_closure_depth {
2056 over_l = stack.reanalyze_in_outer_closure(outer_closure_depth, |stack| {
2057 let mut t = AnalysisResult::default();
2058 analyze(&data.over, stack, &mut t)
2059 });
2060 }
20042061
2005 let mut alloc = FrameAlloc::new(stack);2062 let mut alloc = FrameAlloc::new(stack);
2006 let closure = alloc.push_locals_closure();2063 let closure = alloc.push_locals_closure();
2007 let Some((_, key_slot)) = alloc.define_local(data.key.clone(), None) else {2064 let Some((_, key_slot)) = alloc.define_local(data.key.clone(), None) else {
2008 stack.pop_closure(closure);2065 stack.pop_closure(closure);
2009 return go(idx + 1, specs, outer_depth, stack, taint, inside);2066 return go(
2067 idx + 1,
2068 specs,
2069 outer_depth,
2070 outer_closure_depth,
2071 stack,
2072 taint,
2073 inside,
2074 );
2010 };2075 };
2011 let Some(l_value) = alloc.alloc_destruct(&data.value) else {2076 let Some(l_value) = alloc.alloc_destruct(&data.value) else {
2012 stack.pop_closure(closure);2077 stack.pop_closure(closure);
2013 return go(idx + 1, specs, outer_depth, stack, taint, inside);2078 return go(
2079 idx + 1,
2080 specs,
2081 outer_depth,
2082 outer_closure_depth,
2083 stack,
2084 taint,
2085 inside,
2086 );
2014 };2087 };
2015 let mut pending = alloc.finish();2088 let mut pending = alloc.finish();
2024 go(idx + 1, specs, outer_depth, body_frame.stack, taint, inside);2097 idx + 1,
2098 specs,
2099 outer_depth,
2100 outer_closure_depth,
2101 body_frame.stack,
2102 taint,
2103 inside,
2104 );
2025 body_frame.finish();2105 body_frame.finish();
2026 let frame_shape = stack.pop_closure(closure);2106 let frame_shape = stack.pop_closure(closure);
2041 }2121 }
2042 }2122 }
2043 let outer_depth = stack.depth;2123 let outer_depth = stack.depth;
2124 let outer_closure_depth = stack.closure_stack.len();
2044 let (r, compspecs) = go(0, specs, outer_depth, stack, taint, inside);2125 let (r, compspecs) = go(
2126 0,
2127 specs,
2128 outer_depth,
2129 outer_closure_depth,
2130 stack,
2131 taint,
2132 inside,
2133 );
2045 CompSpecResult {2134 CompSpecResult {
2046 inner: r,2135 inner: r,