Mercurial > hg > truffle
diff agent/src/share/classes/sun/jvm/hotspot/interpreter/Bytecodes.java @ 3838:6a991dcb52bb
7012081: JSR 292: SA-JDI can't read MH/MT/Indy ConstantPool entries
Reviewed-by: kvn, twisti, jrose
author | never |
---|---|
date | Thu, 21 Jul 2011 08:38:25 -0700 |
parents | 0a8e0d4345b3 |
children | da91efe96a93 |
line wrap: on
line diff
--- a/agent/src/share/classes/sun/jvm/hotspot/interpreter/Bytecodes.java Wed Jul 20 18:04:17 2011 -0700 +++ b/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); } }