comparison agent/src/share/classes/sun/jvm/hotspot/ui/Inspector.java @ 0:a61af66fc99e jdk7-b24

Initial load
author duke
date Sat, 01 Dec 2007 00:00:00 +0000
parents
children c18cbe5936b8
comparison
equal deleted inserted replaced
-1:000000000000 0:a61af66fc99e
1 /*
2 * Copyright 2000-2006 Sun Microsystems, Inc. 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.ui;
26
27 import java.awt.*;
28 import java.awt.event.*;
29 import java.util.*;
30 import javax.swing.*;
31 import javax.swing.tree.TreePath;
32 import sun.jvm.hotspot.debugger.*;
33 import sun.jvm.hotspot.oops.*;
34 import sun.jvm.hotspot.runtime.*;
35 import sun.jvm.hotspot.types.*;
36 import sun.jvm.hotspot.ui.tree.*;
37 import sun.jvm.hotspot.utilities.*;
38
39 /** This class implements tree-browsing functionality of a particular
40 SimpleTreeNode, and is only designed to be used in a debugging
41 system. It uses a SimpleTreeModel internally. It can inspect both
42 oops as well as C++ objects described by the VMStructs database in
43 the target VM. */
44
45 public class Inspector extends SAPanel {
46 private JTree tree;
47 private SimpleTreeModel model;
48
49 // UI widgets we need permanent handles to
50 private HistoryComboBox addressField;
51 private JLabel statusLabel;
52
53 private JButton livenessButton;
54 private ActionListener livenessButtonListener;
55 private ActionListener showLivenessListener;
56 private static final String computeLivenessText = "Compute Liveness";
57 private static final String showLivenessText = "Show Liveness";
58 private JLabel liveStatus;
59 private LivenessPathList list = null;
60 private Oop currentOop = null;
61
62 public Inspector() {
63 model = new SimpleTreeModel();
64 tree = new JTree(model);
65
66 setLayout(new BorderLayout());
67 Box hbox = Box.createHorizontalBox();
68 JButton button = new JButton("Previous Oop");
69 button.addActionListener(new ActionListener() {
70 public void actionPerformed(ActionEvent e) {
71 String text = addressField.getText();
72 try {
73 VM vm = VM.getVM();
74 Address a = vm.getDebugger().parseAddress(text);
75 OopHandle handle = a.addOffsetToAsOopHandle(-vm.getAddressSize());
76 addressField.setText(handle.toString());
77 } catch (Exception ex) {
78 }
79 }
80 });
81 hbox.add(button);
82 hbox.add(new JLabel("Address / C++ Expression: "));
83 addressField = new HistoryComboBox();
84 hbox.add(addressField);
85 statusLabel = new JLabel();
86 hbox.add(statusLabel);
87
88 Box hboxDown = Box.createHorizontalBox();
89 hboxDown.add(Box.createGlue());
90
91 livenessButton = new JButton(computeLivenessText);
92 livenessButtonListener = new ActionListener() {
93 public void actionPerformed(ActionEvent e) {
94 if (currentOop != null) {
95 fireComputeLiveness();
96 }
97 return;
98 }
99 };
100 showLivenessListener = new ActionListener() {
101 public void actionPerformed(ActionEvent e) {
102 fireShowLiveness();
103 }
104 };
105 livenessButton.addActionListener(livenessButtonListener);
106 hboxDown.add(livenessButton);
107 hboxDown.add(Box.createGlue());
108
109 liveStatus = new JLabel();
110 hboxDown.add(liveStatus);
111 hboxDown.add(Box.createGlue());
112
113 add(hbox, BorderLayout.NORTH);
114 add(hboxDown, BorderLayout.SOUTH);
115
116 addressField.addActionListener(new ActionListener() {
117 public void actionPerformed(ActionEvent e) {
118 String text = addressField.getText();
119 try {
120 Address a = VM.getVM().getDebugger().parseAddress(text);
121 int max_searches = 1000;
122 int searches = 0;
123 int offset = 0;
124 Oop oop = null;
125 if (a != null) {
126 OopHandle handle = a.addOffsetToAsOopHandle(0);
127 while (searches < max_searches) {
128 searches++;
129 if (RobustOopDeterminator.oopLooksValid(handle)) {
130 try {
131 oop = VM.getVM().getObjectHeap().newOop(handle);
132 addressField.setText(handle.toString());
133 break;
134 } catch (UnknownOopException ex) {
135 // ok
136 } catch (RuntimeException ex) {
137 ex.printStackTrace();
138 }
139 }
140 offset -= 4;
141 handle = a.addOffsetToAsOopHandle(offset);
142 }
143 }
144 if (oop != currentOop) {
145 currentOop = oop;
146 liveStatus.setText("");
147 list = null;
148 if (livenessButton.getText().equals(showLivenessText)) {
149 livenessButton.setText(computeLivenessText);
150 livenessButton.removeActionListener(showLivenessListener);
151 livenessButton.addActionListener(livenessButtonListener);
152 }
153 }
154
155 if (oop != null) {
156 statusLabel.setText("");
157 setRoot(new OopTreeNodeAdapter(oop, null));
158 return;
159 }
160
161 // Try to treat this address as a C++ object and deduce its type
162 Type t = VM.getVM().getTypeDataBase().guessTypeForAddress(a);
163 if (t != null) {
164 statusLabel.setText("");
165 setRoot(new CTypeTreeNodeAdapter(a, t, null));
166 return;
167 }
168
169 statusLabel.setText("<bad oop or unknown C++ object " + text + ">");
170 }
171 catch (NumberFormatException ex) {
172 currentOop = null;
173 liveStatus.setText("");
174 list = null;
175 if (livenessButton.getText().equals(showLivenessText)) {
176 livenessButton.setText(computeLivenessText);
177 livenessButton.removeActionListener(showLivenessListener);
178 livenessButton.addActionListener(livenessButtonListener);
179 }
180 // Try to treat this as a C++ expression
181 CPPExpressions.CastExpr cast = CPPExpressions.parseCast(text);
182 if (cast != null) {
183 TypeDataBase db = VM.getVM().getTypeDataBase();
184 Type t = db.lookupType(cast.getType());
185 if (t == null) {
186 statusLabel.setText("<unknown C++ type \"" + cast.getType() + "\">");
187 } else {
188 try {
189 Address a = VM.getVM().getDebugger().parseAddress(cast.getAddress());
190 statusLabel.setText("");
191 setRoot(new CTypeTreeNodeAdapter(a, t, null));
192 } catch (NumberFormatException ex2) {
193 statusLabel.setText("<bad address " + cast.getAddress() + ">");
194 }
195 }
196 return;
197 }
198 CPPExpressions.StaticFieldExpr stat = CPPExpressions.parseStaticField(text);
199 if (stat != null) {
200 TypeDataBase db = VM.getVM().getTypeDataBase();
201 Type t = db.lookupType(stat.getContainingType());
202 if (t == null) {
203 statusLabel.setText("<unknown C++ type \"" + stat.getContainingType() + "\">");
204 } else {
205 sun.jvm.hotspot.types.Field f = t.getField(stat.getFieldName(), true, false);
206 if (f == null) {
207 statusLabel.setText("<unknown field \"" + stat.getFieldName() + "\" in type \"" +
208 stat.getContainingType() + "\">");
209 } else if (!f.isStatic()) {
210 statusLabel.setText("<field \"" + stat.getContainingType() + "::" +
211 stat.getFieldName() + "\" was not static>");
212 } else {
213 Type fieldType = f.getType();
214 if (fieldType.isPointerType()) {
215 fieldType = ((PointerType) fieldType).getTargetType();
216
217 // Try to get a more derived type
218 Type typeGuess = db.guessTypeForAddress(f.getAddress());
219 if (typeGuess != null) {
220 fieldType = typeGuess;
221 }
222
223 statusLabel.setText("");
224 setRoot(new CTypeTreeNodeAdapter(f.getAddress(),
225 fieldType,
226 new NamedFieldIdentifier(text)));
227 } else {
228 statusLabel.setText("");
229 setRoot(new CTypeTreeNodeAdapter(f.getStaticFieldAddress(),
230 f.getType(),
231 new NamedFieldIdentifier(text)));
232 }
233 }
234 }
235 return;
236 }
237
238 statusLabel.setText("<parse error>");
239 }
240 catch (AddressException ex) {
241 ex.printStackTrace();
242 currentOop = null;
243 liveStatus.setText("");
244 list = null;
245 if (livenessButton.getText().equals(showLivenessText)) {
246 livenessButton.setText(computeLivenessText);
247 livenessButton.removeActionListener(showLivenessListener);
248 livenessButton.addActionListener(livenessButtonListener);
249 }
250 statusLabel.setText("<bad address>");
251 }
252 catch (Exception ex) {
253 ex.printStackTrace();
254 currentOop = null;
255 liveStatus.setText("");
256 list = null;
257 if (livenessButton.getText().equals(showLivenessText)) {
258 livenessButton.setText(computeLivenessText);
259 livenessButton.removeActionListener(showLivenessListener);
260 livenessButton.addActionListener(livenessButtonListener);
261 }
262 statusLabel.setText("<error constructing oop>");
263 }
264 }
265 });
266
267 MouseListener ml = new MouseAdapter() {
268 public void mousePressed(MouseEvent e) {
269 int selRow = tree.getRowForLocation(e.getX(), e.getY());
270 TreePath selPath = tree.getPathForLocation(e.getX(), e.getY());
271 if(selRow != -1) {
272 if (e.getClickCount() == 1 && (e.getModifiersEx() & InputEvent.SHIFT_DOWN_MASK) != 0) {
273 Object node = tree.getLastSelectedPathComponent();
274 if (node != null && node instanceof SimpleTreeNode) {
275 showInspector((SimpleTreeNode)node);
276 }
277 }
278 }
279 }
280 };
281 tree.addMouseListener(ml);
282
283 JScrollPane scrollPane = new JScrollPane(tree);
284
285 // Let's see what happens if we let the parent deal with resizing the panel
286 add(scrollPane, BorderLayout.CENTER);
287 }
288
289 public Inspector(final SimpleTreeNode root) {
290 this();
291 SwingUtilities.invokeLater( new Runnable() {
292 public void run() {
293 if (root instanceof OopTreeNodeAdapter) {
294 final Oop oop = ((OopTreeNodeAdapter)root).getOop();
295 addressField.setText(oop.getHandle().toString());
296 }
297 setRoot(root);
298 }
299 });
300 }
301
302 private void setRoot(SimpleTreeNode root) {
303 model.setRoot(root);
304
305 // tree.invalidate();
306 // tree.validate();
307 // repaint();
308 // FIXME: invalidate? How to get to redraw? Will I have to make
309 // tree listeners work?
310 }
311
312 private void fireComputeLiveness() {
313 final Runnable cutoverButtonRunnable = new Runnable() {
314 public void run() {
315 list = LivenessAnalysis.computeAllLivenessPaths(currentOop);
316 if (list == null) {
317 liveStatus.setText("Oop is Dead");
318 } else {
319 liveStatus.setText("Oop is Alive");
320 livenessButton.removeActionListener(livenessButtonListener);
321 livenessButton.addActionListener(showLivenessListener);
322
323 livenessButton.setEnabled(true);
324 livenessButton.setText(showLivenessText);
325 }
326 }
327 };
328
329
330 if (VM.getVM().getRevPtrs() != null) {
331 cutoverButtonRunnable.run();
332 } else {
333 final WorkerThread worker = new WorkerThread();
334 worker.invokeLater(new Runnable() {
335 public void run() {
336 try {
337 ReversePtrsAnalysis rev = new ReversePtrsAnalysis();
338 rev.run();
339 cutoverButtonRunnable.run();
340 } finally {
341 worker.shutdown();
342 }
343 }
344 });
345 }
346 }
347
348 private void fireShowLiveness() {
349 if (list == null) {
350 return; // dead object
351 }
352
353 for (Iterator iter = listeners.iterator(); iter.hasNext(); ) {
354 SAListener listener = (SAListener) iter.next();
355 listener.showLiveness(currentOop, list);
356 }
357 }
358 }