private static void matchNodeSubgraph(Node node1, Node node2, Map<Node, Node> map) { if (map.containsKey(node1)) { assert (node2 == map.get(node1)); return; } map.put(node1, node2); if (secondary_index[4]) { for (Field f : node1.outfields.keySet()) { FieldEdge fe1 = node1.outfields.get(f); assert (fe1.src.getRep() == node1); FieldEdge fe2 = node2.outfields.get(f); assert (fe2 != null); assert (fe2.src.getRep() == node2); matchNodeSubgraph(fe1.dst.getRep(), fe2.dst.getRep(), map); } } else { for (Field f : node1.graph.fedges.keySet()) for (FieldEdge fe1 : node1.graph.fedges.get(f)) { if (fe1.src.getRep() != node1) continue; boolean found = false; assert (node2.graph.fedges.get(f) != null); for (FieldEdge fe2 : node2.graph.fedges.get(f)) { if (fe2.src.getRep() != node2) continue; if (!fe1.field.equals(fe2.field)) continue; matchNodeSubgraph(fe1.dst.getRep(), fe2.dst.getRep(), map); found = true; break; } assert (found); } } }
/* 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); }
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++; }
/* Lookup node for field, create new node if not present */ public Node getNode(Var var, Field field) { Map<Field, Node> map = varmap.get(var); if (map == null) { map = new HashMap<Field, Node>(); varmap.put(var, map); } Node fnode = map.get(field); if (fnode == null) { assert var != null; fnode = new Node(var, field, this); map.put(field, fnode); if (field != null) { Node node = getNode(var, null); w.add(new FieldConstraint(node, fnode, field)); } } return fnode; }
/* 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("}"); }
/* 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(); }