1 salcianu 1.1.2.10 // PAEscapeFunc.java, created Sun Jan 9 20:53:09 2000 by salcianu 2 cananian 1.1.2.27 // Copyright (C) 2000 Alexandru SALCIANU <salcianu@retezat.lcs.mit.edu> 3 salcianu 1.1.2.1 // Licensed under the terms of the GNU GPL; see COPYING for details. 4 salcianu 1.1.2.1 package harpoon.Analysis.PointerAnalysis; 5 salcianu 1.1.2.1 6 salcianu 1.1.2.1 import java.util.HashSet; 7 salcianu 1.1.2.1 import java.util.Set; 8 salcianu 1.1.2.1 import java.util.Iterator; 9 salcianu 1.1.2.1 import java.util.Map; 10 salcianu 1.4 import java.util.Collections; 11 salcianu 1.1.2.1 12 salcianu 1.1.2.20 import harpoon.ClassFile.HMethod; 13 salcianu 1.1.2.1 14 salcianu 1.1.2.21 import harpoon.Util.PredicateWrapper; 15 salcianu 1.1.2.21 import harpoon.Util.DataStructs.Relation; 16 salcianu 1.1.2.21 import harpoon.Util.DataStructs.LightRelation; 17 salcianu 1.1.2.21 import harpoon.Util.DataStructs.RelationEntryVisitor; 18 salcianu 1.1.2.21 19 salcianu 1.1.2.21 20 salcianu 1.1.2.1 /** 21 salcianu 1.1.2.8 * <code>PAEscapeFunc</code> models the escape information. 22 salcianu 1.1.2.14 For each <code>PANode</code> <code>node</code>, it maintains all the nodes 23 salcianu 1.1.2.14 <code>node</code> escapes through (e.g. parameter nodes). 24 salcianu 1.1.2.14 Also, it records whether <code>node</code> escapes into a method hole or not. 25 salcianu 1.1.2.1 * 26 cananian 1.1.2.27 * @author Alexandru SALCIANU <salcianu@retezat.lcs.mit.edu> 27 cananian 1.6 * @version $Id: PAEscapeFunc.java,v 1.6 2004/02/08 03:20:03 cananian Exp $ 28 salcianu 1.1.2.1 */ 29 salcianu 1.1.2.25 public class PAEscapeFunc implements java.io.Serializable { 30 salcianu 1.1.2.1 31 salcianu 1.1.2.1 // rel_n attaches to each node the set of all the nodes 32 salcianu 1.1.2.1 // that it can escape through. 33 salcianu 1.1.2.1 Relation rel_n; 34 salcianu 1.1.2.1 35 salcianu 1.1.2.20 //////////////// 36 salcianu 1.1.2.14 // set of nodes that escaped into an unanalyzed method 37 salcianu 1.1.2.20 // Set escaped_into_mh; 38 salcianu 1.1.2.20 //////////////// 39 salcianu 1.1.2.20 40 salcianu 1.1.2.20 // rel_m attaches to each node the set of all the methods 41 salcianu 1.1.2.20 // that it can escape into. 42 salcianu 1.1.2.20 Relation rel_m; 43 salcianu 1.1.2.1 44 salcianu 1.1.2.1 /** Creates a <code>EscapeFunc</code>. */ 45 salcianu 1.1.2.1 public PAEscapeFunc() { 46 salcianu 1.1.2.21 rel_n = new LightRelation(); 47 salcianu 1.1.2.20 ///////// escaped_into_mh = new HashSet(); 48 salcianu 1.1.2.21 rel_m = new LightRelation(); 49 salcianu 1.1.2.1 } 50 salcianu 1.1.2.1 51 salcianu 1.1.2.14 /** Records the fact that <code>node</code> can escape through 52 salcianu 1.1.2.8 the node <code>n_hole</code>. Returns <code>true</code> 53 salcianu 1.1.2.8 if new information has been gained */ 54 salcianu 1.5 public final boolean addNodeHole(PANode node, PANode n_hole) { 55 salcianu 1.4 if(node.type == PANode.NULL) return false; 56 salcianu 1.1.2.14 return rel_n.add(node, n_hole); 57 salcianu 1.1.2.1 } 58 salcianu 1.1.2.1 59 salcianu 1.1.2.14 /** Records the fact that <code>node</code> can escape through 60 salcianu 1.1.2.8 the node <code>n_holes</code>. Returns <code>true</code> 61 salcianu 1.1.2.8 if new information has been gained */ 62 salcianu 1.4 public final boolean addNodeHoles(PANode node, Set n_holes) { 63 salcianu 1.4 if(node.type == PANode.NULL) return false; 64 salcianu 1.1.2.14 return rel_n.addAll(node, n_holes); 65 salcianu 1.1.2.1 } 66 salcianu 1.1.2.1 67 salcianu 1.1.2.1 /** The dual of <code>addNodeHole</code> */ 68 salcianu 1.1.2.14 public final void removeNodeHole(PANode node, PANode n_hole){ 69 salcianu 1.1.2.14 rel_n.remove(node, n_hole); 70 salcianu 1.1.2.1 } 71 salcianu 1.1.2.1 72 salcianu 1.1.2.14 /** Removes a node hole from all the nodes: 73 salcianu 1.1.2.14 <code>esc(n) = esc(n) - {n_hole}</code> for all <code>n</code>. */ 74 salcianu 1.1.2.5 public void removeNodeHoleFromAll(PANode n_hole){ 75 salcianu 1.1.2.14 // make a private copy of the set of keys so that I avoid 76 salcianu 1.1.2.14 // "java.util.ConcurrentModificationException" 77 salcianu 1.1.2.21 Set set = new HashSet(rel_n.keys()); 78 salcianu 1.1.2.14 for(Iterator it = set.iterator(); it.hasNext(); ) 79 salcianu 1.1.2.14 rel_n.remove((PANode) it.next(), n_hole); 80 salcianu 1.1.2.5 } 81 salcianu 1.1.2.5 82 salcianu 1.1.2.20 /** Returns the set of all the node "holes" <code>node</code> 83 salcianu 1.1.2.20 escapes through. */ 84 salcianu 1.1.2.20 public Set nodeHolesSet(PANode node){ 85 salcianu 1.1.2.21 return rel_n.getValues(node); 86 salcianu 1.1.2.20 } 87 salcianu 1.1.2.20 88 salcianu 1.1.2.20 /** Checks whether <code>node</code> escapes through a node or not. */ 89 salcianu 1.1.2.20 public boolean hasEscapedIntoANode(PANode node){ 90 salcianu 1.1.2.21 return !rel_n.getValues(node).isEmpty(); 91 salcianu 1.1.2.20 } 92 salcianu 1.1.2.20 93 salcianu 1.1.2.14 /** Records the fact that <code>node</code> escaped into a method hole. 94 salcianu 1.1.2.14 Returns <code>true</code> if this was a new information. */ 95 salcianu 1.4 public boolean addMethodHole(PANode node, HMethod hm) { 96 salcianu 1.4 if(node.type == PANode.NULL) return false; 97 salcianu 1.4 98 salcianu 1.4 if(PointerAnalysis.CONDENSED_ESCAPE_INFO) { 99 salcianu 1.4 if(!rel_m.getValues(node).isEmpty()) 100 salcianu 1.4 return false; 101 salcianu 1.4 } 102 salcianu 1.4 103 salcianu 1.1.2.20 ////// return escaped_into_mh.add(node); 104 salcianu 1.1.2.20 return rel_m.add(node, hm); 105 salcianu 1.1.2.1 } 106 salcianu 1.1.2.1 107 salcianu 1.1.2.20 /** Records the fact that <code>node</code> escaped into a set of 108 salcianu 1.1.2.20 method holes. 109 salcianu 1.1.2.20 Returns <code>true</code> if this was a new information. */ 110 salcianu 1.1.2.20 public boolean addMethodHoles(PANode node, Set mholes){ 111 salcianu 1.1.2.20 boolean changed = false; 112 salcianu 1.1.2.20 for(Iterator it = mholes.iterator(); it.hasNext(); ){ 113 salcianu 1.1.2.20 boolean changed_last = addMethodHole(node, (HMethod) it.next()); 114 salcianu 1.1.2.20 changed = changed || changed_last; 115 salcianu 1.1.2.20 } 116 salcianu 1.1.2.20 return changed; 117 salcianu 1.1.2.1 } 118 vivien 1.1.2.24 119 vivien 1.1.2.24 120 vivien 1.1.2.24 /** The dual of <code>addMethodHole</code> */ 121 vivien 1.1.2.24 public final void removeMethodHole(PANode node, HMethod hm){ 122 vivien 1.1.2.24 rel_m.remove(node, hm); 123 vivien 1.1.2.24 } 124 vivien 1.1.2.24 125 salcianu 1.1.2.1 126 salcianu 1.1.2.20 127 salcianu 1.1.2.20 /** The methods from the set <code>good_holes</code> are unharmful 128 salcianu 1.1.2.20 to the specific application that uses the pointer analysis. So, they 129 salcianu 1.1.2.20 can be erased from the set of method holes into which a specific node 130 salcianu 1.1.2.20 escapes. */ 131 salcianu 1.1.2.20 public void removeMethodHoles(final Set good_holes) { 132 salcianu 1.4 133 salcianu 1.4 // for condensed escape info, we cannot remove method holes 134 salcianu 1.4 if(PointerAnalysis.CONDENSED_ESCAPE_INFO) 135 salcianu 1.4 return; 136 salcianu 1.4 137 salcianu 1.4 rel_m.removeValues(new PredicateWrapper() { 138 salcianu 1.1.2.20 public boolean check(Object obj) { 139 salcianu 1.1.2.20 return good_holes.contains(obj); 140 salcianu 1.1.2.20 } 141 salcianu 1.1.2.20 }); 142 salcianu 1.1.2.20 } 143 salcianu 1.1.2.20 144 salcianu 1.1.2.20 /** Returns the set of methods that <code>node</code> escapes into. */ 145 salcianu 1.1.2.20 public Set methodHolesSet(PANode node){ 146 salcianu 1.1.2.21 return rel_m.getValues(node); 147 salcianu 1.1.2.20 } 148 salcianu 1.1.2.20 149 salcianu 1.1.2.20 /** Returns the set of nodes which escape into a method hole. */ 150 salcianu 1.1.2.20 public Set getEscapedIntoMH(){ 151 salcianu 1.1.2.20 ////// return escaped_into_mh; 152 salcianu 1.1.2.21 return rel_m.keys(); 153 salcianu 1.1.2.19 } 154 salcianu 1.1.2.19 155 salcianu 1.1.2.19 /** Checks whether <code>node</code> escapes into a method hole or not. */ 156 salcianu 1.1.2.19 public boolean hasEscapedIntoAMethod(PANode node){ 157 salcianu 1.1.2.20 ///// return escaped_into_mh.contains(node); 158 salcianu 1.1.2.21 return !rel_m.getValues(node).isEmpty(); 159 salcianu 1.1.2.1 } 160 salcianu 1.1.2.1 161 salcianu 1.1.2.20 /** Checks if <code>node</code> has escaped in some hole, ie if 162 salcianu 1.1.2.20 <code>node</code> could be accessed by unanalyzed code. */ 163 salcianu 1.1.2.20 public boolean hasEscaped(PANode node){ 164 salcianu 1.1.2.20 return 165 salcianu 1.1.2.20 hasEscapedIntoANode(node) || hasEscapedIntoAMethod(node); 166 salcianu 1.1.2.9 } 167 salcianu 1.1.2.23 168 salcianu 1.1.2.23 169 salcianu 1.1.2.23 /** Checks whether <code>node</code> escapes at most in the caller. 170 salcianu 1.1.2.23 ie it doesn't escape in an unanalyzed method, a thread or a static 171 salcianu 1.1.2.23 field. */ 172 salcianu 1.1.2.23 public boolean escapesOnlyInCaller(PANode node) { 173 salcianu 1.1.2.23 if(hasEscapedIntoAMethod(node)) 174 salcianu 1.1.2.23 return false; // escapes into an unanalyzed method 175 cananian 1.6 for(Object hole_nodeO : nodeHolesSet(node)) { 176 cananian 1.6 PANode hole_node = (PANode) hole_nodeO; 177 salcianu 1.1.2.23 if(hole_node.type() != PANode.PARAM) 178 salcianu 1.1.2.23 return false; // escapes into a thread or a static 179 salcianu 1.1.2.23 } 180 salcianu 1.1.2.23 return true; 181 salcianu 1.1.2.23 } 182 salcianu 1.1.2.23 183 salcianu 1.1.2.9 184 salcianu 1.1.2.9 /** Remove all the <code>PANode</code>s that appear in <code>set</code> 185 salcianu 1.1.2.9 from <code>this</code> object. */ 186 salcianu 1.1.2.9 public void remove(Set set){ 187 cananian 1.6 for(Object nodeO : set){ 188 cananian 1.6 PANode node = (PANode) nodeO; 189 salcianu 1.1.2.21 rel_n.removeKey(node); 190 salcianu 1.1.2.20 //////// escaped_into_mh.remove(node); 191 salcianu 1.1.2.21 rel_m.removeKey(node); 192 salcianu 1.1.2.9 } 193 salcianu 1.1.2.1 } 194 salcianu 1.1.2.1 195 salcianu 1.4 public void union(PAEscapeFunc e2) { 196 salcianu 1.4 union(e2, null); 197 salcianu 1.4 } 198 salcianu 1.4 199 salcianu 1.1.2.8 /** Computes the union of <code>this</code> <code>PAEscapeFunc</code> 200 salcianu 1.1.2.8 with <code>e2</code>. This function is called in the control flow 201 salcianu 1.1.2.8 <i>join</i> points. */ 202 salcianu 1.4 public void union(PAEscapeFunc e2, Set/*<PANode>*/ ppgRoots) { 203 salcianu 1.4 // rel_n.union(e2.rel_n) + collect in ppgRoots nodes whose 204 salcianu 1.4 // escape info has changed 205 cananian 1.6 for(Object nodeO : e2.rel_n.keys()) { 206 cananian 1.6 PANode node = (PANode) nodeO; 207 salcianu 1.4 Set holes = e2.rel_n.getValues(node); 208 salcianu 1.4 if(rel_n.addAll(node, holes) && (ppgRoots != null)) 209 salcianu 1.4 ppgRoots.add(node); 210 salcianu 1.4 } 211 salcianu 1.4 212 salcianu 1.4 if(PointerAnalysis.CONDENSED_ESCAPE_INFO) { 213 salcianu 1.4 //////// escaped_into_mh.addAll(e2.escaped_into_mh); 214 salcianu 1.4 // avoid adding multiple method holes for the same node 215 salcianu 1.4 for(Iterator/*<PANode>*/ it = e2.getEscapedIntoMH().iterator(); 216 salcianu 1.4 it.hasNext(); ) { 217 salcianu 1.4 PANode node = (PANode) it.next(); 218 salcianu 1.4 Set/*<HMethod>*/ newMHs = e2.methodHolesSet(node); 219 salcianu 1.4 if(!newMHs.isEmpty() && methodHolesSet(node).isEmpty()) { 220 salcianu 1.4 addMethodHole(node, (HMethod) newMHs.iterator().next()); 221 salcianu 1.4 if(ppgRoots != null) 222 salcianu 1.4 ppgRoots.add(node); 223 salcianu 1.4 } 224 salcianu 1.4 } 225 salcianu 1.4 } 226 salcianu 1.4 else { /* !PointerAnalysis.CONDENSED_ESCAPE_INFO) */ 227 salcianu 1.4 assert ppgRoots == null : 228 salcianu 1.4 "ppgRoots implemented only for CONDENSED_ESCAPE_INFO"; 229 salcianu 1.4 rel_m.union(e2.rel_m); 230 salcianu 1.4 } 231 salcianu 1.1.2.8 } 232 salcianu 1.1.2.8 233 salcianu 1.4 234 salcianu 1.1.2.8 /** Inserts the image of <code>e2</code> through the <code>mu</code> 235 salcianu 1.1.2.26 mapping into <code>this</code> <code>PAEscapeFunc</code>. */ 236 salcianu 1.4 public void insert(PAEscapeFunc e2, final Relation mu, final Set noholes, 237 salcianu 1.4 final Set/*<PANode>*/ ppgRoots) { 238 salcianu 1.1.2.8 // insert the node holes 239 salcianu 1.1.2.8 RelationEntryVisitor nvisitor = 240 salcianu 1.4 new RelationEntryVisitor() { 241 salcianu 1.4 public void visit(Object key, Object value) { 242 salcianu 1.4 if(noholes.contains(value)) return; 243 salcianu 1.4 PANode origHole = (PANode) value; 244 salcianu 1.4 Set holes = 245 salcianu 1.4 (origHole.type == PANode.LOST) ? 246 salcianu 1.4 Collections.singleton(origHole) : 247 salcianu 1.4 mu.getValues(origHole); 248 salcianu 1.4 Set nodes = mu.getValues(key); 249 cananian 1.6 for(Object nodeO : nodes) { 250 cananian 1.6 PANode node = (PANode) nodeO; 251 salcianu 1.4 if(addNodeHoles(node, holes) && (ppgRoots != null)) 252 salcianu 1.4 ppgRoots.add(node); 253 salcianu 1.1.2.8 } 254 salcianu 1.4 } 255 salcianu 1.4 }; 256 salcianu 1.1.2.8 257 salcianu 1.1.2.8 e2.rel_n.forAllEntries(nvisitor); 258 salcianu 1.1.2.8 259 salcianu 1.1.2.20 ///// for(Iterator it = e2.escaped_into_mh.iterator(); it.hasNext(); ){ 260 salcianu 1.1.2.20 ///// PANode node = (PANode) it.next(); 261 salcianu 1.1.2.21 ///// escaped_into_mh.addAll(mu.getValues(node)); 262 salcianu 1.1.2.20 ///// } 263 cananian 1.6 for(Object nodeO : e2.getEscapedIntoMH()) { 264 cananian 1.6 PANode node = (PANode) nodeO; 265 salcianu 1.4 Set imgs = mu.getValues(node); 266 salcianu 1.4 Set holes = e2.methodHolesSet(node); 267 cananian 1.6 for(Object node_imgO : imgs) { 268 cananian 1.6 PANode node_img = (PANode) node_imgO; 269 salcianu 1.4 if(addMethodHoles(node_img, holes) && (ppgRoots != null)) 270 salcianu 1.4 ppgRoots.add(node_img); 271 salcianu 1.1.2.20 } 272 salcianu 1.1.2.14 } 273 salcianu 1.1.2.11 } 274 salcianu 1.1.2.11 275 salcianu 1.1.2.11 /* Specializes <code>this</code> according to <code>map</code>. */ 276 salcianu 1.1.2.11 public PAEscapeFunc specialize(Map map){ 277 salcianu 1.1.2.11 PAEscapeFunc e2 = new PAEscapeFunc(); 278 salcianu 1.1.2.11 279 cananian 1.6 for(Object nodeO : rel_n.keys()){ 280 cananian 1.6 PANode node = (PANode) nodeO; 281 salcianu 1.1.2.11 PANode node2 = PANode.translate(node, map); 282 salcianu 1.1.2.21 Iterator itnh = rel_n.getValues(node).iterator(); 283 salcianu 1.1.2.21 while(itnh.hasNext()) 284 salcianu 1.1.2.11 e2.addNodeHole(node2, 285 salcianu 1.1.2.11 PANode.translate((PANode)itnh.next(),map)); 286 salcianu 1.1.2.11 } 287 salcianu 1.1.2.11 288 salcianu 1.1.2.20 ///// for(Iterator it = escaped_into_mh.iterator(); it.hasNext(); ){ 289 salcianu 1.1.2.20 ///// PANode node = (PANode) it.next(); 290 salcianu 1.1.2.20 ///// e2.escaped_into_mh.add(PANode.translate(node, map)); 291 salcianu 1.1.2.20 ///// } 292 cananian 1.6 for(Object nodeO : getEscapedIntoMH()) { 293 cananian 1.6 PANode node = (PANode) nodeO; 294 salcianu 1.1.2.20 PANode node2 = PANode.translate(node, map); 295 salcianu 1.1.2.20 e2.addMethodHoles(node2, methodHolesSet(node)); 296 salcianu 1.1.2.20 } 297 salcianu 1.1.2.20 ///// 298 salcianu 1.1.2.14 299 salcianu 1.1.2.11 return e2; 300 salcianu 1.1.2.1 } 301 salcianu 1.1.2.1 302 salcianu 1.1.2.14 /** Checks the equality of two <code>PAEscapeFunc</code> objects. */ 303 salcianu 1.1.2.14 public boolean equals(Object obj){ 304 salcianu 1.1.2.14 if(obj == null) return false; 305 salcianu 1.1.2.14 PAEscapeFunc e2 = (PAEscapeFunc) obj; 306 salcianu 1.1.2.14 307 salcianu 1.1.2.20 ///// return 308 salcianu 1.1.2.20 ///// rel_n.equals(e2.rel_n) && 309 salcianu 1.1.2.20 ///// escaped_into_mh.equals(e2.escaped_into_mh); 310 salcianu 1.1.2.20 return 311 salcianu 1.4 rel_n.equals(e2.rel_n) && 312 salcianu 1.4 (PointerAnalysis.CONDENSED_ESCAPE_INFO ? 313 salcianu 1.4 rel_m.keys().equals(e2.rel_m.keys()) : 314 salcianu 1.4 rel_m.equals(e2.rel_m)); 315 salcianu 1.1.2.3 } 316 salcianu 1.1.2.3 317 salcianu 1.1.2.14 /** Returns the set of escaped nodes. */ 318 salcianu 1.1.2.3 public Set escapedNodes(){ 319 salcianu 1.1.2.21 HashSet set = new HashSet(rel_n.keys()); 320 salcianu 1.1.2.20 ////// set.addAll(escaped_into_mh); 321 salcianu 1.1.2.21 set.addAll(rel_m.keys()); 322 salcianu 1.1.2.20 ////// 323 salcianu 1.1.2.3 return set; 324 salcianu 1.1.2.2 } 325 salcianu 1.1.2.2 326 salcianu 1.1.2.5 /** Private constructor used only by <code>select</code> and 327 salcianu 1.1.2.5 <code>clone</code> */ 328 salcianu 1.1.2.20 ///// private PAEscapeFunc(Relation rel_n, Set escaped_into_mh){ 329 salcianu 1.1.2.20 ///// this.rel_n = rel_n; 330 salcianu 1.1.2.20 ///// this.escaped_into_mh = escaped_into_mh; 331 salcianu 1.1.2.20 ///// } 332 salcianu 1.1.2.20 private PAEscapeFunc(Relation rel_n, Relation rel_m){ 333 salcianu 1.1.2.20 this.rel_n = rel_n; 334 salcianu 1.1.2.20 this.rel_m = rel_m; 335 salcianu 1.1.2.1 } 336 salcianu 1.1.2.5 337 salcianu 1.1.2.5 /** Returns a <code>PAEscapeFunc</code> containing escape information 338 salcianu 1.1.2.5 only about the nodes from the set <code>remaining_nodes</code>. */ 339 salcianu 1.1.2.5 public PAEscapeFunc select(Set remaining_nodes){ 340 salcianu 1.1.2.5 Relation _rel_n = rel_n.select(remaining_nodes); 341 salcianu 1.1.2.14 342 salcianu 1.1.2.20 ///// Set set = new HashSet(); 343 salcianu 1.1.2.20 ///// for(Iterator it = escaped_into_mh.iterator(); it.hasNext(); ){ 344 salcianu 1.1.2.20 ///// PANode node = (PANode) it.next(); 345 salcianu 1.1.2.20 ///// if(remaining_nodes.contains(node)) 346 salcianu 1.1.2.20 ///// set.add(node); 347 salcianu 1.1.2.20 ///// } 348 salcianu 1.1.2.20 Relation _rel_m = rel_m.select(remaining_nodes); 349 salcianu 1.1.2.14 350 salcianu 1.1.2.20 //// return new PAEscapeFunc(_rel_n, set); 351 salcianu 1.1.2.20 return new PAEscapeFunc(_rel_n, _rel_m); 352 salcianu 1.1.2.5 } 353 salcianu 1.1.2.5 354 salcianu 1.1.2.1 355 cananian 1.3 /** <code>clone</code> does a deep copy of <code>this</code> object. */ 356 salcianu 1.1.2.1 public Object clone(){ 357 salcianu 1.1.2.20 ///// return 358 salcianu 1.1.2.20 ///// new PAEscapeFunc((Relation)(rel_n.clone()), 359 salcianu 1.1.2.20 ///// (Set) ((HashSet) escaped_into_mh).clone()); 360 salcianu 1.1.2.1 return 361 salcianu 1.1.2.21 new PAEscapeFunc((Relation) (rel_n.clone()), 362 salcianu 1.1.2.21 (Relation) (rel_m.clone())); 363 salcianu 1.1.2.1 } 364 salcianu 1.1.2.1 365 salcianu 1.1.2.6 /** Pretty-print debug function. 366 salcianu 1.1.2.6 Two equal <code>PAEscapeFunc</code>s are guaranteed to have the same 367 salcianu 1.1.2.6 string representation. */ 368 salcianu 1.1.2.1 public String toString(){ 369 salcianu 1.1.2.7 StringBuffer buffer = new StringBuffer(" Escape function:\n"); 370 salcianu 1.1.2.1 371 salcianu 1.1.2.21 Set set = new HashSet(rel_n.keys()); 372 salcianu 1.1.2.20 ////// set.addAll(escaped_into_mh); 373 salcianu 1.1.2.21 set.addAll(rel_m.keys()); 374 salcianu 1.1.2.1 375 salcianu 1.1.2.6 Object[] nodes = Debug.sortedSet(set); 376 salcianu 1.1.2.6 for(int i = 0; i < nodes.length ; i++){ 377 salcianu 1.1.2.6 PANode n = (PANode) nodes[i]; 378 salcianu 1.1.2.6 buffer.append(" " + n + ":"); 379 salcianu 1.1.2.1 380 salcianu 1.1.2.6 Object[] nholes = Debug.sortedSet(nodeHolesSet(n)); 381 salcianu 1.1.2.6 for(int j = 0 ; j < nholes.length ; j++){ 382 salcianu 1.1.2.6 buffer.append(" "); 383 salcianu 1.1.2.6 buffer.append((PANode)nholes[j]); 384 salcianu 1.1.2.1 } 385 salcianu 1.1.2.6 386 salcianu 1.1.2.20 Object[] mholes = Debug.sortedSet(methodHolesSet(n)); 387 salcianu 1.1.2.20 for(int j = 0 ; j < mholes.length ; j++){ 388 salcianu 1.4 buffer.append("\n\t"); 389 salcianu 1.1.2.20 buffer.append((HMethod)mholes[j]); 390 salcianu 1.1.2.20 } 391 salcianu 1.1.2.14 392 salcianu 1.1.2.20 ///// if(escaped_into_mh.contains(n)) 393 salcianu 1.1.2.20 ///// buffer.append(" M"); 394 salcianu 1.1.2.6 buffer.append("\n"); 395 salcianu 1.1.2.1 } 396 salcianu 1.1.2.1 397 salcianu 1.1.2.1 return buffer.toString(); 398 salcianu 1.1.2.1 } 399 salcianu 1.1.2.1 }