Mercurial > hg > truffle
annotate agent/src/share/classes/sun/jvm/hotspot/ui/Inspector.java @ 17524:89152779163c
Merge with jdk8-b132
author | Gilles Duboscq <duboscq@ssw.jku.at> |
---|---|
date | Wed, 15 Oct 2014 11:59:32 +0200 |
parents | c18cbe5936b8 |
children |
rev | line source |
---|---|
0 | 1 /* |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
0
diff
changeset
|
2 * Copyright (c) 2000, 2006, Oracle and/or its affiliates. All rights reserved. |
0 | 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 * | |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
0
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
0
diff
changeset
|
20 * or visit www.oracle.com if you need additional information or have any |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
0
diff
changeset
|
21 * questions. |
0 | 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 } |