1 /* 2 * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 20 * CA 95054 USA or visit www.sun.com if you need additional information or 21 * have any questions. 22 * 23 */ 24 25 package sun.jvm.hotspot.opto; 26 27 import java.io.*; 28 import java.lang.reflect.Constructor; 29 import java.util.*; 30 import sun.jvm.hotspot.debugger.*; 31 import sun.jvm.hotspot.runtime.*; 32 import sun.jvm.hotspot.oops.*; 33 import sun.jvm.hotspot.types.*; 34 35 public class Node extends VMObject { 36 static { 37 VM.registerVMInitializedObserver(new Observer() { 38 public void update(Observable o, Object data) { 39 initialize(VM.getVM().getTypeDataBase()); 40 } 41 }); 42 } 43 44 private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { 45 Type type = db.lookupType("Node"); 46 outmaxField = new CIntField(type.getCIntegerField("_outmax"), 0); 47 outcntField = new CIntField(type.getCIntegerField("_outcnt"), 0); 48 maxField = new CIntField(type.getCIntegerField("_max"), 0); 49 cntField = new CIntField(type.getCIntegerField("_cnt"), 0); 50 idxField = new CIntField(type.getCIntegerField("_idx"), 0); 51 outField = type.getAddressField("_out"); 52 inField = type.getAddressField("_in"); 53 54 nodeType = db.lookupType("Node"); 55 56 virtualConstructor = new VirtualBaseConstructor(db, nodeType, "sun.jvm.hotspot.opto", Node.class); 57 } 58 59 private static CIntField outmaxField; 60 private static CIntField outcntField; 61 private static CIntField maxField; 62 private static CIntField cntField; 63 private static CIntField idxField; 64 private static AddressField outField; 65 private static AddressField inField; 66 67 private static VirtualBaseConstructor virtualConstructor; 68 69 private static Type nodeType; 70 71 static HashMap nodes = new HashMap(); 72 73 static HashMap constructors = new HashMap(); 74 75 static abstract class Instantiator { 76 abstract Node create(Address addr); 77 } 78 79 static public Node create(Address addr) { 80 if (addr == null) return null; 81 Node result = (Node)nodes.get(addr); 82 if (result == null) { 83 result = (Node)virtualConstructor.instantiateWrapperFor(addr); 84 nodes.put(addr, result); 85 } 86 return result; 87 } 88 89 public Node(Address addr) { 90 super(addr); 91 } 92 93 public int outcnt() { 94 return (int)outcntField.getValue(this.getAddress()); 95 } 96 97 public int req() { 98 return (int)cntField.getValue(this.getAddress()); 99 } 100 101 public int len() { 102 return (int)maxField.getValue(this.getAddress()); 103 } 104 105 public int idx() { 106 return (int)idxField.getValue(this.getAddress()); 107 } 108 109 private Node[] _out; 110 private Node[] _in; 111 112 public Node rawOut(int i) { 113 if (_out == null) { 114 int addressSize = (int)VM.getVM().getAddressSize(); 115 _out = new Node[outcnt()]; 116 Address ptr = outField.getValue(this.getAddress()); 117 for (int j = 0; j < outcnt(); j++) { 118 _out[j] = Node.create(ptr.getAddressAt(j * addressSize)); 119 } 120 } 121 return _out[i]; 122 } 123 124 public Node in(int i) { 125 if (_in == null) { 126 int addressSize = (int)VM.getVM().getAddressSize(); 127 _in = new Node[len()]; 128 Address ptr = inField.getValue(this.getAddress()); 129 for (int j = 0; j < len(); j++) { 130 _in[j] = Node.create(ptr.getAddressAt(j * addressSize)); 131 } 132 } 133 return _in[i]; 134 } 135 136 public ArrayList collect(int d, boolean onlyCtrl) { 137 int depth = Math.abs(d); 138 ArrayList nstack = new ArrayList(); 139 BitSet set = new BitSet(); 140 141 nstack.add(this); 142 set.set(idx()); 143 int begin = 0; 144 int end = 0; 145 for (int i = 0; i < depth; i++) { 146 end = nstack.size(); 147 for(int j = begin; j < end; j++) { 148 Node tp = (Node)nstack.get(j); 149 int limit = d > 0 ? tp.len() : tp.outcnt(); 150 for(int k = 0; k < limit; k++) { 151 Node n = d > 0 ? tp.in(k) : tp.rawOut(k); 152 153 // if (NotANode(n)) continue; 154 if (n == null) continue; 155 // do not recurse through top or the root (would reach unrelated stuff) 156 // if (n.isRoot() || n.isTop()) continue; 157 // if (onlyCtrl && !n.isCfg()) continue; 158 159 if (!set.get(n.idx())) { 160 nstack.add(n); 161 set.set(n.idx()); 162 } 163 } 164 } 165 begin = end; 166 } 167 return nstack; 168 } 169 170 protected void dumpNodes(Node s, int d, boolean onlyCtrl, PrintStream out) { 171 if (s == null) return; 172 173 ArrayList nstack = s.collect(d, onlyCtrl); 174 int end = nstack.size(); 175 if (d > 0) { 176 for(int j = end-1; j >= 0; j--) { 177 ((Node)nstack.get(j)).dump(out); 178 } 179 } else { 180 for(int j = 0; j < end; j++) { 181 ((Node)nstack.get(j)).dump(out); 182 } 183 } 184 } 185 186 public void dump(int depth, PrintStream out) { 187 dumpNodes(this, depth, false, out); 188 } 189 190 public String Name() { 191 Type t = VM.getVM().getTypeDataBase().findDynamicTypeForAddress(getAddress(), nodeType); 192 String name = null; 193 if (t != null) { 194 name = t.toString(); 195 } else { 196 Class c = getClass(); 197 if (c == Node.class) { 198 // couldn't identify class type 199 return "UnknownNode<" + getAddress().getAddressAt(0) + ">"; 200 } 201 name = getClass().getName(); 202 if (name.startsWith("sun.jvm.hotspot.opto.")) { 203 name = name.substring("sun.jvm.hotspot.opto.".length()); 204 } 205 } 206 if (name.endsWith("Node")) { 207 return name.substring(0, name.length() - 4); 208 } 209 return name; 210 } 211 212 public void dump(PrintStream out) { 213 out.print(" "); 214 out.print(idx()); 215 out.print("\t"); 216 out.print(Name()); 217 out.print("\t=== "); 218 int i = 0; 219 for (i = 0; i < req(); i++) { 220 Node n = in(i); 221 if (n != null) { 222 out.print(' '); 223 out.print(in(i).idx()); 224 } else { 225 out.print("_"); 226 } 227 out.print(" "); 228 } 229 if (len() != req()) { 230 int prec = 0; 231 for (; i < len(); i++) { 232 Node n = in(i); 233 if (n != null) { 234 if (prec++ == 0) { 235 out.print("| "); 236 } 237 out.print(in(i).idx()); 238 } 239 out.print(" "); 240 } 241 } 242 dumpOut(out); 243 dumpSpec(out); 244 out.println(); 245 } 246 247 void dumpOut(PrintStream out) { 248 // Delimit the output edges 249 out.print(" [["); 250 // Dump the output edges 251 for (int i = 0; i < outcnt(); i++) { // For all outputs 252 Node u = rawOut(i); 253 if (u == null) { 254 out.print("_ "); 255 // } else if (NotANode(u)) { 256 // out.print("NotANode "); 257 } else { 258 // out.print("%c%d ", Compile::current()->nodeArena()->contains(u) ? ' ' : 'o', u->_idx); 259 out.print(' '); 260 out.print(u.idx()); 261 out.print(' '); 262 } 263 } 264 out.print("]] "); 265 } 266 267 public void dumpSpec(PrintStream out) { 268 } 269 }