difftreelog
refactor for loop-invariant compspecs, reanalyze overs in outer
in: master
1 file changed
crates/jrsonnet-evaluator/src/analyze.rsdiffbeforeafterboth1027 }1027 }1028 }1028 }10291030 /// Temporarily detach closure frames above `keep_len` so an expression1031 /// 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 v1045 }102910461030 /// Resolve a `LocalId` reference to an `LSlot` against the innermost1047 /// Resolve a `LocalId` reference to an `LSlot` against the innermost1031 /// closure frame. May insert capture entries up the closure stack as1048 /// closure frame. May insert capture entries up the closure stack as1934 }))1951 }))1935}1952}193619531954#[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);19951996 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 }196720021968 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);20542055 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 }200420612005 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,