1 /*
   2  * Copyright 2001-2002 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.bugspot;
  26 
  27 import java.awt.*;
  28 import javax.swing.*;
  29 import java.util.*;
  30 import sun.jvm.hotspot.debugger.*;
  31 import sun.jvm.hotspot.debugger.cdbg.*;
  32 import sun.jvm.hotspot.bugspot.tree.*;
  33 import sun.jvm.hotspot.oops.*;
  34 import sun.jvm.hotspot.runtime.*;
  35 import sun.jvm.hotspot.ui.tree.*;
  36 import sun.jvm.hotspot.ui.treetable.*;
  37 
  38 /** Manages display of a set of local variables in a frame, or the
  39     contents of the "this" pointer */
  40 
  41 public class VariablePanel extends JPanel {
  42   private JTreeTable treeTable;
  43   private SimpleTreeTableModel model;
  44   private SimpleTreeGroupNode root;
  45 
  46   public VariablePanel() {
  47     super();
  48 
  49     model = new SimpleTreeTableModel();
  50     model.setValuesEditable(false);
  51     root = new SimpleTreeGroupNode();
  52     model.setRoot(root);
  53     treeTable = new JTreeTable(model);
  54     treeTable.setRootVisible(false);
  55     treeTable.setShowsRootHandles(true);
  56     treeTable.setShowsIcons(false);
  57     treeTable.setTreeEditable(false);
  58     treeTable.getTableHeader().setReorderingAllowed(false);
  59     treeTable.setCellSelectionEnabled(true);
  60     treeTable.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
  61     treeTable.setDragEnabled(true);
  62     JScrollPane sp = new JScrollPane(treeTable);
  63     sp.getViewport().setBackground(Color.white);
  64 
  65     setLayout(new BorderLayout());
  66     add(sp, BorderLayout.CENTER);
  67   }
  68 
  69   /** Clear the contents of this VariablePanel */
  70   public void clear() {
  71     root.removeAllChildren();
  72     model.fireTreeStructureChanged();
  73   }
  74 
  75   /** Update the contents of this VariablePanel from the given CFrame */
  76   public void update(CFrame fr) {
  77     // Collect locals
  78     CCollector coll = new CCollector();
  79     fr.iterateLocals(coll);
  80     update(coll);
  81   }
  82 
  83   /** Update the contents of this VariablePanel from the given JavaVFrame */
  84   public void update(JavaVFrame jfr) {
  85     Method m = jfr.getMethod();
  86     if (!m.hasLocalVariableTable()) {
  87       return;
  88     }
  89     int bci = jfr.getBCI();
  90     // Get local variable table
  91     LocalVariableTableElement[] locals = m.getLocalVariableTable();
  92     // Get locals as StackValueCollection
  93     StackValueCollection coll = jfr.getLocals();
  94     root.removeAllChildren();
  95     // See which locals are live
  96     for (int i = 0; i < locals.length; i++) {
  97       LocalVariableTableElement local = locals[i];
  98       if (local.getStartBCI() <= bci && bci < local.getStartBCI() + local.getLength()) {
  99         // Valid; add it
 100         SimpleTreeNode node = null;
 101         Symbol name = null;
 102         try {
 103           name = m.getConstants().getSymbolAt(local.getNameCPIndex());
 104           if (name == null) {
 105             System.err.println("Null name at slot " +
 106                                local.getNameCPIndex() +
 107                                " for local variable at slot " +
 108                                local.getSlot());
 109             continue;
 110           }
 111         } catch (Exception e) {
 112           System.err.println("Unable to fetch name at slot " +
 113                              local.getNameCPIndex() +
 114                              " for local variable at slot " +
 115                              local.getSlot());
 116           e.printStackTrace();
 117           continue;
 118         }
 119         sun.jvm.hotspot.oops.NamedFieldIdentifier f =
 120           new sun.jvm.hotspot.oops.NamedFieldIdentifier(name.asString());
 121         Symbol descriptor = null;
 122         try {
 123           descriptor = m.getConstants().getSymbolAt(local.getDescriptorCPIndex());
 124         } catch (Exception e) {
 125           System.err.println("Unable to fetch descriptor at slot " +
 126                              local.getDescriptorCPIndex() +
 127                              " for local variable " + f.getName() +
 128                              " at slot " + local.getSlot());
 129           e.printStackTrace();
 130           continue;
 131         }
 132 
 133         if (descriptor != null) {
 134           switch (descriptor.getByteAt(0)) {
 135           case 'F': {
 136             node = new sun.jvm.hotspot.ui.tree.FloatTreeNodeAdapter(coll.floatAt(local.getSlot()), f, true);
 137             break;
 138           }
 139           case 'D': {
 140             node = new sun.jvm.hotspot.ui.tree.DoubleTreeNodeAdapter(coll.doubleAt(local.getSlot()), f, true);
 141             break;
 142           }
 143           case 'C': {
 144             node = new sun.jvm.hotspot.ui.tree.CharTreeNodeAdapter((char) coll.intAt(local.getSlot()), f, true);
 145             break;
 146           }
 147           case 'B':
 148           case 'S':
 149           case 'I': {
 150             node = new sun.jvm.hotspot.ui.tree.LongTreeNodeAdapter(coll.intAt(local.getSlot()), f, true);
 151             break;
 152           }
 153           case 'Z': {
 154             node = new sun.jvm.hotspot.ui.tree.BooleanTreeNodeAdapter(
 155               ((coll.intAt(local.getSlot()) != 0) ? true : false), f, true
 156             );
 157             break;
 158           }
 159           case 'J': {
 160             node = new sun.jvm.hotspot.ui.tree.LongTreeNodeAdapter(coll.longAt(local.getSlot()), f, true);
 161             break;
 162           }
 163           default: {
 164             try {
 165               node = new sun.jvm.hotspot.ui.tree.OopTreeNodeAdapter(
 166                 VM.getVM().getObjectHeap().newOop(coll.oopHandleAt(local.getSlot())), f, true
 167               );
 168             } catch (AddressException e) {
 169               node = new sun.jvm.hotspot.ui.tree.FieldTreeNodeAdapter(f, true) {
 170                   public int getChildCount()                       { return 0;     }
 171                   public SimpleTreeNode getChild(int i)            { return null;  }
 172                   public boolean isLeaf()                          { return false; }
 173                   public int getIndexOfChild(SimpleTreeNode child) { return 0;     }
 174                   public String getValue() {
 175                     return "<Bad oop>";
 176                   }
 177                 };
 178             }
 179             break;
 180           }
 181           }
 182           if (node != null) {
 183             root.addChild(node);
 184           }
 185         }
 186       }
 187     }
 188 
 189     model.fireTreeStructureChanged();
 190   }
 191 
 192   /** Update the contents of this VariablePanel from the given "this"
 193       pointer of the given type */
 194   public void update(Address thisAddr, Type type) {
 195     // Collect fields
 196     CCollector coll = new CCollector();
 197     type.iterateObject(thisAddr, coll);
 198     update(coll);
 199   }
 200 
 201   private void update(CCollector coll) {
 202     root.removeAllChildren();
 203     for (int i = 0; i < coll.getNumChildren(); i++) {
 204       root.addChild(coll.getChild(i));
 205     }
 206     model.fireTreeStructureChanged();
 207   }
 208 
 209   static class CCollector extends DefaultObjectVisitor {
 210     private java.util.List children;
 211 
 212     public CCollector() {
 213       children = new ArrayList();
 214     }
 215 
 216     public int getNumChildren() {
 217       return children.size();
 218     }
 219 
 220     public SimpleTreeNode getChild(int i) {
 221       return (SimpleTreeNode) children.get(i);
 222     }
 223 
 224     public void doBit(sun.jvm.hotspot.debugger.cdbg.FieldIdentifier f, long val) {
 225       children.add(new sun.jvm.hotspot.bugspot.tree.LongTreeNodeAdapter(val, f, true));
 226     }
 227     public void doInt(sun.jvm.hotspot.debugger.cdbg.FieldIdentifier f, long val) {
 228       children.add(new sun.jvm.hotspot.bugspot.tree.LongTreeNodeAdapter(val, f, true));
 229     }
 230     public void doEnum(sun.jvm.hotspot.debugger.cdbg.FieldIdentifier f, long val, String enumName) {
 231       children.add(new sun.jvm.hotspot.bugspot.tree.EnumTreeNodeAdapter(enumName, val, f, true));
 232     }
 233     public void doFloat(sun.jvm.hotspot.debugger.cdbg.FieldIdentifier f, float val) {
 234       children.add(new sun.jvm.hotspot.bugspot.tree.FloatTreeNodeAdapter(val, f, true));
 235     }
 236     public void doDouble(sun.jvm.hotspot.debugger.cdbg.FieldIdentifier f, double val) {
 237       children.add(new sun.jvm.hotspot.bugspot.tree.DoubleTreeNodeAdapter(val, f, true));
 238     }
 239     public void doPointer(sun.jvm.hotspot.debugger.cdbg.FieldIdentifier f, Address val) {
 240       children.add(new sun.jvm.hotspot.bugspot.tree.AddressTreeNodeAdapter(val, f, true));
 241     }
 242     public void doArray(sun.jvm.hotspot.debugger.cdbg.FieldIdentifier f, Address val) {
 243       children.add(new sun.jvm.hotspot.bugspot.tree.AddressTreeNodeAdapter(val, f, true));
 244     }
 245     public void doRef(sun.jvm.hotspot.debugger.cdbg.FieldIdentifier f, Address val) {
 246       children.add(new sun.jvm.hotspot.bugspot.tree.AddressTreeNodeAdapter(val, f, true));
 247     }
 248     public void doCompound(sun.jvm.hotspot.debugger.cdbg.FieldIdentifier f, Address val) {
 249       children.add(new sun.jvm.hotspot.bugspot.tree.ObjectTreeNodeAdapter(val, f, true));
 250     }
 251   }
 252 }