Title: Heap liveness and its usage in automatic memory management
1 Heap liveness and its usage in automatic
memory management
- Ran Shaham
- Elliot Kolodner
- Mooly Sagiv
TVLA inside
http//www.cs.tau.ac.il/ransh/
2Motivation
- An object could be collected once it is no longer
needed - Yet, run-time garbage collectors (RTGCs) are
typically based on reachability - Profiling tools can detect when objects are
needed - The compiler can
- Statically identify a subset of unneeded objects
- Issue a free instruction (compile-time Garbage
Collection) - Issue a warning when a potentially needed object
is reclaimed - Inform run-time garbage collector that a
reference to an object is not further used
3A Pathological C Program
a malloc() b a free (a) c malloc
() if (b c) printf(unexpected equality)
4Inefficient Java Class
- public Class Stack
- private Object stack
- private int top
- public Stack(int len)
- stack new Objectlen
- top 0
-
- public synchronized Object pop()
- top top-1
- return stacktop
-
- public synchronized void push(Object o)
- stacktopo
- top top1
-
- public synchronized void print()
- for (int i0 ilttop i)
- System.out.println(stacki)
-
GC does not reclaim the memory stacktop1
5Needed Location
l is needed
a reference to l is used
p
p
l is allocated
6Needed Reference Expression
a reference to l is used
e is needed
p
p
l is allocated
e references l
e is not needed ? free(e) is valid
7A Pathological C Program
a malloc() b a free (a) c malloc
() if (b c) printf(unexpected equality)
a is needed
8Location Liveness
l is live
l is used
p
p
l is not assigned
9Reference Expression Liveness
e is live
l is used
p
p
l is not assigned
e denotes a location l
Generalizes liveness of program variables when l
is x
10Inefficient Java Class
- public Class Stack
- private Object stack
- private int top
- public Stack(int len)
- stack new Objectlen
- top 0
-
- public synchronized Object pop()
- top top-1
- return stacktop
-
- public synchronized void push(Object o)
- stacktopo
- top top1
-
- public synchronized void print()
- for (int i0 ilttop i)
- System.out.println(stacki)
-
stacktop1 is not live
11Typical GC Limits
- class Node
- Node left, right
- int data
-
- class C
- void main()
- Node root createTree()
- processTree(root.right)
-
root
12Typical GC Limits
- class Node
- Node left, right
- int data
-
- class C
- void main()
- Node root createTree()
- processTree(root.right)
-
root
13Typical GC Limits
- class Node
- Node left, right
- int data
-
- class C
- void main()
- Node root createTree()
- processTree(root.right)
-
root
14Liveness Analysis Aids GC
- class Node
- Node left, right
- int data
-
- class C
- void main()
- Node root createTree()
- processTree(root.right)
-
root
root.right is live, root.left is dead
15Liveness Analysis Aids GC
- class Node
- Node left, right
- int data
-
- class C
- void main()
- Node root createTree()
- processTree(root.right)
-
root
root.right is live, root.left is dead
16Liveness Analysis Aids GC
- class Node
- Node left, right
- int data
-
- class C
- void main()
- Node root createTree()
- processTree(root.right)
-
root
root.right is live, root.left is dead
17Liveness Analysis Aids GC
- class Node
- Node left, right
- int data
-
- class C
- void main()
- Node root createTree()
- processTree(root.right)
-
root
root.right is live, root.left is dead
18Typical GC Limits
Program Variables
a
b
c
d
e
f
19Outline
- Dynamic liveness measurements
- Complete location liveness
- Assign-null interface
- Static analysis algorithms
- (Exact) assign null (improve GC)
- (Exact) free (CTGC)
20Dynamic Liveness Measurements
- Estimating the potential of static analysis
- Find upper bounds on expected savings
- Can be used in as an assistant tool
- Liveness information kinds
- Stack reference liveness
- Global reference liveness
- Heap reference liveness
21Main Results
- Dynamic measurements for 10 benchmarks
- Shallow information ? Small Potential
- local variables 2
- global variables 5
- local global 9
- Deep information ? Larger Potential
- heap liveness 39 complete location liveness
15 assign-null
interface
22Dynamic measurements
- Implemented via an instrumented JVM
- Complete location liveness measurements
- Single-run algorithm
- Assign-null liveness interface
- Determines the liveness of expressions
- Assign null to dead reference expressions
- Requires two runs of the program
23Complete Liveness Measurements
- An Observation
- The last use of the references to an object
determines the time an object could be collected
assuming liveness information
24Heap Liveness Example I
Stack
use z.f
? t
x
f
y
f1
f2
z
HeapL t
HeapL
f
f
f
Static
g
25Heap Liveness Example I
Stack
use y.f2
? t2
x
f
y
f1
f2
z
HeapL t2
HeapL t
f
f
f
Static
g
26Heap Liveness Example II
Stack
? t
StackR Directly stack reachable (computed
during GC)
x
f
StackR t
HeapL t
y
f1
Collection time max(t, t)
f2
z
f
f
f
Static
g
Collection time(obj) max(HeapL(obj),
StackR(obj), StaticR(obj), OtherR(obj))
27Stack Liveness Example I
Stack
use z Current Time t
x
f
y
f1
f2
z
f
f
StackL t
StackL
f
Static
g
28Stack Liveness Example I
Stack
use y Current Time t2
x
f
y
f1
StackL t2
f2
z
f
f
StackL t
f
Static
g
29Stack Liveness Example I
Stack
StackL path starting with a live stack
root (computed during GC trace phase)
x
f
y
f1
StackL t2
f2
z
f
f
StackL t
f
Static
g
30Stack Liveness Example I
Stack
StackL path starting with a live stack
root (computed during GC trace phase)
x
f
y
f1
StackL t2
f2
z
StackL t2
f
f
StackL t
f
Static
g
31Stack Liveness Example II
Stack
StaticR path starting with a static
root (computed during GC trace phase)
x
f
y
f1
StackL t2
f2
z
StackL t2
f
f
StackL t2 StaticR t
StackL t
f
Static
Collection time max(t2, t)
g
StaticR t
Collection time(obj) max(StackL(obj),
StaticR(obj), OtherR(obj))
32Property Intended Meaning
heapL(obj) obj is referenced by a live heap reference at time heapL(obj)
stackL(obj) obj is referenced by a live stack root at time stackL(obj)
stackL(obj) obj is reachable along a path starting from a live stack root at time stackL(obj)
stackR(obj) obj is referenced by a stack root at time stackR(obj)
stackR(obj) obj is reachable along a path starting from a stack root at time stackR(obj)
staticL(obj) obj is referenced by a live static root at time staticL(obj)
staticL(obj) obj is reachable along a path starting from a live static root at time staticl(obj)
staticR(obj) obj is referenced by a static root at time staticR(obj)
staticR(obj) obj is reachable along a path starting from a static root at time staticR(obj)
otherR(obj) obj is referenced by an other root at time otherR(obj)
otherR(obj) obj is reachable along a path starting from an other root at time otherR(obj)
33Complete Liveness Summary
- Mutator
- Tracks the last use of references to an object
- Collector
- Propagation needed for stack/static liveness
- Propagates reachability information
- Propagates path liveness
- Object Collection/Program Termination
- Maximum of liveness/reachability properties of an
object - Depends on liveness scheme (heap liveness etc.)
34Experimental Results
- Instrumented Suns classic JVM (1.2)
- 10 benchmarks (5 SPECjvm)
- Time is measured bytes allocated by the mutator
so far in program - Total space savings (integral)
- Maximum heap size savings (footprint)
35(No Transcript)
36Potential Savings Total Space
37Restricted GC Interface
- GC Interface
- Should be simple/effective/efficient
- Feasible heap liveness representation
- Assign null to dead heap references
- Simple
- Effective?
- Partially answered by our experiments
- Efficient?
- Will be answered by static analysis
38Null Assignable Program Points
- Normalized statements (Java Bytecode)
- Manipulate at most one heap reference
- x y.f is null assignable
- Could be followed by y.f null
- Dynamic algorithm
- First run
- Determine null assignable program points
- Assume all program points are null assignable
- Detect non-null-assignable program points during
the run - Second run
- Assign null in null assignable program points
39Doubly-Linked List Example First Run
// processing list elements in pairs pt1
y x.n // x.n null x
null while (y ! null) pt2 t
y.p // y.p null pt3 d1 t.d
// t.d null pt4 d2 y.d
// y.d null process(d1, d2) pt5
t y.n // y.n null y
t
n
x
p
d
d
40Doubly-Linked List Example First Run
// processing list elements in pairs pt1
y x.n // x.n null x
null while (y ! null) pt2 t
y.p // y.p null pt3 d1 t.d
// t.d null pt4 d2 y.d
// y.d null process(d1, d2) pt5
t y.n // y.n null y
t
y
n
pt1
x
p
d
d
41Doubly-Linked List Example First Run
// processing list elements in pairs pt1
y x.n // x.n null x
null while (y ! null) pt2 t
y.p // y.p null pt3 d1 t.d
// t.d null pt4 d2 y.d
// y.d null process(d1, d2) pt5
t y.n // y.n null y
t
y
t
n
pt1
pt2
p
d
d
42Doubly-Linked List Example First Run
// processing list elements in pairs pt1
y x.n // x.n null x
null while (y ! null) pt2 t
y.p // y.p null pt3 d1 t.d
// t.d null pt4 d2 y.d
// y.d null process(d1, d2) pt5
t y.n // y.n null y
t
y
t
n
pt1
pt2
p
pt3
d
d
d1
43Doubly-Linked List Example First Run
// processing list elements in pairs pt1
y x.n // x.n null x
null while (y ! null) pt2 t
y.p // y.p null pt3 d1 t.d
// t.d null pt4 d2 y.d
// y.d null process(d1, d2) pt5
t y.n // y.n null y
t
y
t
n
pt1
pt2
p
pt3
d
d
pt4
d2
d1
44Doubly-Linked List Example First Run
// processing list elements in pairs pt1
y x.n // x.n null x
null while (y ! null) pt2 t
y.p // y.p null pt3 d1 t.d
// t.d null pt4 d2 y.d
// y.d null process(d1, d2) pt5
t y.n // y.n null y
t
y
t
n
pt1
pt5
pt2
p
pt3
d
d
pt4
d2
d1
45Doubly-Linked List Example First Run
// processing list elements in pairs pt1
y x.n // x.n null x
null while (y ! null) pt2 t
y.p // y.p null pt3 d1 t.d
// t.d null pt4 d2 y.d
// y.d null process(d1, d2) pt5
t y.n // y.n null y
t
t
y
n
pt1
pt5
pt2
pt2
p
pt3
d
d
pt4
d2
d1
46Doubly-Linked List Example First Run
// processing list elements in pairs pt1
y x.n // x.n null x
null while (y ! null) pt2 t
y.p // y.p null pt3 d1 t.d
// t.d null pt4 d2 y.d
// y.d null process(d1, d2) pt5
t y.n // y.n null y
t
t
y
n
pt1
pt5
pt2
pt1
p
pt3
pt4
d
d
pt3
d2
d1
47Doubly-Linked List Example First Run
// processing list elements in pairs pt1
y x.n // x.n null x
null while (y ! null) pt2 t
y.p // y.p null pt3 d1 t.d
// t.d null pt4 d2 y.d
process(d1, d2) pt5 t y.n
// y.n null y t
n
pt1
pt5
pt2
pt3
p
pt3
d
d
pt3
pt3
d1
d2
48Doubly-Linked List Example - Second Run
// processing list elements in pairs pt1
y x.n x.n null x
null while (y ! null) pt2 t
y.p y.p null pt3 d1 t.d
t.d null pt4 d2 y.d
process(d1, d2) pt5 t y.n
y.n null y t
n
x
p
d
d
49Doubly-Linked List Example - Second Run
// processing list elements in pairs pt1
y x.n x.n null x
null while (y ! null) pt2 t
y.p y.p null pt3 d1 t.d
t.d null pt4 d2 y.d
process(d1, d2) pt5 t y.n
y.n null y t
t
y
n
n
p
p
d
d
d
d2
d1
50Doubly-Linked List Example - Second Run
// processing list elements in pairs pt1
y x.n x.n null x
null while (y ! null) pt2 t
y.p y.p null pt3 d1 t.d
t.d null pt4 d2 y.d
process(d1, d2) pt5 t y.n
y.n null y t
t
y
n
p
d
d
d2
d1
51- 15 average savings for context 2
- 11 assigning null to instance fields
- 10 assigning null to array elements
- Results are valid across runs
- Detecting null assignable program points on a
second input - Running the program with the first input
- null assignable program points are those detected
for both inputs
52Related Work
- On the Usefulness of Liveness for Garbage
Collection and Leak Detection HDH01 - Does not handle heap liveness
- Algorithm requires two runs
- First run record uses and defs
- Analyze log backwards for liveness information
- Second run use liveness results
- Garbage Collection and Local Variable
Type-Precision and Liveness in Java Virtual
Machines ADM98 - Stack liveness static analysis
- Actual trends match our upper bounds
- On the Effectiveness of GC in Java SKS00
- Drag information
- Slightly larger potential than heap liveness
information - Not clear how to automate space savings
- HUP tool (PLDI01 M. Pan)
53Dynamic liveness measurements -Conclusion
- Liveness Information has large potential
- Assign null savings achievable by static
analysis - Stack liveness information
- Small potential
- Stackstatic liveness information
- Medium potential
- Heap liveness information
- Is feasible
- Recording history on heap is a powerful mechanism
- Larger potential
- Depends on static analysis precision
- Depends on GC interface
54Static Analysis
- Combine history with shape analysis
- a-La- Horwitz, Pfeiffer, and Reps 1989
- Assign null
- Assign null to a dead reference expression
- GC exploits information
- Free
- free an unneeded object
55Assign Null Analysis
- Insert x.fld null after statements in which
the expression x.fld becomes dead - Limitations
- Only one reference is assigned null
- All the paths to the statement must agree
- Detects last-use
- Technically
- llastupt,x.fld(v)
- The last use of the location denoted by x.fld
occurs at pt - nullpt,x.fld()
- It is safe to insert x.fld null after pt
56Assign Null Example
// traversing list elements pt1 y
x pt2 while (y ! null) pt3 t
y.n pt4 y t
n
n
nullpt3,y.n
x
57Assign Null Example
// traversing list elements pt1 y
x pt2 while (y ! null) pt3 t
y.n pt4 y t
n
n
nullpt3,y.n
x,y
58Assign Null Example
// traversing list elements pt1 y
x pt2 while (y ! null) pt3 t
y.n pt4 y t
n
n
nullpt3,y.n
x,y
59Assign Null Example
// traversing list elements pt1 y
x pt2 while (y ! null) pt3 t
y.n pt4 y t
t
n
n
n
nullpt3,y.n
x,y
llastupt3,y.n
60Assign Null Example
// traversing list elements pt1 y
x pt2 while (y ! null) pt3 t
y.n pt4 y t
y,t
n
n
n
nullpt3,y.n
x
llastupt3,y.n
61Assign Null Example
// traversing list elements pt1 y
x pt2 while (y ! null) pt3 t
y.n pt4 y t
y,t
n
n
n
nullpt3,y.n
x
llastupt3,y.n
62Assign Null Example
// traversing list elements pt1 y
x pt2 while (y ! null) pt3 t
y.n pt4 y t
nullpt3,y.n
y
t
n
n
n
n
x
llastupt3,y.n
llastupt3,y.n
63Assign Null Example
// traversing list elements pt1 y
x pt2 while (y ! null) pt3 t
y.n pt4 y t
nullpt3,y.n
y,t
n
n
n
n
x
llastupt3,y.n
llastupt3,y.n
64Assign Null Example
// traversing list elements pt1 y
x pt2 while (y ! null) pt3 t
y.n pt4 y t
nullpt3,y.n
y,t
n
n
n
n
x
llastupt3,y.n
llastupt3,y.n
65Assign Null Example
// traversing list elements pt1 y
x pt2 while (y ! null) pt3 t
y.n pt4 y t
nullpt3,y.n
y
t
n
n
n
n
n
llastupt3,y.n
x
llastupt3,y.n
llastupt3,y.n
66Assign Null Example
// traversing list elements pt1 y
x pt2 while (y ! null) pt3 t
y.n pt4 y t
nullpt3,y.n
n
y,t
n
n
n
n
llastupt3,y.n
x
llastupt3,y.n
67Assign Null Example
// traversing list elements pt1 y
x pt2 while (y ! null) pt3 t
y.n pt4 y t
n
y,t
n
n
n
n
llastupt3,y.n
x
llastupt3,y.n
68Assign Null Example
// traversing list elements pt1 y
x pt2 while (y ! null) pt3 t
y.n pt4 y t
nullpt3,y.n
n
y
t
n
n
n
n
n
llastupt3,y.n
x
llastupt3,y.n
llastupt3,y.n
69Assign Null Example
// traversing list elements pt1 y
x pt2 while (y ! null) pt3 t
y.n pt4 y t
nullpt3,y.n
n
y,t
n
n
n
n
x
llastupt3,y.n
llastupt3,y.n
70Assign Null Example
// traversing list elements pt1 y
x pt2 while (y ! null) pt3 t
y.n pt4 y t
nullpt3,y.n
n
y,t
n
n
n
n
x
llastupt3,y.n
llastupt3,y.n
71Assign Null Example
// traversing list elements pt1 y
x pt2 while (y ! null) pt3 t
y.n pt4 y t
nullpt3,y.n
n
y
n
n
llastupt3,y.n
x
llastupt3,y.n
llastupt3,y.n
72Assign Null Example
// traversing list elements pt1 y
x pt2 while (y ! null) pt3 t
y.n pt4 y t
nullpt3,y.n
n
n
x
llastupt3,y.n
llastupt3,y.n
73Assign Null Example
// traversing list elements pt1 y
x pt2 while (y ! null) pt3 t
y.n pt4 y t
nullpt3,y.n
n
n
x
llastupt3,y.n
llastupt3,y.n
74Compile-Time Garbage Collection
- Static Reachability Information
Static Liveness Information
CT garbage
detection - Issue free(e) for unneeded e
75Exact Free Analysis
- Insert free(x) at program points when the x
becomes unneeded - Only one location is freed
- All the paths to the statement must agree on the
garbage - History predicates
- lastupt,x(v)
- the last use of the location pointed-to by x
occurs - unneeded pt,x()
- free(x) is safe after pt
76Exact Free Example
// traversing list elements pt1 y
x pt2 while (y ! null) pt3 t
y.n pt4 y t
n
unneededpt1,x unneededpt2,y unneededpt3,y un
neededpt4,t
n
x
77Exact unneeded Example
// traversing list elements pt1 y
x pt2 while (y ! null) pt3 t
y.n pt4 y t
n
unneededpt1,x unneededpt2,y unneededpt3,y un
neededpt4,t
n
x,y
lastupt1,x
78Exact Free Example
// traversing list elements pt1 y
x pt2 while (y ! null) pt3 t
y.n pt4 y t
n
n
unneededpt2,y unneededpt3,y unneededpt4,t
x,y
lastupt2,y
79Exact Free Example
// traversing list elements pt1 y
x pt2 while (y ! null) pt3 t
y.n pt4 y t
t
n
n
n
unneededpt3,y unneededpt4,t
x,y
lastupt3,y
80Exact Free Example
// traversing list elements pt1 y
x pt2 while (y ! null) pt3 t
y.n pt4 y t
y,t
n
n
n
unneededpt3,y unneededpt4,t
x
lastupt4,t
lastupt3,y
81Exact Free Example
// traversing list elements pt1 y
x pt2 while (y ! null) pt3 t
y.n pt4 y t
y,t
n
n
n
unneededpt3,y
x
lastupt2,y
lastupt3,y
82Exact Free Example
// traversing list elements pt1 y
x pt2 while (y ! null) pt3 t
y.n pt4 y t
unneededpt3,y
y
t
n
n
n
n
x
lastupt3,y
lastupt3,y
83Exact Free Example
// traversing list elements pt1 y
x pt2 while (y ! null) pt3 t
y.n pt4 y t
unneededpt3,y
y,t
n
n
n
n
lastupt4,t
x
lastupt3,y
lastupt3,y
84Exact Free Example
// traversing list elements pt1 y
x pt2 while (y ! null) pt3 t
y.n pt4 y t
unneededpt3,y
y,t
n
n
n
n
lastupt2,y
x
lastupt3,y
lastupt3,y
85Exact Free Example
// traversing list elements pt1 y
x pt2 while (y ! null) pt3 t
y.n pt4 y t
unneededpt3,y
y
t
n
n
n
n
n
lastupt3,y
x
lastupt3,y
lastupt3,y
86Exact Free Example
// traversing list elements pt1 y
x pt2 while (y ! null) pt3 t
y.n pt4 y t
unneededpt3,y
n
y,t
n
n
n
n
lastupt3,y
lastupt4,t
x
lastupt3,y
87Exact Free Example
// traversing list elements pt1 y
x pt2 while (y ! null) pt3 t
y.n pt4 y t
unneededpt3,y
n
y,t
n
n
n
n
lastupt3,y
lastupt2,y
x
lastupt3,y
88Exact Free Example
// traversing list elements pt1 y
x pt2 while (y ! null) pt3 t
y.n pt4 y t
unneededpt3,y
n
y
t
n
n
n
n
n
lastupt3,y
x
lastupt3,y
lastupt3,y
89Exact Free Example
// traversing list elements pt1 y
x pt2 while (y ! null) pt3 t
y.n pt4 y t
unneededpt3,y
n
y,t
n
n
n
n
lastupt4,t
x
lastupt3,y
lastupt3,y
90Exact Free Example
// traversing list elements pt1 y
x pt2 while (y ! null) pt3 t
y.n pt4 y t
unneededpt3,y
n
y,t
n
n
n
n
lastupt2,y
x
lastupt3,y
lastupt3,y
91Exact Free Example
// traversing list elements pt1 y
x pt2 while (y ! null) pt3 t
y.n pt4 y t
unneededpt3,y
n
y
n
n
lastupt3,y
x
lastupt3,y
lastupt3,y
92Exact Free Example
// traversing list elements pt1 y
x pt2 while (y ! null) pt3 t
y.n pt4 y t
unneededpt3,y
n
n
x
lastupt3,y
lastupt3,y
93Exact Free Example
// traversing list elements pt1 y
x pt2 while (y ! null) pt3 t
y.n pt4 y t
unneededpt3,y
n
n
x
lastupt3,y
lastupt3,y
94Preliminary Conclusions
- Heap Liveness is useful
- Can be dynamically computed for large programs
- More data is needed to confirm scalability of
static analysis - Recording local history is a powerful tool
- Refines the abstraction