protected RegionVar getUniqueRegionOf(Var var) { assert (var != null && varmap.get(var) != null) : " Var " + var + method + " " + var.getDeclaringMethod(); Node node = (varmap.get(var)).get(null); if (node == null) return null; return node.getRep().getRegion(); }
protected List<RegionVar> getRegionsOf(Var var, Map<RegionVar, Set<Field>> dead) { Node node = (varmap.get(var)).get(null); if (node == null) return null; List<RegionVar> regions = new ArrayList<RegionVar>(); getRegionsHelper(node.getRep(), dead, regions); return regions; }
private void computeCaches() { cacheAllRegions = new ArrayList<RegionVar>(); cacheI2R = new HashMap<Integer, RegionVar>(); for (Node n : nodes) getRegionsHelper(n.getRep(), null, cacheAllRegions); for (RegionVar r : cacheAllRegions) { r.setIndex(++numRegions); cacheI2R.put(r.getIndex(), r); } numRegions++; }
/* Matches the subgraphs rooted at two nodes and records the * isomorphism into a map. */ private static void matchSubgraph(Node node1, Node node2, Map<RegionVar, RegionVar> map) { RegionVar r1 = node1.getRep().getRegion(); RegionVar r2 = node2.getRep().getRegion(); if (map.containsKey(r1)) { assert (r2 == map.get(r1)) : "at call: " + node2.graph.method + " to " + node1.graph.method + "\n" + r2 + "(" + node2 + ") vs " + map.get(r1) + " corresponding to " + r1 + "(" + node1 + ")"; return; } map.put(r1, r2); if (secondary_index[3]) { node1 = node1.getRep(); node2 = node2.getRep(); for (Field f : node1.outfields.keySet()) { FieldEdge fe1 = node1.outfields.get(f); assert (fe1.src == node1); FieldEdge fe2 = node2.outfields.get(f); assert (fe2 != null); matchSubgraph(fe1.dst, fe2.dst, map); } } else { for (Field f : node1.graph.fedges.keySet()) for (FieldEdge fe1 : node1.graph.fedges.get(f)) { if (fe1.src != node1) continue; boolean found = false; assert (node2.graph.fedges.get(f) != null); for (FieldEdge fe2 : node2.graph.fedges.get(f)) { if (fe2.src != node2) continue; if (!fe1.field.equals(fe2.field)) continue; matchSubgraph(fe1.dst, fe2.dst, map); found = true; break; } assert (found); } } }
/* Processing assignments of allocation statements. Left hand side is either a variable or the field of a variable. The right hand side is the allocation site, represented by the allocation instruction. */ public void assignAlloc(Var x, Field f, New a) { Node nodeL = getNode(x, f); nodeL.hasallocs = true; nodeL.istouched = true; setTouched(x); if (IRHelper.isLibrary(method.getDeclaringClass())) nodeL.hasliballocs = true; Node nodeR = allocmap.get(a); assert (nodeR == null) : "Allocation site already entered"; allocmap.put(a, nodeL); }
protected void addRegionsFrom( Node node, Map<RegionVar, Set<Field>> dead, IBitVector<RegionVar> marked) { RegionVar reg = node.getRegion(); if (reg.isHeap() || marked.get(reg)) return; marked.set(reg); if (secondary_index[6]) { for (Field f : node.getRep().outfields.keySet()) { FieldEdge fe = node.getRep().outfields.get(f); assert (fe.src == node); if (dead == null || dead.get(reg) == null || !dead.get(reg).contains(fe.field)) addRegionsFrom(fe.dst.getRep(), dead, marked); } } else { for (Field f : fedges.keySet()) for (FieldEdge fe : fedges.get(f)) { if (fe.src == node) { if (dead == null || dead.get(reg) == null || !dead.get(reg).contains(fe.field)) addRegionsFrom(fe.dst, dead, marked); } } } }
private void getRegionsHelper( Node node, Map<RegionVar, Set<Field>> dead, List<RegionVar> regions) { RegionVar reg = node.getRegion(); if (regions.contains(reg)) return; regions.add(reg); if (secondary_index[6]) { for (Field f : node.getRep().outfields.keySet()) { FieldEdge fe = node.getRep().outfields.get(f); assert (fe.src == node); if (dead == null || dead.get(reg) == null || !dead.get(reg).contains(fe.field)) getRegionsHelper(fe.dst.getRep(), dead, regions); } } else { for (Field f : fedges.keySet()) for (FieldEdge fe : fedges.get(f)) { if (fe.src == node) { if (dead == null || dead.get(reg) == null || !dead.get(reg).contains(fe.field)) getRegionsHelper(fe.dst, dead, regions); } } } }
protected RegionVar getUniqueRegionOf(Node n, Field f) { if (secondary_index[5]) { FieldEdge fe = n.getRep().outfields.get(f); assert (fe != null && fe.src == n); return fe.dst.getRep().getRegion(); } if (fedges.get(f) == null) return null; for (FieldEdge fe : fedges.get(f)) { assert (fe.field.equals(f)); if (fe.src.equals(n)) return fe.dst.getRep().getRegion(); } return null; }
/** Is tag reachable from node on paths with no visited nodes? */ private Node reachesTag(Node node, UniqueTag tag, Set<Node> visited) { assert (node.isRep()); if (visited.contains(node)) return null; if (tag.mergeable(node.tag)) return node; visited.add(node); if (secondary_index[2]) { for (Field f : node.infields.keySet()) for (FieldEdge e : node.infields.get(f)) { assert (e.dst == node); Node result = reachesTag(e.src.getRep(), tag, visited); if (result != null) return result; } } else { for (Field f : fedges.keySet()) for (FieldEdge e : fedges.get(f)) { if (e.dst != node) continue; Node result = reachesTag(e.src, tag, visited); if (result != null) return result; } } return null; }
protected int numTouched() { int c = 0; for (Node node : nodes) if (node.isRep() && node.isTouched()) c++; return c; }
protected int numAlloc() { int c = 0; for (Node node : nodes) if (node.isRep() && node.hasAllocations()) c++; return c; }
protected int numHeap() { int c = 0; for (Node node : nodes) if (node.isRep() && node.isHeap()) c++; return c; }
protected void setGlobal(Var v) { Node node = getNode(v, null); assert (!v.isLocal() || v.isException()); node.isheap = true; }
/* Print the current type graph to the dotfile */ public void printDot(String title, Call call) { boolean printUnifications = false; PrintStream ps = PointsToAnalysis.v().file; if (ps == null) return; ps.println("\ndigraph F {"); ps.println(" size = \"7,7\"; rankdir = LR;"); ps.println(" orientation = landscape;"); ps.println(" subgraph cluster1 {"); ps.println(" \"Method: " + method.getName() + "\" [color=white];"); if (nodes.isEmpty()) { ps.println(" \"empty graph\" [color = white];"); ps.println(" }"); ps.println("}"); return; } for (Node node : nodes) { if (!printUnifications && !node.isRep()) continue; String color = "style=filled,fillcolor="; if (node.isheap && node.hasallocs) color += "red,"; else if (node.isheap) color += "orange,"; else if (node.hasallocs) color += "grey,"; else color += "white,"; // if (node.istouched) color = "khaki"; // if (node.hassync) color = "khaki"; String shape = "shape="; if (node.istouched) shape += "box"; else shape += "ellipse"; ps.println(" o" + node.id + "[label = \"" + node.getName() + "\"," + color + shape + "];"); } ps.println(" }"); Map<Integer, Map<Integer, String>> labels = new HashMap<Integer, Map<Integer, String>>(); for (Field f : fedges.keySet()) for (FieldEdge e : fedges.get(f)) { if (labels.containsKey(e.src.id)) { if (labels.get(e.src.id).containsKey(e.dst.id)) { labels.get(e.src.id).put(e.dst.id, "*"); // labels.get(e.src.id).get(e.dst.id) + ", " + // e.field.getName()); } else labels.get(e.src.id).put(e.dst.id, e.field.getName()); } else { Map<Integer, String> is = new HashMap<Integer, String>(); is.put(e.dst.id, e.field.getName()); labels.put(e.src.id, is); } } for (Integer i : labels.keySet()) for (Integer j : labels.get(i).keySet()) ps.print( " o" + i + " -> o" + j + "[label=\"" + labels.get(i).get(j) + "\",style=solid,color=black];"); for (Call ce : cedges.keySet()) for (CallEdge e : cedges.get(ce)) { if (!(e.call instanceof VirtualCallExpr)) continue; // if (!e.call.equals(call)) continue; ps.print( " o" + e.src.id + " -> o" + e.dst.id + "[label=\"" + e.call + "\",style=solid,color=red];"); } if (printUnifications) for (Node node : nodes) if (node.parent != null) ps.println(" o" + node.id + " -> o" + node.parent.id + " [color = blue];"); ps.println("}"); }
public void setTouched(Var x) { Node ni = getNode(x, null); ni.istouched = true; }
/* Adds syncronization placed on an object */ public void monitorUse(Var x) { Node ni = getNode(x, null); ni.hassync = true; ni.istouched = true; }
protected RegionVar getUniqueRegionOf(VarF vf) { Node node = (varmap.get(vf.getVar())).get(vf.getField()); if (node == null) return null; return node.getRep().getRegion(); }
/** Does the graph contain a node of a given tag? */ private Node containsTag(UniqueTag tag) { for (Node node : nodes) if (node.isRep() && tag.mergeable(node.tag)) return node; return null; }
protected int numSync() { int c = 0; for (Node node : nodes) if (node.isRep() && node.hasSync()) c++; return c; }
/* process unification constraints */ protected void process(UnifyConstraint c) { Node n1 = c.node1.getRep(); Node n2 = c.node2.getRep(); assert (n1.graph == this); assert (n2.graph == this); if (n1 == n2) return; if (heapfix && n2.isheap && !n1.isheap) { Node sw = n1; n1 = n2; n2 = sw; } n1.mergeTags(n2); n1.mergeFlags(n2); n2.parent = n1; n2.tag = null; n2.region = null; if (secondary_index[0]) { for (FieldEdge e : n2.outfields.values()) { assert (e.src == n2); if (e.dst == n2) w.addLast(new FieldConstraint(n1, n1, e.field)); else { w.addLast(new FieldConstraint(n1, e.dst, e.field)); e.dst.infields.get(e.field).remove(e); } fedges.get(e.field).remove(e); } for (Field f : n2.infields.keySet()) for (FieldEdge e : n2.infields.get(f)) { assert (e.dst == n2); e.dst = n1; addInField(n1, f, e); } n2.outfields = null; n2.infields = null; } else { HashSet<FieldEdge> fremove = new HashSet<FieldEdge>(); for (Field f : fedges.keySet()) { Collection<FieldEdge> fed = fedges.get(f); int size = fed.size(); fremove.clear(); for (FieldEdge e : fed) { if (e.src == n2) { if (e.dst == n2) w.addLast(new FieldConstraint(n1, n1, e.field)); else w.addLast(new FieldConstraint(n1, e.dst, e.field)); } else { if (e.dst == n2) e.dst = n1; continue; } if (!fremove.contains(e)) { fremove.add(e); size--; } } fed.removeAll(fremove); assert (fed.size() == size); } } HashSet<CallEdge> cremove = new HashSet<CallEdge>(); for (Call ce : cedges.keySet()) { Collection<CallEdge> ced = cedges.get(ce); cremove.clear(); int size = ced.size(); for (CallEdge e : ced) { if (e.dst == n2) { if (e.src == n2) w.addLast(new CallConstraint(n1, n1, e.call)); else w.addLast(new CallConstraint(e.src, n1, e.call)); } else { if (e.src == n2) e.src = n1; continue; } if (!cremove.contains(e)) { cremove.add(e); size--; } } ced.removeAll(cremove); assert (ced.size() == size); } }
/* Return the region of an allocation site in this method */ protected RegionVar getAllocRegion(New alloc) { Node node = allocmap.get(alloc); assert (node != null); return node.getRep().getRegion(); }