Pointer and Escape Analysis for Multithreaded Programs by pp00pp

VIEWS: 13 PAGES: 69

• pg 1
```									Pointer and Escape Analysis for

Alexandru Salcianu Martin Rinard
Laboratory for Computer Science
Massachusetts Institute of Technology
{salcianu, rinard}@lcs.mit.edu
Goal

Automatically extract precise points-
to and escape information for

Application
programs which use region-based
memory allocation
Outline

•   Example
•   Analysis
•   Experimental Results
•   Related Work
•   Conclusions
Parallel Fibonacci Computation
Fib(3)
Parallel Fibonacci Computation
Fib(3)

Fib(2)             Fib(1)
Parallel Fibonacci Computation
Fib(3)

Fib(2)                Fib(1)

Fib(1)            Fib(0)
Parallel Fibonacci Computation
Fib(3)

Fib(2)                Fib(1)

Fib(1)             Fib(0)

Parallel Fibonacci Computation
Fib(3)

Fib(2)                    Fib(1)

Fib(1)            Fib(0)

Parallel Fibonacci Computation
Fib(3)

Fib(2)                    Fib(1)

Fib(1)            Fib(0)

Final result
Fibonacci Code
int i = read_input();                  Integer source, target;
Fib f = new Fib(i);
}
public void run() {
class Fib implements Runnable {               int v = source.intValue();
int source;                                  if(v<=1) {
target = value;
Fib(int i) { source = i; }                } else {
t.start();                                int x = t1.target.intValue();
t.join();                                 int y = t2.target.intValue();
System.out.println(t.target);             target = new Integer(x+y);
}                                       }
}                                       }
Parallel Fibonacci Computation
Fib(3)

Fib(2)                    Fib(1)

Fib(1)            Fib(0)

Final result
Impact of Dynamic Object
Allocation
• More garbage collection

• The garbage collection cycles interfere
with the application
• Real time constraints are difficult to
meet

• Try to solve this by exploiting the strong
Solution

Execute each computation in its own memory
region:

• computation allocates its objects in that
region

• when computation ends, all objects are
deallocated

• Good news: no need for garbage collection !

• More predictable programs

• Great for real time applications with
hard time constraints

• Good news: no need for garbage collection !

• More predictable programs

• Great for real time applications with
hard time constraints

• Adopted in the Real Time Specification for
Java (Bollela et al., 2000)
Using Regions in Example

while(1) {
Fib f = new Fib(i);
Region r = new Region();
r.enter(f);
}

r.enter(f) will execute the run() method of f in
the memory region r.

Nested Regions

• Short-lived computations are embedded
into bigger computations
• The nesting of regions corresponds to the
nesting of computations
• Hierarchy of memory regions
• Lifetime of a child region is included in the
Nested Regions Example

Memory
Object
Region
Nested Regions Example

Parent
Object
Memory
Region

Child
Memory
Region
Nested Regions Example

Parent
Object
Memory
Region

Child
Memory
Region
Safety Problem

Parent
Object
Memory
Dangling                Region
reference

Child
Memory
Region
Dynamic Check Approach

Memory
Referencing          Object
Region
Down Regions
Is NOT OK

Referencing
Up Regions
Is OK

Dynamic checks to make sure all references go up
Problems with Dynamic Check
Approach

• Programs have to cope with a new kind of
runtime exception

• Detecting the error at runtime may not be
that useful …
Our Goal

• Analyze the program and statically check
that it never creates dangling references

• If no object is reachable from outside the
computation that creates it, clearly no
dangling references
Dynamic Check Approach

Memory
Referencing         Object
Region
Down Regions
Is NOT OK

Referencing
Up Regions
Is OK
Escaped
object
Our Goal

• Analyze the program and statically check
that it never creates dangling references

• If no object is reachable from outside the
computation that creates it, clearly no
dangling references

• Escape analysis: given a computation, find
out which objects escape from the
computation, i.e., are reachable from
outside the computation
Region Safety Analysis

1. Identify all run() methods that might be
called by Region.enter()
• Each such method + threads it starts
represent one possible computation
2. Use pointer and escape analysis to check
that for every computation, no object
created inside it is reachable from
outside
3. If so, no dangling references
4. Can remove all checks!
Why Do We Need a New Analysis?

• Existing analyses treat threads in a very
conservative way:
• All objects reachable from a thread are
considered to escape
• No attempt is done to recapture them

• But in Fib example, all objects escape into
some thread, but none of them escape the
whole computation
Key Contribution of Analysis

• Can recognize when objects do not escape
• Even when the objects are accessed by
Outline

•   Example
•   Analysis
•   Experimental Results
•   Related Work
•   Conclusions
Analysis Key Features
• Uses graphs to model heap
• Nodes represent objects
• Edges represent references
• Intra-procedural analysis is flow sensitive
• Inter-procedural analysis is bottom-up
• Compositional at both method and thread
level:
• Analyzes a method / thread once,
specializes the result for each use
• Records enough info to analyze the
Nodes
• NI = inside nodes          nI
• represent objects created within the analyzed
part of the program
• one inside node for each object creation site;
represents all objects created at site
• NO = outside nodes         nO
• placeholders for unknown nodes
• will be disambiguated in the inter-procedural/
• key element for compositionality
Outside node types

• NP = parameter nodes
• represent objects passed as incoming
parameters

• represent objects loaded from a node
reachable from outside the analyzed part of
the program
method
Edges
• Used to model heap references

f
• Inside edges         n1          n2

• represent references created by the analyzed
part of the program

f
• Outside edges        n3          n4

• represent heap references read from nodes
reachable from outside the analyzed part of the
program
Escape function

• A node escapes if it is reachable from
outside the analyzed part of the program:
• Parameter nodes escape
• Nodes corresponding to unanalyzed
• Nodes reachable from an escaped node
escape too
• The escape function records how each node
escapes: through a parameter, through an
Parallel Interaction Graph

• Models the result of the execution of the
analyzed part of the program

• Contains:
• Inside edges        Inherited from base
• Outside edges       algorithm for
sequential programs
• Escape function
Key extension for

Improves precision
• Action ordering      of analysis
Intra-procedural analysis
• Analysis scope = one method

• Initial state:
• formals point to parameter nodes
• each parameter nP escapes through
itself: e(nP) = { nP }
• no thread has been started yet

• Transfer functions for each type of
instruction
void static foo() {
b = new C();
a.f = b;
a.start();
c = b.g;
}
void foo() {
b = new C();
a.f = b;
a.start();
c = b.g;
}

a        1
void foo() {
b = new C();
a.f = b;
a.start();
c = b.g;
}

a        1

b        2
void foo() {
b = new C();
a.f = b;
a.start();
c = b.g;
}

a        1
f

b        2
void foo() {
b = new C();
a.f = b;
a.start();
c = b.g;
}

a        1
f

b        2

1 is started
1 and 2 escape into 1
void foo() {
b = new C();
a.f = b;
a.start();
c = b.g;
}

a        1
f

b        2
g

c                      3

1 is started
1 , 2 and 3 escape into 1

• Extends the scope of the analysis from a
method to a method + threads it starts

• Given a program point P
• Find a parallel interaction graph that
reflects the interaction of:
• Current method up to P

• Suppose there is only one started thread

• First step: get the parallel interaction
graph at the end of the run() method of
void foo() {
b = new C();
a.f = b;
a.start();
c = b.g;
}

a        1
f

b        2
g

c                      3

1 is started
1 , 2 and 3 escape into 1
a = new SThread();            public void run() {
b = new C();                    x = this.f;
a.f = b;                        y = new C();
a.start();                      x.g = y;
c = b.g;                      }
}                             }

a        1
f

b        2
g

c                      3

1 is started
1 , 2 and 3 escape into 1
a = new SThread();            public void run() {
b = new C();                    x = this.f;
a.f = b;                        y = new C();
a.start();                      x.g = y;
c = b.g;                      }
}                             }

a        1                  this       4
f
f

b        2                    x                   5
g
g
c                      3      y        6

1 is started
1 , 2 and 3 escape into 1        4 , 5 and 6 escape through 4

• We want to combine the two parallel
interaction graphs in a single one

• Need to disambiguate the outside nodes

• Second step: map the outside nodes from
one graph to nodes from the other graph
• Initial mappings
• Rules for extending them
a = new SThread();            public void run() {
b = new C();                    x = this.f;
a.f = b;                        y = new C();
a.start();                      x.g = y;
c = b.g;                      }
}                             }
2

a        1                  this       4
f
f

b        2                    x                   5
g
g
c                      3      y        6

1 is started
1 , 2 and 3 escape into 1        4 , 5 and 6 escape through 4
a = new SThread();            public void run() {
b = new C();                    x = this.f;
a.f = b;                        y = new C();
a.start();                      x.g = y;
c = b.g;                      }
}                             }
2

a        1                  this       4
f
f           2

b        2                      x                 5
g
g
c                      3        y      6

1 is started
1 , 2 and 3 escape into 1        4 , 5 and 6 escape through 4
a = new SThread();            public void run() {
b = new C();                    x = this.f;
a.f = b;                        y = new C();
a.start();                      x.g = y;
c = b.g;                      }
}                             }
2

a        1                  this       4
f
f           2

b        2                       x                5
g
1
g
c                      3         y     6

1 is started
1 , 2 and 3 escape into 1        4 , 5 and 6 escape through 4
2

a   1                this      4
f
f            2

b   2                      x           5
g
1
g
c               3          y   6
2

a   1                    this      4
f
f                2

b   2                          x           5
g
1
g
c               3              y   6

a   1
f

b   2                5
g
c               3              6
2

a   1                     this         4
f
f                 2

b   2                           x                  5
g
1
g
c               3               y      6

a   1                     Thread 1 has been analyzed;
f                objects no longer escape through it !
Nothing escapes in the new graph !
b   2                5
g
c               3               6
2

a   1                    this        4
f
f                2

b   2                          x                5
g
1
g
c               3              y     6

a   1
f
can be removed
b   2                5
g
c               3              6
2

a   1                 this      4
f
f             2

b   2                       x             5
g
1
g
c               3           y   6

a   1
f        No node escapes from the scope
represented by method foo() +
b   2            the thread it starts.
g

c   6
Final look over the analysis

• What makes the inter-thread analysis
possible?

• Analysis deals with unknown execution
contexts by using placeholders (outside
nodes)

• In the inter-thread analysis, the
matching rules are able to disambiguate
these placeholders
Outline

•   Example
•   Analysis
•   Experimental Results
•   Related Work
•   Conclusions
Analyzed applications

Http     web server
Quote    quote server
Barnes   scientific computation
Water    scientific computation
Tree     synthetic benchmark
Array    synthetic benchmark
Use of regions in the applications

• Http and Quote use one region per each
connection

• Barnes and Water:
• Sequence of computations
• Each computation spawns multiple
threads and executes in its own memory
region
Analysis was able to check that regions
are correctly used!

Analysis vs. Backend time

80
Analysis time
70
Backend time
60

50
seconds

40
30

20

10

0
http   quote barnes   water   tree   array
Execution time
50
45          Original version
40          Checks
35          No checks
seconds

30
25
20
15
10
5
0
http      quote barnes water   tree   array
Outline

•   Motivation
•   Analysis
•   Experimental Results
•   Related Work
•   Conclusions
Related Work
• Standard escape/pointer analyses:
• Blanchet (OOPLSA99)
• Bogda and Hoelzle (OOPSLA99)
• Choi, Gupta, Serrano, Sreedhar and
Midkiff (OOPSLA99)
• Whaley and Rinard (OOPSLA99)

• Any object reachable from a thread is
considered to escape forever
Related Work
• Rugina and Rinard (PLDI 99) go beyond this
but deal only with structured parallelism:
parbegin / parend blocks of code
• We are able to analyze general threads
(POSIX style)

• Ruf (PLDI 00) is able to remove
synchronizations on objects synced on by a
• In some cases, we can do so even for
objects synced on by multiple threads
Outline

•   Motivation
•   Analysis
•   Experimental Results
•   Related Work
•   Conclusions
Conclusions
• Inter-thread analysis is challenging but
possible

• The main use of the analysis will be to check
statically that programs use regions correctly

• Removing dynamic checks can also provide a
modest performance improvement

```
To top