9.1 anagram—a modular java framework for high-performance ...
JPure: a Modular Purity System for Java
-
Upload
penelope-duncan -
Category
Documents
-
view
30 -
download
2
description
Transcript of JPure: a Modular Purity System for Java
![Page 1: JPure: a Modular Purity System for Java](https://reader034.fdocuments.in/reader034/viewer/2022052603/56813391550346895d9a9f02/html5/thumbnails/1.jpg)
JPure: a Modular Purity System for Java
David J. PearceVictoria University of Wellington
New Zealand
![Page 2: JPure: a Modular Purity System for Java](https://reader034.fdocuments.in/reader034/viewer/2022052603/56813391550346895d9a9f02/html5/thumbnails/2.jpg)
Introduction
int sum(int[] items) {
int r = 0;
for(int v : items) { r += v; }
return r;
}
Definition: A method is considered pure if it does not assign (directly of indirectly) to any field or array cell that existed before it was called.
boolean isSorted(List<Integer> items) {
int last = Integer.MIN_VALUE;
for(Integer v : items) {
if(last > v) { return false; }
last = v;
}
return true;
}
![Page 3: JPure: a Modular Purity System for Java](https://reader034.fdocuments.in/reader034/viewer/2022052603/56813391550346895d9a9f02/html5/thumbnails/3.jpg)
Typical Previous Purity Systems
• Pointer Analysis feeds Purity Inference
– Pointer Analysis typically whole-program
– Inferred annotations cannot be checked easily• i.e. without regeneration pointer information
PointerAnalysis
?
Java Source Annotated Source
Annotated Bytecode
PurityInference
![Page 4: JPure: a Modular Purity System for Java](https://reader034.fdocuments.in/reader034/viewer/2022052603/56813391550346895d9a9f02/html5/thumbnails/4.jpg)
Modular Purity System
• Purity Inference:
– Generates annotations via interprocedural analysis
– Generated annotations are modularly checkable
• Purity Checker:
– Verifies annotations via intraprocedural analysis
– Integrates easily with Java Bytecode Verification
PurityInference
PurityChecker
Java Source Annotated Source
Annotated Bytecode
Java Compiler
![Page 5: JPure: a Modular Purity System for Java](https://reader034.fdocuments.in/reader034/viewer/2022052603/56813391550346895d9a9f02/html5/thumbnails/5.jpg)
Simple (Modular) Approach
• Pure Methods:
– Cannot contain field assignments
– Can only call methods marked @Pure
– Only pure methods can override pure methods
Parent
private int afield;
@Pure void method() { }
Child
@Pure void method() { }
Client
@Pure void f(Parent p) {
p.method();
}
![Page 6: JPure: a Modular Purity System for Java](https://reader034.fdocuments.in/reader034/viewer/2022052603/56813391550346895d9a9f02/html5/thumbnails/6.jpg)
Simple (Modular) Approach
• Pure Methods:
– Cannot contain field assignments
– Can only call methods marked @Pure
– Only pure methods can override pure methods
Parent
private int afield;
@Pure void method() { }
Child
@Pure void method() { }
Client
@Pure void f(Parent p) {
p.method();
}
![Page 7: JPure: a Modular Purity System for Java](https://reader034.fdocuments.in/reader034/viewer/2022052603/56813391550346895d9a9f02/html5/thumbnails/7.jpg)
Simple (Modular) Approach
• Pure Methods:
– Cannot contain field assignments
– Can only call methods marked @Pure
– Only pure methods can override pure methods
Parent
private int f;
@Pure void method(){f=1;}
Child
@Pure void method() { }
Client
@Pure void f(Parent p) {
p.method();
}
![Page 8: JPure: a Modular Purity System for Java](https://reader034.fdocuments.in/reader034/viewer/2022052603/56813391550346895d9a9f02/html5/thumbnails/8.jpg)
Simple (Modular) Approach
• Pure Methods:
– Cannot contain field assignments
– Can only call methods marked @Pure
– Only pure methods can override pure methods
Child
@Pure void method() { }
Client
@Pure void f(Parent p) {
p.method();
}
![Page 9: JPure: a Modular Purity System for Java](https://reader034.fdocuments.in/reader034/viewer/2022052603/56813391550346895d9a9f02/html5/thumbnails/9.jpg)
Simple (Modular) Approach
• Pure Methods:
– Cannot contain field assignments
– Can only call methods marked @Pure
– Only pure methods can override pure methods
Parent
private int afield;
@Pure void method() { }
Client
@Pure void f(Parent p) {
p.method();
}
![Page 10: JPure: a Modular Purity System for Java](https://reader034.fdocuments.in/reader034/viewer/2022052603/56813391550346895d9a9f02/html5/thumbnails/10.jpg)
Problems
public class AbstractStringBuilder {
private char[] data;
private int count; // number of items used
public AbstractStringBuilder append(String s) {
…
s.getChars(0, s.length(), data, count);
}}
@Pure String f(String x) { return x + “hello”; }
public class Test {
private List<String> items;
@Pure boolean has(String s) {
for(String i : items) {
if(s == i) { return true; }
}
return false;
} }
![Page 11: JPure: a Modular Purity System for Java](https://reader034.fdocuments.in/reader034/viewer/2022052603/56813391550346895d9a9f02/html5/thumbnails/11.jpg)
Problems
public class AbstractStringBuilder {
private char[] data;
private int count; // number of items used
public AbstractStringBuilder append(String s) {
…
s.getChars(0, s.length(), data, count);
}}
@Pure String f(String x) { return x + “hello”; }
public class Test {
private List<String> items;
@Pure boolean has(String s) {
for(String i : items) {
if(s == i) { return true; }
}
return false;
} }
![Page 12: JPure: a Modular Purity System for Java](https://reader034.fdocuments.in/reader034/viewer/2022052603/56813391550346895d9a9f02/html5/thumbnails/12.jpg)
Problems
public class AbstractStringBuilder {
private char[] data;
private int count; // number of items used
public AbstractStringBuilder append(String s) {
…
s.getChars(0, s.length(), data, count);
}}
@Pure String f(String x) { return x + “hello”; }
public class Test {
private List<String> items;
@Pure boolean has(String s) {
for(String i : items) {
if(s == i) { return true; }
}
return false;
} }
![Page 13: JPure: a Modular Purity System for Java](https://reader034.fdocuments.in/reader034/viewer/2022052603/56813391550346895d9a9f02/html5/thumbnails/13.jpg)
Problems
public class AbstractStringBuilder {
private char[] data;
private int count; // number of items used
public AbstractStringBuilder append(String s) {
…
s.getChars(0, s.length(), data, count);
}}
@Pure String f(String x) { return x + “hello”; }
public class Test {
private List<String> items;
@Pure boolean has(String s) {
for(String i : items) {
if(s == i) { return true; }
}
return false;
} }
![Page 14: JPure: a Modular Purity System for Java](https://reader034.fdocuments.in/reader034/viewer/2022052603/56813391550346895d9a9f02/html5/thumbnails/14.jpg)
interface Collection {
@Fresh Object iterator();
}
interface Iterator {
@Pure boolean hasNext();
@Local Object next();
}
class Test {
List<String> items;
@Pure boolean has(String s){
for(String i : items) {
if(s == i) return true;
}
return false;
} }
Introducing JPure!
![Page 15: JPure: a Modular Purity System for Java](https://reader034.fdocuments.in/reader034/viewer/2022052603/56813391550346895d9a9f02/html5/thumbnails/15.jpg)
interface Collection {
@Fresh Object iterator();
}
interface Iterator {
@Pure boolean hasNext();
@Local Object next();
}
class Test {
List<String> items;
@Pure boolean has(String s){
for(String i : items) {
if(s == i) return true;
}
return false;
} }
Introducing JPure!Indicates iterator() returns “fresh” object
![Page 16: JPure: a Modular Purity System for Java](https://reader034.fdocuments.in/reader034/viewer/2022052603/56813391550346895d9a9f02/html5/thumbnails/16.jpg)
interface Collection {
@Fresh Object iterator();
}
interface Iterator {
@Pure boolean hasNext();
@Local Object next();
}
class Test {
List<String> items;
@Pure boolean has(String s){
for(String i : items) {
if(s == i) return true;
}
return false;
} }
Introducing JPure!Indicates iterator() returns “fresh” object
Indicates next() only modifies “local” state
![Page 17: JPure: a Modular Purity System for Java](https://reader034.fdocuments.in/reader034/viewer/2022052603/56813391550346895d9a9f02/html5/thumbnails/17.jpg)
interface Collection {
@Fresh Object iterator();
}
interface Iterator {
@Pure boolean hasNext();
@Local Object next();
}
class Test {
List<String> items;
@Pure boolean has(String s){
for(String i : items) {
if(s == i) return true;
}
return false;
} }
Introducing JPure!Indicates iterator() returns “fresh” object
Indicates next() only modifies “local” state
![Page 18: JPure: a Modular Purity System for Java](https://reader034.fdocuments.in/reader034/viewer/2022052603/56813391550346895d9a9f02/html5/thumbnails/18.jpg)
interface Collection {
@Fresh Object iterator();
}
interface Iterator {
@Pure boolean hasNext();
@Local Object next();
}
class Test {
List<String> items;
@Pure boolean has(String s){
for(String i : items) {
if(s == i) return true;
}
return false;
} }
Introducing JPure!
@Pure boolean has(String s) {
Iterator tmp;
tmp = items.iterator();
while(tmp.hasNext()) {
i = tmp.next();
if(s == i) return true;
}
return false;
}
Indicates iterator() returns “fresh” object
Indicates next() only modifies “local” state
![Page 19: JPure: a Modular Purity System for Java](https://reader034.fdocuments.in/reader034/viewer/2022052603/56813391550346895d9a9f02/html5/thumbnails/19.jpg)
interface Collection {
@Fresh Object iterator();
}
interface Iterator {
@Pure boolean hasNext();
@Local Object next();
}
class Test {
List<String> items;
@Pure boolean has(String s){
for(String i : items) {
if(s == i) return true;
}
return false;
} }
Introducing JPure!
@Pure boolean has(String s) {
Iterator tmp;
tmp = items.iterator();
while(tmp.hasNext()) {
i = tmp.next();
if(s == i) return true;
}
return false;
}
Indicates iterator() returns “fresh” object
Indicates next() only modifies “local” state
![Page 20: JPure: a Modular Purity System for Java](https://reader034.fdocuments.in/reader034/viewer/2022052603/56813391550346895d9a9f02/html5/thumbnails/20.jpg)
• Methods annotated @Fresh– Must return new objects– Or, values returned by methods marked @Fresh
• Methods annotated @Local– May update “local” state … – But otherwise must remain pure
class ArrayList implements Collection{
…
@Fresh Object iterator() { return new Iterator(data); }
static class Iterator {
Object[] data; int idx = 0;
…
@Pure boolean hasNext() { return idx < data.size(); }
@Local Object next() { return data[idx++]; }
}}
![Page 21: JPure: a Modular Purity System for Java](https://reader034.fdocuments.in/reader034/viewer/2022052603/56813391550346895d9a9f02/html5/thumbnails/21.jpg)
Iterator Implementation
• Methods annotated @Fresh– Must return new objects– Or, values returned by methods marked @Fresh
• Methods annotated @Local– May update “local” state … – But otherwise must remain pure
class ArrayList implements Collection{ …
@Fresh Object iterator() { return new Iterator(data); }
static class Iterator {
Object[] data; int idx = 0; …
@Pure boolean hasNext() { return idx < data.size(); }
@Local Object next() { return data[idx++]; }
}}
![Page 22: JPure: a Modular Purity System for Java](https://reader034.fdocuments.in/reader034/viewer/2022052603/56813391550346895d9a9f02/html5/thumbnails/22.jpg)
Locality Invariant 2 (Preservation). When the locality of a fresh object is modified, its locality must remain fresh.
Locality Invariant 1 (Construction). When a new object is constructed its locality is always fresh.
class TList {
private int length;
private @Local Object[] data;
private Type type;
@Local public TList(Type t, int m) {
length = 0;
data = new Object[m];
type = t;
}
@Local public void copy(TList dst) {
length = dst.length;
type = dst.type;
data = new Object[dst.length];
for(int i=0;i!=length;++i) { data[i] = dst.data[i]; }
}}
TListdata
length,type
![Page 23: JPure: a Modular Purity System for Java](https://reader034.fdocuments.in/reader034/viewer/2022052603/56813391550346895d9a9f02/html5/thumbnails/23.jpg)
Locality Invariant 2 (Preservation). When the locality of a fresh object is modified, its locality must remain fresh.
Locality Invariant 1 (Construction). When a new object is constructed its locality is always fresh.
class TList {
private int length;
private @Local Object[] data;
private Type type;
@Local public TList(Type t, int m) {
length = 0;
data = new Object[m];
type = t;
}
@Local public void copy(TList dst) {
length = dst.length;
type = dst.type;
data = new Object[dst.length];
for(int i=0;i!=length;++i) { data[i] = dst.data[i]; }
}}
TListdata
length,type
Required forInvariant 1
![Page 24: JPure: a Modular Purity System for Java](https://reader034.fdocuments.in/reader034/viewer/2022052603/56813391550346895d9a9f02/html5/thumbnails/24.jpg)
Locality Invariant 2 (Preservation). When the locality of a fresh object is modified, its locality must remain fresh.
Locality Invariant 1 (Construction). When a new object is constructed its locality is always fresh.
class TList {
private int length;
private @Local Object[] data;
private Type type;
@Local public TList(Type t, int m) {
length = 0;
data = new Object[m];
type = t;
}
@Local public void copy(TList dst) {
length = dst.length;
type = dst.type;
data = new Object[dst.length];
for(int i=0;i!=length;++i) { data[i] = dst.data[i]; }
}}
TListdata
length,type
Required forInvariant 1
Safe underInvariant 2
![Page 25: JPure: a Modular Purity System for Java](https://reader034.fdocuments.in/reader034/viewer/2022052603/56813391550346895d9a9f02/html5/thumbnails/25.jpg)
Detailed Example@Local public void copy(TList dst) {
var tmp = dst.length;
this.length = tmp;
tmp = dst.type;
this.type = tmp;
tmp = new Object[dst.length];
this.data = tmp;
for(int i=0;i!=length;++i) {
tmp = dst.data[i];
this.data[i] = tmp;
} }
LTHIS LDST ?
tmpdstthis
![Page 26: JPure: a Modular Purity System for Java](https://reader034.fdocuments.in/reader034/viewer/2022052603/56813391550346895d9a9f02/html5/thumbnails/26.jpg)
Detailed Example@Local public void copy(TList dst) {
var tmp = dst.length;
this.length = tmp;
tmp = dst.type;
this.type = tmp;
tmp = new Object[dst.length];
this.data = tmp;
for(int i=0;i!=length;++i) {
tmp = dst.data[i];
this.data[i] = tmp;
} }
LTHIS LDST ?
tmpdstthis
LTHIS LDST
![Page 27: JPure: a Modular Purity System for Java](https://reader034.fdocuments.in/reader034/viewer/2022052603/56813391550346895d9a9f02/html5/thumbnails/27.jpg)
Detailed Example@Local public void copy(TList dst) {
var tmp = dst.length;
this.length = tmp;
tmp = dst.type;
this.type = tmp;
tmp = new Object[dst.length];
this.data = tmp;
for(int i=0;i!=length;++i) {
tmp = dst.data[i];
this.data[i] = tmp;
} }
LTHIS LDST ?
tmpdstthis
LTHIS LDST
LTHIS LDST
![Page 28: JPure: a Modular Purity System for Java](https://reader034.fdocuments.in/reader034/viewer/2022052603/56813391550346895d9a9f02/html5/thumbnails/28.jpg)
Detailed Example@Local public void copy(TList dst) {
var tmp = dst.length;
this.length = tmp;
tmp = dst.type;
this.type = tmp;
tmp = new Object[dst.length];
this.data = tmp;
for(int i=0;i!=length;++i) {
tmp = dst.data[i];
this.data[i] = tmp;
} }
LTHIS LDST ?
tmpdstthis
LTHIS LDST
LTHIS LDST
LTHIS LDST ?
![Page 29: JPure: a Modular Purity System for Java](https://reader034.fdocuments.in/reader034/viewer/2022052603/56813391550346895d9a9f02/html5/thumbnails/29.jpg)
Detailed Example@Local public void copy(TList dst) {
var tmp = dst.length;
this.length = tmp;
tmp = dst.type;
this.type = tmp;
tmp = new Object[dst.length];
this.data = tmp;
for(int i=0;i!=length;++i) {
tmp = dst.data[i];
this.data[i] = tmp;
} }
LTHIS LDST ?
tmpdstthis
LTHIS LDST
LTHIS LDST
LTHIS LDST ?
LTHIS LDST ?
![Page 30: JPure: a Modular Purity System for Java](https://reader034.fdocuments.in/reader034/viewer/2022052603/56813391550346895d9a9f02/html5/thumbnails/30.jpg)
Detailed Example@Local public void copy(TList dst) {
var tmp = dst.length;
this.length = tmp;
tmp = dst.type;
this.type = tmp;
tmp = new Object[dst.length];
this.data = tmp;
for(int i=0;i!=length;++i) {
tmp = dst.data[i];
this.data[i] = tmp;
} }
LTHIS LDST ?
tmpdstthis
LTHIS LDST
LTHIS LDST
LTHIS LDST ?
LTHIS LDST ?
LTHIS LDST
![Page 31: JPure: a Modular Purity System for Java](https://reader034.fdocuments.in/reader034/viewer/2022052603/56813391550346895d9a9f02/html5/thumbnails/31.jpg)
Detailed Example@Local public void copy(TList dst) {
var tmp = dst.length;
this.length = tmp;
tmp = dst.type;
this.type = tmp;
tmp = new Object[dst.length];
this.data = tmp;
for(int i=0;i!=length;++i) {
tmp = dst.data[i];
this.data[i] = tmp;
} }
LTHIS LDST ?
tmpdstthis
LTHIS LDST
LTHIS LDST
LTHIS LDST ?
LTHIS LDST ?
LTHIS LDST
LTHIS LDST
![Page 32: JPure: a Modular Purity System for Java](https://reader034.fdocuments.in/reader034/viewer/2022052603/56813391550346895d9a9f02/html5/thumbnails/32.jpg)
Detailed Example@Local public void copy(TList dst) {
var tmp = dst.length;
this.length = tmp;
tmp = dst.type;
this.type = tmp;
tmp = new Object[dst.length];
this.data = tmp;
for(int i=0;i!=length;++i) {
tmp = dst.data[i];
this.data[i] = tmp;
} }
LTHIS LDST ?
tmpdstthis
LTHIS LDST
LTHIS LDST
LTHIS LDST ?
LTHIS LDST ?
LTHIS LDST
LTHIS LDST
LTHIS LDST
![Page 33: JPure: a Modular Purity System for Java](https://reader034.fdocuments.in/reader034/viewer/2022052603/56813391550346895d9a9f02/html5/thumbnails/33.jpg)
Detailed Example@Local public void copy(TList dst) {
var tmp = dst.length;
this.length = tmp;
tmp = dst.type;
this.type = tmp;
tmp = new Object[dst.length];
this.data = tmp;
for(int i=0;i!=length;++i) {
tmp = dst.data[i];
this.data[i] = tmp;
} }
LTHIS LDST ?
tmpdstthis
LTHIS LDST
LTHIS LDST
LTHIS LDST ?
LTHIS LDST ?
LTHIS LDST
LTHIS LDST
LTHIS LDST
LTHIS LDST LDST
![Page 34: JPure: a Modular Purity System for Java](https://reader034.fdocuments.in/reader034/viewer/2022052603/56813391550346895d9a9f02/html5/thumbnails/34.jpg)
Detailed Example@Local public void copy(TList dst) {
var tmp = dst.length;
this.length = tmp;
tmp = dst.type;
this.type = tmp;
tmp = new Object[dst.length];
this.data = tmp;
for(int i=0;i!=length;++i) {
tmp = dst.data[i];
this.data[i] = tmp;
} }
LTHIS LDST ?
tmpdstthis
LTHIS LDST
LTHIS LDST
LTHIS LDST ?
LTHIS LDST ?
LTHIS LDST
LTHIS LDST
LTHIS LDST
LTHIS LDST
LTHIS LDST
LDST
LDST
![Page 35: JPure: a Modular Purity System for Java](https://reader034.fdocuments.in/reader034/viewer/2022052603/56813391550346895d9a9f02/html5/thumbnails/35.jpg)
Detailed Example@Local public void copy(TList dst) {
var tmp = dst.length;
this.length = tmp;
tmp = dst.type;
this.type = tmp;
tmp = new Object[dst.length];
this.data = tmp;
for(int i=0;i!=length;++i) {
tmp = dst.data[i];
this.data[i] = tmp;
} }
LTHIS LDST ?
tmpdstthis
LTHIS LDST
LTHIS LDST
LTHIS LDST ?
LTHIS LDST ?
LTHIS LDST
LTHIS LDST
LTHIS LDST
LTHIS LDST
LTHIS LDST
LDST
LDST
LDST
![Page 36: JPure: a Modular Purity System for Java](https://reader034.fdocuments.in/reader034/viewer/2022052603/56813391550346895d9a9f02/html5/thumbnails/36.jpg)
Checking vs Inference
• Purity Checker:
– Intraprocedural dataflow analysis
– Uses static information about called methods
– Checks fresh objects flow to @Fresh returns
– Checks assignments to @Local fields are fresh
– Checks assignments to other fields are in locality
– Checks annotations overridden correctly
• Purity Inference:
– Interprocedural dataflow analysis
– Uses static call graph
– Essentially works in opposite direction to checker
– E.g. if all returned values fresh -> method annotated @Fresh
![Page 37: JPure: a Modular Purity System for Java](https://reader034.fdocuments.in/reader034/viewer/2022052603/56813391550346895d9a9f02/html5/thumbnails/37.jpg)
![Page 38: JPure: a Modular Purity System for Java](https://reader034.fdocuments.in/reader034/viewer/2022052603/56813391550346895d9a9f02/html5/thumbnails/38.jpg)
Limitations
• Disappointment!– Object.equals() not inferred @Pure– Object.hashCode() not inferred @Pure
class Test {
private int hashCode;
public boolean equals(Object o) {
if(hashCode() == o.hashCode()) { … }
return false;
}
public int hashCode() {
if(hashCode == -1) { hashCode = …; }
return hashCode;
}}
![Page 39: JPure: a Modular Purity System for Java](https://reader034.fdocuments.in/reader034/viewer/2022052603/56813391550346895d9a9f02/html5/thumbnails/39.jpg)
Conclusion
• The JPure System
– Built around Modularly Checkable Annotations
– Interprocedural analysis infers annotations
– Intraprocedural analysis checks annotations• Could be incorporated in Java Bytecode Verifier
– Locality & freshness help uncover more purity• 41% on average for benchmarks (vs 25% for simple)
See http://www.ecs.vuw.ac.nz/~djp/jpure
![Page 40: JPure: a Modular Purity System for Java](https://reader034.fdocuments.in/reader034/viewer/2022052603/56813391550346895d9a9f02/html5/thumbnails/40.jpg)
Law of Locality
• Example:
– What if other aliased with this?
– Applying Law of Locality seems counter-intuitive
class Test {
private int field;
@Local void f(Test other){
this.field = 1;
}}
Law of Locality. When checking @Local annotations, one can safely assume parameters are not aliased (!)