7012081: JSR 292: SA-JDI can't read MH/MT/Indy ConstantPool entries
Reviewed-by: kvn, twisti, jrose
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/interpreter/Bytecode.java Wed Jul 20 18:04:17 2011 -0700
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/interpreter/Bytecode.java Thu Jul 21 08:38:25 2011 -0700
@@ -26,6 +26,7 @@
import sun.jvm.hotspot.oops.*;
import sun.jvm.hotspot.utilities.*;
+import sun.jvm.hotspot.runtime.VM;
public class Bytecode {
Method method;
@@ -45,6 +46,23 @@
return Bits.roundTo(bci + offset, jintSize) - bci;
}
+ public int getIndexU1() { return method.getBytecodeOrBPAt(bci() + 1) & 0xFF; }
+ public int getIndexU2(int bc, boolean isWide) {
+ if (can_use_native_byte_order(bc, isWide)) {
+ return method.getNativeShortArg(bci() + (isWide ? 2 : 1)) & 0xFFFF;
+ }
+ return method.getBytecodeShortArg(bci() + (isWide ? 2 : 1)) & 0xFFFF;
+ }
+ public int getIndexU4() { return method.getNativeIntArg(bci() + 1); }
+ public boolean hasIndexU4() { return code() == Bytecodes._invokedynamic; }
+
+ public int getIndexU1Cpcache() { return method.getBytecodeOrBPAt(bci() + 1) & 0xFF; }
+ public int getIndexU2Cpcache() { return method.getNativeShortArg(bci() + 1) & 0xFFFF; }
+
+ static boolean can_use_native_byte_order(int bc, boolean is_wide) {
+ return (VM.getVM().isBigEndian() || Bytecodes.native_byte_order(bc /*, is_wide*/));
+ }
+
int javaSignedWordAt(int offset) {
return method.getBytecodeIntArg(bci + offset);
}
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/interpreter/BytecodeFastAAccess0.java Wed Jul 20 18:04:17 2011 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,78 +0,0 @@
-/*
- * Copyright (c) 2002, 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.interpreter;
-
-import sun.jvm.hotspot.oops.*;
-import sun.jvm.hotspot.utilities.*;
-
-public class BytecodeFastAAccess0 extends BytecodeGetPut {
- BytecodeFastAAccess0(Method method, int bci) {
- super(method, bci);
- }
-
- public int index() {
- return (int) (0xFF & javaShortAt(2));
- }
-
- public boolean isStatic() {
- return false;
- }
-
- public void verify() {
- if (Assert.ASSERTS_ENABLED) {
- Assert.that(isValid(), "check fast_aaccess_0");
- }
- }
-
- public boolean isValid() {
- return code() == Bytecodes._fast_aaccess_0;
- }
-
- public static BytecodeFastAAccess0 at(Method method, int bci) {
- BytecodeFastAAccess0 b = new BytecodeFastAAccess0(method, bci);
- if (Assert.ASSERTS_ENABLED) {
- b.verify();
- }
- return b;
- }
-
- /** Like at, but returns null if the BCI is not at fast_aaccess_0 */
- public static BytecodeFastAAccess0 atCheck(Method method, int bci) {
- BytecodeFastAAccess0 b = new BytecodeFastAAccess0(method, bci);
- return (b.isValid() ? b : null);
- }
-
- public static BytecodeFastAAccess0 at(BytecodeStream bcs) {
- return new BytecodeFastAAccess0(bcs.method(), bcs.bci());
- }
-
- public String toString() {
- StringBuffer buf = new StringBuffer();
- buf.append("aload_0");
- buf.append(spaces);
- buf.append(super.toString());
- return buf.toString();
- }
-}
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/interpreter/BytecodeFastIAccess0.java Wed Jul 20 18:04:17 2011 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,78 +0,0 @@
-/*
- * Copyright (c) 2002, 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.interpreter;
-
-import sun.jvm.hotspot.oops.*;
-import sun.jvm.hotspot.utilities.*;
-
-public class BytecodeFastIAccess0 extends BytecodeGetPut {
- BytecodeFastIAccess0(Method method, int bci) {
- super(method, bci);
- }
-
- public int index() {
- return (int) (0xFF & javaShortAt(2));
- }
-
- public boolean isStatic() {
- return false;
- }
-
- public void verify() {
- if (Assert.ASSERTS_ENABLED) {
- Assert.that(isValid(), "check fast_iaccess_0");
- }
- }
-
- public boolean isValid() {
- return code() == Bytecodes._fast_iaccess_0;
- }
-
- public static BytecodeFastIAccess0 at(Method method, int bci) {
- BytecodeFastIAccess0 b = new BytecodeFastIAccess0(method, bci);
- if (Assert.ASSERTS_ENABLED) {
- b.verify();
- }
- return b;
- }
-
- /** Like at, but returns null if the BCI is not at fast_iaccess_0 */
- public static BytecodeFastIAccess0 atCheck(Method method, int bci) {
- BytecodeFastIAccess0 b = new BytecodeFastIAccess0(method, bci);
- return (b.isValid() ? b : null);
- }
-
- public static BytecodeFastIAccess0 at(BytecodeStream bcs) {
- return new BytecodeFastIAccess0(bcs.method(), bcs.bci());
- }
-
- public String toString() {
- StringBuffer buf = new StringBuffer();
- buf.append("aload_0");
- buf.append(spaces);
- buf.append(super.toString());
- return buf.toString();
- }
-}
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/interpreter/BytecodeLoadConstant.java Wed Jul 20 18:04:17 2011 -0700
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/interpreter/BytecodeLoadConstant.java Thu Jul 21 08:38:25 2011 -0700
@@ -28,29 +28,25 @@
import sun.jvm.hotspot.runtime.*;
import sun.jvm.hotspot.utilities.*;
-public class BytecodeLoadConstant extends BytecodeWithCPIndex {
+public class BytecodeLoadConstant extends Bytecode {
BytecodeLoadConstant(Method method, int bci) {
super(method, bci);
}
public boolean hasCacheIndex() {
// normal ldc uses CP index, but fast_aldc uses swapped CP cache index
- return javaCode() != code();
+ return code() >= Bytecodes.number_of_java_codes;
}
- public int index() {
- int i = javaCode() == Bytecodes._ldc ?
- (int) (0xFF & javaByteAt(1))
- : (int) (0xFFFF & javaShortAt(1));
- if (hasCacheIndex()) {
- return (0xFFFF & VM.getVM().getBytes().swapShort((short) i));
- } else {
- return i;
- }
+ int rawIndex() {
+ if (javaCode() == Bytecodes._ldc)
+ return getIndexU1();
+ else
+ return getIndexU2(code(), false);
}
public int poolIndex() {
- int i = index();
+ int i = rawIndex();
if (hasCacheIndex()) {
ConstantPoolCache cpCache = method().getConstants().getCache();
return cpCache.getEntryAt(i).getConstantPoolIndex();
@@ -61,12 +57,18 @@
public int cacheIndex() {
if (hasCacheIndex()) {
- return index();
+ return rawIndex();
} else {
return -1; // no cache index
}
}
+ public BasicType resultType() {
+ int index = poolIndex();
+ ConstantTag tag = method().getConstants().getTagAt(index);
+ return tag.basicType();
+ }
+
private Oop getCachedConstant() {
int i = cacheIndex();
if (i >= 0) {
@@ -88,7 +90,7 @@
jcode == Bytecodes._ldc2_w;
if (! codeOk) return false;
- ConstantTag ctag = method().getConstants().getTagAt(index());
+ ConstantTag ctag = method().getConstants().getTagAt(rawIndex());
if (jcode == Bytecodes._ldc2_w) {
// has to be double or long
return (ctag.isDouble() || ctag.isLong()) ? true: false;
@@ -107,7 +109,7 @@
return false;
}
- ConstantTag ctag = method().getConstants().getTagAt(index());
+ ConstantTag ctag = method().getConstants().getTagAt(poolIndex());
return ctag.isKlass() || ctag.isUnresolvedKlass();
}
@@ -120,7 +122,7 @@
// We just look at the object at the corresponding index and
// decide based on the oop type.
ConstantPool cpool = method().getConstants();
- int cpIndex = index();
+ int cpIndex = poolIndex();
ConstantPool.CPSlot oop = cpool.getSlotAt(cpIndex);
if (oop.isOop()) {
return (Klass) oop.getOop();
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/interpreter/BytecodeStream.java Wed Jul 20 18:04:17 2011 -0700
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/interpreter/BytecodeStream.java Thu Jul 21 08:38:25 2011 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2002, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2011, 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
@@ -130,7 +130,13 @@
public int getIndex() { return (isWide())
? (_method.getBytecodeShortArg(bci() + 2) & 0xFFFF)
: (_method.getBytecodeOrBPAt(bci() + 1) & 0xFF); }
- public int getIndexBig() { return _method.getBytecodeShortArg(bci() + 1); }
+ public int getIndexU1() { return _method.getBytecodeOrBPAt(bci() + 1) & 0xFF; }
+ public int getIndexU2() { return _method.getBytecodeShortArg(bci() + 1) & 0xFFFF; }
+ public int getIndexU4() { return _method.getNativeIntArg(bci() + 1); }
+ public boolean hasIndexU4() { return code() == Bytecodes._invokedynamic; }
+
+ public int getIndexU1Cpcache() { return _method.getBytecodeOrBPAt(bci() + 1) & 0xFF; }
+ public int getIndexU2Cpcache() { return _method.getNativeShortArg(bci() + 1) & 0xFFFF; }
// Fetch at absolute BCI (for manual parsing of certain bytecodes)
public int codeAt(int bci) {
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/interpreter/BytecodeWideable.java Wed Jul 20 18:04:17 2011 -0700
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/interpreter/BytecodeWideable.java Thu Jul 21 08:38:25 2011 -0700
@@ -38,7 +38,6 @@
// the local variable index
public int getLocalVarIndex() {
- return (isWide()) ? (int) (0xFFFF & javaShortAt(1))
- : (int) (0xFF & javaByteAt(1));
+ return (isWide()) ? getIndexU2(code(), true) : getIndexU1();
}
}
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/interpreter/BytecodeWithCPIndex.java Wed Jul 20 18:04:17 2011 -0700
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/interpreter/BytecodeWithCPIndex.java Thu Jul 21 08:38:25 2011 -0700
@@ -35,7 +35,7 @@
}
// the constant pool index for this bytecode
- public int index() { return 0xFFFF & javaShortAt(1); }
+ public int index() { return getIndexU2(code(), false); }
public int getSecondaryIndex() {
throw new IllegalArgumentException("must be invokedynamic");
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/interpreter/Bytecodes.java Wed Jul 20 18:04:17 2011 -0700
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/interpreter/Bytecodes.java Thu Jul 21 08:38:25 2011 -0700
@@ -276,6 +276,34 @@
public static final int number_of_codes = 233;
+ // Flag bits derived from format strings, can_trap, can_rewrite, etc.:
+ // semantic flags:
+ static final int _bc_can_trap = 1<<0; // bytecode execution can trap or block
+ static final int _bc_can_rewrite = 1<<1; // bytecode execution has an alternate form
+
+ // format bits (determined only by the format string):
+ static final int _fmt_has_c = 1<<2; // constant, such as sipush "bcc"
+ static final int _fmt_has_j = 1<<3; // constant pool cache index, such as getfield "bjj"
+ static final int _fmt_has_k = 1<<4; // constant pool index, such as ldc "bk"
+ static final int _fmt_has_i = 1<<5; // local index, such as iload
+ static final int _fmt_has_o = 1<<6; // offset, such as ifeq
+ static final int _fmt_has_nbo = 1<<7; // contains native-order field(s)
+ static final int _fmt_has_u2 = 1<<8; // contains double-byte field(s)
+ static final int _fmt_has_u4 = 1<<9; // contains quad-byte field
+ static final int _fmt_not_variable = 1<<10; // not of variable length (simple or wide)
+ static final int _fmt_not_simple = 1<<11; // either wide or variable length
+ static final int _all_fmt_bits = (_fmt_not_simple*2 - _fmt_has_c);
+
+ // Example derived format syndromes:
+ static final int _fmt_b = _fmt_not_variable;
+ static final int _fmt_bc = _fmt_b | _fmt_has_c;
+ static final int _fmt_bi = _fmt_b | _fmt_has_i;
+ static final int _fmt_bkk = _fmt_b | _fmt_has_k | _fmt_has_u2;
+ static final int _fmt_bJJ = _fmt_b | _fmt_has_j | _fmt_has_u2 | _fmt_has_nbo;
+ static final int _fmt_bo2 = _fmt_b | _fmt_has_o | _fmt_has_u2;
+ static final int _fmt_bo4 = _fmt_b | _fmt_has_o | _fmt_has_u4;
+
+
public static int specialLengthAt(Method method, int bci) {
int code = codeAt(method, bci);
switch (code) {
@@ -337,18 +365,20 @@
// static Code non_breakpoint_code_at(address bcp, methodOop method = null);
// Bytecode attributes
- public static boolean isDefined (int code) { return 0 <= code && code < number_of_codes && _format[code] != null; }
- public static boolean wideIsDefined(int code) { return isDefined(code) && _wide_format[code] != null; }
+ public static boolean isDefined (int code) { return 0 <= code && code < number_of_codes && flags(code, false) != 0; }
+ public static boolean wideIsDefined(int code) { return isDefined(code) && flags(code, true) != 0; }
public static String name (int code) { check(code); return _name [code]; }
public static String format (int code) { check(code); return _format [code]; }
public static String wideFormat (int code) { wideCheck(code); return _wide_format [code]; }
public static int resultType (int code) { check(code); return _result_type [code]; }
public static int depth (int code) { check(code); return _depth [code]; }
- public static int lengthFor (int code) { check(code); return _length [code]; }
- public static boolean canTrap (int code) { check(code); return _can_trap [code]; }
+ public static int lengthFor (int code) { check(code); return _lengths [code] & 0xF; }
+ public static int wideLengthFor(int code) { check(code); return _lengths [code] >> 4; }
+ public static boolean canTrap (int code) { check(code); return has_all_flags(code, _bc_can_trap, false); }
public static int javaCode (int code) { check(code); return _java_code [code]; }
- public static boolean canRewrite (int code) { check(code); return _can_rewrite [code]; }
- public static int wideLengthFor(int code) { wideCheck(code); return wideFormat(code).length(); }
+ public static boolean canRewrite (int code) { check(code); return has_all_flags(code, _bc_can_rewrite, false); }
+ public static boolean native_byte_order(int code) { check(code); return has_all_flags(code, _fmt_has_nbo, false); }
+ public static boolean uses_cp_cache (int code) { check(code); return has_all_flags(code, _fmt_has_j, false); }
public static int lengthAt (Method method, int bci) { int l = lengthFor(codeAt(method, bci)); return l > 0 ? l : specialLengthAt(method, bci); }
public static int javaLengthAt (Method method, int bci) { int l = lengthFor(javaCode(codeAt(method, bci))); return l > 0 ? l : specialLengthAt(method, bci); }
public static boolean isJavaCode (int code) { return 0 <= code && code < number_of_java_codes; }
@@ -362,6 +392,92 @@
public static boolean isZeroConst (int code) { return (code == _aconst_null || code == _iconst_0
|| code == _fconst_0 || code == _dconst_0); }
+ static int flags (int code, boolean is_wide) {
+ assert code == (code & 0xff) : "must be a byte";
+ return _flags[code + (is_wide ? 256 : 0)];
+ }
+ static int format_bits (int code, boolean is_wide) { return flags(code, is_wide) & _all_fmt_bits; }
+ static boolean has_all_flags (int code, int test_flags, boolean is_wide) {
+ return (flags(code, is_wide) & test_flags) == test_flags;
+ }
+
+ static char compute_flags(String format) {
+ return compute_flags(format, 0);
+ }
+ static char compute_flags(String format, int more_flags) {
+ if (format == null) return 0; // not even more_flags
+ int flags = more_flags;
+ int fp = 0;
+ if (format.length() == 0) {
+ flags |= _fmt_not_simple; // but variable
+ } else {
+ switch (format.charAt(fp)) {
+ case 'b':
+ flags |= _fmt_not_variable; // but simple
+ ++fp; // skip 'b'
+ break;
+ case 'w':
+ flags |= _fmt_not_variable | _fmt_not_simple;
+ ++fp; // skip 'w'
+ assert(format.charAt(fp) == 'b') : "wide format must start with 'wb'";
+ ++fp; // skip 'b'
+ break;
+ }
+ }
+
+ boolean has_nbo = false, has_jbo = false;
+ int has_size = 0;
+ while (fp < format.length()) {
+ int this_flag = 0;
+ char fc = format.charAt(fp++);
+ switch (fc) {
+ case '_': continue; // ignore these
+
+ case 'j': this_flag = _fmt_has_j; has_jbo = true; break;
+ case 'k': this_flag = _fmt_has_k; has_jbo = true; break;
+ case 'i': this_flag = _fmt_has_i; has_jbo = true; break;
+ case 'c': this_flag = _fmt_has_c; has_jbo = true; break;
+ case 'o': this_flag = _fmt_has_o; has_jbo = true; break;
+
+ // uppercase versions mark native byte order (from Rewriter)
+ // actually, only the 'J' case happens currently
+ case 'J': this_flag = _fmt_has_j; has_nbo = true; break;
+ case 'K': this_flag = _fmt_has_k; has_nbo = true; break;
+ case 'I': this_flag = _fmt_has_i; has_nbo = true; break;
+ case 'C': this_flag = _fmt_has_c; has_nbo = true; break;
+ case 'O': this_flag = _fmt_has_o; has_nbo = true; break;
+ default: assert false : "bad char in format";
+ }
+
+ flags |= this_flag;
+
+ assert !(has_jbo && has_nbo) : "mixed byte orders in format";
+ if (has_nbo)
+ flags |= _fmt_has_nbo;
+
+ int this_size = 1;
+ if (fp < format.length() && format.charAt(fp) == fc) {
+ // advance beyond run of the same characters
+ this_size = 2;
+ while (fp + 1 < format.length() && format.charAt(++fp) == fc) this_size++;
+ switch (this_size) {
+ case 2: flags |= _fmt_has_u2; break;
+ case 4: flags |= _fmt_has_u4; break;
+ default: assert false : "bad rep count in format";
+ }
+ }
+ assert has_size == 0 || // no field yet
+ this_size == has_size || // same size
+ this_size < has_size && fp == format.length() : // last field can be short
+ "mixed field sizes in format";
+ has_size = this_size;
+ }
+
+ assert flags == (char)flags : "change _format_flags";
+ return (char)flags;
+ }
+
+
//----------------------------------------------------------------------
// Internals only below this point
//
@@ -371,10 +487,9 @@
private static String[] _wide_format;
private static int[] _result_type;
private static byte[] _depth;
- private static byte[] _length;
- private static boolean[] _can_trap;
+ private static byte[] _lengths;
private static int[] _java_code;
- private static boolean[] _can_rewrite;
+ private static char[] _flags;
static {
_name = new String [number_of_codes];
@@ -382,10 +497,9 @@
_wide_format = new String [number_of_codes];
_result_type = new int [number_of_codes]; // See BasicType.java
_depth = new byte [number_of_codes];
- _length = new byte [number_of_codes];
- _can_trap = new boolean[number_of_codes];
+ _lengths = new byte [number_of_codes];
_java_code = new int [number_of_codes];
- _can_rewrite = new boolean[number_of_codes];
+ _flags = new char[256 * 2]; // all second page for wide formats
// In case we want to fetch this information from the VM in the
// future
@@ -712,18 +826,19 @@
if (Assert.ASSERTS_ENABLED) {
Assert.that(wide_format == null || format != null, "short form must exist if there's a wide form");
}
+ int len = (format != null ? format.length() : 0);
+ int wlen = (wide_format != null ? wide_format.length() : 0);
_name [code] = name;
- _format [code] = format;
- _wide_format [code] = wide_format;
_result_type [code] = result_type;
_depth [code] = (byte) depth;
- _can_trap [code] = can_trap;
- _length [code] = (byte) (format != null ? format.length() : 0);
+ _lengths [code] = (byte)((wlen << 4) | (len & 0xF));
_java_code [code] = java_code;
- if (java_code != code) {
- _can_rewrite[java_code] = true;
- } else {
- _can_rewrite[java_code] = false;
- }
+ _format [code] = format;
+ _wide_format [code] = wide_format;
+ int bc_flags = 0;
+ if (can_trap) bc_flags |= _bc_can_trap;
+ if (java_code != code) bc_flags |= _bc_can_rewrite;
+ _flags[code+0*256] = compute_flags(format, bc_flags);
+ _flags[code+1*256] = compute_flags(wide_format, bc_flags);
}
}
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/ConstMethod.java Wed Jul 20 18:04:17 2011 -0700
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/ConstMethod.java Thu Jul 21 08:38:25 2011 -0700
@@ -164,6 +164,18 @@
return (short) ((hi << 8) | lo);
}
+ /** Fetches a 16-bit native ordered value from the
+ bytecode stream */
+ public short getNativeShortArg(int bci) {
+ int hi = getBytecodeOrBPAt(bci);
+ int lo = getBytecodeOrBPAt(bci + 1);
+ if (VM.getVM().isBigEndian()) {
+ return (short) ((hi << 8) | lo);
+ } else {
+ return (short) ((lo << 8) | hi);
+ }
+ }
+
/** Fetches a 32-bit big-endian ("Java ordered") value from the
bytecode stream */
public int getBytecodeIntArg(int bci) {
@@ -175,6 +187,21 @@
return (b4 << 24) | (b3 << 16) | (b2 << 8) | b1;
}
+ /** Fetches a 32-bit native ordered value from the
+ bytecode stream */
+ public int getNativeIntArg(int bci) {
+ int b4 = getBytecodeOrBPAt(bci);
+ int b3 = getBytecodeOrBPAt(bci + 1);
+ int b2 = getBytecodeOrBPAt(bci + 2);
+ int b1 = getBytecodeOrBPAt(bci + 3);
+
+ if (VM.getVM().isBigEndian()) {
+ return (b4 << 24) | (b3 << 16) | (b2 << 8) | b1;
+ } else {
+ return (b1 << 24) | (b2 << 16) | (b3 << 8) | b4;
+ }
+ }
+
public byte[] getByteCode() {
byte[] bc = new byte[ (int) getCodeSize() ];
for( int i=0; i < bc.length; i++ )
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/ConstantPool.java Wed Jul 20 18:04:17 2011 -0700
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/ConstantPool.java Thu Jul 21 08:38:25 2011 -0700
@@ -212,13 +212,60 @@
}
public Symbol getNameRefAt(int which) {
- int nameIndex = getNameAndTypeAt(getNameAndTypeRefIndexAt(which))[0];
- return getSymbolAt(nameIndex);
+ return implGetNameRefAt(which, false);
+ }
+
+ private Symbol implGetNameRefAt(int which, boolean uncached) {
+ int signatureIndex = getNameRefIndexAt(implNameAndTypeRefIndexAt(which, uncached));
+ return getSymbolAt(signatureIndex);
}
public Symbol getSignatureRefAt(int which) {
- int sigIndex = getNameAndTypeAt(getNameAndTypeRefIndexAt(which))[1];
- return getSymbolAt(sigIndex);
+ return implGetSignatureRefAt(which, false);
+ }
+
+ private Symbol implGetSignatureRefAt(int which, boolean uncached) {
+ int signatureIndex = getSignatureRefIndexAt(implNameAndTypeRefIndexAt(which, uncached));
+ return getSymbolAt(signatureIndex);
+ }
+
+
+ private int implNameAndTypeRefIndexAt(int which, boolean uncached) {
+ int i = which;
+ if (!uncached && getCache() != null) {
+ if (ConstantPoolCache.isSecondaryIndex(which)) {
+ // Invokedynamic index.
+ int pool_index = getCache().getMainEntryAt(which).getConstantPoolIndex();
+ pool_index = invokeDynamicNameAndTypeRefIndexAt(pool_index);
+ // assert(tagAt(pool_index).isNameAndType(), "");
+ return pool_index;
+ }
+ // change byte-ordering and go via cache
+ i = remapInstructionOperandFromCache(which);
+ } else {
+ if (getTagAt(which).isInvokeDynamic()) {
+ int pool_index = invokeDynamicNameAndTypeRefIndexAt(which);
+ // assert(tag_at(pool_index).is_name_and_type(), "");
+ return pool_index;
+ }
+ }
+ // assert(tag_at(i).is_field_or_method(), "Corrupted constant pool");
+ // assert(!tag_at(i).is_invoke_dynamic(), "Must be handled above");
+ int ref_index = getIntAt(i);
+ return extractHighShortFromInt(ref_index);
+ }
+
+ private int remapInstructionOperandFromCache(int operand) {
+ int cpc_index = operand;
+ // DEBUG_ONLY(cpc_index -= CPCACHE_INDEX_TAG);
+ // assert((int)(u2)cpc_index == cpc_index, "clean u2");
+ int member_index = getCache().getEntryAt(cpc_index).getConstantPoolIndex();
+ return member_index;
+ }
+
+ int invokeDynamicNameAndTypeRefIndexAt(int which) {
+ // assert(tag_at(which).is_invoke_dynamic(), "Corrupted constant pool");
+ return extractHighShortFromInt(getIntAt(which));
}
// returns null, if not resolved.
@@ -253,15 +300,7 @@
}
public int getNameAndTypeRefIndexAt(int index) {
- int refIndex = getFieldOrMethodAt(index);
- if (DEBUG) {
- System.err.println("ConstantPool.getNameAndTypeRefIndexAt(" + index + "): refIndex = " + refIndex);
- }
- int i = extractHighShortFromInt(refIndex);
- if (DEBUG) {
- System.err.println("ConstantPool.getNameAndTypeRefIndexAt(" + index + "): result = " + i);
- }
- return i;
+ return implNameAndTypeRefIndexAt(index, false);
}
/** Lookup for entries consisting of (name_index, signature_index) */
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/ConstantPoolCache.java Wed Jul 20 18:04:17 2011 -0700
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/ConstantPoolCache.java Thu Jul 21 08:38:25 2011 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2011, 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
@@ -72,9 +72,7 @@
}
public ConstantPoolCacheEntry getEntryAt(int i) {
- if (Assert.ASSERTS_ENABLED) {
- Assert.that(0 <= i && i < getLength(), "index out of bounds");
- }
+ if (i < 0 || i >= getLength()) throw new IndexOutOfBoundsException(i + " " + getLength());
return new ConstantPoolCacheEntry(this, i);
}
@@ -84,21 +82,27 @@
// secondary entries hold invokedynamic call site bindings
public ConstantPoolCacheEntry getSecondaryEntryAt(int i) {
- ConstantPoolCacheEntry e = new ConstantPoolCacheEntry(this, decodeSecondaryIndex(i));
+ int rawIndex = i;
+ if (isSecondaryIndex(i)) {
+ rawIndex = decodeSecondaryIndex(i);
+ }
+ ConstantPoolCacheEntry e = getEntryAt(rawIndex);
if (Assert.ASSERTS_ENABLED) {
- Assert.that(e.isSecondaryEntry(), "must be a secondary entry");
+ Assert.that(e.isSecondaryEntry(), "must be a secondary entry:" + rawIndex);
}
return e;
}
public ConstantPoolCacheEntry getMainEntryAt(int i) {
+ int primaryIndex = i;
if (isSecondaryIndex(i)) {
// run through an extra level of indirection:
- i = getSecondaryEntryAt(i).getMainEntryIndex();
+ int rawIndex = decodeSecondaryIndex(i);
+ primaryIndex = getEntryAt(rawIndex).getMainEntryIndex();
}
- ConstantPoolCacheEntry e = new ConstantPoolCacheEntry(this, i);
+ ConstantPoolCacheEntry e = getEntryAt(primaryIndex);
if (Assert.ASSERTS_ENABLED) {
- Assert.that(!e.isSecondaryEntry(), "must not be a secondary entry");
+ Assert.that(!e.isSecondaryEntry(), "must not be a secondary entry:" + primaryIndex);
}
return e;
}
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/GenerateOopMap.java Wed Jul 20 18:04:17 2011 -0700
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/GenerateOopMap.java Thu Jul 21 08:38:25 2011 -0700
@@ -569,10 +569,10 @@
case Bytecodes._invokedynamic:
// FIXME: print signature of referenced method (need more
// accessors in ConstantPool and ConstantPoolCache)
- int idx = currentBC.getIndexBig();
+ int idx = currentBC.hasIndexU4() ? currentBC.getIndexU4() : currentBC.getIndexU2();
tty.print(" idx " + idx);
/*
- int idx = currentBC.getIndexBig();
+ int idx = currentBC.getIndexU2();
ConstantPool cp = method().getConstants();
int nameAndTypeIdx = cp.name_and_type_ref_index_at(idx);
int signatureIdx = cp.signature_ref_index_at(nameAndTypeIdx);
@@ -609,10 +609,10 @@
case Bytecodes._invokedynamic:
// FIXME: print signature of referenced method (need more
// accessors in ConstantPool and ConstantPoolCache)
- int idx = currentBC.getIndexBig();
+ int idx = currentBC.hasIndexU4() ? currentBC.getIndexU4() : currentBC.getIndexU2();
tty.print(" idx " + idx);
/*
- int idx = currentBC.getIndexBig();
+ int idx = currentBC.getIndexU2();
constantPoolOop cp = method().constants();
int nameAndTypeIdx = cp.name_and_type_ref_index_at(idx);
int signatureIdx = cp.signature_ref_index_at(nameAndTypeIdx);
@@ -1118,7 +1118,8 @@
current instruction, starting in the current state. */
void interp1 (BytecodeStream itr) {
if (DEBUG) {
- System.err.println(" - bci " + itr.bci());
+ System.err.println(" - bci " + itr.bci() + " " + itr.code());
+ printCurrentState(System.err, itr, false);
}
// if (TraceNewOopMapGeneration) {
@@ -1179,8 +1180,8 @@
case Bytecodes._ldc2_w: ppush(vvCTS); break;
- case Bytecodes._ldc: doLdc(itr.getIndex(), itr.bci()); break;
- case Bytecodes._ldc_w: doLdc(itr.getIndexBig(), itr.bci());break;
+ case Bytecodes._ldc: doLdc(itr.bci()); break;
+ case Bytecodes._ldc_w: doLdc(itr.bci()); break;
case Bytecodes._iload:
case Bytecodes._fload: ppload(vCTS, itr.getIndex()); break;
@@ -1372,18 +1373,16 @@
case Bytecodes._jsr: doJsr(itr.dest()); break;
case Bytecodes._jsr_w: doJsr(itr.dest_w()); break;
- case Bytecodes._getstatic: doField(true, true,
- itr.getIndexBig(),
- itr.bci()); break;
- case Bytecodes._putstatic: doField(false, true, itr.getIndexBig(), itr.bci()); break;
- case Bytecodes._getfield: doField(true, false, itr.getIndexBig(), itr.bci()); break;
- case Bytecodes._putfield: doField(false, false, itr.getIndexBig(), itr.bci()); break;
+ case Bytecodes._getstatic: doField(true, true, itr.getIndexU2Cpcache(), itr.bci()); break;
+ case Bytecodes._putstatic: doField(false, true, itr.getIndexU2Cpcache(), itr.bci()); break;
+ case Bytecodes._getfield: doField(true, false, itr.getIndexU2Cpcache(), itr.bci()); break;
+ case Bytecodes._putfield: doField(false, false, itr.getIndexU2Cpcache(), itr.bci()); break;
case Bytecodes._invokevirtual:
- case Bytecodes._invokespecial: doMethod(false, false, itr.getIndexBig(), itr.bci()); break;
- case Bytecodes._invokestatic: doMethod(true, false, itr.getIndexBig(), itr.bci()); break;
- case Bytecodes._invokedynamic: doMethod(false, true, itr.getIndexBig(), itr.bci()); break;
- case Bytecodes._invokeinterface: doMethod(false, true, itr.getIndexBig(), itr.bci()); break;
+ case Bytecodes._invokespecial: doMethod(false, false, itr.getIndexU2Cpcache(), itr.bci()); break;
+ case Bytecodes._invokestatic: doMethod(true, false, itr.getIndexU2Cpcache(), itr.bci()); break;
+ case Bytecodes._invokedynamic: doMethod(true, false, itr.getIndexU4(), itr.bci()); break;
+ case Bytecodes._invokeinterface: doMethod(false, true, itr.getIndexU2Cpcache(), itr.bci()); break;
case Bytecodes._newarray:
case Bytecodes._anewarray: ppNewRef(vCTS, itr.bci()); break;
case Bytecodes._checkcast: doCheckcast(); break;
@@ -1665,13 +1664,11 @@
}
}
- void doLdc (int idx, int bci) {
+ void doLdc (int bci) {
+ BytecodeLoadConstant ldc = BytecodeLoadConstant.at(_method, bci);
ConstantPool cp = method().getConstants();
- ConstantTag tag = cp.getTagAt(idx);
- CellTypeState cts = (tag.isString() || tag.isUnresolvedString() ||
- tag.isKlass() || tag.isUnresolvedKlass())
- ? CellTypeState.makeLineRef(bci)
- : valCTS;
+ BasicType bt = ldc.resultType();
+ CellTypeState cts = (bt == BasicType.T_OBJECT) ? CellTypeState.makeLineRef(bci) : valCTS;
ppush1(cts);
}
@@ -1729,15 +1726,7 @@
void doMethod (boolean is_static, boolean is_interface, int idx, int bci) {
// Dig up signature for field in constant pool
ConstantPool cp = _method.getConstants();
- int nameAndTypeIdx = cp.getTagAt(idx).isNameAndType() ? idx : cp.getNameAndTypeRefIndexAt(idx);
- int signatureIdx = cp.getSignatureRefIndexAt(nameAndTypeIdx);
- Symbol signature = cp.getSymbolAt(signatureIdx);
-
- if (DEBUG) {
- System.err.println("doMethod: signature = " + signature.asString() + ", idx = " + idx +
- ", nameAndTypeIdx = " + nameAndTypeIdx + ", signatureIdx = " + signatureIdx +
- ", bci = " + bci);
- }
+ Symbol signature = cp.getSignatureRefAt(idx);
// Parse method signature
CellTypeStateList out = new CellTypeStateList(4);
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/Method.java Wed Jul 20 18:04:17 2011 -0700
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/Method.java Thu Jul 21 08:38:25 2011 -0700
@@ -180,12 +180,24 @@
return getConstMethod().getBytecodeShortArg(bci);
}
+ /** Fetches a 16-bit native ordered value from the
+ bytecode stream */
+ public short getNativeShortArg(int bci) {
+ return getConstMethod().getNativeShortArg(bci);
+ }
+
/** Fetches a 32-bit big-endian ("Java ordered") value from the
bytecode stream */
public int getBytecodeIntArg(int bci) {
return getConstMethod().getBytecodeIntArg(bci);
}
+ /** Fetches a 32-bit native ordered value from the
+ bytecode stream */
+ public int getNativeIntArg(int bci) {
+ return getConstMethod().getNativeIntArg(bci);
+ }
+
public byte[] getByteCode() {
return getConstMethod().getByteCode();
}
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/TypeArray.java Wed Jul 20 18:04:17 2011 -0700
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/TypeArray.java Thu Jul 21 08:38:25 2011 -0700
@@ -53,6 +53,9 @@
public boolean isTypeArray() { return true; }
public byte getByteAt(long index) {
+ if (index < 0 || index >= getLength()) {
+ throw new ArrayIndexOutOfBoundsException(index + " " + getLength());
+ }
long offset = baseOffsetInBytes(BasicType.T_BYTE) + index * getHeap().getByteSize();
return getHandle().getJByteAt(offset);
}
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/utilities/ConstantTag.java Wed Jul 20 18:04:17 2011 -0700
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/utilities/ConstantTag.java Thu Jul 21 08:38:25 2011 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2011, 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
@@ -24,31 +24,33 @@
package sun.jvm.hotspot.utilities;
+import sun.jvm.hotspot.runtime.BasicType;
+
public class ConstantTag {
// These replicated from the VM to save space
- private static int JVM_CONSTANT_Utf8 = 1;
- private static int JVM_CONSTANT_Unicode = 2; // unused
- private static int JVM_CONSTANT_Integer = 3;
- private static int JVM_CONSTANT_Float = 4;
- private static int JVM_CONSTANT_Long = 5;
- private static int JVM_CONSTANT_Double = 6;
- private static int JVM_CONSTANT_Class = 7;
- private static int JVM_CONSTANT_String = 8;
- private static int JVM_CONSTANT_Fieldref = 9;
- private static int JVM_CONSTANT_Methodref = 10;
- private static int JVM_CONSTANT_InterfaceMethodref = 11;
- private static int JVM_CONSTANT_NameAndType = 12;
- private static int JVM_CONSTANT_MethodHandle = 15; // JSR 292
- private static int JVM_CONSTANT_MethodType = 16; // JSR 292
- // static int JVM_CONSTANT_(unused) = 17; // JSR 292 early drafts only
- private static int JVM_CONSTANT_InvokeDynamic = 18; // JSR 292
- private static int JVM_CONSTANT_Invalid = 0; // For bad value initialization
- private static int JVM_CONSTANT_UnresolvedClass = 100; // Temporary tag until actual use
- private static int JVM_CONSTANT_ClassIndex = 101; // Temporary tag while constructing constant pool
- private static int JVM_CONSTANT_UnresolvedString = 102; // Temporary tag until actual use
- private static int JVM_CONSTANT_StringIndex = 103; // Temporary tag while constructing constant pool
- private static int JVM_CONSTANT_UnresolvedClassInError = 104; // Resolution failed
- private static int JVM_CONSTANT_Object = 105; // Required for BoundMethodHandle arguments.
+ private static final int JVM_CONSTANT_Utf8 = 1;
+ private static final int JVM_CONSTANT_Unicode = 2; // unused
+ private static final int JVM_CONSTANT_Integer = 3;
+ private static final int JVM_CONSTANT_Float = 4;
+ private static final int JVM_CONSTANT_Long = 5;
+ private static final int JVM_CONSTANT_Double = 6;
+ private static final int JVM_CONSTANT_Class = 7;
+ private static final int JVM_CONSTANT_String = 8;
+ private static final int JVM_CONSTANT_Fieldref = 9;
+ private static final int JVM_CONSTANT_Methodref = 10;
+ private static final int JVM_CONSTANT_InterfaceMethodref = 11;
+ private static final int JVM_CONSTANT_NameAndType = 12;
+ private static final int JVM_CONSTANT_MethodHandle = 15; // JSR 292
+ private static final int JVM_CONSTANT_MethodType = 16; // JSR 292
+ // static final int JVM_CONSTANT_(unused) = 17; // JSR 292 early drafts only
+ private static final int JVM_CONSTANT_InvokeDynamic = 18; // JSR 292
+ private static final int JVM_CONSTANT_Invalid = 0; // For bad value initialization
+ private static final int JVM_CONSTANT_UnresolvedClass = 100; // Temporary tag until actual use
+ private static final int JVM_CONSTANT_ClassIndex = 101; // Temporary tag while constructing constant pool
+ private static final int JVM_CONSTANT_UnresolvedString = 102; // Temporary tag until actual use
+ private static final int JVM_CONSTANT_StringIndex = 103; // Temporary tag while constructing constant pool
+ private static final int JVM_CONSTANT_UnresolvedClassInError = 104; // Resolution failed
+ private static final int JVM_CONSTANT_Object = 105; // Required for BoundMethodHandle arguments.
// JVM_CONSTANT_MethodHandle subtypes //FIXME: connect these to data structure
private static int JVM_REF_getField = 1;
@@ -99,4 +101,31 @@
public boolean isKlassReference() { return isKlassIndex() || isUnresolvedKlass(); }
public boolean isFieldOrMethod() { return isField() || isMethod() || isInterfaceMethod(); }
public boolean isSymbol() { return isUtf8(); }
+
+ public BasicType basicType() {
+ switch (tag) {
+ case JVM_CONSTANT_Integer :
+ return BasicType.T_INT;
+ case JVM_CONSTANT_Float :
+ return BasicType.T_FLOAT;
+ case JVM_CONSTANT_Long :
+ return BasicType.T_LONG;
+ case JVM_CONSTANT_Double :
+ return BasicType.T_DOUBLE;
+
+ case JVM_CONSTANT_Class :
+ case JVM_CONSTANT_String :
+ case JVM_CONSTANT_UnresolvedClass :
+ case JVM_CONSTANT_UnresolvedClassInError :
+ case JVM_CONSTANT_ClassIndex :
+ case JVM_CONSTANT_UnresolvedString :
+ case JVM_CONSTANT_StringIndex :
+ case JVM_CONSTANT_MethodHandle :
+ case JVM_CONSTANT_MethodType :
+ case JVM_CONSTANT_Object :
+ return BasicType.T_OBJECT;
+ default:
+ throw new InternalError("unexpected tag: " + tag);
+ }
+ }
}
--- a/hotspot/src/share/vm/oops/generateOopMap.cpp Wed Jul 20 18:04:17 2011 -0700
+++ b/hotspot/src/share/vm/oops/generateOopMap.cpp Thu Jul 21 08:38:25 2011 -0700
@@ -1556,9 +1556,7 @@
case Bytecodes::_jsr: do_jsr(itr->dest()); break;
case Bytecodes::_jsr_w: do_jsr(itr->dest_w()); break;
- case Bytecodes::_getstatic: do_field(true, true,
- itr->get_index_u2_cpcache(),
- itr->bci()); break;
+ case Bytecodes::_getstatic: do_field(true, true, itr->get_index_u2_cpcache(), itr->bci()); break;
case Bytecodes::_putstatic: do_field(false, true, itr->get_index_u2_cpcache(), itr->bci()); break;
case Bytecodes::_getfield: do_field(true, false, itr->get_index_u2_cpcache(), itr->bci()); break;
case Bytecodes::_putfield: do_field(false, false, itr->get_index_u2_cpcache(), itr->bci()); break;