flatNodesToVisit = new HashSet<FlatNode>();
flatNodesToVisit.add(flatm);
+
+ // A YUCKY HACK--this is to make sure that an initially empty
+ // graph (no parameters) will get passed the first "any changes?"
+ // test when it comes up for analysis. It's ugly but throwing
+ // a child in works.
+ FlatNode fnJ = flatm.getNext(0);
+ assert fnJ != null;
+ flatNodesToVisit.add(fnJ);
+
+
// initilize the mapping of flat nodes in this flat method to
// ownership graph results to an empty mapping
mapFlatNodeToOwnershipGraph = new Hashtable<FlatNode, OwnershipGraph>();
case FKind.FlatOpNode:
FlatOpNode fon = (FlatOpNode) fn;
if( fon.getOp().getOp() == Operation.ASSIGN ) {
- lhs = fon.getLeft();
- rhs = fon.getDest();
+ lhs = fon.getDest();
+ rhs = fon.getLeft();
og.assignTempXEqualToTempY(lhs, rhs);
}
break;
case FKind.FlatFieldNode:
FlatFieldNode ffn = (FlatFieldNode) fn;
- lhs = ffn.getSrc();
- rhs = ffn.getDst();
+ lhs = ffn.getDst();
+ rhs = ffn.getSrc();
fld = ffn.getField();
if( !fld.getType().isPrimitive() ) {
og.assignTempXEqualToTempYFieldF(lhs, rhs, fld);
case FKind.FlatSetFieldNode:
FlatSetFieldNode fsfn = (FlatSetFieldNode) fn;
- lhs = fsfn.getSrc();
+ lhs = fsfn.getDst();
fld = fsfn.getField();
- rhs = fsfn.getDst();
+ rhs = fsfn.getSrc();
og.assignTempXFieldFEqualToTempY(lhs, fld, rhs);
break;
public HashSet<AllocationSite> allocationSites;
- protected static TempDescriptor lnReturn = new TempDescriptor("_Return___");
+ protected static TempDescriptor tdReturn = new TempDescriptor("_Return___");
public OwnershipGraph(int allocationDepth) {
public void assignReturnEqualToTemp(TempDescriptor x) {
- LabelNode lnR = getLabelNodeFromTemp(lnReturn);
+ LabelNode lnR = getLabelNodeFromTemp(tdReturn);
LabelNode lnX = getLabelNodeFromTemp(x);
clearReferenceEdgesFrom(lnR, null, true);
// a reference edge in the caller for every possible (src,dst) pair
HashSet<HeapRegionNode> possibleCallerSrcs =
getHRNSetThatPossiblyMapToCalleeHRN(ogCallee,
- edgeCallee,
+ (HeapRegionNode) edgeCallee.getSrc(),
true,
paramIndex2reachableCallerNodes);
HashSet<HeapRegionNode> possibleCallerDsts =
getHRNSetThatPossiblyMapToCalleeHRN(ogCallee,
- edgeCallee,
+ edgeCallee.getDst(),
false,
paramIndex2reachableCallerNodes);
}
+
+ // return value may need to be assigned in caller
+ if( fc.getReturnTemp() != null ) {
+
+ HashSet<HeapRegionNode> assignCallerRhs = new HashSet<HeapRegionNode>();
+
+ LabelNode lnReturnCallee = ogCallee.getLabelNodeFromTemp(tdReturn);
+ Iterator<ReferenceEdge> edgeCalleeItr = lnReturnCallee.iteratorToReferencees();
+ while( edgeCalleeItr.hasNext() ) {
+ ReferenceEdge edgeCallee = edgeCalleeItr.next();
+
+ HashSet<HeapRegionNode> possibleCallerHRNs =
+ getHRNSetThatPossiblyMapToCalleeHRN(ogCallee,
+ edgeCallee.getDst(),
+ false,
+ paramIndex2reachableCallerNodes);
+
+ assignCallerRhs.addAll(possibleCallerHRNs);
+ }
+
+ LabelNode lnLhsCaller = getLabelNodeFromTemp(fc.getReturnTemp() );
+ clearReferenceEdgesFrom(lnLhsCaller, null, true);
+
+ Iterator<HeapRegionNode> itrHrn = assignCallerRhs.iterator();
+ while( itrHrn.hasNext() ) {
+ HeapRegionNode hrnCaller = itrHrn.next();
+
+ ReferenceEdge edgeNew = new ReferenceEdge(lnLhsCaller,
+ hrnCaller,
+ null,
+ false,
+ new ReachabilitySet().makeCanonical()
+ );
+
+ addReferenceEdge(lnLhsCaller, hrnCaller, edgeNew);
+ }
+ }
+
+
+
// merge the shadow nodes of allocation sites back down to normal capacity
Iterator<AllocationSite> allocItr = ogCallee.allocationSites.iterator();
while( allocItr.hasNext() ) {
private HashSet<HeapRegionNode>
getHRNSetThatPossiblyMapToCalleeHRN(OwnershipGraph ogCallee,
- ReferenceEdge edgeCallee,
+ HeapRegionNode hrnCallee,
boolean mapFromSrc,
Hashtable<Integer, HashSet<HeapRegionNode> > paramIndex2reachableCallerNodes
) {
HashSet<HeapRegionNode> possibleCallerHRNs = new HashSet<HeapRegionNode>();
- HeapRegionNode hrnCallee;
- if( mapFromSrc ) {
- OwnershipNode on = edgeCallee.getSrc();
- assert on instanceof HeapRegionNode;
- hrnCallee = (HeapRegionNode) on;
- } else {
- hrnCallee = edgeCallee.getDst();
- }
-
Integer paramIndexCallee = ogCallee.id2paramIndex.get(hrnCallee.getID() );
if( paramIndexCallee == null ) {
/*
public class Parameter {
- flag w;
- int a, b;
- Parameter f, g;
- Penguin p;
- Foo h;
-
- public Parameter() { a = 0; b = 0; f = null; g = null; }
-
- public void bar() { foo(); }
- public void foo() { bar(); }
+ flag w;
+ int a, b;
+ Parameter f, g;
+ Penguin p;
+ Foo h;
+
+ public Parameter() { a = 0; b = 0; f = null; g = null; }
+
+ public void bar() { foo(); }
+ public void foo() { bar(); }
}
public class Penguin {
- int x, y;
- Foo h;
-
- public Penguin() { x = 0; y = 0; }
-
- public void bar() { x = 1; }
+ int x, y;
+ Foo h;
+
+ public Penguin() { x = 0; y = 0; }
+
+ public void bar() { x = 1; }
}
-*/
+
public class Voo {
flag f; int x; Baw b; Baw bb;
}
public class Baw {
- int y;
- Foo f;
+ int y;
+ Foo f;
+
+ public Baw() {}
+
+ public void doTheBaw( Voo v ) { v = new Voo(); }
+}
+*/
- public Baw() {}
- public void doTheBaw( Voo v ) { v = new Voo(); }
-}
+task ObjectChainByMethodCalls( Foo a{ f } ) {
+ Foo f = a.getAFoo();
+ Foo g = a.newFooChain( f );
+ // g -> f
-public class Foo {
- flag f;
+ taskexit( a{ !f } );
+}
- public Foo() {}
- public Foo x;
- public Foo y;
- public Foo z;
+public class Foo {
+ flag f;
+
+ public Foo() {}
+
+ public Foo x;
+ public Foo y;
+ public Foo z;
- /*
- public void ruinSomeFoos( Foo a, Foo b ) {
- a.x = b.x;
- }
- static public void aStaticMethod( Foo p0, Foo p1 ) {
- Foo f0 = new Foo();
- Foo f1 = new Foo();
- Foo f2 = new Foo();
+ public Foo getAFoo() {
+ return new Foo();
+ }
- f0.x = f1;
- p0.x = f0;
- p1.x = f1;
- p1.x = f2;
- }
- */
+ public Foo newFooChain( Foo a ) {
+ Foo b = new Foo();
+ b.x = a;
+ return b;
+ }
+
+ /*
+ public void ruinSomeFoos( Foo a, Foo b ) {
+ a.x = b.x;
+ }
+
+ static public void aStaticMethod( Foo p0, Foo p1 ) {
+ Foo f0 = new Foo();
+ Foo f1 = new Foo();
+ Foo f2 = new Foo();
+
+ f0.x = f1;
+ p0.x = f0;
+ p1.x = f1;
+ p1.x = f2;
+ }
+
static public void m1_( Foo p0 ) {
Foo g0 = new Foo();
Foo g1 = new Foo();
-
+
g0.x = p0;
p0.x = g1;
}
-
- /*
+
static public void m2_( Foo p0 ) {
Foo g0 = new Foo();
-
+
g0.x = p0;
g0.y = p0;
}
-
+
static public void m3_( Foo p0 ) {
Foo g0 = new Foo();
-
+
p0.x = g0;
p0.y = g0;
}
taskexit( a{ !f }, b{ !f } );
}
+
task NewObjectB( Foo a{ f }, Foo b{ f } ) {
Foo c = new Foo();
taskexit( a{ !f }, b{ !f } );
}
-*/
-/*
+
task NewObjectC( Foo a{ f }, Foo b{ f } ) {
Foo z = new Foo();
taskexit( a{ !f }, b{ !f } );
}
-*/
-/*
+
task forMethod( Foo p0{ f } ) {
Foo a0;
taskexit( p0{ !f } );
}
-*/
-/*
// this task allocates a new object, so there should
// be a heap region for the parameter, and several
// heap regions for the allocation site, but the label
taskexit( p0{ !f } );
}
-*/
task getNewFromMethod( Foo p0{ f } ) {
taskexit( p0{ !f }, p1{ !f } );
}
-/*
+
task methodTest02_( Foo p0{ f }, Foo p1{ f } ) {
Foo a0before = new Foo();
-public class Parameter1 {
+public class Parameter {
flag w;
Node root;
- public Parameter1() {}
+ public Parameter() {}
}
public class Node {
task Startup( StartupObject s{ initialstate } ) {
- Parameter1 p1 = new Parameter1();
+ Parameter p1 = new Parameter();
taskexit( s{ !initialstate } );
}
-task MakeGraph( Parameter1 p1{ !w } ) {
+task MakeGraph( Parameter p1{ !w } ) {
Node n1 = Node.makeNode();
Node n2 = Node.makeNode();
Node n3 = Node.makeNode();
- /*
n1.addNeighbor( n2 );
n2.addNeighbor( n3 );
n3.addNeighbor( n1 );
p1.root = n1;
- */
+
taskexit( p1{ w } );
}