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
25package sun.jvm.hotspot.ui;
26
27import java.io.*;
28import java.awt.*;
29import java.awt.event.*;
30import javax.swing.*;
31import javax.swing.event.*;
32import javax.swing.text.*;
33
34import sun.jvm.hotspot.debugger.*;
35import sun.jvm.hotspot.oops.*;
36import sun.jvm.hotspot.runtime.*;
37import sun.jvm.hotspot.utilities.*;
38import sun.jvm.hotspot.code.*;
39import 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
44public 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}
222