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 }