提交 85eeb43c 编写于 作者: N never

7012081: JSR 292: SA-JDI can't read MH/MT/Indy ConstantPool entries

Reviewed-by: kvn, twisti, jrose
上级 af8f4bbe
......@@ -26,6 +26,7 @@ package sun.jvm.hotspot.interpreter;
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 @@ public class Bytecode {
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);
}
......
/*
* 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();
}
}
/*
* 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();
}
}
......@@ -28,29 +28,25 @@ import sun.jvm.hotspot.oops.*;
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 class BytecodeLoadConstant extends BytecodeWithCPIndex {
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 @@ public class BytecodeLoadConstant extends BytecodeWithCPIndex {
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 @@ public class BytecodeLoadConstant extends BytecodeWithCPIndex {
return false;
}
ConstantTag ctag = method().getConstants().getTagAt(index());
ConstantTag ctag = method().getConstants().getTagAt(poolIndex());
return ctag.isKlass() || ctag.isUnresolvedKlass();
}
......@@ -120,7 +122,7 @@ public class BytecodeLoadConstant extends BytecodeWithCPIndex {
// 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();
......
/*
* 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 class BytecodeStream {
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) {
......
......@@ -38,7 +38,6 @@ public abstract class BytecodeWideable extends Bytecode {
// the local variable index
public int getLocalVarIndex() {
return (isWide()) ? (int) (0xFFFF & javaShortAt(1))
: (int) (0xFF & javaByteAt(1));
return (isWide()) ? getIndexU2(code(), true) : getIndexU1();
}
}
......@@ -35,7 +35,7 @@ public abstract class BytecodeWithCPIndex extends Bytecode {
}
// 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");
......
......@@ -276,6 +276,34 @@ public class Bytecodes {
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 @@ public class Bytecodes {
// 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 class Bytecodes {
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 @@ public class Bytecodes {
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 @@ public class Bytecodes {
_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 @@ public class Bytecodes {
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);
}
}
......@@ -164,6 +164,18 @@ public class ConstMethod extends Oop {
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 @@ public class ConstMethod extends Oop {
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++ )
......
......@@ -212,13 +212,60 @@ public class ConstantPool extends Oop implements ClassConstants {
}
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 class ConstantPool extends Oop implements ClassConstants {
}
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) */
......
/*
* 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 class ConstantPoolCache extends Oop {
}
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 @@ public class ConstantPoolCache extends Oop {
// 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;
}
......
......@@ -569,10 +569,10 @@ public class GenerateOopMap {
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 @@ public class GenerateOopMap {
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 @@ public class GenerateOopMap {
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 @@ public class GenerateOopMap {
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 @@ public class GenerateOopMap {
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 @@ public class GenerateOopMap {
}
}
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 @@ public class GenerateOopMap {
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);
......
......@@ -180,12 +180,24 @@ public class Method extends Oop {
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();
}
......
......@@ -53,6 +53,9 @@ public class TypeArray extends Array {
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);
}
......
/*
* 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 class ConstantTag {
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);
}
}
}
......@@ -1556,9 +1556,7 @@ void GenerateOopMap::interp1(BytecodeStream *itr) {
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;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册