1 / 19

Dynamic Program Analysis with Partial Execution and Summary

Dynamic Program Analysis with Partial Execution and Summary. Thomas Huining Feng http://www.eecs.berkeley.edu/~tfeng/ CHESS, UC Berkeley May 8, 2007 CS 294-5 Class Project. Motivating Example 1. public class A { void f(boolean op1, boolean op2, boolean op3, boolean failure) {

evalle
Download Presentation

Dynamic Program Analysis with Partial Execution and Summary

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Dynamic Program Analysis with Partial Execution and Summary Thomas Huining Feng http://www.eecs.berkeley.edu/~tfeng/ CHESS, UC Berkeley May 8, 2007 CS 294-5 Class Project

  2. Motivating Example 1 public class A { void f(boolean op1, boolean op2, boolean op3, boolean failure) { if (op1) { System.out.println("Operation 1"); } if (op2) { System.out.println("Operation 2"); } if (op3) { System.out.println("Operation 3"); } @Failure("failure") int fail; } } • JCute finds 24=16 paths. • Overall failure constraint is [failure] (after simplification). • Can we reduce the number of paths? Parameters are generated by JCute. op1 op2 op3 if (failure) { System.out.println(“FAILURE”); return; } else { return; } fail

  3. Motivating Example 2 public class B { void f(int i, int j) { for (int k = 0; k < i; k++) { if (i == j) { @Failure(“true”) int fail; } } } } • JCute never halts. • An unbounded number of paths exist, because i is arbitrary. • Can we handle this problem? Yes. • Can we handle this problem within 10 runs? Yes. Raise a failing signal when [i == j]. Equivalent to: @Failure(“i == j”) int fail;

  4. Overview • Examples exhibit 2 problems: • Exponential paths to explore. • Unbounded paths to explore before a loop constraint is found. • Assumption: Free of side effect, deterministic Java programs. • To solve problem 1: • For a program with n = n1 + n2 + … + nk sequential tests • split the program into k trunks • reduce the complexity to 2n1 + 2n2 + … + 2nk (best case) • Let n1 = n2 = … = nk = 1 to achieve linear growth. • To solve problem 2: • Partially execute the loop. • Compute a fixpoint of constraints.

  5. Solving Problem 1 • Examples exhibit 2 problems: • Exponential paths to explore. • Unbounded paths to explore before a loop constraint is found. • Assumption: Free of side effect, deterministic Java programs. • To solve problem 1: • For a program with n = n1 + n2 + … + nk sequential tests • split the program into k trunks • reduce the complexity to 2n1 + 2n2 + … + 2nk (best case) • Let n1 = n2 = … = nk = 1 to achieve linear growth. • To solve problem 2: • Partially execute the loop. • Compute a fixpoint of constraints.

  6. Partition the Program public class A { void f(boolean op1, boolean op2, boolean op3, boolean failure) { if (op1) { System.out.println("Operation 1"); } if (op2) { System.out.println("Operation 2"); } if (op3) { System.out.println("Operation 3"); } @Failure("failure") int fail; } } • 1st execution: the last test of the program. 2 branches; 4 paths. • Constraint: [op3 && failure || !op3 && failure] ⇔[failure] public class A { void f(boolean op1, boolean op2, boolean op3, boolean failure) { if (op3) { System.out.println("Operation 3"); } @Failure("failure") int fail; } } Seg. 3 Seg. 1 Seg. 2 Seg. 1

  7. Rewrite the Program public class A { void f(boolean op1, boolean op2, boolean op3, boolean failure) { if (op1) { System.out.println("Operation 1"); } if (op2) { System.out.println("Operation 2"); } if (op3) { System.out.println("Operation 3"); } @Failure("failure") int fail; } } public class A { void f(boolean op1, boolean op2, boolean op3, boolean failure) { if (op1) { System.out.println("Operation 1"); } if (op2) { System.out.println("Operation 2"); } @Failure("failure") int fail; } } Rewrite

  8. Segment the Program Again public class A { void f(boolean op1, boolean op2, boolean op3, boolean failure) { if (op1) { System.out.println("Operation 1"); } if (op2) { System.out.println("Operation 2"); } @Failure("failure") int fail; } } • 2nd execution: the last test of the program. 2 branches; 4 paths. • Constraint: [op2 && failure || !op2 && failure] ⇔[failure] public class A { void f(boolean op1, boolean op2, boolean op3, boolean failure) { if (op2) { System.out.println("Operation 3"); } @Failure("failure") int fail; } } Seg. 3 Seg. 2 Seg. 2

  9. Assessment • Repeat this process until head of the program is reached. • A big gain? op1 op2 op2 op3 op1 op3 fail fail fail fail Total # of paths: 24 = 16 Total # of paths: 4 + 4 + 4 = 12

  10. Assessment Total # of paths: 8 * 8 * 2 = 128 Total # of paths: 8*2 + 8*2 = 32

  11. Solving Problem 2 • Examples exhibit 2 problems: • Exponential paths to explore. • Unbounded paths to explore before a loop constraint is found. • Assumption: Free of side effect, deterministic Java programs. • To solve problem 1: • For a program with n = n1 + n2 + … + nk sequential tests • split the program into k trunks • reduce the complexity to 2n1 + 2n2 + … + 2nk (best case) • Let n1 = n2 = … = nk = 1 to achieve linear growth. • To solve problem 2: • Partially execute the loop. • Compute a fixpoint of constraints.

  12. Bounded Loop Execution • First, identify the loop. public class B { void f(int i, int j) { int k; k = 0; l1: if (k < i) { if (i == j) { @Failure(“true”) int fail; } k++; goto l1; } } } public class B { void f(int i, int j) { for (int k = 0; k < i; k++) { if (i == j) { @Failure(“true”) int fail; } } } }

  13. Bounded Loop Execution public class B { void f(int i, int j) { int k; k = 0; l1: if (k < i) { if (i == j) { @Failure(“true”) int fail; } k++; goto l1; } } } • Assume that the loop exits in n = 3 iterations. • Partition the program into 4 segments. Seg. 4 k<i k<i Seg. 3 N Y N Y i==j i==j N Y N Y k<i k<i Seg. 2 i==j i==j k<i k<i Seg. 1 i==j i==j k<i … …

  14. Bounded Loop Execution • Run the tree from the tail. • Repeat computing the failure constraint. • Test for fixpoint. • Reduce the loop into a simple branch. k<i k<i k<i C3 N N N N Y Y Y Y i==j i==j i==j N N N Y Y Y Test 3: C3 C2 k<i k<i i==j i==j Test 2: C2 C1 k<i i==j Test 1: C1

  15. Bounded Loop Execution • 1st execution: 3 paths. • Constraint: [k <= i-1 && i == j] public class B { void f(int i, int j) { int k; k = 0; l1: if (k < i) { if (i == j) { @Failure(“true”) int fail; } k++; goto l1; } } } public class B { void f(int i, int j) { int k = JCute.input.Integer(); if (k < i) { if (i == j) { @Failure(“true”) int fail; } k++; } } } Seg

  16. Bounded Loop Execution • Analyze 1 more iteration. • Re-execute: 4 paths. • Constraint: [k <= i-1 && i == j] (fixpoint) public class B { void f(int i, int j) { int k = JCute.input.Integer(); if (k < i) { if (i == j) { @Failure(“true”) int fail; } k++; if (k < i) { if (i == j) { @Failure(“true”) int fail; } k++; } } } } public class B { void f(int i, int j) { int k = JCute.input.Integer(); if (k < i) { if (i == j) { @Failure(“true”) int fail; } k++; @Failure(“k <= i-1 && i == j”) int fail; } } } public class B { void f(int i, int j) { int k; k = 0; l1: if (k < i) { if (i == j) { @Failure(“true”) int fail; } k++; goto l1; } } } Seg

  17. Bounded Loop Execution • Substitute the whole loop with the fixpoint constraint. • Execute the program: 3 paths. • Constraint: [i >= 1 && i == j] • Total # of paths: 3 + 4 + 3 = 10 public class B { void f(int i, int j) { int k; k = 0; l1: if (k < i) { if (i == j) { @Failure(“true”) int fail; } k++; goto l1; } } } public class B { void f(int i, int j) { int k; k = 0; @Failure(“k <= i-1 && i == j”) int fail; } } Seg

  18. Demo: Eclipse Plugin

  19. Conclusion: Advantage and Drawback • Advantages: • Greatly reduce the number of paths in some cases. • Derive constraints for unbounded loops. • Limitations • Need transformation and compilation every time you want to simplify the program with the newly derived constraints. • Advantage 1 is lost if constraints are not (cannot be) simplified. void f(boolean op1, boolean op2, boolean op3, boolean failure) { if (op1) { System.out.println("Operation 1"); } if (op2) { System.out.println("Operation 2"); } if (op3) { System.out.println("Operation 3"); } @Failure("failure“) int fail; } [op1 && op2 && op3 && failure || op1 && op2 && !op3 && failure || ...] (16 paths) [op2 && op3 && failure || op2 && !op3 && failure || !op2 && op3 && failure || !op2 && !op3 && failure] (8 paths) [op3 && failure || !op3 && failure] (4 paths)

More Related