blob: 99a489d837d3d3f42f7d0da7ed7c19e6356b12d2 [file] [log] [blame]
/*
* 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;
}