# HG changeset patch # User never # Date 1311262705 25200 # Node ID 71b8938a2821ef88f9d541f67f83306711cb0b0d # Parent 0794cd144834ef3ffe122a8005d0c042ff0c03f8 7012081: JSR 292: SA-JDI can't read MH/MT/Indy ConstantPool entries Reviewed-by: kvn, twisti, jrose diff -r 0794cd144834 -r 71b8938a2821 hotspot/agent/src/share/classes/sun/jvm/hotspot/interpreter/Bytecode.java --- 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); } diff -r 0794cd144834 -r 71b8938a2821 hotspot/agent/src/share/classes/sun/jvm/hotspot/interpreter/BytecodeFastAAccess0.java --- 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(); - } -} diff -r 0794cd144834 -r 71b8938a2821 hotspot/agent/src/share/classes/sun/jvm/hotspot/interpreter/BytecodeFastIAccess0.java --- 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(); - } -} diff -r 0794cd144834 -r 71b8938a2821 hotspot/agent/src/share/classes/sun/jvm/hotspot/interpreter/BytecodeLoadConstant.java --- 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(); diff -r 0794cd144834 -r 71b8938a2821 hotspot/agent/src/share/classes/sun/jvm/hotspot/interpreter/BytecodeStream.java --- 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) { diff -r 0794cd144834 -r 71b8938a2821 hotspot/agent/src/share/classes/sun/jvm/hotspot/interpreter/BytecodeWideable.java --- 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(); } } diff -r 0794cd144834 -r 71b8938a2821 hotspot/agent/src/share/classes/sun/jvm/hotspot/interpreter/BytecodeWithCPIndex.java --- 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"); diff -r 0794cd144834 -r 71b8938a2821 hotspot/agent/src/share/classes/sun/jvm/hotspot/interpreter/Bytecodes.java --- 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); } } diff -r 0794cd144834 -r 71b8938a2821 hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/ConstMethod.java --- 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++ ) diff -r 0794cd144834 -r 71b8938a2821 hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/ConstantPool.java --- 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) */ diff -r 0794cd144834 -r 71b8938a2821 hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/ConstantPoolCache.java --- 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; } diff -r 0794cd144834 -r 71b8938a2821 hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/GenerateOopMap.java --- 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); diff -r 0794cd144834 -r 71b8938a2821 hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/Method.java --- 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(); } diff -r 0794cd144834 -r 71b8938a2821 hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/TypeArray.java --- 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); } diff -r 0794cd144834 -r 71b8938a2821 hotspot/agent/src/share/classes/sun/jvm/hotspot/utilities/ConstantTag.java --- 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); + } + } } diff -r 0794cd144834 -r 71b8938a2821 hotspot/src/share/vm/oops/generateOopMap.cpp --- 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;