View Javadoc
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  
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  
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  
86      public void epilogue() {
87      }
88  
89      public void cleanup() {
90        iterated = 0;
91        updateProgressBar(result);
92        searching = false;
93        result = null;
94      }
95  
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 
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 
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 
201   private void clearResultWindow() {
202     SwingUtilities.invokeLater(new Runnable() {
203         public void run() {
204           contentEditor.setText("");
205         }
206       });
207   }
208 
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 }