establishing local temporal heap safety properties with applications to compile-time memory...
Post on 19-Dec-2015
219 views
TRANSCRIPT
Establishing Local Temporal Heap Safety Properties with Applications to
Compile-Time Memory Management
Ran Shaham
Eran Yahav
Elliot Kolodner
Mooly Sagiv
Memory deallocation in a timely manner is a hard problem
• Premature deallocation Program errors
• Late deallocation Memory leaks Inefficient use of memory
(Old) Idea: Compile-Time GC
• The compiler can issue free when objects are no longer needed– Object may still be reachable– Potentially collects objects earlier than run-time
garbage collection• Low cost• Candidate for memory/cpu constrained
environments• Difficult for imperative heap-manipulating
programs– No static names for objects– Destructive updates (mutations) x.field=null
Results
• A framework for developing static algorithms for memory management– Compile-Time GC
• Free an unneeded object• Handle destructive updates
– GC assistance • Assign null to heap references• Reduces reachability heap graph• GC exploits information
Plan
• A motivating example program
• The heap safety automaton
• Concrete semantics for deallocating space
• Abstract semantics for deallocating space
• Assign Null
• Summary
A Linked List Example class L { // L is a singly linked list public L n; // next field public int val; // data field } class Main { // Creation and traversal of a singly-linked list public static void main(String args[]) { L x, y, t; [1] x = null; [2] while (...) { // list creation [3] y = new L(); [4] y.val = ...; [5] y.n = x; [6] x = y; } [7] y = x; [8] while (y != null) { // list traversal [9] System.out.print(y.val);[10] t = y.n;[11] y = t; } } }
A Linked List Example class L { // L is a singly linked list public L n; // next field public int val; // data field } class Main { // Creation and traversal of a singly-linked list public static void main(String args[]) { L x, y, t; [1] x = null; [2] while (...) { // list creation [3] y = new L(); [4] y.val = ...; [5] y.n = x; [6] x = y; } [7] y = x; [8] while (y != null) { // list traversal [9] System.out.print(y.val);[10] t = y.n;[11] y = t; } } }
xu1 u2 u3 u7u6
y
u4n nn n n n nu5
A Linked List Example class L { // L is a singly linked list public L n; // next field public int val; // data field } class Main { // Creation and traversal of a singly-linked list public static void main(String args[]) { L x, y, t; [1] x = null; [2] while (...) { // list creation [3] y = new L(); [4] y.val = ...; [5] y.n = x; [6] x = y; } [7] y = x; [8] while (y != null) { // list traversal [9] System.out.print(y.val);[10] t = y.n;[11] y = t; } } }
t
xu1 u2 u3 u7u6
y
u4n nn n n n nu5
A Linked List Example class L { // L is a singly linked list public L n; // next field public int val; // data field } class Main { // Creation and traversal of a singly-linked list public static void main(String args[]) { L x, y, t; [1] x = null; [2] while (...) { // list creation [3] y = new L(); [4] y.val = ...; [5] y.n = x; [6] x = y; } [7] y = x; [8] while (y != null) { // list traversal [9] System.out.print(y.val);[10] t = y.n;[11] y = t; } } }
t
xu1 u2 u3 u7u6
y
u4n nn n n n nu5
A Linked List Example class L { // L is a singly linked list public L n; // next field public int val; // data field } class Main { // Creation and traversal of a singly-linked list public static void main(String args[]) { L x, y, t; [1] x = null; [2] while (...) { // list creation [3] y = new L(); [4] y.val = ...; [5] y.n = x; [6] x = y; } [7] y = x; [8] while (y != null) { // list traversal [9] System.out.print(y.val);[10] t = y.n;[11] y = t; } } }
y t
xu1 u2 u3 u7u6u4
n nn n n n nu5
A Linked List Example class L { // L is a singly linked list public L n; // next field public int val; // data field } class Main { // Creation and traversal of a singly-linked list public static void main(String args[]) { L x, y, t; [1] x = null; [2] while (...) { // list creation [3] y = new L(); [4] y.val = ...; [5] y.n = x; [6] x = y; } [7] y = x; [8] while (y != null) { // list traversal [9] System.out.print(y.val);[10] t = y.n;[11] y = t; } } }
y t
xu1 u2 u3 u7u6u4
n nn n n n nu5
Free Unneeded Objects class L { // L is a singly linked list public L n; // next field public int val; // data field } class Main { // Creation and traversal of a singly-linked list public static void main(String args[]) { L x, y, t; [1] x = null; [2] while (...) { // list creation [3] y = new L(); [4] y.val = ...; [5] y.n = x; [6] x = y; } [7] y = x; [8] while (y != null) { // list traversal [9] System.out.print(y.val);[10] t = y.n; “free y;”[11] y = t; } } }
y t
xu1 u2 u3 u7u6u4
n nn n n n nu5
When can we free an object?
a = malloc(…) ;
b = a;
// free (a); ?
c = malloc (…);
if (b == c) printf(“unexpected equality”);
Cannot free an object if it has a reference with a future use!
When can free x be inserted after p?
pcannot free x
x references an object l
some reference to l is used
On all execution paths after p there are no uses of references to the object referenced by x
inserting free x after p is valid
Computing Free Information
• Forward (history) information– Heap paths– For free x after p
• Aliases of x after p
• Backward (future) information– Use of references– For free x after p
• Future use of aliases of x after p
• Integration of forward and backward heap information– Alternatives
• Integration of an operational semantics and a backward collecting semantics
• Automaton-based solution– Automaton states record “future” information
The Heap Safety Automaton
• Describes a local temporal heap safety property (a typestate property)– Holds on an execution path for an object– Independent of other objects– In an accepting state on an execution path for an
object
• Used for property verification– Automaton does not reach the “err” state– For all execution paths for all objects
free x after p automaton
pcannot free x
x references an object l
some reference to l is used
errinitial refp,x use
0
use refp,x
1
Automaton for an object l
A Concrete Semantics for Deallocating Space
• Program state– “Usual heap information”
• Variable values, Field Values
– Free x after p automaton state• For every object l
• Program statement effect– “Usual semantics”– Trigger automaton events
class L { // L is a singly linked list public L n; // next field public int val; // data field } class Main { // Creation and traversal of a singly-linked list public static void main(String args[]) { L x, y, t; [1] x = null; [2] while (...) { // list creation [3] y = new L(); [4] y.val = ...; [5] y.n = x; [6] x = y; } [7] y = x; [8] while (y != null) { // list traversal [9] System.out.print(y.val);[10] t = y.n;[11] y = t; } } }
Automaton for an object l
Free “y at 10” Automaton
errinitial ref10,y use
0
use ref10,y
1
xu1 u2 u3 u7u6
y
u4n nn n n n nu5
S[0] S[0] S[0] S[0]S[0] S[0]S[0]
class L { // L is a singly linked list public L n; // next field public int val; // data field } class Main { // Creation and traversal of a singly-linked list public static void main(String args[]) { L x, y, t; [1] x = null; [2] while (...) { // list creation [3] y = new L(); [4] y.val = ...; [5] y.n = x; [6] x = y; } [7] y = x; (use x) [8] while (y != null) { // list traversal [9] System.out.print(y.val);[10] t = y.n;[11] y = t; } } }
Automaton for an object l
Free “y at 10” Automaton
errinitial ref10,y use
0
use ref10,y
1
xu1 u2 u3 u7u6
y
u4n nn n n n nu5
S[0] S[0] S[0] S[0]S[0] S[0]S[0]
class L { // L is a singly linked list public L n; // next field public int val; // data field } class Main { // Creation and traversal of a singly-linked list public static void main(String args[]) { L x, y, t; [1] x = null; [2] while (...) { // list creation [3] y = new L(); [4] y.val = ...; [5] y.n = x; [6] x = y; } [7] y = x; [8] while (y != null) { // list traversal [9] System.out.print(y.val);[10] t = y.n;[11] y = t; } } }
Automaton for an object l
Free “y at 10” Automaton
errinitial ref10,y use
0
use ref10,y
1
y t
xu1 u2 u3 u7u6u4
n nn n n n nu5S[0] S[0] S[0] S[0]S[0] S[0]S[0]
class L { // L is a singly linked list public L n; // next field public int val; // data field } class Main { // Creation and traversal of a singly-linked list public static void main(String args[]) { L x, y, t; [1] x = null; [2] while (...) { // list creation [3] y = new L(); [4] y.val = ...; [5] y.n = x; [6] x = y; } [7] y = x; [8] while (y != null) { // list traversal [9] System.out.print(y.val);[10] t = y.n; (use y, use y.n, ref10,y)[11] y = t; } } }
Automaton for an object l
Free “y at 10” Automaton
errinitial ref10,y use
0
use ref10,y
1
y t
xu1 u2 u3 u7u6u4
n nn n n n nu5S[0] S[0] S[0] S[0]S[0] S[0]S[0]
class L { // L is a singly linked list public L n; // next field public int val; // data field } class Main { // Creation and traversal of a singly-linked list public static void main(String args[]) { L x, y, t; [1] x = null; [2] while (...) { // list creation [3] y = new L(); [4] y.val = ...; [5] y.n = x; [6] x = y; } [7] y = x; [8] while (y != null) { // list traversal [9] System.out.print(y.val);[10] t = y.n; (use y, use y.n, ref10,y)[11] y = t; } } }
Automaton for an object l
Free “y at 10” Automaton
errinitial ref10,y use
0
use ref10,y
1
y t
xu1 u2 u3 u7u6u4
n nn n n n nu5S[0] S[0] S[0] S[0]S[0] S[0]S[0]
class L { // L is a singly linked list public L n; // next field public int val; // data field } class Main { // Creation and traversal of a singly-linked list public static void main(String args[]) { L x, y, t; [1] x = null; [2] while (...) { // list creation [3] y = new L(); [4] y.val = ...; [5] y.n = x; [6] x = y; } [7] y = x; [8] while (y != null) { // list traversal [9] System.out.print(y.val);[10] t = y.n; (use y, use y.n, ref10,y)[11] y = t; } } }
Automaton for an object l
Free “y at 10” Automaton
errinitial ref10,y use
0
use ref10,y
1
y t
xu1 u2 u3 u7u6u4
n nn n n n nu5S[0] S[0] S[0] S[0]S[0] S[0]S[0]
class L { // L is a singly linked list public L n; // next field public int val; // data field } class Main { // Creation and traversal of a singly-linked list public static void main(String args[]) { L x, y, t; [1] x = null; [2] while (...) { // list creation [3] y = new L(); [4] y.val = ...; [5] y.n = x; [6] x = y; } [7] y = x; [8] while (y != null) { // list traversal [9] System.out.print(y.val);[10] t = y.n; (use y, use y.n, ref10,y)[11] y = t; } } }
Automaton for an object l
Free “y at 10” Automaton
errinitial ref10,y use
0
use ref10,y
1
y t
xu1 u2 u3 u7u6u4
n nn n n n nu5S[1] S[0] S[0] S[0]S[0] S[0]S[0]
class L { // L is a singly linked list public L n; // next field public int val; // data field } class Main { // Creation and traversal of a singly-linked list public static void main(String args[]) { L x, y, t; [1] x = null; [2] while (...) { // list creation [3] y = new L(); [4] y.val = ...; [5] y.n = x; [6] x = y; } [7] y = x; [8] while (y != null) { // list traversal [9] System.out.print(y.val);[10] t = y.n; (use y, use y.n, ref10,y)[11] y = t; } } }
Automaton for an object l
Free “y at 10” Automaton
errinitial ref10,y use
0
use ref10,y
1
y t
xu1 u2 u3 u7u6u4
n nn n n n nu5S[1] S[1] S[1] S[0]S[0] S[0]S[1]
Abstract Semantics for Deallocating Space –
Challenges• Infinite states
– Number of objects is unbounded
• Precise heap path information– Precise Association of
• an event• corresponding automaton state of a program object
• Our framework– Allows a rather precise heap abstraction– Abstraction refinement
• automaton state of each program object
Abstract Semantics for Deallocating Space
• Program state– Heap Abstraction
• Parametric Shape Analysis [SRW02]• Based on 3-valued logical structures
– Automaton States• Unary predicates s[q]• q ranges over automaton states
• Program statement effect– Shape analysis abstract transformers– Events associated with every statement update s[q]
• Property Verification– s[err] does not hold
Automaton for an object l
Free “y at 10” Automaton class L { // L is a singly linked list public L n; // next field public int val; // data field } class Main { // Creation and traversal of a singly-linked list public static void main(String args[]) { L x, y, t; [1] x = null; [2] while (...) { // list creation [3] y = new L(); [4] y.val = ...; [5] y.n = x; [6] x = y; } [7] y = x; [8] while (y != null) { // list traversal [9] System.out.print(y.val);[10] t = y.n;[11] y = t; } } }
errinitial ref10,y use
0
use ref10,y
1
x S[1]
y
S[0]n n n
S[1]
nt
S[0]n
n
S[0]
Automaton for an object l
Free “y at 10” Automaton class L { // L is a singly linked list public L n; // next field public int val; // data field } class Main { // Creation and traversal of a singly-linked list public static void main(String args[]) { L x, y, t; [1] x = null; [2] while (...) { // list creation [3] y = new L(); [4] y.val = ...; [5] y.n = x; [6] x = y; } [7] y = x; [8] while (y != null) { // list traversal [9] System.out.print(y.val);[10] t = y.n; (use y, use y.n, ref10,y)[11] y = t; } } }
errinitial ref10,y use
0
use ref10,y
1
x S[1]
y
S[0]n n n
S[1]
nt
S[0]n
n
S[0]
Automaton for an object l
Free “y at 10” Automaton class L { // L is a singly linked list public L n; // next field public int val; // data field } class Main { // Creation and traversal of a singly-linked list public static void main(String args[]) { L x, y, t; [1] x = null; [2] while (...) { // list creation [3] y = new L(); [4] y.val = ...; [5] y.n = x; [6] x = y; } [7] y = x; [8] while (y != null) { // list traversal [9] System.out.print(y.val);[10] t = y.n; (use y, use y.n, ref10,y)[11] y = t; } } }
errinitial ref10,y use
0
use ref10,y
1
x S[1]
y
S[0]n n n
S[1]
nt
S[0]n
n
S[0]
Automaton for an object l
Free “y at 10” Automaton class L { // L is a singly linked list public L n; // next field public int val; // data field } class Main { // Creation and traversal of a singly-linked list public static void main(String args[]) { L x, y, t; [1] x = null; [2] while (...) { // list creation [3] y = new L(); [4] y.val = ...; [5] y.n = x; [6] x = y; } [7] y = x; [8] while (y != null) { // list traversal [9] System.out.print(y.val);[10] t = y.n; (use y, use y.n, ref10,y)[11] y = t; } } }
errinitial ref10,y use
0
use ref10,y
1
x S[1]
y
S[0]n n n
S[1]
nt
S[0]n
n
S[0]
Automaton for an object l
Free “y at 10” Automaton class L { // L is a singly linked list public L n; // next field public int val; // data field } class Main { // Creation and traversal of a singly-linked list public static void main(String args[]) { L x, y, t; [1] x = null; [2] while (...) { // list creation [3] y = new L(); [4] y.val = ...; [5] y.n = x; [6] x = y; } [7] y = x; [8] while (y != null) { // list traversal [9] System.out.print(y.val);[10] t = y.n; (use y, use y.n, ref10,y)[11] y = t; } } }
errinitial ref10,y use
0
use ref10,y
1
x S[1]
y
S[1]n n n
S[1]
nt
S[0]n
n
S[0]
Assign Null
• Allows GC to collect more space– Reduces heap reachability
• Assign-Null automaton– Contains “back-edges”
When can x.f = null be inserted after p?
pp’
x.f cannot be assigned null
On all execution paths after p, x.f is not used before redefinition
inserting x.f = null after p is valid
field f of object l is not assigned
field f of object l is used
x references an object l
pp’field f of object l
is not assigned
field f of object l is used
errinitial refp,x usef0
usef,deff refp,x
1
deff
x.f cannot be assigned null
x references an object l
When can x.f = null be inserted after p?
pp’field f of object l
is not assigned
field f of object l is used
errinitial refp,x usef0
usef,deff refp,x
1
deff
x.f cannot be assigned null
x references an object l
When can x.f = null be inserted after p?
pp’field f of object l
is not assigned
field f of object l is used
errinitial refp,x usef0
usef,deff refp,x
1
deff
x.f cannot be assigned null
x references an object l
When can x.f = null be inserted after p?
pp’field f of object l
is not assigned
field f of object l is used
errinitial refp,x usef0
usef,deff refp,x
1
deff
x.f cannot be assigned null
x references an object l
When can x.f = null be inserted after p?
pp’field f of object l
is not assigned
field f of object l is used
errinitial refp,x usef0
usef,deff refp,x
1
deff
x.f cannot be assigned null
x references an object l
When can x.f = null be inserted after p?
Prototype Implementation
• Analysis of Java/JavaCard programs
• Precise– Points-to is not enough
• Even when it is flow-sensitive, field-sensitive with unbounded context [Emami et al. – PLDI 94]
• Scalability issues– Interprocedural shape analysis
Related Work
• Memory Management– Compile-Time GC
• Mostly for functional languages
– Escape Analysis• Limited to objects not escaping their allocating method
– Region-based memory management• Usually requires programmer awareness
• Software verification of safety properties– Bandera, ESP, SLAM
• Precision• Application domain
Summary
• Statically identify a subset of unneeded objects • Free
– Free an unneeded object– Similar to compile-time GC studied for functional languages
• We need to handle destructive updates
• Assign null – Assign null to heap references– Reduces reachability heap graph– GC exploits information
• Identify potential errors– Issue a warning when a potentially needed object is reclaimed
• False alarms may arise
• A framework– Formulate compile-time memory management as a verification
problem