/* * Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. * */ package sun.jvm.hotspot.utilities.soql; import java.util.*; import sun.jvm.hotspot.debugger.*; import sun.jvm.hotspot.oops.*; import sun.jvm.hotspot.runtime.*; public class JSJavaFrame extends DefaultScriptObject { private static final int FIELD_METHOD = 0; private static final int FIELD_BCI = 1; private static final int FIELD_LINE_NUMBER = 2; private static final int FIELD_LOCALS = 3; private static final int FIELD_THIS_OBJECT = 4; private static final int FIELD_THREAD = 5; private static final int FIELD_UNDEFINED = -1; public JSJavaFrame(JavaVFrame jvf, JSJavaFactory fac) { this.jvf = jvf; this.factory = fac; } public Object get(String name) { int fieldID = getFieldID(name); switch (fieldID) { case FIELD_METHOD: return getMethod(); case FIELD_BCI: return new Integer(getBCI()); case FIELD_LINE_NUMBER: return new Integer(getLineNumber()); case FIELD_LOCALS: return getLocals(); case FIELD_THIS_OBJECT: return getThisObject(); case FIELD_THREAD: return getThread(); case FIELD_UNDEFINED: default: return super.get(name); } } public Object[] getIds() { Object[] fieldNames = fields.keySet().toArray(); Object[] superFields = super.getIds(); Object[] res = new Object[fieldNames.length + superFields.length]; System.arraycopy(fieldNames, 0, res, 0, fieldNames.length); System.arraycopy(superFields, 0, res, fieldNames.length, superFields.length); return res; } public boolean has(String name) { if (getFieldID(name) != FIELD_UNDEFINED) { return true; } else { return super.has(name); } } public void put(String name, Object value) { if (getFieldID(name) == FIELD_UNDEFINED) { super.put(name, value); } } public String toString() { StringBuffer buf = new StringBuffer(); buf.append("Frame (method="); buf.append(jvf.getMethod().externalNameAndSignature()); buf.append(", bci="); buf.append(getBCI()); buf.append(", line="); buf.append(getLineNumber()); buf.append(')'); return buf.toString(); } //-- Internals only below this point private static Map fields = new HashMap(); private static void addField(String name, int fieldId) { fields.put(name, new Integer(fieldId)); } private static int getFieldID(String name) { Integer res = (Integer) fields.get(name); return (res != null)? res.intValue() : FIELD_UNDEFINED; } static { addField("method", FIELD_METHOD); addField("bci", FIELD_BCI); addField("line", FIELD_LINE_NUMBER); addField("locals", FIELD_LOCALS); addField("thisObject", FIELD_THIS_OBJECT); addField("thread", FIELD_THREAD); } private JSJavaMethod getMethod() { return factory.newJSJavaMethod(jvf.getMethod()); } private int getBCI() { return jvf.getBCI(); } private int getLineNumber() { int bci = jvf.getBCI(); if (bci == -1) { return 0; } else { int lineNum = jvf.getMethod().getLineNumberFromBCI(bci); return (lineNum <= 0)? 0 : lineNum; } } private synchronized JSMap getLocals() { if (localsCache == null) { Map map = new HashMap(); localsCache = factory.newJSMap(map); StackValueCollection values = jvf.getLocals(); Method method = jvf.getMethod(); if (method.isNative() || ! method.hasLocalVariableTable() || values == null) { return localsCache; } LocalVariableTableElement[] localVars = method.getLocalVariableTable(); int bci = getBCI(); List visibleVars = new ArrayList(0); for (int i = 0; i < localVars.length; i++) { LocalVariableTableElement cur = localVars[i]; int startBCI = cur.getStartBCI(); if (startBCI <= bci && bci < startBCI + cur.getLength()) { visibleVars.add(cur); } } OopHandle handle = null; ObjectHeap heap = VM.getVM().getObjectHeap(); for (Iterator varItr = visibleVars.iterator(); varItr.hasNext();) { LocalVariableTableElement cur = (LocalVariableTableElement) varItr.next(); String name = method.getConstants().getSymbolAt(cur.getNameCPIndex()).asString(); int slot = cur.getSlot(); String signature = method.getConstants().getSymbolAt(cur.getDescriptorCPIndex()).asString(); BasicType variableType = BasicType.charToBasicType(signature.charAt(0)); Object value = null; if (variableType == BasicType.T_BOOLEAN) { value = Boolean.valueOf(values.booleanAt(slot)); } else if (variableType == BasicType.T_CHAR) { value = new Character(values.charAt(slot)); } else if (variableType == BasicType.T_FLOAT) { value = new Float(values.floatAt(slot)); } else if (variableType == BasicType.T_DOUBLE) { value = new Double(values.doubleAt(slot)); } else if (variableType == BasicType.T_BYTE) { value = new Byte(values.byteAt(slot)); } else if (variableType == BasicType.T_SHORT) { value = new Short(values.shortAt(slot)); } else if (variableType == BasicType.T_INT) { value = new Integer(values.intAt(slot)); } else if (variableType == BasicType.T_LONG) { value = new Long(values.longAt(slot)); } else if (variableType == BasicType.T_OBJECT || variableType == BasicType.T_ARRAY) { handle = values.oopHandleAt(slot); value = factory.newJSJavaObject(heap.newOop(handle)); } else { // ignore } map.put(name, value); } } return localsCache; } private JSJavaObject getThisObject() { Method method = jvf.getMethod(); if (method.isStatic()) { return null; } StackValueCollection values = jvf.getLocals(); if (values != null) { // 'this' at index 0. OopHandle handle = values.oopHandleAt(0); ObjectHeap heap = VM.getVM().getObjectHeap(); return factory.newJSJavaObject(heap.newOop(handle)); } else { // can't get locals, return null. return null; } } private JSJavaThread getThread() { return factory.newJSJavaThread(jvf.getThread()); } private final JavaVFrame jvf; private final JSJavaFactory factory; private JSMap localsCache; }