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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20  * or visit www.oracle.com if you need additional information or have any
21  * 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 {
VM.registerVMInitializedObserver(new Observer() { public void update(Observable o, Object data) { initialize(VM.getVM().getTypeDataBase()); } })37     VM.registerVMInitializedObserver(new Observer() {
38         public void update(Observable o, Object data) {
39           initialize(VM.getVM().getTypeDataBase());
40         }
41       });
42   }
43 
initialize(TypeDataBase db)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 {
create(Address addr)76     abstract Node create(Address addr);
77   }
78 
create(Address addr)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 
Node(Address addr)89   public Node(Address addr) {
90     super(addr);
91   }
92 
outcnt()93   public int outcnt() {
94     return (int)outcntField.getValue(this.getAddress());
95   }
96 
req()97   public int req() {
98     return (int)cntField.getValue(this.getAddress());
99   }
100 
len()101   public int len() {
102     return (int)maxField.getValue(this.getAddress());
103   }
104 
idx()105   public int idx() {
106     return (int)idxField.getValue(this.getAddress());
107   }
108 
109   private Node[] _out;
110   private Node[] _in;
111 
rawOut(int i)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 
in(int i)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 
collect(int d, boolean onlyCtrl)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 
dumpNodes(Node s, int d, boolean onlyCtrl, PrintStream out)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 
dump(int depth, PrintStream out)186   public void dump(int depth, PrintStream out) {
187     dumpNodes(this, depth, false, out);
188   }
189 
Name()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 
dump(PrintStream out)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 
dumpOut(PrintStream out)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 
dumpSpec(PrintStream out)267   public void dumpSpec(PrintStream out) {
268   }
269 }
270