1 /*
2  * Copyright (c) 2004, 2010, 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.ui;
26 
27 import java.io.*;
28 import java.awt.*;
29 import java.awt.event.*;
30 import javax.swing.*;
31 import javax.swing.event.*;
32 import javax.swing.text.*;
33 
34 import sun.jvm.hotspot.debugger.*;
35 import sun.jvm.hotspot.oops.*;
36 import sun.jvm.hotspot.runtime.*;
37 import sun.jvm.hotspot.utilities.*;
38 import sun.jvm.hotspot.code.*;
39 import sun.jvm.hotspot.ui.classbrowser.*;
40 
41 /** Finds a given (Address) value in the code cache. Only intended for use
42     in a debugging system. */
43 
44 public class FindInCodeCachePanel extends SAPanel {
45   private Visitor          iterator;
46   private long             usedSize;
47   private long             iterated;
48   private Address          value;
49   private ProgressBarPanel progressBar;
50   private HistoryComboBox  addressField;
51   private JButton          findButton;
52   private SAEditorPane     contentEditor;
53 
54   class Visitor implements CodeCacheVisitor {
55     Address base;
56     StringBuffer result;
57     boolean searching;
58 
prologue(Address start, Address end)59     public void prologue(Address start, Address end) {
60       searching = true;
61       base = start;
62       usedSize = end.minus(start);
63       iterated = 0;
64       result = new StringBuffer();
65       clearResultWindow();
66     }
67 
visit(CodeBlob blob)68     public void visit(CodeBlob blob) {
69       Address begin = blob.headerBegin();
70       Address end = begin.addOffsetTo(blob.getSize());
71       long addressSize = VM.getVM().getAddressSize();
72 
73       boolean found = false;
74       while (!found && begin.lessThan(end)) {
75         Address val = begin.getAddressAt(0);
76         if (AddressOps.equal(val, value)) {
77           reportResult(result, blob);
78           found = true;
79         }
80         begin = begin.addOffsetTo(addressSize);
81       }
82       iterated = end.minus(base);;
83       updateProgressBar(null);
84     }
85 
epilogue()86     public void epilogue() {
87     }
88 
cleanup()89     public void cleanup() {
90       iterated = 0;
91       updateProgressBar(result);
92       searching = false;
93       result = null;
94     }
95 
search()96     private void search() {
97       // Parse text
98       Address val = null;
99       try {
100         val = VM.getVM().getDebugger().parseAddress(addressField.getText());
101       } catch (Exception ex) {
102         contentEditor.setText("<b>Error parsing address</b>");
103         return;
104       }
105 
106       // make sure we don't start up multiple search threads in parallel
107       synchronized (iterator) {
108         if (searching && value.equals(val)) {
109           return;
110         }
111 
112         value = val;
113         contentEditor.setText("");
114         findButton.setEnabled(false);
115 
116         System.out.println("Searching " + value);
117         java.lang.Thread t = new java.lang.Thread(new Runnable() {
118             public void run() {
119               synchronized (iterator) {
120                 try {
121                   VM.getVM().getCodeCache().iterate(iterator);
122                 } finally {
123                   iterator.cleanup();
124                 }
125               }
126             }
127           });
128         t.start();
129       }
130     }
131   }
132 
133 
FindInCodeCachePanel()134   public FindInCodeCachePanel() {
135     super();
136 
137     setLayout(new BorderLayout());
138 
139     JPanel topPanel = new JPanel();
140     topPanel.setLayout(new BoxLayout(topPanel, BoxLayout.Y_AXIS));
141 
142     JPanel panel = new JPanel();
143     panel.setLayout(new BoxLayout(panel, BoxLayout.X_AXIS));
144     panel.add(new JLabel("Address to search for:"));
145 
146     addressField = new HistoryComboBox();
147     panel.add(addressField);
148 
149     iterator = new Visitor();
150 
151     findButton = new JButton("Find");
152     ActionListener listener = new ActionListener() {
153         public void actionPerformed(ActionEvent e) {
154           iterator.search();
155         }
156       };
157     panel.add(findButton);
158     findButton.addActionListener(listener);
159     addressField.addActionListener(listener);
160     topPanel.add(panel);
161 
162     progressBar = new ProgressBarPanel(ProgressBarPanel.HORIZONTAL, "Search progress:");
163     topPanel.add(progressBar);
164 
165     add(topPanel, BorderLayout.NORTH);
166 
167     contentEditor = new SAEditorPane();
168 
169     HyperlinkListener hyperListener = new HyperlinkListener() {
170         public void hyperlinkUpdate(HyperlinkEvent e) {
171           if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
172             String description = e.getDescription();
173             int index = description.indexOf(':');
174             if (index != -1) {
175               String item = description.substring(0, index);
176               if (item.equals("blob")) {
177                 Address blob = VM.getVM().getDebugger().parseAddress(description.substring(index + 1));
178                 showCodeViewer(blob);
179               }
180             }
181           }
182         }
183       };
184 
185     contentEditor.addHyperlinkListener(hyperListener);
186 
187     JScrollPane scroller = new JScrollPane(contentEditor);
188     add(scroller, BorderLayout.CENTER);
189   }
190 
reportResult(StringBuffer result, CodeBlob blob)191   private void reportResult(StringBuffer result, CodeBlob blob) {
192     result.append("<a href='blob:");
193     result.append(blob.contentBegin().toString());
194     result.append("'>");
195     result.append(blob.getName());
196     result.append("@");
197     result.append(blob.contentBegin());
198     result.append("</a><br>");
199   }
200 
clearResultWindow()201   private void clearResultWindow() {
202     SwingUtilities.invokeLater(new Runnable() {
203         public void run() {
204           contentEditor.setText("");
205         }
206       });
207   }
208 
updateProgressBar(final StringBuffer result)209   private void updateProgressBar(final StringBuffer result) {
210     SwingUtilities.invokeLater(new Runnable() {
211         public void run() {
212           progressBar.setValue((double) iterated / (double) usedSize);
213           if (result != null) {
214             String s = "<html> <head> </head> <body>\n" + result + " </body> </html>";
215             contentEditor.setText(s);
216             findButton.setEnabled(true);
217           }
218         }
219       });
220   }
221 }
222