Shape Analysis Termination Analysis Linear Time From to in Shape Analysis Termination Analysis Linear Time Roman Manevich Ben-Gurion University of the Negev Noam Rinetzky Tel Aviv University Boris Dogadov Tel Aviv University [Required math fonts available here]
UPGRADE YOUR SHAPE ANALYSIS START PROVING TOTAL CORRECTNESS TODAY FOR JUST 5% OF THE RUNNING TIME
Research problem Automatically verify termination of heap-manipulating programs Dynamic memory allocation Destructive updates Applications Systems codes, e.g., Windows device drivers containing linked data structures: lists, trees, etc. Object-oriented programs utilizing containers: sets, maps, and graphs
Scalability “dimensions” Shape complexity (complexity of heap invariants) PL features overlaid hierarchical numeric data containers concurrency recursive recursion Code size
Shape analysis-specific Termination undecidable Classic approach Naughty idea: Once shape analysis does the heavy lifting termination is easy Shape analysis-specific Heavyweight Heap-manipulating Program Instrumented Shape Analyzer Termination undecidable Safety property Integer Program [Berdine et al. CAV 2006] [Berdine et al. POPL 2007] [Magill et al. POPL 2010] TRS [AProVE Giesl et al. CAV 2012, RTA 2011, IJCAR 2014] Logic Program [Albert et al. FMOOBDS 2008] [Spoto et al. TOPLAS 2010] Always terminates Termination Analyzer May not terminate
Our solution Partition-based Shape Analyzer Termination Analyzer Termination checked in linear time Most shape analyses (Sep. Logic, TVLA, Boolean heaps, TRS) Abstract transition relation Heap-manipulating Program Partition-based Shape Analyzer Safety property Evolution relation Always terminates Termination Analyzer May not terminate Easy to implement Induced by shape analysis
Main results Termination analysis parametrized by partition-based shape analysis Enables handling wide range of shape invariants (both inductive data structures and unstructured graphs) Novel ranking function based on evolution relation Featherweight analysis Linear time modulo shape analysis Modular Handles recursion very precisely Limited support for concurrency Precise enough on a variety of benchmarks Shape complexity Code size PL features
Agenda Our recipe for proving termination Apply recipe for shape analysis Handling nested loops and recursion Experiments and conclusion
Reminder: general recipe for proving termination To show that a transition system (, ) does not contain infinite paths: Find well-founded ordering : (all descending chains finite) Show that every infinite path must contain an infinite -descending chain * * * * 1 i j k
Our recipe To show that a transition system (, ) does not contain infinite paths: Find well-founded ordering : that is monotone: ’ ’ Compute a (finite) abstract transition system (, ) 3. Find all decreasing transitions := {} for each ’ do if ’ then := (, ’) fi od // linear time 4. Check for cutting set if \ contains no cycles then answer true else answer “may not terminate” fi // linear time
Agenda Our recipe for proving termination Apply recipe for shape analysis Handling nested loops and recursion Experiments and conclusion
Partition-based shape analysis: symbolic heaps example 1 = ls(x, y) * ls(y, nil) x y nil Concrete heaps abstracted into heap descriptors that partition the set of concrete objects into a finite number of heap regions
Abstract transition relation A shape analysis results in a finite abstract transition relation 1 = ls(x, y) * ls(y, nil) x y nil y := y.n x y nil ls(x, y) ls(y, nil) * 2 =
Concrete evolution relation A consistent renaming of object identifiers x y nil y := y.n x y nil
Abstract evolution relation May/must edges express how objects change membership in regions 1 = ls(x, y) * ls(y, nil) x y nil y := y.n x y nil 2 = ls(x, y) * ls(y, nil)
Must evolution edges help deplete regions May/must edges express how objects change membership in regions 1 = ls(x, y) * ls(y, nil) x y nil y := y.n Region size decreases x y nil 2 = ls(x, y) * ls(y, nil)
Modeling dynamic allocation/deallocation 1 = ls(x, nil) * free Infinite region x … nil y := new x y … nil 2 = ls(x, nil) * yv * free
Defining a monotone WF for shape analysis Use evolution relation to define monotone WF relation for objects Use it to define monotone WF relation for heaps
Abstract evolution relation is a finite graph Nodes are region:descriptor pairs 1 = ls(x, y) * ls(y, nil) * free y := y.n 2 = ls(x, y) ls(y, nil) * * free
Abstract evolution relation to WF over regions Nodes are region:descriptor pairs Lemma: collapsing strongly-connected component yields WF relation (linear time) 1:ls(x, y) 1:ls(y, nil) free 2:ls(x, y) 2:ls(y, nil) free
Ranking objects Merged nodes = region ranks Assign each object its respective region ranks Suffix rank 1:ls(y, nil) free 2:ls(y, nil) Prefix rank Condensation graph 1:ls(x, y) 2:ls(x, y) x y P P S S S S nil P
Before y:=y.n Merged nodes = region ranks Assign each object its respective region ranks Lemma: monotone WF Suffix rank 1:ls(y, nil) free 2:ls(y, nil) Prefix rank 1:ls(x, y) 2:ls(x, y) x y P P S S S S nil P
After y:=y.n Merged nodes = region ranks Assign each object its respective region ranks Lemma: monotone WF Suffix rank 1:ls(y, nil) free 2:ls(y, nil) Prefix rank 1:ls(x, y) 2:ls(x, y) x y P P P S S S nil P
Monotone WF relation for heaps Order heaps by comparing the ranks of their objects points-wise Lemma: monotone WF (have to be careful with memory allocation) x y P P S S S S nil P = y := y.n = = = = = x y P P P S S S nil P
Agenda Our recipe for proving termination Apply recipe for shape analysis Handling nested loops and recursion Experiments and conclusion
Assume control-flow graphs are structured assume innil out := nil x := in N2 N3 if xnil return out N4 y := out N5 if ynil y.nnil y.d<x.d InsertionSort FindPos N6 y := y.n N7 if y=out then // replace list head out := new Node(out, x.d) else // insert element after y y.n := new Node(y.n, x.d) x := x.n
Handling nested loops Problem: proving termination for nested loops often requires lexicographic ranking functions Solution: summarize loops Simply compose relations across statements: precise Linear time Prove termination from inner loop up to outer loop Limited to structured programs Improved in ongoing work [Boris Dogadov, M.Sc. thesis]
Termination for recursive procedures Model call stack as linked list [Rinetzky & Sagiv, CC 2001] [Rival & Chang POPL 2011] Call modelled as allocation of stack object and insertion to call stack list Return modelled as removing from call stack For precision use predicates to capture shape patterns across calls Our algorithms can be applied without change Future work: extend to local interprocedural analysis based on heap cutpoints [Rinetzky et al. POPL 2005, SAS 2005]
Agenda Our recipe for proving termination Apply recipe for shape analysis Handling nested loops and recursion Experiments and conclusion
Required (manual) abstraction refinement Implementation Use TVLA as underlying shape analysis No need to refine abstraction (two exceptions) Overhead usually < 5% Required (manual) abstraction refinement
Thanks for listening Questions? Conclusion Upgrade almost any shape analysis to automatically prove termination Simple to implement Featherweight reasoning Linear time in output of shape analysis Usually 5% of overall running time Naturally supports recursion Some support for concurrency Improving with ongoing work Practically quite precise Thanks for listening Questions?
Suggested questions How easy it is to extend a shape analysis with an abstract evolution relation? Which programs defeat your analysis? How would you handle integer/string-valued fields? How would you handle integer variables?
Inference rules extended with evolution relation v, Q H * ls(E, F) Unroll1 v, Q H * ls(E, F) Unroll>1 v, Q H * (Ez) * ls(z, F) Fold v, Q H * (EF) v, Q H * (Ez) * ls(z, F) where z is fresh v, Q H * ls(E, F) v, Q H * (yw) y := y.n Next v, Q H assume EF assume EF v’, Q H[y/w, z/y] * (zy) where z is fresh v’, Q EF H