An Efficient and Parallel Abstract Interpreter in Scala — First Algorithm

An Efficient and Parallel Abstract Interpreter in Scala — First Algorithm

Transcript

  1. 1.

    Universit´ e Libre de Bruxelles Computer Science Department MEMO-F524 Masters

    thesis An Efficient and Parallel Abstract Interpreter in Scala — First Algorithm — Olivier Pirson — opi@opimedia.be orcid.org/0000-0001-6296-9659 November 12, 2018 (Little correction: February 19, 2019) https://bitbucket.org/OPiMedia/efficient-parallel-abstract-interpreter-in-scala Vrije Universiteit Brussel Promotors Coen De Roover Wolfgang De Meuter Advisor Quentin Stievenart
  2. 2.

    An Efficient and Parallel Abstract Interpreter in Scala — First

    Algorithm The context: Abstract Interpretation for Static Analysis The problematic: Too heavy for real programs First parallel algorithm Implementation First results Done and todo References 1 The context: Abstract Interpretation for Static Analysis 2 The problematic: Too heavy for real programs 3 First parallel algorithm 4 Implementation 5 First results 6 Done and todo 7 References An Efficient and Parallel Abstract Interpreter in Scala — First Algorithm 2 / 32
  3. 3.

    An Efficient and Parallel Abstract Interpreter in Scala — First

    Algorithm The context: Abstract Interpretation for Static Analysis The problematic: Too heavy for real programs First parallel algorithm Implementation First results Done and todo References The context: Abstract Interpretation for Static Analysis We need tools to help us to build correct programs. Figure: First “flight” of Ariane 5 in 1996. Testing is not enough. Static Analysis: study the behaviour of programs without executing them. Not trivial questions about the behaviour of a program are undecidable (Rice’s theorem). Abstract Interpretation: approximation technique to perform static analysis. Trade-off: approximation must be enough precise to have an useful analysis, and enough imprecise to make the problem decidable. An Efficient and Parallel Abstract Interpreter in Scala — First Algorithm 3 / 32
  4. 4.

    An Efficient and Parallel Abstract Interpreter in Scala — First

    Algorithm The context: Abstract Interpretation for Static Analysis The problematic: Too heavy for real programs First parallel algorithm Implementation First results Done and todo References From Concrete Interpretation. . . Trace: concrete interpretation with small-step semantics, for one instance. e s0 s1 s2 s3 s4 · · · injection function concrete transition function Program is executed by interpreter, described by an Abstract Machine (AM). One execution is for one instance on this program. e is for one expression, i.e. a program. si are the successive states during this execution. An Efficient and Parallel Abstract Interpreter in Scala — First Algorithm 4 / 32
  5. 5.

    An Efficient and Parallel Abstract Interpreter in Scala — First

    Algorithm The context: Abstract Interpretation for Static Analysis The problematic: Too heavy for real programs First parallel algorithm Implementation First results Done and todo References From Concrete Interpretation to Abstract Interpretation Trace: concrete interpretation with small-step semantics, for one instance. e s0 s1 s2 s3 s4 · · · s0 s1 s2 s3 s4 s3′ injection function injection function abstract transition function abstraction function α Abstracting Abstract Machine (AAM). 2 over-approximations: on addresses: by modulo; give a finite state space on values: abstraction Abstract transition function returns all directly reachable states. State graph: abstract interpretation, for all instances. “The abstract simulates the concrete” (Might). An Efficient and Parallel Abstract Interpreter in Scala — First Algorithm 5 / 32
  6. 6.

    An Efficient and Parallel Abstract Interpreter in Scala — First

    Algorithm The context: Abstract Interpretation for Static Analysis The problematic: Too heavy for real programs First parallel algorithm Implementation First results Done and todo References Approximation of values: abstraction Based on mathematical notion of lattice (partially ordered sets with additional properties). Examples of abstraction for the set of integer values: Figure: Ren´ e Magritte, Le Calcul Mental. 1940. the type integer intervals sign: {. . . , −3, −2, −1, 0, 1, 2, 3, . . .} abstracted by {⊥, −, 0, +, (− and 0), (0 and +), ⊤} ⊤ (top, no information) (− and 0) (0 and +) − 0 + ⊥ (bottom, no information yet) Figure: Hasse diagram of the complete lattice of signs. Properties of a lattice are such that it contains the join of 2 elements and the succession of operation give a fixed point. An Efficient and Parallel Abstract Interpreter in Scala — First Algorithm 6 / 32
  7. 7.

    An Efficient and Parallel Abstract Interpreter in Scala — First

    Algorithm The context: Abstract Interpretation for Static Analysis The problematic: Too heavy for real programs First parallel algorithm Implementation First results Done and todo References Example of a state graph on a very simple program ev((letrec ((abs (lambda (x) (if (>= x 0) x (- x))))) (abs -42))) 0 ev((abs -42)) 1 ev((if (>= x 0) x (- x))) 2 ev((>= x 0)) 3 ko(Bool) 4 ev(x) 5 ev((- x)) 6 ko(Int) 7 #nodes: 8 #edges: 8 graph density: 0,143 outdegree min: 1 outdegree max: 2 outdegree avg: 1,000 language: Scheme machine: AAM lattice: TypeSet address: Classical Figure: State graph of the abs program with lattice type. Algorithm 1: Absolute value of −42 ( Ò ( abs x ) ( (>= x 0) x (− x ) ) ) ( abs −42) An Efficient and Parallel Abstract Interpreter in Scala — First Algorithm 7 / 32
  8. 8.

    An Efficient and Parallel Abstract Interpreter in Scala — First

    Algorithm The context: Abstract Interpretation for Static Analysis The problematic: Too heavy for real programs First parallel algorithm Implementation First results Done and todo References 1 The context: Abstract Interpretation for Static Analysis 2 The problematic: Too heavy for real programs 3 First parallel algorithm 4 Implementation 5 First results 6 Done and todo 7 References An Efficient and Parallel Abstract Interpreter in Scala — First Algorithm 8 / 32
  9. 9.

    An Efficient and Parallel Abstract Interpreter in Scala — First

    Algorithm The context: Abstract Interpretation for Static Analysis The problematic: Too heavy for real programs First parallel algorithm Implementation First results Done and todo References Example of a state graph on a other very simple program ev((letrec ((fibonacci (lambda (n) (if (<= n 1) n (+ (fibonacci (- n 1)) (fibonacci (- n 2))))))) (fibonacci 10))) 0 ev((fibonacci 10)) 1 ev((if (<= n 1) n (+ (fibonacci (- n 1)) (fibonacci (- n 2))))) 2 ev((<= n 1)) 3 ko(Bool) 4 ev(n) 5 ev((+ (fibonacci (- n 1)) (fibonacci (- n 2)))) 6 ko(Int) 7 ev((fibonacci (- n 1))) 8 ev((- n 1)) 9 ko(Int) 10 ev((if (<= n 1) n (+ (fibonacci (- n 1)) (fibonacci (- n 2))))) 11 ev((<= n 1)) 12 ko(Bool) 13 ev(n) 14 ev((+ (fibonacci (- n 1)) (fibonacci (- n 2)))) 15 ev(n) 16 ev((+ (fibonacci (- n 1)) (fibonacci (- n 2)))) 17 ko(Int) 18 ev((fibonacci (- n 1))) 19 ko(Int) 20 ev((fibonacci (- n 1))) 21 ev((- n 1)) 22 ev((fibonacci (- n 2))) 23 ev((- n 1)) 24 ko(Int) 25 ev((- n 2)) 26 ko(Int) 27 ev((if (<= n 1) n (+ (fibonacci (- n 1)) (fibonacci (- n 2))))) 28 ko(Int) 29 ev((if (<= n 1) n (+ (fibonacci (- n 1)) (fibonacci (- n 2))))) 30 ev((if (<= n 1) n (+ (fibonacci (- n 1)) (fibonacci (- n 2))))) 31 ev((<= n 1)) 32 ev((<= n 1)) 33 ko(Bool) 34 ko(Bool) 35 ev(n) 36 ev((+ (fibonacci (- n 1)) (fibonacci (- n 2)))) 37 ev(n) 38 ev((+ (fibonacci (- n 1)) (fibonacci (- n 2)))) 39 ev((+ (fibonacci (- n 1)) (fibonacci (- n 2)))) 40 ev((+ (fibonacci (- n 1)) (fibonacci (- n 2)))) 41 ev(n) 42 ev((+ (fibonacci (- n 1)) (fibonacci (- n 2)))) 43 ev(n) 44 ev(n) 45 ko(Int) 46 ko(Int) 47 ev((fibonacci (- n 1))) 49 ev((fibonacci (- n 1))) 52 ko(Int) 48 ev((fibonacci (- n 1))) 51 ko(Int) 50 ko(Int) 53 ev((fibonacci (- n 2))) 54 ev((fibonacci (- n 2))) 55 ev((- n 1)) 56 ev((- n 1)) 57 ev((- n 1)) 58 ev((fibonacci (- n 2))) 59 ev((- n 2)) 60 ev((- n 2)) 61 ko(Int) 62 ko(Int) 63 ko(Int) 64 ev((- n 2)) 65 ko(Int) 66 ko(Int) 67 ev((if (<= n 1) n (+ (fibonacci (- n 1)) (fibonacci (- n 2))))) 68 ev((if (<= n 1) n (+ (fibonacci (- n 1)) (fibonacci (- n 2))))) 69 ev((if (<= n 1) n (+ (fibonacci (- n 1)) (fibonacci (- n 2))))) 70 ko(Int) 71 ev((if (<= n 1) n (+ (fibonacci (- n 1)) (fibonacci (- n 2))))) 72 ev((if (<= n 1) n (+ (fibonacci (- n 1)) (fibonacci (- n 2))))) 73 ev((<= n 1)) 74 ev((<= n 1)) 75 ev((if (<= n 1) n (+ (fibonacci (- n 1)) (fibonacci (- n 2))))) 76 ev((<= n 1)) 77 ko(Bool) 78 ko(Bool) 79 ko(Bool) 80 ev(n) 81 ev(n) 82 ev((+ (fibonacci (- n 1)) (fibonacci (- n 2)))) 83 ev((+ (fibonacci (- n 1)) (fibonacci (- n 2)))) 84 ev(n) 85 ev((+ (fibonacci (- n 1)) (fibonacci (- n 2)))) 86 ev(n) 87 ev((+ (fibonacci (- n 1)) (fibonacci (- n 2)))) 88 ev(n) 89 ev((+ (fibonacci (- n 1)) (fibonacci (- n 2)))) 90 ev((+ (fibonacci (- n 1)) (fibonacci (- n 2)))) 91 ev(n) 92 ev(n) 93 ev((+ (fibonacci (- n 1)) (fibonacci (- n 2)))) 94 ev((+ (fibonacci (- n 1)) (fibonacci (- n 2)))) 95 ev(n) 96 ev((+ (fibonacci (- n 1)) (fibonacci (- n 2)))) 97 ev(n) 98 ko(Int) 100 ko(Int) 99 ev((fibonacci (- n 1))) 101 ko(Int) 102 ko(Int) 103 ko(Int) 105 ko(Int) 104 ko(Int) 109 ev((fibonacci (- n 1))) 106 ev((fibonacci (- n 1))) 110 ko(Int) 108 ko(Int) 107 ev((fibonacci (- n 2))) 111 ev((fibonacci (- n 2))) 112 ev((- n 1)) 113 ev((fibonacci (- n 2))) 114 ev((fibonacci (- n 2))) 115 ev((- n 1)) 116 ev((fibonacci (- n 2))) 117 ev((- n 1)) 118 ev((- n 2)) 119 ev((- n 2)) 120 ko(Int) 121 ev((- n 2)) 122 ev((- n 2)) 123 ko(Int) 124 ev((- n 2)) 125 ko(Int) 126 ko(Int) 127 ko(Int) 128 ev((if (<= n 1) n (+ (fibonacci (- n 1)) (fibonacci (- n 2))))) 129 ko(Int) 130 ko(Int) 131 ev((if (<= n 1) n (+ (fibonacci (- n 1)) (fibonacci (- n 2))))) 132 ko(Int) 133 ev((if (<= n 1) n (+ (fibonacci (- n 1)) (fibonacci (- n 2))))) 134 ev((if (<= n 1) n (+ (fibonacci (- n 1)) (fibonacci (- n 2))))) 135 ev((if (<= n 1) n (+ (fibonacci (- n 1)) (fibonacci (- n 2))))) 136 ev((<= n 1)) 137 ev((if (<= n 1) n (+ (fibonacci (- n 1)) (fibonacci (- n 2))))) 138 ev((if (<= n 1) n (+ (fibonacci (- n 1)) (fibonacci (- n 2))))) 139 ev((if (<= n 1) n (+ (fibonacci (- n 1)) (fibonacci (- n 2))))) 140 ev((<= n 1)) 141 ev((<= n 1)) 142 ko(Bool) 143 ev((<= n 1)) 144 ko(Bool) 145 ko(Bool) 146 ev(n) 147 ev((+ (fibonacci (- n 1)) (fibonacci (- n 2)))) 148 ev((+ (fibonacci (- n 1)) (fibonacci (- n 2)))) 149 ev(n) 150 ev((+ (fibonacci (- n 1)) (fibonacci (- n 2)))) 151 ev(n) 152 ko(Bool) 153 ev((+ (fibonacci (- n 1)) (fibonacci (- n 2)))) 154 ev((+ (fibonacci (- n 1)) (fibonacci (- n 2)))) 155 ev(n) 156 ev((+ (fibonacci (- n 1)) (fibonacci (- n 2)))) 157 ev(n) 158 ev(n) 159 ev(n) 160 ev((+ (fibonacci (- n 1)) (fibonacci (- n 2)))) 161 ev((+ (fibonacci (- n 1)) (fibonacci (- n 2)))) 162 ev(n) 163 ev(n) 164 ev((+ (fibonacci (- n 1)) (fibonacci (- n 2)))) 165 ko(Int) 167 ko(Int) 168 ko(Int) 166 ev(n) 169 ev((+ (fibonacci (- n 1)) (fibonacci (- n 2)))) 170 ev(n) 171 ev(n) 172 ev((+ (fibonacci (- n 1)) (fibonacci (- n 2)))) 173 ev((+ (fibonacci (- n 1)) (fibonacci (- n 2)))) 174 ko(Int) 177 ko(Int) 175 ko(Int) 176 ko(Int) 178 ev((fibonacci (- n 1))) 180 ko(Int) 181 ko(Int) 179 ev((fibonacci (- n 1))) 182 ev((fibonacci (- n 2))) 183 ev((fibonacci (- n 2))) 184 ev((fibonacci (- n 2))) 185 ko(Int) 190 ev((fibonacci (- n 1))) 187 ko(Int) 189 ko(Int) 188 ev((fibonacci (- n 1))) 186 ev((fibonacci (- n 2))) 191 ev((fibonacci (- n 2))) 192 ev((- n 1)) 193 ev((- n 1)) 194 ev((- n 2)) 195 ev((- n 2)) 196 ev((- n 2)) 197 ev((- n 1)) 198 ev((- n 1)) 199 ev((- n 2)) 200 ev((- n 2)) 201 ko(Int) 202 ko(Int) 203 ko(Int) 204 ko(Int) 205 ko(Int) 206 ko(Int) 207 ko(Int) 208 ko(Int) 209 ko(Int) 210 ev((if (<= n 1) n (+ (fibonacci (- n 1)) (fibonacci (- n 2))))) 211 ev((if (<= n 1) n (+ (fibonacci (- n 1)) (fibonacci (- n 2))))) 212 ev((if (<= n 1) n (+ (fibonacci (- n 1)) (fibonacci (- n 2))))) 213 ev((if (<= n 1) n (+ (fibonacci (- n 1)) (fibonacci (- n 2))))) 214 ev((if (<= n 1) n (+ (fibonacci (- n 1)) (fibonacci (- n 2))))) 215 ev((if (<= n 1) n (+ (fibonacci (- n 1)) (fibonacci (- n 2))))) 216 ev((if (<= n 1) n (+ (fibonacci (- n 1)) (fibonacci (- n 2))))) 217 ev((if (<= n 1) n (+ (fibonacci (- n 1)) (fibonacci (- n 2))))) 218 ev((if (<= n 1) n (+ (fibonacci (- n 1)) (fibonacci (- n 2))))) 219 ev((<= n 1)) 220 ev((<= n 1)) 221 ev((<= n 1)) 222 ko(Bool) 223 ko(Bool) 224 ko(Bool) 225 ev((+ (fibonacci (- n 1)) (fibonacci (- n 2)))) 226 ev(n) 227 ev(n) 228 ev((+ (fibonacci (- n 1)) (fibonacci (- n 2)))) 229 ev((+ (fibonacci (- n 1)) (fibonacci (- n 2)))) 230 ev(n) 231 ev((+ (fibonacci (- n 1)) (fibonacci (- n 2)))) 232 ev(n) 233 ev(n) 234 ev((+ (fibonacci (- n 1)) (fibonacci (- n 2)))) 235 ev(n) 236 ev((+ (fibonacci (- n 1)) (fibonacci (- n 2)))) 237 ev((+ (fibonacci (- n 1)) (fibonacci (- n 2)))) 238 ev(n) 239 ev((+ (fibonacci (- n 1)) (fibonacci (- n 2)))) 240 ev((+ (fibonacci (- n 1)) (fibonacci (- n 2)))) 241 ev(n) 242 ev(n) 243 ko(Int) 246 ko(Int) 244 ko(Int) 245 ko(Int) 248 ko(Int) 249 ko(Int) 247 ev((fibonacci (- n 1))) 251 ko(Int) 253 ko(Int) 250 ko(Int) 252 ev((fibonacci (- n 2))) 254 ev((- n 1)) 255 ev((- n 2)) 256 ko(Int) 257 ko(Int) 258 ev((if (<= n 1) n (+ (fibonacci (- n 1)) (fibonacci (- n 2))))) 259 ev((if (<= n 1) n (+ (fibonacci (- n 1)) (fibonacci (- n 2))))) 260 ev((<= n 1)) 261 ko(Bool) 262 ev(n) 263 ev(n) 264 ev((+ (fibonacci (- n 1)) (fibonacci (- n 2)))) 265 ev((+ (fibonacci (- n 1)) (fibonacci (- n 2)))) 266 ev(n) 267 ev((+ (fibonacci (- n 1)) (fibonacci (- n 2)))) 268 ko(Int) 271 ko(Int) 269 ev((fibonacci (- n 1))) 270 ko(Int) 272 ev((- n 1)) 273 ko(Int) 274 ev((if (<= n 1) n (+ (fibonacci (- n 1)) (fibonacci (- n 2))))) 275 #nodes: 276 #edges: 346 graph density: 0,005 outdegree min: 1 outdegree max: 6 outdegree avg: 1,254 language: Scheme machine: AAM lattice: TypeSet address: Classical Figure: State graph of the Fibonacci program with lattice type. Algorithm 2: The 10th Fibonacci number. ; ; nth number of F i b o n a c c i ( by r e c u r s i v e p r o c e s s ) ( Ò ( f i b o n a c c i n ) ( (<= n 1) n (+ ( f i b o n a c c i (− n 1)) ( f i b o n a c c i (− n 2 ) ) ) ) ) ( f i b o n a c c i 10) An Efficient and Parallel Abstract Interpreter in Scala — First Algorithm 9 / 32
  10. 10.

    An Efficient and Parallel Abstract Interpreter in Scala — First

    Algorithm The context: Abstract Interpretation for Static Analysis The problematic: Too heavy for real programs First parallel algorithm Implementation First results Done and todo References Example of a state graph on a other very simple program (bis) ev((letrec ((fibonacci2 (lambda (n fn_1 fn) (if (= n 0) (cons fn_1 fn) (fibonacci2 (- n 1) fn (+ fn fn_1))))) (fibonacci (lambda (n) (cdr (fibonacci2 n 1 0))))) (fibonacci 10))) 0 ev((fibonacci 10)) 1 ev((cdr (fibonacci2 n 1 0))) 2 ev((fibonacci2 n 1 0)) 3 ev((if (= n 0) (cons fn_1 fn) (fibonacci2 (- n 1) fn (+ fn fn_1)))) 4 ev((= n 0)) 5 ko({#f,#t}) 6 ev((cons fn_1 fn)) 7 ev((fibonacci2 (- n 1) fn (+ fn fn_1))) 8 ko(Cons(@fn_1-Time(),@fn-Time())) 9 ev((- n 1)) 10 ko(Int) 11 ko(Int) 12 ev((+ fn fn_1)) 13 ko(Int) 14 ev((if (= n 0) (cons fn_1 fn) (fibonacci2 (- n 1) fn (+ fn fn_1)))) 15 ev((= n 0)) 16 ko({#f,#t}) 17 ev((cons fn_1 fn)) 18 ev((fibonacci2 (- n 1) fn (+ fn fn_1))) 19 ko(Cons(@fn_1-Time(),@fn-Time())) 20 ev((- n 1)) 21 ko(Int) 22 ko(Int) 23 #nodes: 24 #edges: 24 graph density: 0,043 outdegree min: 1 outdegree max: 2 outdegree avg: 1,000 language: Scheme machine: AAM lattice: TypeSet address: Classical Figure: State graph of the Fibonacci program with lattice type. Algorithm 3: The 10th Fibonacci number. ; ; nth number of F i b o n a c c i ( by i t e r a t i v e p r o c e s s ) ( Ò ( f i b o n a c c i 2 n f n 1 fn ) ( (= n 0) ( ÓÒ× f n 1 fn ) ( f i b o n a c c i 2 (− n 1) fn (+ fn f n 1 ) ) ) ) ( Ò ( f i b o n a c c i n ) ( Ö ( f i b o n a c c i 2 n 1 0 ) ) ) ( f i b o n a c c i 10) An Efficient and Parallel Abstract Interpreter in Scala — First Algorithm 10 / 32
  11. 11.

    An Efficient and Parallel Abstract Interpreter in Scala — First

    Algorithm The context: Abstract Interpretation for Static Analysis The problematic: Too heavy for real programs First parallel algorithm Implementation First results Done and todo References The problematic: Too heavy for real programs With an AAM the problem is became decidable. But in general an AAM is too slow to analyse real programs. One way to have a faster AAM is to parallelize generation of the state graph. Goal of this master thesis: implement and compare several parallelizations of AAM in the framework Scala-AM. Parallel model for the implementation: actors with Akka. Language analysed: Scheme. Figure: Agents Smith from the Matrix trilogy. An Efficient and Parallel Abstract Interpreter in Scala — First Algorithm 11 / 32
  12. 12.

    An Efficient and Parallel Abstract Interpreter in Scala — First

    Algorithm The context: Abstract Interpretation for Static Analysis The problematic: Too heavy for real programs First parallel algorithm Implementation First results Done and todo References Actor model Actor, like an object, isolated entity with its own encapsulated data and behaviour. With some fundamental differences. Entirely private. No shared mutable state (so no data race). Communication by immutable asynchronous messages (sent and received sequentially). Each actor has a mailbox (a queue). Capability to create other actors. Figure: Richard Doyle. Using Akka and Scala to Render a Mandelbrot Set. 2014. http://blog.scottlogic.com/2014/08/15/using-akka-and-scala-to-render-a-mandelbrot-set.html An Efficient and Parallel Abstract Interpreter in Scala — First Algorithm 12 / 32
  13. 13.

    An Efficient and Parallel Abstract Interpreter in Scala — First

    Algorithm The context: Abstract Interpretation for Static Analysis The problematic: Too heavy for real programs First parallel algorithm Implementation First results Done and todo References 1 The context: Abstract Interpretation for Static Analysis 2 The problematic: Too heavy for real programs 3 First parallel algorithm 4 Implementation 5 First results 6 Done and todo 7 References An Efficient and Parallel Abstract Interpreter in Scala — First Algorithm 13 / 32
  14. 14.

    An Efficient and Parallel Abstract Interpreter in Scala — First

    Algorithm The context: Abstract Interpretation for Static Analysis The problematic: Too heavy for real programs First parallel algorithm Implementation First results Done and todo References Sequential worklist strategy Factorized version from K. Dewey, V. Kashyap, B. Hardekopf. A parallel abstract interpreter for JavaScript. 2015. Algorithm 4: The sequential worklist algorithm ÔÖÓ ÙÖ main process(worklist, memo, ςold, ςnew, ς) memo does not c on tai n partition(ς) Ø Ò memo[partition(ς)] := ς put ς on worklist Ð× ςold := memo[partition(ς)] ςnew := ςold ⊔ ς ςnew = ςold Ø Ò memo[partition(ς)] := ςnew put ςnew on worklist Ò Ò Ò ÔÖÓ ÙÖ ÔÖÓ ÙÖ sequential put the i n i t i a l a b s t r a c t s t a t e ς0 on the worklist i n i t i a l i z e map memo : Partition → Σ♯ to empty Ö Ô Ø remove an a b s t r a c t s t a t e ς from the worklist ÓÖ ÐÐ a b s t r a c t s t a t e s ς′ i n next states(ς) Ó main process(worklist, memo, ςold, ςnew, ς′) Ò ÓÖ ÙÒØ Ð worklist i s empty Ò ÔÖÓ ÙÖ s s s s s worklist An Efficient and Parallel Abstract Interpreter in Scala — First Algorithm 14 / 32
  15. 15.

    An Efficient and Parallel Abstract Interpreter in Scala — First

    Algorithm The context: Abstract Interpretation for Static Analysis The problematic: Too heavy for real programs First parallel algorithm Implementation First results Done and todo References Worklist parallel strategy Factorized version from K. Dewey, V. Kashyap, B. Hardekopf. A parallel abstract interpreter for JavaScript. 2015. Algorithm 5: The worklist parallel algorithm put the i n i t i a l a b s t r a c t s t a t e ς0 on the worklist i n i t i a l i z e templist to empty i n i t i a l i z e map memo : Partition → Σ♯ to empty Ö Ô Ø ÓÖ ÐÐ a b s t r a c t s t a t e s ς i n the worklist Ó Ò Ô Ö ÐÐ Ð ÓÖ ÐÐ a b s t r a c t s t a t e s ς′ i n next states(ς) Ó Ò Ø Ö × main process(templist, memo, ςold, ςnew, ς′) Ò Ø Ö × Ò ÓÖ Ò Ô Ö ÐÐ Ð ÓÖ swap worklist and templist ÙÒØ Ð worklist i s empty s s s s s worklist merge An Efficient and Parallel Abstract Interpreter in Scala — First Algorithm 15 / 32
  16. 16.

    An Efficient and Parallel Abstract Interpreter in Scala — First

    Algorithm The context: Abstract Interpretation for Static Analysis The problematic: Too heavy for real programs First parallel algorithm Implementation First results Done and todo References Worklist parallel strategy Redundant computations. Synchronization at the merge step. Article test on few real JavaScript programs. Results show that this adaptation of the sequential algorithm is not optimal. Figure: L. Andersen, M. Might. Multi-core Parallelization of Abstracted. 2013. Improvements with producer/consumer model. An Efficient and Parallel Abstract Interpreter in Scala — First Algorithm 16 / 32
  17. 17.

    An Efficient and Parallel Abstract Interpreter in Scala — First

    Algorithm The context: Abstract Interpretation for Static Analysis The problematic: Too heavy for real programs First parallel algorithm Implementation First results Done and todo References Better, per-context parallel strategy Authors of A parallel abstract interpreter for JavaScript introduce a per-context parallel strategy. The main idea is to separate these two parts: state exploration control of state space by some merging operations. The intuitive idea is to parallelize “functions” instead basic “blocks”. An Efficient and Parallel Abstract Interpreter in Scala — First Algorithm 17 / 32
  18. 18.

    An Efficient and Parallel Abstract Interpreter in Scala — First

    Algorithm The context: Abstract Interpretation for Static Analysis The problematic: Too heavy for real programs First parallel algorithm Implementation First results Done and todo References 1 The context: Abstract Interpretation for Static Analysis 2 The problematic: Too heavy for real programs 3 First parallel algorithm 4 Implementation 5 First results 6 Done and todo 7 References An Efficient and Parallel Abstract Interpreter in Scala — First Algorithm 18 / 32
  19. 19.

    An Efficient and Parallel Abstract Interpreter in Scala — First

    Algorithm The context: Abstract Interpretation for Static Analysis The problematic: Too heavy for real programs First parallel algorithm Implementation First results Done and todo References Actor logic ZDLW IXWXUH DQG ORRS XQWLO WRGR LV HPSW\ $FWRU6WDWH 1 (YDO VWDWH YLVLWHG $FWRU6WDUWHU ,QLW WRGR YLVLWHG KDOWHG JUDSK 6WDUW $FWRU6WDWH (YDO VWDWH YLVLWHG $FWRU6WDWH (YDO VWDWH YLVLWHG « IRU HDFK VWDWH LQ WRGR DIWHU VHQG DOO VWDWHV $FWRU&ROOHFWHU ,QLW KDOWHG JUDSK $OO6WDUWHG YLVLWHG QE6WDWH:DLWHG $OUHDG\ 6XEVXPHG +DOWHG VWDWH 1HZ6WDWH VWDWH VXFFHVVRUV ZKHQ $OO6WDUWHG DQG QE6WDWH:DLWHG VWDWH UHVXOWV UHFHLYHG PDLQ ORRS « Figure: Actors logic used to implemented the worklist parallel strategy. An Efficient and Parallel Abstract Interpreter in Scala — First Algorithm 19 / 32
  20. 20.

    An Efficient and Parallel Abstract Interpreter in Scala — First

    Algorithm The context: Abstract Interpretation for Static Analysis The problematic: Too heavy for real programs First parallel algorithm Implementation First results Done and todo References Scala implementation – main loop Algorithm 6: The main loop, until the worklist todo is empty  s c a l a . an n otati on . t a i l r e c l oop ( todo : L i s t [ S tate ] , v i s i t e d : VS [ S tate ] , h a l t e d : Set [ S tate ] , graph : Graph ) : ParAAMOutput todo Ñ Ø { × N i l { // f i n i s h e d , the w o r k l i s t todo i s empty actorSystem . te rmi n ate ParAAMOutput( h al te d , V i s i t e d S e t [VS ] . s i z e ( v i s i t e d ) , timeout . time , graph , Ð× , s t a t s ) } × ( timeout . re ac h e d ) // exceeded the maximal time allowed , stop ParAAMOutput( h al te d , V i s i t e d S e t [VS ] . s i z e ( v i s i t e d ) , timeout . time , graph , ØÖÙ , s t a t s ) Ð× { // w i l l send each s t a t e from w o r k l i s t todo to Ac torS tate Ú Ð f u t u r e a c t o r S t a r t e r ? A c t o r S t a r t e r . I n i t ( todo , v i s i t e d , h al te d , graph ) Ú Ð ( newTodo , n e wVi si te d , newHalted , newGraph ) Await . r e s u l t ( fu tu re , Timeout( "some" se c on d s ) . d u r a t i o n ) . asIn stan c e O f [ ( L i s t [ S tate ] , VS [ S tate ] , Set [ S tate ] , Graph ) ] l oop ( newTodo , n e wVi si te d , newHalted , newGraph ) } } An Efficient and Parallel Abstract Interpreter in Scala — First Algorithm 20 / 32
  21. 21.

    An Efficient and Parallel Abstract Interpreter in Scala — First

    Algorithm The context: Abstract Interpretation for Static Analysis The problematic: Too heavy for real programs First parallel algorithm Implementation First results Done and todo References Scala implementation – ActorStarter 1/2 Algorithm 7: Init other actors, send states to all ActorState Ò Ð Ð ×× A c t o r S t a r t e r ÜØ Ò × Actor { ÑÔÓÖØ A c t o r S t a r t e r . Ú Ö todo : L i s t [ S tate ] ÒÙÐÐ Ú Ö n e wVi si te d : VS [ S tate ] V i s i t e d S e t [VS ] . empty Ú Ö a c t o r I : I n t −1 Ú Ö nb : I n t −1 ÓÚ ÖÖ r e c e i v e { × I n i t ( todo : L i s t [ S tate ] , v i s i t e d , h a l t e d : Set [ S tate ] , graph : Graph ) Ø × . todo todo n e wVi si te d v i s i t e d a c t o r I 0 nb 0 a c t o r C o l l e c t e r ! A c t o r C o l l e c t e r . I n i t ( h al te d , graph , se n d e r ) × S t a r t ÓÖ ( s t a t e ¹ todo ) { ( a c t o r s ( a c t o r I ) ÒÙÐÐ ) // c r e a t e new ac tor a c t o r s ( a c t o r I ) actorSystem . ac torO f ( Props ( Ò Û Ac torS tate )) a c t o r s ( a c t o r I ) ! Ac torS tate . Eval ( state , n e wVi si te d , a c t o r C o l l e c t e r ) n e wVi si te d V i s i t e d S e t [VS ] . add ( n e wVi si te d , s t a t e ) a c t o r I + 1 ( a c t o r I maxActorStates ) a c t o r I 0 nb + 1 } a c t o r C o l l e c t e r ! A c t o r C o l l e c t e r . A l l S t a r t e d ( n e wVi si te d , nb ) } } . . . An Efficient and Parallel Abstract Interpreter in Scala — First Algorithm 21 / 32
  22. 22.

    An Efficient and Parallel Abstract Interpreter in Scala — First

    Algorithm The context: Abstract Interpretation for Static Analysis The problematic: Too heavy for real programs First parallel algorithm Implementation First results Done and todo References Scala implementation – ActorStarter 2/2 Algorithm 8: Init other actors, send states to all ActorState . . . Ó Ø A c t o r S t a r t e r { Ú Ð S t a r t 1 × Ð ×× I n i t ( todo : L i s t [ S tate ] , v i s i t e d : VS [ S tate ] , h a l t e d : Set [ S tate ] , graph : Graph ) } Ú Ð a c t o r S t a r t e r : ActorRef actorSystem . ac torO f ( Props ( Ò Û A c t o r S t a r t e r )) An Efficient and Parallel Abstract Interpreter in Scala — First Algorithm 22 / 32
  23. 23.

    An Efficient and Parallel Abstract Interpreter in Scala — First

    Algorithm The context: Abstract Interpretation for Static Analysis The problematic: Too heavy for real programs First parallel algorithm Implementation First results Done and todo References Scala implementation – ActorCollecter 1/2 Algorithm 9: Starts ActorStarter, collect results from all ActorState Ò Ð Ð ×× A c t o r C o l l e c t e r ÜØ Ò × Actor { ÑÔÓÖØ A c t o r C o l l e c t e r . Ú Ö mainSender: ActorRef ÒÙÐÐ Ú Ö newTodo : L i s t [ S tate ] ÒÙÐÐ Ú Ö newHalted : Set [ S tate ] ÒÙÐÐ Ú Ö newGraph : Graph ÒÙÐÐ Ú Ö nb : I n t −1 // count A l l S t a r t e d r e c e i v e d + the number of s t a t e r e s u l t s r e c e i v e Ú Ö nbStateWaited : I n t −1 Ú Ö n e wVi si te d : VS [ S tate ] V i s i t e d S e t [VS ] . empty i n c re me n t () { nb + 1 ( nb > nbStateWaited ) // a l l s t a r t e d and f i n i s h e d a l l s t a t e s , then send r e s u l t s mainSender ! ( newTodo , n e wVi si te d , newHalted , newGraph ) // to c a l l e r l oop } ÓÚ ÖÖ r e c e i v e { × NewState( s t a t e : State , s u c c e s s o r s : Set [ S tate ] ) newGraph newGraph . map( . addEdges ( state , s u c c e s s o r s )) newTodo ++ s u c c e s s o r s i n c re me n t × Al re ad y i n c re me n t × Subsumed i n c re me n t × Halted ( s t a t e : S tate ) newHalted + s t a t e i n c re me n t . . . An Efficient and Parallel Abstract Interpreter in Scala — First Algorithm 23 / 32
  24. 24.

    An Efficient and Parallel Abstract Interpreter in Scala — First

    Algorithm The context: Abstract Interpretation for Static Analysis The problematic: Too heavy for real programs First parallel algorithm Implementation First results Done and todo References Scala implementation – ActorCollecter 2/2 Algorithm 10: Starts ActorStarter, collect results from all ActorState . . . × I n i t ( h a l t e d : Set [ S tate ] , graph : Graph , mainSender: ActorRef ) Ø × . mainSender mainSender newTodo N i l newHalted h a l t e d newGraph graph nb 0 nbStateWaited I n t . MaxValue // b i g g e s t val u e to avoi d end b e f o r e i n i t par A l l S t a r t e d n e wVi si te d V i s i t e d S e t [VS ] . empty se n d e r ! A c t o r S t a r t e r . S t a r t // to a c t o r S t a r t e r × A l l S t a r t e d ( v i s i t e d , nbStateWaited : I n t ) Ø × . nbStateWaited nbStateWaited n e wVi si te d v i s i t e d i n c re me n t } } Ó Ø A c t o r C o l l e c t e r { Ú Ð Al re ad y 2 Ú Ð Subsumed 3 × Ð ×× NewState( s t a t e : State , s u c c e s s o r s : Set [ S tate ] ) × Ð ×× Halted ( s t a t e : S tate ) × Ð ×× I n i t ( h a l t e d : Set [ S tate ] , graph : Graph , mainSender : ActorRef ) × Ð ×× A l l S t a r t e d ( v i s i t e d : VS [ S tate ] , nbStateWaited : I n t ) } Ú Ð a c t o r C o l l e c t e r : ActorRef actorSystem . ac torO f ( Props ( Ò Û A c t o r C o l l e c t e r )) An Efficient and Parallel Abstract Interpreter in Scala — First Algorithm 24 / 32
  25. 25.

    An Efficient and Parallel Abstract Interpreter in Scala — First

    Algorithm The context: Abstract Interpretation for Static Analysis The problematic: Too heavy for real programs First parallel algorithm Implementation First results Done and todo References Scala implementation – ActorState Algorithm 11: evaluate states Ò Ð Ð ×× Ac torS tate ÜØ Ò × Actor { ÑÔÓÖØ Ac torS tate . Eval ÓÚ ÖÖ r e c e i v e { × Eval ( s t a t e : State , v i s i t e d , a c t o r C o l l e c t e r : ActorRef ) ( V i s i t e d S e t [VS ] . c o n t a i n s ( v i s i t e d , s t a t e )) // a l r e a d y a c t o r C o l l e c t e r ! A c t o r C o l l e c t e r . Al re ad y Ð× ( subsumption && // subsumed V i s i t e d S e t [VS ] . e x i s t s ( v i s i t e d , state , ( s2 : S tate ) s2 . subsumes ( s t a t e ) ) ) a c t o r C o l l e c t e r ! A c t o r C o l l e c t e r . Subsumed Ð× ( s t a t e . h a l t e d ) // h a l t e d s t a t e d a c t o r C o l l e c t e r ! A c t o r C o l l e c t e r . Halted ( s t a t e ) Ð× // new s t a t e a c t o r C o l l e c t e r ! A c t o r C o l l e c t e r . NewState ( state , s t a t e . ste p ( sem )) } } Ó Ø Ac torS tate { × Ð ×× Eval ( s t a t e : State , v i s i t e d : VS [ S tate ] , a c t o r C o l l e c t e r : ActorRef ) } An Efficient and Parallel Abstract Interpreter in Scala — First Algorithm 25 / 32
  26. 26.

    An Efficient and Parallel Abstract Interpreter in Scala — First

    Algorithm The context: Abstract Interpretation for Static Analysis The problematic: Too heavy for real programs First parallel algorithm Implementation First results Done and todo References 1 The context: Abstract Interpretation for Static Analysis 2 The problematic: Too heavy for real programs 3 First parallel algorithm 4 Implementation 5 First results 6 Done and todo 7 References An Efficient and Parallel Abstract Interpreter in Scala — First Algorithm 26 / 32
  27. 27.

    An Efficient and Parallel Abstract Interpreter in Scala — First

    Algorithm The context: Abstract Interpretation for Static Analysis The problematic: Too heavy for real programs First parallel algorithm Implementation First results Done and todo References First (very rough) results 60 70 80 90 100 110 120 130 S 1 2 4 8 16 32 64 seconds Sequential or number of ActorState rsa.scm 0.045 0.05 0.055 0.06 0.065 0.07 0.075 0.08 S 1 2 4 8 16 32 64 seconds Sequential or number of ActorState Fibonacci recursive - subsumption 2.2 2.4 2.6 2.8 3 3.2 3.4 3.6 3.8 4 4.2 S 1 2 4 8 16 32 64 seconds Sequential or number of ActorState sat.scm 0 2 4 6 8 10 12 14 S 1 2 4 8 16 32 64 seconds Sequential or number of ActorState sat.scm - subsumption Quick average on 5 repetitions after 3 repetitions skipped (3 and 1 for rsa.scm) with Scala 2.12.7 and Akka 2.5.18 (Java 1.8.0 – GraalVM 1.0.0) on Intel Xeon Gold 6148 2.40GHz, 16 “cores” available (Hydra). An Efficient and Parallel Abstract Interpreter in Scala — First Algorithm 27 / 32
  28. 28.

    An Efficient and Parallel Abstract Interpreter in Scala — First

    Algorithm The context: Abstract Interpretation for Static Analysis The problematic: Too heavy for real programs First parallel algorithm Implementation First results Done and todo References 1 The context: Abstract Interpretation for Static Analysis 2 The problematic: Too heavy for real programs 3 First parallel algorithm 4 Implementation 5 First results 6 Done and todo 7 References An Efficient and Parallel Abstract Interpreter in Scala — First Algorithm 28 / 32
  29. 29.

    An Efficient and Parallel Abstract Interpreter in Scala — First

    Algorithm The context: Abstract Interpretation for Static Analysis The problematic: Too heavy for real programs First parallel algorithm Implementation First results Done and todo References Work done Reading of theoretical background on lattices, AAM and parallelism. Redaction of an introduction to the subject (preparatory work, previous year). Learning actors, Akka. Learning use of some tools: sbt, Scala environments. . . Learning functioning of Scala-AM. Removed some parts of Scala-AM (other machines or languages), implementation of little features. Implemented the worklist parallel algorithm. Reimplemented the Graph data structure. Some thoughts about a kind of metric to characterize “ideal” parallelization of given Scheme programs. An Efficient and Parallel Abstract Interpreter in Scala — First Algorithm 29 / 32
  30. 30.

    An Efficient and Parallel Abstract Interpreter in Scala — First

    Algorithm The context: Abstract Interpretation for Static Analysis The problematic: Too heavy for real programs First parallel algorithm Implementation First results Done and todo References Work to be done Maybe revise the implementation of the worklist parallel algorithm. Think about how and to what to benchmark. Implement better parallel algorithm(s). Try impact of metrics considered. Evaluate all of them, identify advantages and disadvantages for each of them. Reading of other articles on parallelization. Final redaction. An Efficient and Parallel Abstract Interpreter in Scala — First Algorithm 30 / 32
  31. 31.

    An Efficient and Parallel Abstract Interpreter in Scala — First

    Algorithm The context: Abstract Interpretation for Static Analysis The problematic: Too heavy for real programs First parallel algorithm Implementation First results Done and todo References 1 The context: Abstract Interpretation for Static Analysis 2 The problematic: Too heavy for real programs 3 First parallel algorithm 4 Implementation 5 First results 6 Done and todo 7 References An Efficient and Parallel Abstract Interpreter in Scala — First Algorithm 31 / 32
  32. 32.

    An Efficient and Parallel Abstract Interpreter in Scala — First

    Algorithm The context: Abstract Interpretation for Static Analysis The problematic: Too heavy for real programs First parallel algorithm Implementation First results Done and todo References References Thank you! Questions time. . . L. Andersen, M. Might. Multi-core Parallelization of Abstracted Abstract Machines. 2013. K. Dewey, V. Kashyap, B. Hardekopf. A parallel abstract interpreter for JavaScript. 2015. Matthew Might. Tutorial: Small-step CFA. 2011. Quentin Sti´ evenart. Static Analysis of Concurrency Constructs in Higher-Order Programs. 2014. D. Van Horn, M. Might. Abstracting Abstract Machines. 2010. Document, L A TEX sources, other references and previous presentations on https:// Ø Ù ØºÓÖ »ÇÈ Å /efficient-parallel-abstract-interpreter-in-scala Olivier Pirson. An Efficient and Parallel Abstract Interpreter in Scala — Preparatory Work. 2017. An Efficient and Parallel Abstract Interpreter in Scala — First Algorithm 32 / 32