Merge
This commit is contained in:
commit
2d9848a160
@ -72,6 +72,7 @@ public class BytecodeDisassembler {
|
|||||||
addBytecodeClass(Bytecodes._invokestatic, BytecodeInvoke.class);
|
addBytecodeClass(Bytecodes._invokestatic, BytecodeInvoke.class);
|
||||||
addBytecodeClass(Bytecodes._invokespecial, BytecodeInvoke.class);
|
addBytecodeClass(Bytecodes._invokespecial, BytecodeInvoke.class);
|
||||||
addBytecodeClass(Bytecodes._invokeinterface, BytecodeInvoke.class);
|
addBytecodeClass(Bytecodes._invokeinterface, BytecodeInvoke.class);
|
||||||
|
addBytecodeClass(Bytecodes._invokedynamic, BytecodeInvoke.class);
|
||||||
addBytecodeClass(Bytecodes._jsr, BytecodeJsr.class);
|
addBytecodeClass(Bytecodes._jsr, BytecodeJsr.class);
|
||||||
addBytecodeClass(Bytecodes._jsr_w, BytecodeJsrW.class);
|
addBytecodeClass(Bytecodes._jsr_w, BytecodeJsrW.class);
|
||||||
addBytecodeClass(Bytecodes._iload, BytecodeLoad.class);
|
addBytecodeClass(Bytecodes._iload, BytecodeLoad.class);
|
||||||
|
@ -54,15 +54,31 @@ public class BytecodeInvoke extends BytecodeWithCPIndex {
|
|||||||
// returns the name of the invoked method
|
// returns the name of the invoked method
|
||||||
public Symbol name() {
|
public Symbol name() {
|
||||||
ConstantPool cp = method().getConstants();
|
ConstantPool cp = method().getConstants();
|
||||||
|
if (isInvokedynamic()) {
|
||||||
|
int[] nt = cp.getNameAndTypeAt(indexForFieldOrMethod());
|
||||||
|
return cp.getSymbolAt(nt[0]);
|
||||||
|
}
|
||||||
return cp.getNameRefAt(index());
|
return cp.getNameRefAt(index());
|
||||||
}
|
}
|
||||||
|
|
||||||
// returns the signature of the invoked method
|
// returns the signature of the invoked method
|
||||||
public Symbol signature() {
|
public Symbol signature() {
|
||||||
ConstantPool cp = method().getConstants();
|
ConstantPool cp = method().getConstants();
|
||||||
|
if (isInvokedynamic()) {
|
||||||
|
int[] nt = cp.getNameAndTypeAt(indexForFieldOrMethod());
|
||||||
|
return cp.getSymbolAt(nt[1]);
|
||||||
|
}
|
||||||
return cp.getSignatureRefAt(index());
|
return cp.getSignatureRefAt(index());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getSecondaryIndex() {
|
||||||
|
if (isInvokedynamic()) {
|
||||||
|
// change byte-ordering of 4-byte integer
|
||||||
|
return VM.getVM().getBytes().swapInt(javaSignedWordAt(1));
|
||||||
|
}
|
||||||
|
return super.getSecondaryIndex(); // throw an error
|
||||||
|
}
|
||||||
|
|
||||||
public Method getInvokedMethod() {
|
public Method getInvokedMethod() {
|
||||||
return method().getConstants().getMethodRefAt(index());
|
return method().getConstants().getMethodRefAt(index());
|
||||||
}
|
}
|
||||||
@ -87,6 +103,7 @@ public class BytecodeInvoke extends BytecodeWithCPIndex {
|
|||||||
public boolean isInvokevirtual() { return adjustedInvokeCode() == Bytecodes._invokevirtual; }
|
public boolean isInvokevirtual() { return adjustedInvokeCode() == Bytecodes._invokevirtual; }
|
||||||
public boolean isInvokestatic() { return adjustedInvokeCode() == Bytecodes._invokestatic; }
|
public boolean isInvokestatic() { return adjustedInvokeCode() == Bytecodes._invokestatic; }
|
||||||
public boolean isInvokespecial() { return adjustedInvokeCode() == Bytecodes._invokespecial; }
|
public boolean isInvokespecial() { return adjustedInvokeCode() == Bytecodes._invokespecial; }
|
||||||
|
public boolean isInvokedynamic() { return adjustedInvokeCode() == Bytecodes._invokedynamic; }
|
||||||
|
|
||||||
public boolean isValid() { return isInvokeinterface() ||
|
public boolean isValid() { return isInvokeinterface() ||
|
||||||
isInvokevirtual() ||
|
isInvokevirtual() ||
|
||||||
@ -104,6 +121,11 @@ public class BytecodeInvoke extends BytecodeWithCPIndex {
|
|||||||
buf.append(spaces);
|
buf.append(spaces);
|
||||||
buf.append('#');
|
buf.append('#');
|
||||||
buf.append(Integer.toString(indexForFieldOrMethod()));
|
buf.append(Integer.toString(indexForFieldOrMethod()));
|
||||||
|
if (isInvokedynamic()) {
|
||||||
|
buf.append('(');
|
||||||
|
buf.append(Integer.toString(getSecondaryIndex()));
|
||||||
|
buf.append(')');
|
||||||
|
}
|
||||||
buf.append(" [Method ");
|
buf.append(" [Method ");
|
||||||
StringBuffer sigBuf = new StringBuffer();
|
StringBuffer sigBuf = new StringBuffer();
|
||||||
new SignatureConverter(signature(), sigBuf).iterateReturntype();
|
new SignatureConverter(signature(), sigBuf).iterateReturntype();
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
package sun.jvm.hotspot.interpreter;
|
package sun.jvm.hotspot.interpreter;
|
||||||
|
|
||||||
import sun.jvm.hotspot.oops.*;
|
import sun.jvm.hotspot.oops.*;
|
||||||
|
import sun.jvm.hotspot.runtime.*;
|
||||||
import sun.jvm.hotspot.utilities.*;
|
import sun.jvm.hotspot.utilities.*;
|
||||||
|
|
||||||
public class BytecodeLoadConstant extends BytecodeWithCPIndex {
|
public class BytecodeLoadConstant extends BytecodeWithCPIndex {
|
||||||
@ -32,10 +33,47 @@ public class BytecodeLoadConstant extends BytecodeWithCPIndex {
|
|||||||
super(method, bci);
|
super(method, bci);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean hasCacheIndex() {
|
||||||
|
// normal ldc uses CP index, but fast_aldc uses swapped CP cache index
|
||||||
|
return javaCode() != code();
|
||||||
|
}
|
||||||
|
|
||||||
public int index() {
|
public int index() {
|
||||||
return javaCode() == Bytecodes._ldc ?
|
int i = javaCode() == Bytecodes._ldc ?
|
||||||
(int) (0xFF & javaByteAt(1))
|
(int) (0xFF & javaByteAt(1))
|
||||||
: (int) (0xFFFF & javaShortAt(1));
|
: (int) (0xFFFF & javaShortAt(1));
|
||||||
|
if (hasCacheIndex()) {
|
||||||
|
return (0xFFFF & VM.getVM().getBytes().swapShort((short) i));
|
||||||
|
} else {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int poolIndex() {
|
||||||
|
int i = index();
|
||||||
|
if (hasCacheIndex()) {
|
||||||
|
ConstantPoolCache cpCache = method().getConstants().getCache();
|
||||||
|
return cpCache.getEntryAt(i).getConstantPoolIndex();
|
||||||
|
} else {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int cacheIndex() {
|
||||||
|
if (hasCacheIndex()) {
|
||||||
|
return index();
|
||||||
|
} else {
|
||||||
|
return -1; // no cache index
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Oop getCachedConstant() {
|
||||||
|
int i = cacheIndex();
|
||||||
|
if (i >= 0) {
|
||||||
|
ConstantPoolCache cpCache = method().getConstants().getCache();
|
||||||
|
return cpCache.getEntryAt(i).getF1();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void verify() {
|
public void verify() {
|
||||||
@ -58,6 +96,7 @@ public class BytecodeLoadConstant extends BytecodeWithCPIndex {
|
|||||||
// has to be int or float or String or Klass
|
// has to be int or float or String or Klass
|
||||||
return (ctag.isUnresolvedString() || ctag.isString()
|
return (ctag.isUnresolvedString() || ctag.isString()
|
||||||
|| ctag.isUnresolvedKlass() || ctag.isKlass()
|
|| ctag.isUnresolvedKlass() || ctag.isKlass()
|
||||||
|
|| ctag.isMethodHandle() || ctag.isMethodType()
|
||||||
|| ctag.isInt() || ctag.isFloat())? true: false;
|
|| ctag.isInt() || ctag.isFloat())? true: false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -112,7 +151,7 @@ public class BytecodeLoadConstant extends BytecodeWithCPIndex {
|
|||||||
|
|
||||||
public String getConstantValue() {
|
public String getConstantValue() {
|
||||||
ConstantPool cpool = method().getConstants();
|
ConstantPool cpool = method().getConstants();
|
||||||
int cpIndex = index();
|
int cpIndex = poolIndex();
|
||||||
ConstantTag ctag = cpool.getTagAt(cpIndex);
|
ConstantTag ctag = cpool.getTagAt(cpIndex);
|
||||||
if (ctag.isInt()) {
|
if (ctag.isInt()) {
|
||||||
return "<int " + Integer.toString(cpool.getIntAt(cpIndex)) +">";
|
return "<int " + Integer.toString(cpool.getIntAt(cpIndex)) +">";
|
||||||
@ -149,6 +188,18 @@ public class BytecodeLoadConstant extends BytecodeWithCPIndex {
|
|||||||
} else {
|
} else {
|
||||||
throw new RuntimeException("should not reach here");
|
throw new RuntimeException("should not reach here");
|
||||||
}
|
}
|
||||||
|
} else if (ctag.isMethodHandle() || ctag.isMethodType()) {
|
||||||
|
Oop x = getCachedConstant();
|
||||||
|
int refidx = cpool.getMethodHandleIndexAt(cpIndex);
|
||||||
|
int refkind = cpool.getMethodHandleRefKindAt(cpIndex);
|
||||||
|
return "<MethodHandle kind=" + Integer.toString(refkind) +
|
||||||
|
" ref=" + Integer.toString(refidx)
|
||||||
|
+ (x == null ? "" : " @" + x.getHandle()) + ">";
|
||||||
|
} else if (ctag.isMethodType()) {
|
||||||
|
Oop x = getCachedConstant();
|
||||||
|
int refidx = cpool.getMethodTypeIndexAt(cpIndex);
|
||||||
|
return "<MethodType " + cpool.getSymbolAt(refidx).asString()
|
||||||
|
+ (x == null ? "" : " @" + x.getHandle()) + ">";
|
||||||
} else {
|
} else {
|
||||||
if (Assert.ASSERTS_ENABLED) {
|
if (Assert.ASSERTS_ENABLED) {
|
||||||
Assert.that(false, "invalid load constant type");
|
Assert.that(false, "invalid load constant type");
|
||||||
@ -162,7 +213,12 @@ public class BytecodeLoadConstant extends BytecodeWithCPIndex {
|
|||||||
buf.append(getJavaBytecodeName());
|
buf.append(getJavaBytecodeName());
|
||||||
buf.append(spaces);
|
buf.append(spaces);
|
||||||
buf.append('#');
|
buf.append('#');
|
||||||
buf.append(Integer.toString(index()));
|
buf.append(Integer.toString(poolIndex()));
|
||||||
|
if (hasCacheIndex()) {
|
||||||
|
buf.append('(');
|
||||||
|
buf.append(Integer.toString(cacheIndex()));
|
||||||
|
buf.append(')');
|
||||||
|
}
|
||||||
buf.append(spaces);
|
buf.append(spaces);
|
||||||
buf.append(getConstantValue());
|
buf.append(getConstantValue());
|
||||||
if (code() != javaCode()) {
|
if (code() != javaCode()) {
|
||||||
|
@ -37,12 +37,19 @@ public abstract class BytecodeWithCPIndex extends Bytecode {
|
|||||||
// the constant pool index for this bytecode
|
// the constant pool index for this bytecode
|
||||||
public int index() { return 0xFFFF & javaShortAt(1); }
|
public int index() { return 0xFFFF & javaShortAt(1); }
|
||||||
|
|
||||||
|
public int getSecondaryIndex() {
|
||||||
|
throw new IllegalArgumentException("must be invokedynamic");
|
||||||
|
}
|
||||||
|
|
||||||
protected int indexForFieldOrMethod() {
|
protected int indexForFieldOrMethod() {
|
||||||
ConstantPoolCache cpCache = method().getConstants().getCache();
|
ConstantPoolCache cpCache = method().getConstants().getCache();
|
||||||
// get ConstantPool index from ConstantPoolCacheIndex at given bci
|
// get ConstantPool index from ConstantPoolCacheIndex at given bci
|
||||||
int cpCacheIndex = index();
|
int cpCacheIndex = index();
|
||||||
if (cpCache == null) {
|
if (cpCache == null) {
|
||||||
return cpCacheIndex;
|
return cpCacheIndex;
|
||||||
|
} else if (code() == Bytecodes._invokedynamic) {
|
||||||
|
int secondaryIndex = getSecondaryIndex();
|
||||||
|
return cpCache.getMainEntryAt(secondaryIndex).getConstantPoolIndex();
|
||||||
} else {
|
} else {
|
||||||
// change byte-ordering and go via cache
|
// change byte-ordering and go via cache
|
||||||
return cpCache.getEntryAt((int) (0xFFFF & VM.getVM().getBytes().swapShort((short) cpCacheIndex))).getConstantPoolIndex();
|
return cpCache.getEntryAt((int) (0xFFFF & VM.getVM().getBytes().swapShort((short) cpCacheIndex))).getConstantPoolIndex();
|
||||||
|
@ -222,7 +222,7 @@ public class Bytecodes {
|
|||||||
public static final int _invokespecial = 183; // 0xb7
|
public static final int _invokespecial = 183; // 0xb7
|
||||||
public static final int _invokestatic = 184; // 0xb8
|
public static final int _invokestatic = 184; // 0xb8
|
||||||
public static final int _invokeinterface = 185; // 0xb9
|
public static final int _invokeinterface = 185; // 0xb9
|
||||||
public static final int _xxxunusedxxx = 186; // 0xba
|
public static final int _invokedynamic = 186; // 0xba
|
||||||
public static final int _new = 187; // 0xbb
|
public static final int _new = 187; // 0xbb
|
||||||
public static final int _newarray = 188; // 0xbc
|
public static final int _newarray = 188; // 0xbc
|
||||||
public static final int _anewarray = 189; // 0xbd
|
public static final int _anewarray = 189; // 0xbd
|
||||||
@ -269,9 +269,12 @@ public class Bytecodes {
|
|||||||
public static final int _fast_invokevfinal = 226;
|
public static final int _fast_invokevfinal = 226;
|
||||||
public static final int _fast_linearswitch = 227;
|
public static final int _fast_linearswitch = 227;
|
||||||
public static final int _fast_binaryswitch = 228;
|
public static final int _fast_binaryswitch = 228;
|
||||||
public static final int _shouldnotreachhere = 229; // For debugging
|
public static final int _fast_aldc = 229;
|
||||||
|
public static final int _fast_aldc_w = 230;
|
||||||
|
public static final int _return_register_finalizer = 231;
|
||||||
|
public static final int _shouldnotreachhere = 232; // For debugging
|
||||||
|
|
||||||
public static final int number_of_codes = 230;
|
public static final int number_of_codes = 233;
|
||||||
|
|
||||||
public static int specialLengthAt(Method method, int bci) {
|
public static int specialLengthAt(Method method, int bci) {
|
||||||
int code = codeAt(method, bci);
|
int code = codeAt(method, bci);
|
||||||
@ -458,9 +461,9 @@ public class Bytecodes {
|
|||||||
def(_dconst_1 , "dconst_1" , "b" , null , BasicType.getTDouble() , 2, false);
|
def(_dconst_1 , "dconst_1" , "b" , null , BasicType.getTDouble() , 2, false);
|
||||||
def(_bipush , "bipush" , "bc" , null , BasicType.getTInt() , 1, false);
|
def(_bipush , "bipush" , "bc" , null , BasicType.getTInt() , 1, false);
|
||||||
def(_sipush , "sipush" , "bcc" , null , BasicType.getTInt() , 1, false);
|
def(_sipush , "sipush" , "bcc" , null , BasicType.getTInt() , 1, false);
|
||||||
def(_ldc , "ldc" , "bi" , null , BasicType.getTIllegal(), 1, true );
|
def(_ldc , "ldc" , "bk" , null , BasicType.getTIllegal(), 1, true );
|
||||||
def(_ldc_w , "ldc_w" , "bii" , null , BasicType.getTIllegal(), 1, true );
|
def(_ldc_w , "ldc_w" , "bkk" , null , BasicType.getTIllegal(), 1, true );
|
||||||
def(_ldc2_w , "ldc2_w" , "bii" , null , BasicType.getTIllegal(), 2, true );
|
def(_ldc2_w , "ldc2_w" , "bkk" , null , BasicType.getTIllegal(), 2, true );
|
||||||
def(_iload , "iload" , "bi" , "wbii" , BasicType.getTInt() , 1, false);
|
def(_iload , "iload" , "bi" , "wbii" , BasicType.getTInt() , 1, false);
|
||||||
def(_lload , "lload" , "bi" , "wbii" , BasicType.getTLong() , 2, false);
|
def(_lload , "lload" , "bi" , "wbii" , BasicType.getTLong() , 2, false);
|
||||||
def(_fload , "fload" , "bi" , "wbii" , BasicType.getTFloat() , 1, false);
|
def(_fload , "fload" , "bi" , "wbii" , BasicType.getTFloat() , 1, false);
|
||||||
@ -618,26 +621,26 @@ public class Bytecodes {
|
|||||||
def(_dreturn , "dreturn" , "b" , null , BasicType.getTDouble() , -2, true );
|
def(_dreturn , "dreturn" , "b" , null , BasicType.getTDouble() , -2, true );
|
||||||
def(_areturn , "areturn" , "b" , null , BasicType.getTObject() , -1, true );
|
def(_areturn , "areturn" , "b" , null , BasicType.getTObject() , -1, true );
|
||||||
def(_return , "return" , "b" , null , BasicType.getTVoid() , 0, true );
|
def(_return , "return" , "b" , null , BasicType.getTVoid() , 0, true );
|
||||||
def(_getstatic , "getstatic" , "bjj" , null , BasicType.getTIllegal(), 1, true );
|
def(_getstatic , "getstatic" , "bJJ" , null , BasicType.getTIllegal(), 1, true );
|
||||||
def(_putstatic , "putstatic" , "bjj" , null , BasicType.getTIllegal(), -1, true );
|
def(_putstatic , "putstatic" , "bJJ" , null , BasicType.getTIllegal(), -1, true );
|
||||||
def(_getfield , "getfield" , "bjj" , null , BasicType.getTIllegal(), 0, true );
|
def(_getfield , "getfield" , "bJJ" , null , BasicType.getTIllegal(), 0, true );
|
||||||
def(_putfield , "putfield" , "bjj" , null , BasicType.getTIllegal(), -2, true );
|
def(_putfield , "putfield" , "bJJ" , null , BasicType.getTIllegal(), -2, true );
|
||||||
def(_invokevirtual , "invokevirtual" , "bjj" , null , BasicType.getTIllegal(), -1, true );
|
def(_invokevirtual , "invokevirtual" , "bJJ" , null , BasicType.getTIllegal(), -1, true );
|
||||||
def(_invokespecial , "invokespecial" , "bjj" , null , BasicType.getTIllegal(), -1, true );
|
def(_invokespecial , "invokespecial" , "bJJ" , null , BasicType.getTIllegal(), -1, true );
|
||||||
def(_invokestatic , "invokestatic" , "bjj" , null , BasicType.getTIllegal(), 0, true );
|
def(_invokestatic , "invokestatic" , "bJJ" , null , BasicType.getTIllegal(), 0, true );
|
||||||
def(_invokeinterface , "invokeinterface" , "bjj__", null , BasicType.getTIllegal(), -1, true );
|
def(_invokeinterface , "invokeinterface" , "bJJ__", null , BasicType.getTIllegal(), -1, true );
|
||||||
def(_xxxunusedxxx , "xxxunusedxxx" , null , null , BasicType.getTVoid() , 0, false);
|
def(_invokedynamic , "invokedynamic" , "bJJJJ", null , BasicType.getTIllegal(), -1, true );
|
||||||
def(_new , "new" , "bii" , null , BasicType.getTObject() , 1, true );
|
def(_new , "new" , "bkk" , null , BasicType.getTObject() , 1, true );
|
||||||
def(_newarray , "newarray" , "bc" , null , BasicType.getTObject() , 0, true );
|
def(_newarray , "newarray" , "bc" , null , BasicType.getTObject() , 0, true );
|
||||||
def(_anewarray , "anewarray" , "bii" , null , BasicType.getTObject() , 0, true );
|
def(_anewarray , "anewarray" , "bkk" , null , BasicType.getTObject() , 0, true );
|
||||||
def(_arraylength , "arraylength" , "b" , null , BasicType.getTVoid() , 0, true );
|
def(_arraylength , "arraylength" , "b" , null , BasicType.getTVoid() , 0, true );
|
||||||
def(_athrow , "athrow" , "b" , null , BasicType.getTVoid() , -1, true );
|
def(_athrow , "athrow" , "b" , null , BasicType.getTVoid() , -1, true );
|
||||||
def(_checkcast , "checkcast" , "bii" , null , BasicType.getTObject() , 0, true );
|
def(_checkcast , "checkcast" , "bkk" , null , BasicType.getTObject() , 0, true );
|
||||||
def(_instanceof , "instanceof" , "bii" , null , BasicType.getTInt() , 0, true );
|
def(_instanceof , "instanceof" , "bkk" , null , BasicType.getTInt() , 0, true );
|
||||||
def(_monitorenter , "monitorenter" , "b" , null , BasicType.getTVoid() , -1, true );
|
def(_monitorenter , "monitorenter" , "b" , null , BasicType.getTVoid() , -1, true );
|
||||||
def(_monitorexit , "monitorexit" , "b" , null , BasicType.getTVoid() , -1, true );
|
def(_monitorexit , "monitorexit" , "b" , null , BasicType.getTVoid() , -1, true );
|
||||||
def(_wide , "wide" , "" , null , BasicType.getTVoid() , 0, false);
|
def(_wide , "wide" , "" , null , BasicType.getTVoid() , 0, false);
|
||||||
def(_multianewarray , "multianewarray" , "biic" , null , BasicType.getTObject() , 1, true );
|
def(_multianewarray , "multianewarray" , "bkkc" , null , BasicType.getTObject() , 1, true );
|
||||||
def(_ifnull , "ifnull" , "boo" , null , BasicType.getTVoid() , -1, false);
|
def(_ifnull , "ifnull" , "boo" , null , BasicType.getTVoid() , -1, false);
|
||||||
def(_ifnonnull , "ifnonnull" , "boo" , null , BasicType.getTVoid() , -1, false);
|
def(_ifnonnull , "ifnonnull" , "boo" , null , BasicType.getTVoid() , -1, false);
|
||||||
def(_goto_w , "goto_w" , "boooo", null , BasicType.getTVoid() , 0, false);
|
def(_goto_w , "goto_w" , "boooo", null , BasicType.getTVoid() , 0, false);
|
||||||
@ -646,38 +649,44 @@ public class Bytecodes {
|
|||||||
|
|
||||||
// JVM bytecodes
|
// JVM bytecodes
|
||||||
// bytecode bytecode name format wide f. result tp stk traps std code
|
// bytecode bytecode name format wide f. result tp stk traps std code
|
||||||
def(_fast_agetfield , "fast_agetfield" , "bjj" , null , BasicType.getTObject() , 0, true , _getfield );
|
def(_fast_agetfield , "fast_agetfield" , "bJJ" , null , BasicType.getTObject() , 0, true , _getfield );
|
||||||
def(_fast_bgetfield , "fast_bgetfield" , "bjj" , null , BasicType.getTInt() , 0, true , _getfield );
|
def(_fast_bgetfield , "fast_bgetfield" , "bJJ" , null , BasicType.getTInt() , 0, true , _getfield );
|
||||||
def(_fast_cgetfield , "fast_cgetfield" , "bjj" , null , BasicType.getTChar() , 0, true , _getfield );
|
def(_fast_cgetfield , "fast_cgetfield" , "bJJ" , null , BasicType.getTChar() , 0, true , _getfield );
|
||||||
def(_fast_dgetfield , "fast_dgetfield" , "bjj" , null , BasicType.getTDouble() , 0, true , _getfield );
|
def(_fast_dgetfield , "fast_dgetfield" , "bJJ" , null , BasicType.getTDouble() , 0, true , _getfield );
|
||||||
def(_fast_fgetfield , "fast_fgetfield" , "bjj" , null , BasicType.getTFloat() , 0, true , _getfield );
|
def(_fast_fgetfield , "fast_fgetfield" , "bJJ" , null , BasicType.getTFloat() , 0, true , _getfield );
|
||||||
def(_fast_igetfield , "fast_igetfield" , "bjj" , null , BasicType.getTInt() , 0, true , _getfield );
|
def(_fast_igetfield , "fast_igetfield" , "bJJ" , null , BasicType.getTInt() , 0, true , _getfield );
|
||||||
def(_fast_lgetfield , "fast_lgetfield" , "bjj" , null , BasicType.getTLong() , 0, true , _getfield );
|
def(_fast_lgetfield , "fast_lgetfield" , "bJJ" , null , BasicType.getTLong() , 0, true , _getfield );
|
||||||
def(_fast_sgetfield , "fast_sgetfield" , "bjj" , null , BasicType.getTShort() , 0, true , _getfield );
|
def(_fast_sgetfield , "fast_sgetfield" , "bJJ" , null , BasicType.getTShort() , 0, true , _getfield );
|
||||||
|
|
||||||
def(_fast_aputfield , "fast_aputfield" , "bjj" , null , BasicType.getTObject() , 0, true , _putfield );
|
def(_fast_aputfield , "fast_aputfield" , "bJJ" , null , BasicType.getTObject() , 0, true , _putfield );
|
||||||
def(_fast_bputfield , "fast_bputfield" , "bjj" , null , BasicType.getTInt() , 0, true , _putfield );
|
def(_fast_bputfield , "fast_bputfield" , "bJJ" , null , BasicType.getTInt() , 0, true , _putfield );
|
||||||
def(_fast_cputfield , "fast_cputfield" , "bjj" , null , BasicType.getTChar() , 0, true , _putfield );
|
def(_fast_cputfield , "fast_cputfield" , "bJJ" , null , BasicType.getTChar() , 0, true , _putfield );
|
||||||
def(_fast_dputfield , "fast_dputfield" , "bjj" , null , BasicType.getTDouble() , 0, true , _putfield );
|
def(_fast_dputfield , "fast_dputfield" , "bJJ" , null , BasicType.getTDouble() , 0, true , _putfield );
|
||||||
def(_fast_fputfield , "fast_fputfield" , "bjj" , null , BasicType.getTFloat() , 0, true , _putfield );
|
def(_fast_fputfield , "fast_fputfield" , "bJJ" , null , BasicType.getTFloat() , 0, true , _putfield );
|
||||||
def(_fast_iputfield , "fast_iputfield" , "bjj" , null , BasicType.getTInt() , 0, true , _putfield );
|
def(_fast_iputfield , "fast_iputfield" , "bJJ" , null , BasicType.getTInt() , 0, true , _putfield );
|
||||||
def(_fast_lputfield , "fast_lputfield" , "bjj" , null , BasicType.getTLong() , 0, true , _putfield );
|
def(_fast_lputfield , "fast_lputfield" , "bJJ" , null , BasicType.getTLong() , 0, true , _putfield );
|
||||||
def(_fast_sputfield , "fast_sputfield" , "bjj" , null , BasicType.getTShort() , 0, true , _putfield );
|
def(_fast_sputfield , "fast_sputfield" , "bJJ" , null , BasicType.getTShort() , 0, true , _putfield );
|
||||||
|
|
||||||
def(_fast_aload_0 , "fast_aload_0" , "b" , null , BasicType.getTObject() , 1, true , _aload_0 );
|
def(_fast_aload_0 , "fast_aload_0" , "b" , null , BasicType.getTObject() , 1, true , _aload_0 );
|
||||||
def(_fast_iaccess_0 , "fast_iaccess_0" , "b_jj" , null , BasicType.getTInt() , 1, true , _aload_0 );
|
def(_fast_iaccess_0 , "fast_iaccess_0" , "b_JJ" , null , BasicType.getTInt() , 1, true , _aload_0 );
|
||||||
def(_fast_aaccess_0 , "fast_aaccess_0" , "b_jj" , null , BasicType.getTObject() , 1, true , _aload_0 );
|
def(_fast_aaccess_0 , "fast_aaccess_0" , "b_JJ" , null , BasicType.getTObject() , 1, true , _aload_0 );
|
||||||
def(_fast_faccess_0 , "fast_faccess_0" , "b_jj" , null , BasicType.getTObject() , 1, true , _aload_0 );
|
def(_fast_faccess_0 , "fast_faccess_0" , "b_JJ" , null , BasicType.getTObject() , 1, true , _aload_0 );
|
||||||
|
|
||||||
def(_fast_iload , "fast_iload" , "bi" , null , BasicType.getTInt() , 1, false, _iload);
|
def(_fast_iload , "fast_iload" , "bi" , null , BasicType.getTInt() , 1, false, _iload);
|
||||||
def(_fast_iload2 , "fast_iload2" , "bi_i" , null , BasicType.getTInt() , 2, false, _iload);
|
def(_fast_iload2 , "fast_iload2" , "bi_i" , null , BasicType.getTInt() , 2, false, _iload);
|
||||||
def(_fast_icaload , "fast_icaload" , "bi_" , null , BasicType.getTInt() , 0, false, _iload);
|
def(_fast_icaload , "fast_icaload" , "bi_" , null , BasicType.getTInt() , 0, false, _iload);
|
||||||
|
|
||||||
// Faster method invocation.
|
// Faster method invocation.
|
||||||
def(_fast_invokevfinal , "fast_invokevfinal" , "bjj" , null , BasicType.getTIllegal(), -1, true, _invokevirtual);
|
def(_fast_invokevfinal , "fast_invokevfinal" , "bJJ" , null , BasicType.getTIllegal(), -1, true, _invokevirtual);
|
||||||
|
|
||||||
def(_fast_linearswitch , "fast_linearswitch" , "" , null , BasicType.getTVoid() , -1, false, _lookupswitch );
|
def(_fast_linearswitch , "fast_linearswitch" , "" , null , BasicType.getTVoid() , -1, false, _lookupswitch );
|
||||||
def(_fast_binaryswitch , "fast_binaryswitch" , "" , null , BasicType.getTVoid() , -1, false, _lookupswitch );
|
def(_fast_binaryswitch , "fast_binaryswitch" , "" , null , BasicType.getTVoid() , -1, false, _lookupswitch );
|
||||||
|
|
||||||
|
def(_return_register_finalizer, "return_register_finalizer", "b" , null , BasicType.getTVoid() , 0, true, _return );
|
||||||
|
|
||||||
|
def(_fast_aldc , "fast_aldc" , "bj" , null , BasicType.getTObject(), 1, true, _ldc );
|
||||||
|
def(_fast_aldc_w , "fast_aldc_w" , "bJJ" , null , BasicType.getTObject(), 1, true, _ldc_w );
|
||||||
|
|
||||||
def(_shouldnotreachhere , "_shouldnotreachhere" , "b" , null , BasicType.getTVoid() , 0, false);
|
def(_shouldnotreachhere , "_shouldnotreachhere" , "b" , null , BasicType.getTVoid() , 0, false);
|
||||||
|
|
||||||
if (Assert.ASSERTS_ENABLED) {
|
if (Assert.ASSERTS_ENABLED) {
|
||||||
|
@ -152,7 +152,7 @@ public class ConstantPool extends Oop implements ClassConstants {
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getNameAndTypeAt(int which) {
|
public int[] getNameAndTypeAt(int which) {
|
||||||
if (Assert.ASSERTS_ENABLED) {
|
if (Assert.ASSERTS_ENABLED) {
|
||||||
Assert.that(getTagAt(which).isNameAndType(), "Corrupted constant pool");
|
Assert.that(getTagAt(which).isNameAndType(), "Corrupted constant pool");
|
||||||
}
|
}
|
||||||
@ -160,18 +160,16 @@ public class ConstantPool extends Oop implements ClassConstants {
|
|||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
System.err.println("ConstantPool.getNameAndTypeAt(" + which + "): result = " + i);
|
System.err.println("ConstantPool.getNameAndTypeAt(" + which + "): result = " + i);
|
||||||
}
|
}
|
||||||
return i;
|
return new int[] { extractLowShortFromInt(i), extractHighShortFromInt(i) };
|
||||||
}
|
}
|
||||||
|
|
||||||
public Symbol getNameRefAt(int which) {
|
public Symbol getNameRefAt(int which) {
|
||||||
int refIndex = getNameAndTypeAt(getNameAndTypeRefIndexAt(which));
|
int nameIndex = getNameAndTypeAt(getNameAndTypeRefIndexAt(which))[0];
|
||||||
int nameIndex = extractLowShortFromInt(refIndex);
|
|
||||||
return getSymbolAt(nameIndex);
|
return getSymbolAt(nameIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Symbol getSignatureRefAt(int which) {
|
public Symbol getSignatureRefAt(int which) {
|
||||||
int refIndex = getNameAndTypeAt(getNameAndTypeRefIndexAt(which));
|
int sigIndex = getNameAndTypeAt(getNameAndTypeRefIndexAt(which))[1];
|
||||||
int sigIndex = extractHighShortFromInt(refIndex);
|
|
||||||
return getSymbolAt(sigIndex);
|
return getSymbolAt(sigIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -220,11 +218,11 @@ public class ConstantPool extends Oop implements ClassConstants {
|
|||||||
|
|
||||||
/** Lookup for entries consisting of (name_index, signature_index) */
|
/** Lookup for entries consisting of (name_index, signature_index) */
|
||||||
public int getNameRefIndexAt(int index) {
|
public int getNameRefIndexAt(int index) {
|
||||||
int refIndex = getNameAndTypeAt(index);
|
int[] refIndex = getNameAndTypeAt(index);
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
System.err.println("ConstantPool.getNameRefIndexAt(" + index + "): refIndex = " + refIndex);
|
System.err.println("ConstantPool.getNameRefIndexAt(" + index + "): refIndex = " + refIndex[0]+"/"+refIndex[1]);
|
||||||
}
|
}
|
||||||
int i = extractLowShortFromInt(refIndex);
|
int i = refIndex[0];
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
System.err.println("ConstantPool.getNameRefIndexAt(" + index + "): result = " + i);
|
System.err.println("ConstantPool.getNameRefIndexAt(" + index + "): result = " + i);
|
||||||
}
|
}
|
||||||
@ -233,17 +231,53 @@ public class ConstantPool extends Oop implements ClassConstants {
|
|||||||
|
|
||||||
/** Lookup for entries consisting of (name_index, signature_index) */
|
/** Lookup for entries consisting of (name_index, signature_index) */
|
||||||
public int getSignatureRefIndexAt(int index) {
|
public int getSignatureRefIndexAt(int index) {
|
||||||
int refIndex = getNameAndTypeAt(index);
|
int[] refIndex = getNameAndTypeAt(index);
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
System.err.println("ConstantPool.getSignatureRefIndexAt(" + index + "): refIndex = " + refIndex);
|
System.err.println("ConstantPool.getSignatureRefIndexAt(" + index + "): refIndex = " + refIndex[0]+"/"+refIndex[1]);
|
||||||
}
|
}
|
||||||
int i = extractHighShortFromInt(refIndex);
|
int i = refIndex[1];
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
System.err.println("ConstantPool.getSignatureRefIndexAt(" + index + "): result = " + i);
|
System.err.println("ConstantPool.getSignatureRefIndexAt(" + index + "): result = " + i);
|
||||||
}
|
}
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Lookup for MethodHandle entries. */
|
||||||
|
public int getMethodHandleIndexAt(int i) {
|
||||||
|
if (Assert.ASSERTS_ENABLED) {
|
||||||
|
Assert.that(getTagAt(i).isMethodHandle(), "Corrupted constant pool");
|
||||||
|
}
|
||||||
|
int res = extractHighShortFromInt(getIntAt(i));
|
||||||
|
if (DEBUG) {
|
||||||
|
System.err.println("ConstantPool.getMethodHandleIndexAt(" + i + "): result = " + res);
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Lookup for MethodHandle entries. */
|
||||||
|
public int getMethodHandleRefKindAt(int i) {
|
||||||
|
if (Assert.ASSERTS_ENABLED) {
|
||||||
|
Assert.that(getTagAt(i).isMethodHandle(), "Corrupted constant pool");
|
||||||
|
}
|
||||||
|
int res = extractLowShortFromInt(getIntAt(i));
|
||||||
|
if (DEBUG) {
|
||||||
|
System.err.println("ConstantPool.getMethodHandleRefKindAt(" + i + "): result = " + res);
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Lookup for MethodType entries. */
|
||||||
|
public int getMethodTypeIndexAt(int i) {
|
||||||
|
if (Assert.ASSERTS_ENABLED) {
|
||||||
|
Assert.that(getTagAt(i).isMethodType(), "Corrupted constant pool");
|
||||||
|
}
|
||||||
|
int res = getIntAt(i);
|
||||||
|
if (DEBUG) {
|
||||||
|
System.err.println("ConstantPool.getMethodHandleTypeAt(" + i + "): result = " + res);
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
final private static String[] nameForTag = new String[] {
|
final private static String[] nameForTag = new String[] {
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -261,6 +295,8 @@ public class ConstantPool extends Oop implements ClassConstants {
|
|||||||
case JVM_CONSTANT_Methodref: return "JVM_CONSTANT_Methodref";
|
case JVM_CONSTANT_Methodref: return "JVM_CONSTANT_Methodref";
|
||||||
case JVM_CONSTANT_InterfaceMethodref: return "JVM_CONSTANT_InterfaceMethodref";
|
case JVM_CONSTANT_InterfaceMethodref: return "JVM_CONSTANT_InterfaceMethodref";
|
||||||
case JVM_CONSTANT_NameAndType: return "JVM_CONSTANT_NameAndType";
|
case JVM_CONSTANT_NameAndType: return "JVM_CONSTANT_NameAndType";
|
||||||
|
case JVM_CONSTANT_MethodHandle: return "JVM_CONSTANT_MethodHandle";
|
||||||
|
case JVM_CONSTANT_MethodType: return "JVM_CONSTANT_MethodType";
|
||||||
case JVM_CONSTANT_Invalid: return "JVM_CONSTANT_Invalid";
|
case JVM_CONSTANT_Invalid: return "JVM_CONSTANT_Invalid";
|
||||||
case JVM_CONSTANT_UnresolvedClass: return "JVM_CONSTANT_UnresolvedClass";
|
case JVM_CONSTANT_UnresolvedClass: return "JVM_CONSTANT_UnresolvedClass";
|
||||||
case JVM_CONSTANT_UnresolvedClassInError: return "JVM_CONSTANT_UnresolvedClassInError";
|
case JVM_CONSTANT_UnresolvedClassInError: return "JVM_CONSTANT_UnresolvedClassInError";
|
||||||
@ -317,6 +353,8 @@ public class ConstantPool extends Oop implements ClassConstants {
|
|||||||
case JVM_CONSTANT_Methodref:
|
case JVM_CONSTANT_Methodref:
|
||||||
case JVM_CONSTANT_InterfaceMethodref:
|
case JVM_CONSTANT_InterfaceMethodref:
|
||||||
case JVM_CONSTANT_NameAndType:
|
case JVM_CONSTANT_NameAndType:
|
||||||
|
case JVM_CONSTANT_MethodHandle:
|
||||||
|
case JVM_CONSTANT_MethodType:
|
||||||
visitor.doInt(new IntField(new NamedFieldIdentifier(nameForTag(ctag)), indexOffset(index), true), true);
|
visitor.doInt(new IntField(new NamedFieldIdentifier(nameForTag(ctag)), indexOffset(index), true), true);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -467,6 +505,18 @@ public class ConstantPool extends Oop implements ClassConstants {
|
|||||||
+ ", type = " + signatureIndex);
|
+ ", type = " + signatureIndex);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case JVM_CONSTANT_MethodHandle: {
|
||||||
|
dos.writeByte(cpConstType);
|
||||||
|
int value = getIntAt(ci);
|
||||||
|
short nameIndex = (short) extractLowShortFromInt(value);
|
||||||
|
short signatureIndex = (short) extractHighShortFromInt(value);
|
||||||
|
dos.writeShort(nameIndex);
|
||||||
|
dos.writeShort(signatureIndex);
|
||||||
|
if (DEBUG) debugMessage("CP[" + ci + "] = N&T name = " + nameIndex
|
||||||
|
+ ", type = " + signatureIndex);
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
throw new InternalError("unknown tag: " + cpConstType);
|
throw new InternalError("unknown tag: " + cpConstType);
|
||||||
} // switch
|
} // switch
|
||||||
@ -488,10 +538,12 @@ public class ConstantPool extends Oop implements ClassConstants {
|
|||||||
//
|
//
|
||||||
|
|
||||||
private static int extractHighShortFromInt(int val) {
|
private static int extractHighShortFromInt(int val) {
|
||||||
|
// must stay in sync with constantPoolOopDesc::name_and_type_at_put, method_at_put, etc.
|
||||||
return (val >> 16) & 0xFFFF;
|
return (val >> 16) & 0xFFFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int extractLowShortFromInt(int val) {
|
private static int extractLowShortFromInt(int val) {
|
||||||
|
// must stay in sync with constantPoolOopDesc::name_and_type_at_put, method_at_put, etc.
|
||||||
return val & 0xFFFF;
|
return val & 0xFFFF;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -78,6 +78,31 @@ public class ConstantPoolCache extends Oop {
|
|||||||
return new ConstantPoolCacheEntry(this, i);
|
return new ConstantPoolCacheEntry(this, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean isSecondaryIndex(int i) { return (i < 0); }
|
||||||
|
public static int decodeSecondaryIndex(int i) { return isSecondaryIndex(i) ? ~i : i; }
|
||||||
|
public static int encodeSecondaryIndex(int i) { return !isSecondaryIndex(i) ? ~i : i; }
|
||||||
|
|
||||||
|
// secondary entries hold invokedynamic call site bindings
|
||||||
|
public ConstantPoolCacheEntry getSecondaryEntryAt(int i) {
|
||||||
|
ConstantPoolCacheEntry e = new ConstantPoolCacheEntry(this, decodeSecondaryIndex(i));
|
||||||
|
if (Assert.ASSERTS_ENABLED) {
|
||||||
|
Assert.that(e.isSecondaryEntry(), "must be a secondary entry");
|
||||||
|
}
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ConstantPoolCacheEntry getMainEntryAt(int i) {
|
||||||
|
if (isSecondaryIndex(i)) {
|
||||||
|
// run through an extra level of indirection:
|
||||||
|
i = getSecondaryEntryAt(i).getMainEntryIndex();
|
||||||
|
}
|
||||||
|
ConstantPoolCacheEntry e = new ConstantPoolCacheEntry(this, i);
|
||||||
|
if (Assert.ASSERTS_ENABLED) {
|
||||||
|
Assert.that(!e.isSecondaryEntry(), "must not be a secondary entry");
|
||||||
|
}
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
|
||||||
public int getIntAt(int entry, int fld) {
|
public int getIntAt(int entry, int fld) {
|
||||||
//alignObjectSize ?
|
//alignObjectSize ?
|
||||||
long offset = baseOffset + /*alignObjectSize*/entry * elementSize + fld* getHeap().getIntSize();
|
long offset = baseOffset + /*alignObjectSize*/entry * elementSize + fld* getHeap().getIntSize();
|
||||||
|
@ -28,6 +28,7 @@ import java.util.*;
|
|||||||
import sun.jvm.hotspot.debugger.*;
|
import sun.jvm.hotspot.debugger.*;
|
||||||
import sun.jvm.hotspot.runtime.*;
|
import sun.jvm.hotspot.runtime.*;
|
||||||
import sun.jvm.hotspot.types.*;
|
import sun.jvm.hotspot.types.*;
|
||||||
|
import sun.jvm.hotspot.utilities.*;
|
||||||
|
|
||||||
public class ConstantPoolCacheEntry {
|
public class ConstantPoolCacheEntry {
|
||||||
private static long size;
|
private static long size;
|
||||||
@ -67,9 +68,23 @@ public class ConstantPoolCacheEntry {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public int getConstantPoolIndex() {
|
public int getConstantPoolIndex() {
|
||||||
|
if (Assert.ASSERTS_ENABLED) {
|
||||||
|
Assert.that(!isSecondaryEntry(), "must not be a secondary CP entry");
|
||||||
|
}
|
||||||
return (int) (getIndices() & 0xFFFF);
|
return (int) (getIndices() & 0xFFFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isSecondaryEntry() {
|
||||||
|
return (getIndices() & 0xFFFF) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getMainEntryIndex() {
|
||||||
|
if (Assert.ASSERTS_ENABLED) {
|
||||||
|
Assert.that(isSecondaryEntry(), "must be a secondary CP entry");
|
||||||
|
}
|
||||||
|
return (int) (getIndices() >>> 16);
|
||||||
|
}
|
||||||
|
|
||||||
private long getIndices() {
|
private long getIndices() {
|
||||||
return cp.getHandle().getCIntegerAt(indices.getOffset() + offset, indices.getSize(), indices.isUnsigned());
|
return cp.getHandle().getCIntegerAt(indices.getOffset() + offset, indices.getSize(), indices.isUnsigned());
|
||||||
}
|
}
|
||||||
|
@ -566,6 +566,7 @@ public class GenerateOopMap {
|
|||||||
case Bytecodes._invokespecial:
|
case Bytecodes._invokespecial:
|
||||||
case Bytecodes._invokestatic:
|
case Bytecodes._invokestatic:
|
||||||
case Bytecodes._invokeinterface:
|
case Bytecodes._invokeinterface:
|
||||||
|
case Bytecodes._invokedynamic:
|
||||||
// FIXME: print signature of referenced method (need more
|
// FIXME: print signature of referenced method (need more
|
||||||
// accessors in ConstantPool and ConstantPoolCache)
|
// accessors in ConstantPool and ConstantPoolCache)
|
||||||
int idx = currentBC.getIndexBig();
|
int idx = currentBC.getIndexBig();
|
||||||
@ -605,6 +606,7 @@ public class GenerateOopMap {
|
|||||||
case Bytecodes._invokespecial:
|
case Bytecodes._invokespecial:
|
||||||
case Bytecodes._invokestatic:
|
case Bytecodes._invokestatic:
|
||||||
case Bytecodes._invokeinterface:
|
case Bytecodes._invokeinterface:
|
||||||
|
case Bytecodes._invokedynamic:
|
||||||
// FIXME: print signature of referenced method (need more
|
// FIXME: print signature of referenced method (need more
|
||||||
// accessors in ConstantPool and ConstantPoolCache)
|
// accessors in ConstantPool and ConstantPoolCache)
|
||||||
int idx = currentBC.getIndexBig();
|
int idx = currentBC.getIndexBig();
|
||||||
@ -1134,6 +1136,7 @@ public class GenerateOopMap {
|
|||||||
case Bytecodes._invokespecial:
|
case Bytecodes._invokespecial:
|
||||||
case Bytecodes._invokestatic:
|
case Bytecodes._invokestatic:
|
||||||
case Bytecodes._invokeinterface:
|
case Bytecodes._invokeinterface:
|
||||||
|
case Bytecodes._invokedynamic:
|
||||||
_itr_send = itr;
|
_itr_send = itr;
|
||||||
_report_result_for_send = true;
|
_report_result_for_send = true;
|
||||||
break;
|
break;
|
||||||
@ -1379,6 +1382,7 @@ public class GenerateOopMap {
|
|||||||
case Bytecodes._invokevirtual:
|
case Bytecodes._invokevirtual:
|
||||||
case Bytecodes._invokespecial: doMethod(false, false, itr.getIndexBig(), itr.bci()); break;
|
case Bytecodes._invokespecial: doMethod(false, false, itr.getIndexBig(), itr.bci()); break;
|
||||||
case Bytecodes._invokestatic: doMethod(true, 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._invokeinterface: doMethod(false, true, itr.getIndexBig(), itr.bci()); break;
|
||||||
case Bytecodes._newarray:
|
case Bytecodes._newarray:
|
||||||
case Bytecodes._anewarray: ppNewRef(vCTS, itr.bci()); break;
|
case Bytecodes._anewarray: ppNewRef(vCTS, itr.bci()); break;
|
||||||
@ -1725,7 +1729,7 @@ public class GenerateOopMap {
|
|||||||
void doMethod (boolean is_static, boolean is_interface, int idx, int bci) {
|
void doMethod (boolean is_static, boolean is_interface, int idx, int bci) {
|
||||||
// Dig up signature for field in constant pool
|
// Dig up signature for field in constant pool
|
||||||
ConstantPool cp = _method.getConstants();
|
ConstantPool cp = _method.getConstants();
|
||||||
int nameAndTypeIdx = cp.getNameAndTypeRefIndexAt(idx);
|
int nameAndTypeIdx = cp.getTagAt(idx).isNameAndType() ? idx : cp.getNameAndTypeRefIndexAt(idx);
|
||||||
int signatureIdx = cp.getSignatureRefIndexAt(nameAndTypeIdx);
|
int signatureIdx = cp.getSignatureRefIndexAt(nameAndTypeIdx);
|
||||||
Symbol signature = cp.getSymbolAt(signatureIdx);
|
Symbol signature = cp.getSymbolAt(signatureIdx);
|
||||||
|
|
||||||
|
@ -40,6 +40,19 @@ public interface ClassConstants
|
|||||||
public static final int JVM_CONSTANT_Methodref = 10;
|
public static final int JVM_CONSTANT_Methodref = 10;
|
||||||
public static final int JVM_CONSTANT_InterfaceMethodref = 11;
|
public static final int JVM_CONSTANT_InterfaceMethodref = 11;
|
||||||
public static final int JVM_CONSTANT_NameAndType = 12;
|
public static final int JVM_CONSTANT_NameAndType = 12;
|
||||||
|
public static final int JVM_CONSTANT_MethodHandle = 15;
|
||||||
|
public static final int JVM_CONSTANT_MethodType = 16;
|
||||||
|
|
||||||
|
// JVM_CONSTANT_MethodHandle subtypes
|
||||||
|
public static final int JVM_REF_getField = 1;
|
||||||
|
public static final int JVM_REF_getStatic = 2;
|
||||||
|
public static final int JVM_REF_putField = 3;
|
||||||
|
public static final int JVM_REF_putStatic = 4;
|
||||||
|
public static final int JVM_REF_invokeVirtual = 5;
|
||||||
|
public static final int JVM_REF_invokeStatic = 6;
|
||||||
|
public static final int JVM_REF_invokeSpecial = 7;
|
||||||
|
public static final int JVM_REF_newInvokeSpecial = 8;
|
||||||
|
public static final int JVM_REF_invokeInterface = 9;
|
||||||
|
|
||||||
// HotSpot specific constant pool constant types.
|
// HotSpot specific constant pool constant types.
|
||||||
|
|
||||||
|
@ -54,14 +54,34 @@ public class ByteCodeRewriter
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected short getConstantPoolIndex(int bci) {
|
protected short getConstantPoolIndex(int rawcode, int bci) {
|
||||||
// get ConstantPool index from ConstantPoolCacheIndex at given bci
|
// get ConstantPool index from ConstantPoolCacheIndex at given bci
|
||||||
short cpCacheIndex = method.getBytecodeShortArg(bci);
|
String fmt = Bytecodes.format(rawcode);
|
||||||
|
int cpCacheIndex;
|
||||||
|
switch (fmt.length()) {
|
||||||
|
case 2: cpCacheIndex = method.getBytecodeByteArg(bci); break;
|
||||||
|
case 3: cpCacheIndex = method.getBytecodeShortArg(bci); break;
|
||||||
|
case 5:
|
||||||
|
if (fmt.indexOf("__") >= 0)
|
||||||
|
cpCacheIndex = method.getBytecodeShortArg(bci);
|
||||||
|
else
|
||||||
|
cpCacheIndex = method.getBytecodeIntArg(bci);
|
||||||
|
break;
|
||||||
|
default: throw new IllegalArgumentException();
|
||||||
|
}
|
||||||
if (cpCache == null) {
|
if (cpCache == null) {
|
||||||
return cpCacheIndex;
|
return (short) cpCacheIndex;
|
||||||
} else {
|
} else if (fmt.indexOf("JJJJ") >= 0) {
|
||||||
|
// change byte-ordering and go via secondary cache entry
|
||||||
|
return (short) cpCache.getMainEntryAt(bytes.swapInt(cpCacheIndex)).getConstantPoolIndex();
|
||||||
|
} else if (fmt.indexOf("JJ") >= 0) {
|
||||||
// change byte-ordering and go via cache
|
// change byte-ordering and go via cache
|
||||||
return (short) cpCache.getEntryAt((int) (0xFFFF & bytes.swapShort(cpCacheIndex))).getConstantPoolIndex();
|
return (short) cpCache.getEntryAt((int) (0xFFFF & bytes.swapShort((short)cpCacheIndex))).getConstantPoolIndex();
|
||||||
|
} else if (fmt.indexOf("j") >= 0) {
|
||||||
|
// go via cache
|
||||||
|
return (short) cpCache.getEntryAt((int) (0xFF & cpCacheIndex)).getConstantPoolIndex();
|
||||||
|
} else {
|
||||||
|
return (short) cpCacheIndex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -100,10 +120,31 @@ public class ByteCodeRewriter
|
|||||||
case Bytecodes._invokespecial:
|
case Bytecodes._invokespecial:
|
||||||
case Bytecodes._invokestatic:
|
case Bytecodes._invokestatic:
|
||||||
case Bytecodes._invokeinterface: {
|
case Bytecodes._invokeinterface: {
|
||||||
cpoolIndex = getConstantPoolIndex(bci + 1);
|
cpoolIndex = getConstantPoolIndex(hotspotcode, bci + 1);
|
||||||
writeShort(code, bci + 1, cpoolIndex);
|
writeShort(code, bci + 1, cpoolIndex);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case Bytecodes._invokedynamic:
|
||||||
|
cpoolIndex = getConstantPoolIndex(hotspotcode, bci + 1);
|
||||||
|
writeShort(code, bci + 1, cpoolIndex);
|
||||||
|
writeShort(code, bci + 3, (short)0); // clear out trailing bytes
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Bytecodes._ldc_w:
|
||||||
|
if (hotspotcode != bytecode) {
|
||||||
|
// fast_aldc_w puts constant in CP cache
|
||||||
|
cpoolIndex = getConstantPoolIndex(hotspotcode, bci + 1);
|
||||||
|
writeShort(code, bci + 1, cpoolIndex);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case Bytecodes._ldc:
|
||||||
|
if (hotspotcode != bytecode) {
|
||||||
|
// fast_aldc puts constant in CP cache
|
||||||
|
cpoolIndex = getConstantPoolIndex(hotspotcode, bci + 1);
|
||||||
|
code[bci + 1] = (byte)(cpoolIndex);
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
len = Bytecodes.lengthFor(bytecode);
|
len = Bytecodes.lengthFor(bytecode);
|
||||||
|
@ -61,10 +61,12 @@ public class ClassWriter implements /* imports */ ClassConstants
|
|||||||
protected short _signatureIndex;
|
protected short _signatureIndex;
|
||||||
|
|
||||||
protected static int extractHighShortFromInt(int val) {
|
protected static int extractHighShortFromInt(int val) {
|
||||||
|
// must stay in sync with constantPoolOopDesc::name_and_type_at_put, method_at_put, etc.
|
||||||
return (val >> 16) & 0xFFFF;
|
return (val >> 16) & 0xFFFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static int extractLowShortFromInt(int val) {
|
protected static int extractLowShortFromInt(int val) {
|
||||||
|
// must stay in sync with constantPoolOopDesc::name_and_type_at_put, method_at_put, etc.
|
||||||
return val & 0xFFFF;
|
return val & 0xFFFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -297,6 +299,28 @@ public class ClassWriter implements /* imports */ ClassConstants
|
|||||||
+ ", type = " + signatureIndex);
|
+ ", type = " + signatureIndex);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case JVM_CONSTANT_MethodHandle: {
|
||||||
|
dos.writeByte(cpConstType);
|
||||||
|
int value = cpool.getIntAt(ci);
|
||||||
|
short refIndex = (short) extractHighShortFromInt(value);
|
||||||
|
byte refKind = (byte) extractLowShortFromInt(value);
|
||||||
|
dos.writeByte(refKind);
|
||||||
|
dos.writeShort(refIndex);
|
||||||
|
if (DEBUG) debugMessage("CP[" + ci + "] = MH index = " + refIndex
|
||||||
|
+ ", kind = " + refKind);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case JVM_CONSTANT_MethodType: {
|
||||||
|
dos.writeByte(cpConstType);
|
||||||
|
int value = cpool.getIntAt(ci);
|
||||||
|
short refIndex = (short) value;
|
||||||
|
dos.writeShort(refIndex);
|
||||||
|
if (DEBUG) debugMessage("CP[" + ci + "] = MT index = " + refIndex);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw new InternalError("Unknown tag: " + cpConstType);
|
throw new InternalError("Unknown tag: " + cpConstType);
|
||||||
} // switch
|
} // switch
|
||||||
|
@ -572,6 +572,16 @@ public class HTMLGenerator implements /* imports */ ClassConstants {
|
|||||||
buf.cell(Integer.toString(cpool.getIntAt(index)));
|
buf.cell(Integer.toString(cpool.getIntAt(index)));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case JVM_CONSTANT_MethodHandle:
|
||||||
|
buf.cell("JVM_CONSTANT_MethodHandle");
|
||||||
|
buf.cell(genLowHighShort(cpool.getIntAt(index)));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case JVM_CONSTANT_MethodType:
|
||||||
|
buf.cell("JVM_CONSTANT_MethodType");
|
||||||
|
buf.cell(Integer.toString(cpool.getIntAt(index)));
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw new InternalError("unknown tag: " + ctag);
|
throw new InternalError("unknown tag: " + ctag);
|
||||||
}
|
}
|
||||||
|
@ -38,12 +38,26 @@ public class ConstantTag {
|
|||||||
private static int JVM_CONSTANT_Methodref = 10;
|
private static int JVM_CONSTANT_Methodref = 10;
|
||||||
private static int JVM_CONSTANT_InterfaceMethodref = 11;
|
private static int JVM_CONSTANT_InterfaceMethodref = 11;
|
||||||
private static int JVM_CONSTANT_NameAndType = 12;
|
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
|
||||||
private static int JVM_CONSTANT_Invalid = 0; // For bad value initialization
|
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_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_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_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_StringIndex = 103; // Temporary tag while constructing constant pool
|
||||||
private static int JVM_CONSTANT_UnresolvedClassInError = 104; // Resolution failed
|
private static int JVM_CONSTANT_UnresolvedClassInError = 104; // Resolution failed
|
||||||
|
private static 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;
|
||||||
|
private static int JVM_REF_getStatic = 2;
|
||||||
|
private static int JVM_REF_putField = 3;
|
||||||
|
private static int JVM_REF_putStatic = 4;
|
||||||
|
private static int JVM_REF_invokeVirtual = 5;
|
||||||
|
private static int JVM_REF_invokeStatic = 6;
|
||||||
|
private static int JVM_REF_invokeSpecial = 7;
|
||||||
|
private static int JVM_REF_newInvokeSpecial = 8;
|
||||||
|
private static int JVM_REF_invokeInterface = 9;
|
||||||
|
|
||||||
private byte tag;
|
private byte tag;
|
||||||
|
|
||||||
@ -62,6 +76,8 @@ public class ConstantTag {
|
|||||||
public boolean isDouble() { return tag == JVM_CONSTANT_Double; }
|
public boolean isDouble() { return tag == JVM_CONSTANT_Double; }
|
||||||
public boolean isNameAndType() { return tag == JVM_CONSTANT_NameAndType; }
|
public boolean isNameAndType() { return tag == JVM_CONSTANT_NameAndType; }
|
||||||
public boolean isUtf8() { return tag == JVM_CONSTANT_Utf8; }
|
public boolean isUtf8() { return tag == JVM_CONSTANT_Utf8; }
|
||||||
|
public boolean isMethodHandle() { return tag == JVM_CONSTANT_MethodHandle; }
|
||||||
|
public boolean isMethodType() { return tag == JVM_CONSTANT_MethodType; }
|
||||||
|
|
||||||
public boolean isInvalid() { return tag == JVM_CONSTANT_Invalid; }
|
public boolean isInvalid() { return tag == JVM_CONSTANT_Invalid; }
|
||||||
|
|
||||||
@ -73,6 +89,8 @@ public class ConstantTag {
|
|||||||
public boolean isUnresolvedString() { return tag == JVM_CONSTANT_UnresolvedString; }
|
public boolean isUnresolvedString() { return tag == JVM_CONSTANT_UnresolvedString; }
|
||||||
public boolean isStringIndex() { return tag == JVM_CONSTANT_StringIndex; }
|
public boolean isStringIndex() { return tag == JVM_CONSTANT_StringIndex; }
|
||||||
|
|
||||||
|
public boolean isObject() { return tag == JVM_CONSTANT_Object; }
|
||||||
|
|
||||||
public boolean isKlassReference() { return isKlassIndex() || isUnresolvedKlass(); }
|
public boolean isKlassReference() { return isKlassIndex() || isUnresolvedKlass(); }
|
||||||
public boolean isFieldOrMethod() { return isField() || isMethod() || isInterfaceMethod(); }
|
public boolean isFieldOrMethod() { return isField() || isMethod() || isInterfaceMethod(); }
|
||||||
public boolean isSymbol() { return isUtf8(); }
|
public boolean isSymbol() { return isUtf8(); }
|
||||||
|
@ -825,6 +825,8 @@ function jdis(method) {
|
|||||||
}
|
}
|
||||||
writeln("");
|
writeln("");
|
||||||
disAsm.decode(new sapkg.interpreter.BytecodeVisitor() {
|
disAsm.decode(new sapkg.interpreter.BytecodeVisitor() {
|
||||||
|
prologue: function(method) { },
|
||||||
|
epilogue: function() { },
|
||||||
visit: function(bytecode) {
|
visit: function(bytecode) {
|
||||||
if (hasLines) {
|
if (hasLines) {
|
||||||
var line = method.getLineNumberFromBCI(bci);
|
var line = method.getLineNumberFromBCI(bci);
|
||||||
|
@ -138,7 +138,11 @@ ADLCFLAGS += -q -T
|
|||||||
|
|
||||||
# Normally, debugging is done directly on the ad_<arch>*.cpp files.
|
# Normally, debugging is done directly on the ad_<arch>*.cpp files.
|
||||||
# But -g will put #line directives in those files pointing back to <arch>.ad.
|
# But -g will put #line directives in those files pointing back to <arch>.ad.
|
||||||
|
# Some builds of gcc 3.2 have a bug that gets tickled by the extra #line directives
|
||||||
|
# so skip it for 3.2 and ealier.
|
||||||
|
ifneq "$(shell expr \( $(CC_VER_MAJOR) \> 3 \) \| \( \( $(CC_VER_MAJOR) = 3 \) \& \( $(CC_VER_MINOR) \>= 3 \) \))" "0"
|
||||||
ADLCFLAGS += -g
|
ADLCFLAGS += -g
|
||||||
|
endif
|
||||||
|
|
||||||
ifdef LP64
|
ifdef LP64
|
||||||
ADLCFLAGS += -D_LP64
|
ADLCFLAGS += -D_LP64
|
||||||
|
@ -318,6 +318,31 @@ void TemplateTable::ldc(bool wide) {
|
|||||||
__ bind(exit);
|
__ bind(exit);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fast path for caching oop constants.
|
||||||
|
// %%% We should use this to handle Class and String constants also.
|
||||||
|
// %%% It will simplify the ldc/primitive path considerably.
|
||||||
|
void TemplateTable::fast_aldc(bool wide) {
|
||||||
|
transition(vtos, atos);
|
||||||
|
|
||||||
|
if (!EnableMethodHandles) {
|
||||||
|
// We should not encounter this bytecode if !EnableMethodHandles.
|
||||||
|
// The verifier will stop it. However, if we get past the verifier,
|
||||||
|
// this will stop the thread in a reasonable way, without crashing the JVM.
|
||||||
|
__ call_VM(noreg, CAST_FROM_FN_PTR(address,
|
||||||
|
InterpreterRuntime::throw_IncompatibleClassChangeError));
|
||||||
|
// the call_VM checks for exception, so we should never return here.
|
||||||
|
__ should_not_reach_here();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Register Rcache = G3_scratch;
|
||||||
|
Register Rscratch = G4_scratch;
|
||||||
|
|
||||||
|
resolve_cache_and_index(f1_oop, Otos_i, Rcache, Rscratch, wide ? sizeof(u2) : sizeof(u1));
|
||||||
|
|
||||||
|
__ verify_oop(Otos_i);
|
||||||
|
}
|
||||||
|
|
||||||
void TemplateTable::ldc2_w() {
|
void TemplateTable::ldc2_w() {
|
||||||
transition(vtos, vtos);
|
transition(vtos, vtos);
|
||||||
Label retry, resolved, Long, exit;
|
Label retry, resolved, Long, exit;
|
||||||
@ -1994,6 +2019,8 @@ void TemplateTable::resolve_cache_and_index(int byte_no,
|
|||||||
case Bytecodes::_invokestatic : // fall through
|
case Bytecodes::_invokestatic : // fall through
|
||||||
case Bytecodes::_invokeinterface: entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_invoke); break;
|
case Bytecodes::_invokeinterface: entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_invoke); break;
|
||||||
case Bytecodes::_invokedynamic : entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_invokedynamic); break;
|
case Bytecodes::_invokedynamic : entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_invokedynamic); break;
|
||||||
|
case Bytecodes::_fast_aldc : entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_ldc); break;
|
||||||
|
case Bytecodes::_fast_aldc_w : entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_ldc); break;
|
||||||
default : ShouldNotReachHere(); break;
|
default : ShouldNotReachHere(); break;
|
||||||
}
|
}
|
||||||
// first time invocation - must resolve first
|
// first time invocation - must resolve first
|
||||||
|
@ -375,6 +375,32 @@ void TemplateTable::ldc(bool wide) {
|
|||||||
__ bind(Done);
|
__ bind(Done);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fast path for caching oop constants.
|
||||||
|
// %%% We should use this to handle Class and String constants also.
|
||||||
|
// %%% It will simplify the ldc/primitive path considerably.
|
||||||
|
void TemplateTable::fast_aldc(bool wide) {
|
||||||
|
transition(vtos, atos);
|
||||||
|
|
||||||
|
if (!EnableMethodHandles) {
|
||||||
|
// We should not encounter this bytecode if !EnableMethodHandles.
|
||||||
|
// The verifier will stop it. However, if we get past the verifier,
|
||||||
|
// this will stop the thread in a reasonable way, without crashing the JVM.
|
||||||
|
__ call_VM(noreg, CAST_FROM_FN_PTR(address,
|
||||||
|
InterpreterRuntime::throw_IncompatibleClassChangeError));
|
||||||
|
// the call_VM checks for exception, so we should never return here.
|
||||||
|
__ should_not_reach_here();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Register cache = rcx;
|
||||||
|
const Register index = rdx;
|
||||||
|
|
||||||
|
resolve_cache_and_index(f1_oop, rax, cache, index, wide ? sizeof(u2) : sizeof(u1));
|
||||||
|
if (VerifyOops) {
|
||||||
|
__ verify_oop(rax);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void TemplateTable::ldc2_w() {
|
void TemplateTable::ldc2_w() {
|
||||||
transition(vtos, vtos);
|
transition(vtos, vtos);
|
||||||
Label Long, Done;
|
Label Long, Done;
|
||||||
@ -2055,6 +2081,8 @@ void TemplateTable::resolve_cache_and_index(int byte_no,
|
|||||||
case Bytecodes::_invokestatic : // fall through
|
case Bytecodes::_invokestatic : // fall through
|
||||||
case Bytecodes::_invokeinterface: entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_invoke); break;
|
case Bytecodes::_invokeinterface: entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_invoke); break;
|
||||||
case Bytecodes::_invokedynamic : entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_invokedynamic); break;
|
case Bytecodes::_invokedynamic : entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_invokedynamic); break;
|
||||||
|
case Bytecodes::_fast_aldc : entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_ldc); break;
|
||||||
|
case Bytecodes::_fast_aldc_w : entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_ldc); break;
|
||||||
default : ShouldNotReachHere(); break;
|
default : ShouldNotReachHere(); break;
|
||||||
}
|
}
|
||||||
__ movl(temp, (int)bytecode());
|
__ movl(temp, (int)bytecode());
|
||||||
|
@ -389,6 +389,32 @@ void TemplateTable::ldc(bool wide) {
|
|||||||
__ bind(Done);
|
__ bind(Done);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fast path for caching oop constants.
|
||||||
|
// %%% We should use this to handle Class and String constants also.
|
||||||
|
// %%% It will simplify the ldc/primitive path considerably.
|
||||||
|
void TemplateTable::fast_aldc(bool wide) {
|
||||||
|
transition(vtos, atos);
|
||||||
|
|
||||||
|
if (!EnableMethodHandles) {
|
||||||
|
// We should not encounter this bytecode if !EnableMethodHandles.
|
||||||
|
// The verifier will stop it. However, if we get past the verifier,
|
||||||
|
// this will stop the thread in a reasonable way, without crashing the JVM.
|
||||||
|
__ call_VM(noreg, CAST_FROM_FN_PTR(address,
|
||||||
|
InterpreterRuntime::throw_IncompatibleClassChangeError));
|
||||||
|
// the call_VM checks for exception, so we should never return here.
|
||||||
|
__ should_not_reach_here();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Register cache = rcx;
|
||||||
|
const Register index = rdx;
|
||||||
|
|
||||||
|
resolve_cache_and_index(f1_oop, rax, cache, index, wide ? sizeof(u2) : sizeof(u1));
|
||||||
|
if (VerifyOops) {
|
||||||
|
__ verify_oop(rax);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void TemplateTable::ldc2_w() {
|
void TemplateTable::ldc2_w() {
|
||||||
transition(vtos, vtos);
|
transition(vtos, vtos);
|
||||||
Label Long, Done;
|
Label Long, Done;
|
||||||
@ -2063,6 +2089,12 @@ void TemplateTable::resolve_cache_and_index(int byte_no,
|
|||||||
case Bytecodes::_invokedynamic:
|
case Bytecodes::_invokedynamic:
|
||||||
entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_invokedynamic);
|
entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_invokedynamic);
|
||||||
break;
|
break;
|
||||||
|
case Bytecodes::_fast_aldc:
|
||||||
|
entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_ldc);
|
||||||
|
break;
|
||||||
|
case Bytecodes::_fast_aldc_w:
|
||||||
|
entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_ldc);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
ShouldNotReachHere();
|
ShouldNotReachHere();
|
||||||
break;
|
break;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 1997, 2009, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1997, 2010, Oracle and/or its affiliates. All Rights Reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -34,7 +34,7 @@ const char* VM_Version::_features_str = "";
|
|||||||
VM_Version::CpuidInfo VM_Version::_cpuid_info = { 0, };
|
VM_Version::CpuidInfo VM_Version::_cpuid_info = { 0, };
|
||||||
|
|
||||||
static BufferBlob* stub_blob;
|
static BufferBlob* stub_blob;
|
||||||
static const int stub_size = 300;
|
static const int stub_size = 400;
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
typedef void (*getPsrInfo_stub_t)(void*);
|
typedef void (*getPsrInfo_stub_t)(void*);
|
||||||
@ -56,7 +56,7 @@ class VM_Version_StubGenerator: public StubCodeGenerator {
|
|||||||
const uint32_t CPU_FAMILY_386 = (3 << CPU_FAMILY_SHIFT);
|
const uint32_t CPU_FAMILY_386 = (3 << CPU_FAMILY_SHIFT);
|
||||||
const uint32_t CPU_FAMILY_486 = (4 << CPU_FAMILY_SHIFT);
|
const uint32_t CPU_FAMILY_486 = (4 << CPU_FAMILY_SHIFT);
|
||||||
|
|
||||||
Label detect_486, cpu486, detect_586, std_cpuid1;
|
Label detect_486, cpu486, detect_586, std_cpuid1, std_cpuid4;
|
||||||
Label ext_cpuid1, ext_cpuid5, done;
|
Label ext_cpuid1, ext_cpuid5, done;
|
||||||
|
|
||||||
StubCodeMark mark(this, "VM_Version", "getPsrInfo_stub");
|
StubCodeMark mark(this, "VM_Version", "getPsrInfo_stub");
|
||||||
@ -131,13 +131,62 @@ class VM_Version_StubGenerator: public StubCodeGenerator {
|
|||||||
__ movl(Address(rsi, 8), rcx);
|
__ movl(Address(rsi, 8), rcx);
|
||||||
__ movl(Address(rsi,12), rdx);
|
__ movl(Address(rsi,12), rdx);
|
||||||
|
|
||||||
__ cmpl(rax, 3); // Is cpuid(0x4) supported?
|
__ cmpl(rax, 0xa); // Is cpuid(0xB) supported?
|
||||||
__ jccb(Assembler::belowEqual, std_cpuid1);
|
__ jccb(Assembler::belowEqual, std_cpuid4);
|
||||||
|
|
||||||
|
//
|
||||||
|
// cpuid(0xB) Processor Topology
|
||||||
|
//
|
||||||
|
__ movl(rax, 0xb);
|
||||||
|
__ xorl(rcx, rcx); // Threads level
|
||||||
|
__ cpuid();
|
||||||
|
|
||||||
|
__ lea(rsi, Address(rbp, in_bytes(VM_Version::tpl_cpuidB0_offset())));
|
||||||
|
__ movl(Address(rsi, 0), rax);
|
||||||
|
__ movl(Address(rsi, 4), rbx);
|
||||||
|
__ movl(Address(rsi, 8), rcx);
|
||||||
|
__ movl(Address(rsi,12), rdx);
|
||||||
|
|
||||||
|
__ movl(rax, 0xb);
|
||||||
|
__ movl(rcx, 1); // Cores level
|
||||||
|
__ cpuid();
|
||||||
|
__ push(rax);
|
||||||
|
__ andl(rax, 0x1f); // Determine if valid topology level
|
||||||
|
__ orl(rax, rbx); // eax[4:0] | ebx[0:15] == 0 indicates invalid level
|
||||||
|
__ andl(rax, 0xffff);
|
||||||
|
__ pop(rax);
|
||||||
|
__ jccb(Assembler::equal, std_cpuid4);
|
||||||
|
|
||||||
|
__ lea(rsi, Address(rbp, in_bytes(VM_Version::tpl_cpuidB1_offset())));
|
||||||
|
__ movl(Address(rsi, 0), rax);
|
||||||
|
__ movl(Address(rsi, 4), rbx);
|
||||||
|
__ movl(Address(rsi, 8), rcx);
|
||||||
|
__ movl(Address(rsi,12), rdx);
|
||||||
|
|
||||||
|
__ movl(rax, 0xb);
|
||||||
|
__ movl(rcx, 2); // Packages level
|
||||||
|
__ cpuid();
|
||||||
|
__ push(rax);
|
||||||
|
__ andl(rax, 0x1f); // Determine if valid topology level
|
||||||
|
__ orl(rax, rbx); // eax[4:0] | ebx[0:15] == 0 indicates invalid level
|
||||||
|
__ andl(rax, 0xffff);
|
||||||
|
__ pop(rax);
|
||||||
|
__ jccb(Assembler::equal, std_cpuid4);
|
||||||
|
|
||||||
|
__ lea(rsi, Address(rbp, in_bytes(VM_Version::tpl_cpuidB2_offset())));
|
||||||
|
__ movl(Address(rsi, 0), rax);
|
||||||
|
__ movl(Address(rsi, 4), rbx);
|
||||||
|
__ movl(Address(rsi, 8), rcx);
|
||||||
|
__ movl(Address(rsi,12), rdx);
|
||||||
|
|
||||||
//
|
//
|
||||||
// cpuid(0x4) Deterministic cache params
|
// cpuid(0x4) Deterministic cache params
|
||||||
//
|
//
|
||||||
|
__ bind(std_cpuid4);
|
||||||
__ movl(rax, 4);
|
__ movl(rax, 4);
|
||||||
|
__ cmpl(rax, Address(rbp, in_bytes(VM_Version::std_cpuid0_offset()))); // Is cpuid(0x4) supported?
|
||||||
|
__ jccb(Assembler::greater, std_cpuid1);
|
||||||
|
|
||||||
__ xorl(rcx, rcx); // L1 cache
|
__ xorl(rcx, rcx); // L1 cache
|
||||||
__ cpuid();
|
__ cpuid();
|
||||||
__ push(rax);
|
__ push(rax);
|
||||||
@ -460,13 +509,18 @@ void VM_Version::get_processor_features() {
|
|||||||
AllocatePrefetchDistance = allocate_prefetch_distance();
|
AllocatePrefetchDistance = allocate_prefetch_distance();
|
||||||
AllocatePrefetchStyle = allocate_prefetch_style();
|
AllocatePrefetchStyle = allocate_prefetch_style();
|
||||||
|
|
||||||
if( AllocatePrefetchStyle == 2 && is_intel() &&
|
if( is_intel() && cpu_family() == 6 && supports_sse3() ) {
|
||||||
cpu_family() == 6 && supports_sse3() ) { // watermark prefetching on Core
|
if( AllocatePrefetchStyle == 2 ) { // watermark prefetching on Core
|
||||||
#ifdef _LP64
|
#ifdef _LP64
|
||||||
AllocatePrefetchDistance = 384;
|
AllocatePrefetchDistance = 384;
|
||||||
#else
|
#else
|
||||||
AllocatePrefetchDistance = 320;
|
AllocatePrefetchDistance = 320;
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
|
if( supports_sse4_2() && supports_ht() ) { // Nehalem based cpus
|
||||||
|
AllocatePrefetchDistance = 192;
|
||||||
|
AllocatePrefetchLines = 4;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
assert(AllocatePrefetchDistance % AllocatePrefetchStepSize == 0, "invalid value");
|
assert(AllocatePrefetchDistance % AllocatePrefetchStepSize == 0, "invalid value");
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 1997, 2009, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1997, 2010, Oracle and/or its affiliates. All Rights Reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -114,6 +114,14 @@ public:
|
|||||||
} bits;
|
} bits;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
union TplCpuidBEbx {
|
||||||
|
uint32_t value;
|
||||||
|
struct {
|
||||||
|
uint32_t logical_cpus : 16,
|
||||||
|
: 16;
|
||||||
|
} bits;
|
||||||
|
};
|
||||||
|
|
||||||
union ExtCpuid1Ecx {
|
union ExtCpuid1Ecx {
|
||||||
uint32_t value;
|
uint32_t value;
|
||||||
struct {
|
struct {
|
||||||
@ -211,6 +219,25 @@ protected:
|
|||||||
uint32_t dcp_cpuid4_ecx; // unused currently
|
uint32_t dcp_cpuid4_ecx; // unused currently
|
||||||
uint32_t dcp_cpuid4_edx; // unused currently
|
uint32_t dcp_cpuid4_edx; // unused currently
|
||||||
|
|
||||||
|
// cpuid function 0xB (processor topology)
|
||||||
|
// ecx = 0
|
||||||
|
uint32_t tpl_cpuidB0_eax;
|
||||||
|
TplCpuidBEbx tpl_cpuidB0_ebx;
|
||||||
|
uint32_t tpl_cpuidB0_ecx; // unused currently
|
||||||
|
uint32_t tpl_cpuidB0_edx; // unused currently
|
||||||
|
|
||||||
|
// ecx = 1
|
||||||
|
uint32_t tpl_cpuidB1_eax;
|
||||||
|
TplCpuidBEbx tpl_cpuidB1_ebx;
|
||||||
|
uint32_t tpl_cpuidB1_ecx; // unused currently
|
||||||
|
uint32_t tpl_cpuidB1_edx; // unused currently
|
||||||
|
|
||||||
|
// ecx = 2
|
||||||
|
uint32_t tpl_cpuidB2_eax;
|
||||||
|
TplCpuidBEbx tpl_cpuidB2_ebx;
|
||||||
|
uint32_t tpl_cpuidB2_ecx; // unused currently
|
||||||
|
uint32_t tpl_cpuidB2_edx; // unused currently
|
||||||
|
|
||||||
// cpuid function 0x80000000 // example, unused
|
// cpuid function 0x80000000 // example, unused
|
||||||
uint32_t ext_max_function;
|
uint32_t ext_max_function;
|
||||||
uint32_t ext_vendor_name_0;
|
uint32_t ext_vendor_name_0;
|
||||||
@ -316,6 +343,9 @@ public:
|
|||||||
static ByteSize ext_cpuid1_offset() { return byte_offset_of(CpuidInfo, ext_cpuid1_eax); }
|
static ByteSize ext_cpuid1_offset() { return byte_offset_of(CpuidInfo, ext_cpuid1_eax); }
|
||||||
static ByteSize ext_cpuid5_offset() { return byte_offset_of(CpuidInfo, ext_cpuid5_eax); }
|
static ByteSize ext_cpuid5_offset() { return byte_offset_of(CpuidInfo, ext_cpuid5_eax); }
|
||||||
static ByteSize ext_cpuid8_offset() { return byte_offset_of(CpuidInfo, ext_cpuid8_eax); }
|
static ByteSize ext_cpuid8_offset() { return byte_offset_of(CpuidInfo, ext_cpuid8_eax); }
|
||||||
|
static ByteSize tpl_cpuidB0_offset() { return byte_offset_of(CpuidInfo, tpl_cpuidB0_eax); }
|
||||||
|
static ByteSize tpl_cpuidB1_offset() { return byte_offset_of(CpuidInfo, tpl_cpuidB1_eax); }
|
||||||
|
static ByteSize tpl_cpuidB2_offset() { return byte_offset_of(CpuidInfo, tpl_cpuidB2_eax); }
|
||||||
|
|
||||||
// Initialization
|
// Initialization
|
||||||
static void initialize();
|
static void initialize();
|
||||||
@ -349,7 +379,12 @@ public:
|
|||||||
static uint cores_per_cpu() {
|
static uint cores_per_cpu() {
|
||||||
uint result = 1;
|
uint result = 1;
|
||||||
if (is_intel()) {
|
if (is_intel()) {
|
||||||
result = (_cpuid_info.dcp_cpuid4_eax.bits.cores_per_cpu + 1);
|
if (_cpuid_info.std_max_function >= 0xB) {
|
||||||
|
result = _cpuid_info.tpl_cpuidB1_ebx.bits.logical_cpus /
|
||||||
|
_cpuid_info.tpl_cpuidB0_ebx.bits.logical_cpus;
|
||||||
|
} else {
|
||||||
|
result = (_cpuid_info.dcp_cpuid4_eax.bits.cores_per_cpu + 1);
|
||||||
|
}
|
||||||
} else if (is_amd()) {
|
} else if (is_amd()) {
|
||||||
result = (_cpuid_info.ext_cpuid8_ecx.bits.cores_per_cpu + 1);
|
result = (_cpuid_info.ext_cpuid8_ecx.bits.cores_per_cpu + 1);
|
||||||
}
|
}
|
||||||
@ -358,7 +393,9 @@ public:
|
|||||||
|
|
||||||
static uint threads_per_core() {
|
static uint threads_per_core() {
|
||||||
uint result = 1;
|
uint result = 1;
|
||||||
if (_cpuid_info.std_cpuid1_edx.bits.ht != 0) {
|
if (is_intel() && _cpuid_info.std_max_function >= 0xB) {
|
||||||
|
result = _cpuid_info.tpl_cpuidB0_ebx.bits.logical_cpus;
|
||||||
|
} else if (_cpuid_info.std_cpuid1_edx.bits.ht != 0) {
|
||||||
result = _cpuid_info.std_cpuid1_ebx.bits.threads_per_cpu /
|
result = _cpuid_info.std_cpuid1_ebx.bits.threads_per_cpu /
|
||||||
cores_per_cpu();
|
cores_per_cpu();
|
||||||
}
|
}
|
||||||
|
@ -820,7 +820,7 @@ int AbstractInterpreter::layout_activation(methodOop method,
|
|||||||
bool is_top_frame) {
|
bool is_top_frame) {
|
||||||
assert(popframe_extra_args == 0, "what to do?");
|
assert(popframe_extra_args == 0, "what to do?");
|
||||||
assert(!is_top_frame || (!callee_locals && !callee_param_count),
|
assert(!is_top_frame || (!callee_locals && !callee_param_count),
|
||||||
"top frame should have no caller")
|
"top frame should have no caller");
|
||||||
|
|
||||||
// This code must exactly match what InterpreterFrame::build
|
// This code must exactly match what InterpreterFrame::build
|
||||||
// does (the full InterpreterFrame::build, that is, not the
|
// does (the full InterpreterFrame::build, that is, not the
|
||||||
|
@ -123,7 +123,7 @@
|
|||||||
|
|
||||||
int set_interrupt_callback (Sync_Interrupt_Callback * cb);
|
int set_interrupt_callback (Sync_Interrupt_Callback * cb);
|
||||||
void remove_interrupt_callback(Sync_Interrupt_Callback * cb);
|
void remove_interrupt_callback(Sync_Interrupt_Callback * cb);
|
||||||
void OSThread::do_interrupt_callbacks_at_interrupt(InterruptArguments *args);
|
void do_interrupt_callbacks_at_interrupt(InterruptArguments *args);
|
||||||
|
|
||||||
// ***************************************************************
|
// ***************************************************************
|
||||||
// java.lang.Thread.interrupt state.
|
// java.lang.Thread.interrupt state.
|
||||||
|
@ -26,7 +26,7 @@ static void pd_conjoint_words(HeapWord* from, HeapWord* to, size_t count) {
|
|||||||
#ifdef AMD64
|
#ifdef AMD64
|
||||||
(void)memmove(to, from, count * HeapWordSize);
|
(void)memmove(to, from, count * HeapWordSize);
|
||||||
#else
|
#else
|
||||||
// Same as pd_aligned_conjoint_words, except includes a zero-count check.
|
// Includes a zero-count check.
|
||||||
intx temp;
|
intx temp;
|
||||||
__asm__ volatile(" testl %6,%6 ;"
|
__asm__ volatile(" testl %6,%6 ;"
|
||||||
" jz 7f ;"
|
" jz 7f ;"
|
||||||
@ -84,7 +84,7 @@ static void pd_disjoint_words(HeapWord* from, HeapWord* to, size_t count) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
// Same as pd_aligned_disjoint_words, except includes a zero-count check.
|
// Includes a zero-count check.
|
||||||
intx temp;
|
intx temp;
|
||||||
__asm__ volatile(" testl %6,%6 ;"
|
__asm__ volatile(" testl %6,%6 ;"
|
||||||
" jz 3f ;"
|
" jz 3f ;"
|
||||||
@ -130,75 +130,18 @@ static void pd_disjoint_words_atomic(HeapWord* from, HeapWord* to, size_t count)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void pd_aligned_conjoint_words(HeapWord* from, HeapWord* to, size_t count) {
|
static void pd_aligned_conjoint_words(HeapWord* from, HeapWord* to, size_t count) {
|
||||||
#ifdef AMD64
|
pd_conjoint_words(from, to, count);
|
||||||
(void)memmove(to, from, count * HeapWordSize);
|
|
||||||
#else
|
|
||||||
// Same as pd_conjoint_words, except no zero-count check.
|
|
||||||
intx temp;
|
|
||||||
__asm__ volatile(" cmpl %4,%5 ;"
|
|
||||||
" leal -4(%4,%6,4),%3;"
|
|
||||||
" jbe 1f ;"
|
|
||||||
" cmpl %7,%5 ;"
|
|
||||||
" jbe 4f ;"
|
|
||||||
"1: cmpl $32,%6 ;"
|
|
||||||
" ja 3f ;"
|
|
||||||
" subl %4,%1 ;"
|
|
||||||
"2: movl (%4),%3 ;"
|
|
||||||
" movl %7,(%5,%4,1) ;"
|
|
||||||
" addl $4,%0 ;"
|
|
||||||
" subl $1,%2 ;"
|
|
||||||
" jnz 2b ;"
|
|
||||||
" jmp 7f ;"
|
|
||||||
"3: rep; smovl ;"
|
|
||||||
" jmp 7f ;"
|
|
||||||
"4: cmpl $32,%2 ;"
|
|
||||||
" movl %7,%0 ;"
|
|
||||||
" leal -4(%5,%6,4),%1;"
|
|
||||||
" ja 6f ;"
|
|
||||||
" subl %4,%1 ;"
|
|
||||||
"5: movl (%4),%3 ;"
|
|
||||||
" movl %7,(%5,%4,1) ;"
|
|
||||||
" subl $4,%0 ;"
|
|
||||||
" subl $1,%2 ;"
|
|
||||||
" jnz 5b ;"
|
|
||||||
" jmp 7f ;"
|
|
||||||
"6: std ;"
|
|
||||||
" rep; smovl ;"
|
|
||||||
" cld ;"
|
|
||||||
"7: nop "
|
|
||||||
: "=S" (from), "=D" (to), "=c" (count), "=r" (temp)
|
|
||||||
: "0" (from), "1" (to), "2" (count), "3" (temp)
|
|
||||||
: "memory", "flags");
|
|
||||||
#endif // AMD64
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pd_aligned_disjoint_words(HeapWord* from, HeapWord* to, size_t count) {
|
static void pd_aligned_disjoint_words(HeapWord* from, HeapWord* to, size_t count) {
|
||||||
#ifdef AMD64
|
|
||||||
pd_disjoint_words(from, to, count);
|
pd_disjoint_words(from, to, count);
|
||||||
#else
|
|
||||||
// Same as pd_disjoint_words, except no zero-count check.
|
|
||||||
intx temp;
|
|
||||||
__asm__ volatile(" cmpl $32,%6 ;"
|
|
||||||
" ja 2f ;"
|
|
||||||
" subl %4,%1 ;"
|
|
||||||
"1: movl (%4),%3 ;"
|
|
||||||
" movl %7,(%5,%4,1);"
|
|
||||||
" addl $4,%0 ;"
|
|
||||||
" subl $1,%2 ;"
|
|
||||||
" jnz 1b ;"
|
|
||||||
" jmp 3f ;"
|
|
||||||
"2: rep; smovl ;"
|
|
||||||
"3: nop "
|
|
||||||
: "=S" (from), "=D" (to), "=c" (count), "=r" (temp)
|
|
||||||
: "0" (from), "1" (to), "2" (count), "3" (temp)
|
|
||||||
: "memory", "cc");
|
|
||||||
#endif // AMD64
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pd_conjoint_bytes(void* from, void* to, size_t count) {
|
static void pd_conjoint_bytes(void* from, void* to, size_t count) {
|
||||||
#ifdef AMD64
|
#ifdef AMD64
|
||||||
(void)memmove(to, from, count);
|
(void)memmove(to, from, count);
|
||||||
#else
|
#else
|
||||||
|
// Includes a zero-count check.
|
||||||
intx temp;
|
intx temp;
|
||||||
__asm__ volatile(" testl %6,%6 ;"
|
__asm__ volatile(" testl %6,%6 ;"
|
||||||
" jz 13f ;"
|
" jz 13f ;"
|
||||||
|
@ -121,10 +121,10 @@ cb_CopyRight:
|
|||||||
jnz 3b
|
jnz 3b
|
||||||
addl %esi,%edi
|
addl %esi,%edi
|
||||||
4: movl %eax,%ecx # byte count less prefix
|
4: movl %eax,%ecx # byte count less prefix
|
||||||
andl $3,%ecx # suffix byte count
|
5: andl $3,%ecx # suffix byte count
|
||||||
jz 7f # no suffix
|
jz 7f # no suffix
|
||||||
# copy suffix
|
# copy suffix
|
||||||
5: xorl %eax,%eax
|
xorl %eax,%eax
|
||||||
6: movb (%esi,%eax,1),%dl
|
6: movb (%esi,%eax,1),%dl
|
||||||
movb %dl,(%edi,%eax,1)
|
movb %dl,(%edi,%eax,1)
|
||||||
addl $1,%eax
|
addl $1,%eax
|
||||||
@ -159,10 +159,10 @@ cb_CopyLeft:
|
|||||||
# copy dwords, aligned or not
|
# copy dwords, aligned or not
|
||||||
3: rep; smovl
|
3: rep; smovl
|
||||||
4: movl %eax,%ecx # byte count
|
4: movl %eax,%ecx # byte count
|
||||||
andl $3,%ecx # suffix byte count
|
5: andl $3,%ecx # suffix byte count
|
||||||
jz 7f # no suffix
|
jz 7f # no suffix
|
||||||
# copy suffix
|
# copy suffix
|
||||||
5: subl %esi,%edi
|
subl %esi,%edi
|
||||||
addl $3,%esi
|
addl $3,%esi
|
||||||
6: movb (%esi),%dl
|
6: movb (%esi),%dl
|
||||||
movb %dl,(%edi,%esi,1)
|
movb %dl,(%edi,%esi,1)
|
||||||
@ -214,10 +214,10 @@ acb_CopyRight:
|
|||||||
# copy aligned dwords
|
# copy aligned dwords
|
||||||
3: rep; smovl
|
3: rep; smovl
|
||||||
4: movl %eax,%ecx
|
4: movl %eax,%ecx
|
||||||
andl $3,%ecx
|
5: andl $3,%ecx
|
||||||
jz 7f
|
jz 7f
|
||||||
# copy suffix
|
# copy suffix
|
||||||
5: xorl %eax,%eax
|
xorl %eax,%eax
|
||||||
6: movb (%esi,%eax,1),%dl
|
6: movb (%esi,%eax,1),%dl
|
||||||
movb %dl,(%edi,%eax,1)
|
movb %dl,(%edi,%eax,1)
|
||||||
addl $1,%eax
|
addl $1,%eax
|
||||||
@ -250,9 +250,9 @@ acb_CopyLeft:
|
|||||||
jnz 3b
|
jnz 3b
|
||||||
addl %esi,%edi
|
addl %esi,%edi
|
||||||
4: movl %eax,%ecx
|
4: movl %eax,%ecx
|
||||||
andl $3,%ecx
|
5: andl $3,%ecx
|
||||||
jz 7f
|
jz 7f
|
||||||
5: subl %esi,%edi
|
subl %esi,%edi
|
||||||
addl $3,%esi
|
addl $3,%esi
|
||||||
6: movb (%esi),%dl
|
6: movb (%esi),%dl
|
||||||
movb %dl,(%edi,%esi,1)
|
movb %dl,(%edi,%esi,1)
|
||||||
@ -287,11 +287,12 @@ cs_CopyRight:
|
|||||||
andl $3,%eax # either 0 or 2
|
andl $3,%eax # either 0 or 2
|
||||||
jz 1f # no prefix
|
jz 1f # no prefix
|
||||||
# copy prefix
|
# copy prefix
|
||||||
|
subl $1,%ecx
|
||||||
|
jl 5f # zero count
|
||||||
movw (%esi),%dx
|
movw (%esi),%dx
|
||||||
movw %dx,(%edi)
|
movw %dx,(%edi)
|
||||||
addl %eax,%esi # %eax == 2
|
addl %eax,%esi # %eax == 2
|
||||||
addl %eax,%edi
|
addl %eax,%edi
|
||||||
subl $1,%ecx
|
|
||||||
1: movl %ecx,%eax # word count less prefix
|
1: movl %ecx,%eax # word count less prefix
|
||||||
sarl %ecx # dword count
|
sarl %ecx # dword count
|
||||||
jz 4f # no dwords to move
|
jz 4f # no dwords to move
|
||||||
@ -454,12 +455,13 @@ ci_CopyRight:
|
|||||||
ret
|
ret
|
||||||
.=.+10
|
.=.+10
|
||||||
2: subl %esi,%edi
|
2: subl %esi,%edi
|
||||||
|
jmp 4f
|
||||||
.p2align 4,,15
|
.p2align 4,,15
|
||||||
3: movl (%esi),%edx
|
3: movl (%esi),%edx
|
||||||
movl %edx,(%edi,%esi,1)
|
movl %edx,(%edi,%esi,1)
|
||||||
addl $4,%esi
|
addl $4,%esi
|
||||||
subl $1,%ecx
|
4: subl $1,%ecx
|
||||||
jnz 3b
|
jge 3b
|
||||||
popl %edi
|
popl %edi
|
||||||
popl %esi
|
popl %esi
|
||||||
ret
|
ret
|
||||||
@ -467,19 +469,20 @@ ci_CopyLeft:
|
|||||||
std
|
std
|
||||||
leal -4(%edi,%ecx,4),%edi # to + count*4 - 4
|
leal -4(%edi,%ecx,4),%edi # to + count*4 - 4
|
||||||
cmpl $32,%ecx
|
cmpl $32,%ecx
|
||||||
ja 3f # > 32 dwords
|
ja 4f # > 32 dwords
|
||||||
subl %eax,%edi # eax == from + count*4 - 4
|
subl %eax,%edi # eax == from + count*4 - 4
|
||||||
|
jmp 3f
|
||||||
.p2align 4,,15
|
.p2align 4,,15
|
||||||
2: movl (%eax),%edx
|
2: movl (%eax),%edx
|
||||||
movl %edx,(%edi,%eax,1)
|
movl %edx,(%edi,%eax,1)
|
||||||
subl $4,%eax
|
subl $4,%eax
|
||||||
subl $1,%ecx
|
3: subl $1,%ecx
|
||||||
jnz 2b
|
jge 2b
|
||||||
cld
|
cld
|
||||||
popl %edi
|
popl %edi
|
||||||
popl %esi
|
popl %esi
|
||||||
ret
|
ret
|
||||||
3: movl %eax,%esi # from + count*4 - 4
|
4: movl %eax,%esi # from + count*4 - 4
|
||||||
rep; smovl
|
rep; smovl
|
||||||
cld
|
cld
|
||||||
popl %edi
|
popl %edi
|
||||||
|
@ -861,7 +861,7 @@ cmpxchg_func_t* os::atomic_cmpxchg_func = os::atomic_cmpxchg_bootstrap
|
|||||||
cmpxchg_long_func_t* os::atomic_cmpxchg_long_func = os::atomic_cmpxchg_long_bootstrap;
|
cmpxchg_long_func_t* os::atomic_cmpxchg_long_func = os::atomic_cmpxchg_long_bootstrap;
|
||||||
add_func_t* os::atomic_add_func = os::atomic_add_bootstrap;
|
add_func_t* os::atomic_add_func = os::atomic_add_bootstrap;
|
||||||
|
|
||||||
extern "C" _solaris_raw_setup_fpu(address ptr);
|
extern "C" void _solaris_raw_setup_fpu(address ptr);
|
||||||
void os::setup_fpu() {
|
void os::setup_fpu() {
|
||||||
address fpu_cntrl = StubRoutines::addr_fpu_cntrl_wrd_std();
|
address fpu_cntrl = StubRoutines::addr_fpu_cntrl_wrd_std();
|
||||||
_solaris_raw_setup_fpu(fpu_cntrl);
|
_solaris_raw_setup_fpu(fpu_cntrl);
|
||||||
|
@ -154,10 +154,10 @@ cb_CopyRight:
|
|||||||
jnz 3b
|
jnz 3b
|
||||||
addl %esi,%edi
|
addl %esi,%edi
|
||||||
4: movl %eax,%ecx / byte count less prefix
|
4: movl %eax,%ecx / byte count less prefix
|
||||||
andl $3,%ecx / suffix byte count
|
5: andl $3,%ecx / suffix byte count
|
||||||
jz 7f / no suffix
|
jz 7f / no suffix
|
||||||
/ copy suffix
|
/ copy suffix
|
||||||
5: xorl %eax,%eax
|
xorl %eax,%eax
|
||||||
6: movb (%esi,%eax,1),%dl
|
6: movb (%esi,%eax,1),%dl
|
||||||
movb %dl,(%edi,%eax,1)
|
movb %dl,(%edi,%eax,1)
|
||||||
addl $1,%eax
|
addl $1,%eax
|
||||||
@ -192,10 +192,10 @@ cb_CopyLeft:
|
|||||||
/ copy dwords, aligned or not
|
/ copy dwords, aligned or not
|
||||||
3: rep; smovl
|
3: rep; smovl
|
||||||
4: movl %eax,%ecx / byte count
|
4: movl %eax,%ecx / byte count
|
||||||
andl $3,%ecx / suffix byte count
|
5: andl $3,%ecx / suffix byte count
|
||||||
jz 7f / no suffix
|
jz 7f / no suffix
|
||||||
/ copy suffix
|
/ copy suffix
|
||||||
5: subl %esi,%edi
|
subl %esi,%edi
|
||||||
addl $3,%esi
|
addl $3,%esi
|
||||||
6: movb (%esi),%dl
|
6: movb (%esi),%dl
|
||||||
movb %dl,(%edi,%esi,1)
|
movb %dl,(%edi,%esi,1)
|
||||||
@ -246,10 +246,10 @@ acb_CopyRight:
|
|||||||
/ copy aligned dwords
|
/ copy aligned dwords
|
||||||
3: rep; smovl
|
3: rep; smovl
|
||||||
4: movl %eax,%ecx
|
4: movl %eax,%ecx
|
||||||
andl $3,%ecx
|
5: andl $3,%ecx
|
||||||
jz 7f
|
jz 7f
|
||||||
/ copy suffix
|
/ copy suffix
|
||||||
5: xorl %eax,%eax
|
xorl %eax,%eax
|
||||||
6: movb (%esi,%eax,1),%dl
|
6: movb (%esi,%eax,1),%dl
|
||||||
movb %dl,(%edi,%eax,1)
|
movb %dl,(%edi,%eax,1)
|
||||||
addl $1,%eax
|
addl $1,%eax
|
||||||
@ -282,9 +282,9 @@ acb_CopyLeft:
|
|||||||
jnz 3b
|
jnz 3b
|
||||||
addl %esi,%edi
|
addl %esi,%edi
|
||||||
4: movl %eax,%ecx
|
4: movl %eax,%ecx
|
||||||
andl $3,%ecx
|
5: andl $3,%ecx
|
||||||
jz 7f
|
jz 7f
|
||||||
5: subl %esi,%edi
|
subl %esi,%edi
|
||||||
addl $3,%esi
|
addl $3,%esi
|
||||||
6: movb (%esi),%dl
|
6: movb (%esi),%dl
|
||||||
movb %dl,(%edi,%esi,1)
|
movb %dl,(%edi,%esi,1)
|
||||||
@ -318,11 +318,12 @@ cs_CopyRight:
|
|||||||
andl $3,%eax / either 0 or 2
|
andl $3,%eax / either 0 or 2
|
||||||
jz 1f / no prefix
|
jz 1f / no prefix
|
||||||
/ copy prefix
|
/ copy prefix
|
||||||
|
subl $1,%ecx
|
||||||
|
jl 5f / zero count
|
||||||
movw (%esi),%dx
|
movw (%esi),%dx
|
||||||
movw %dx,(%edi)
|
movw %dx,(%edi)
|
||||||
addl %eax,%esi / %eax == 2
|
addl %eax,%esi / %eax == 2
|
||||||
addl %eax,%edi
|
addl %eax,%edi
|
||||||
subl $1,%ecx
|
|
||||||
1: movl %ecx,%eax / word count less prefix
|
1: movl %ecx,%eax / word count less prefix
|
||||||
sarl %ecx / dword count
|
sarl %ecx / dword count
|
||||||
jz 4f / no dwords to move
|
jz 4f / no dwords to move
|
||||||
@ -482,12 +483,13 @@ ci_CopyRight:
|
|||||||
ret
|
ret
|
||||||
.=.+10
|
.=.+10
|
||||||
2: subl %esi,%edi
|
2: subl %esi,%edi
|
||||||
|
jmp 4f
|
||||||
.align 16
|
.align 16
|
||||||
3: movl (%esi),%edx
|
3: movl (%esi),%edx
|
||||||
movl %edx,(%edi,%esi,1)
|
movl %edx,(%edi,%esi,1)
|
||||||
addl $4,%esi
|
addl $4,%esi
|
||||||
subl $1,%ecx
|
4: subl $1,%ecx
|
||||||
jnz 3b
|
jge 3b
|
||||||
popl %edi
|
popl %edi
|
||||||
popl %esi
|
popl %esi
|
||||||
ret
|
ret
|
||||||
@ -495,19 +497,20 @@ ci_CopyLeft:
|
|||||||
std
|
std
|
||||||
leal -4(%edi,%ecx,4),%edi / to + count*4 - 4
|
leal -4(%edi,%ecx,4),%edi / to + count*4 - 4
|
||||||
cmpl $32,%ecx
|
cmpl $32,%ecx
|
||||||
ja 3f / > 32 dwords
|
ja 4f / > 32 dwords
|
||||||
subl %eax,%edi / eax == from + count*4 - 4
|
subl %eax,%edi / eax == from + count*4 - 4
|
||||||
|
jmp 3f
|
||||||
.align 16
|
.align 16
|
||||||
2: movl (%eax),%edx
|
2: movl (%eax),%edx
|
||||||
movl %edx,(%edi,%eax,1)
|
movl %edx,(%edi,%eax,1)
|
||||||
subl $4,%eax
|
subl $4,%eax
|
||||||
subl $1,%ecx
|
3: subl $1,%ecx
|
||||||
jnz 2b
|
jge 2b
|
||||||
cld
|
cld
|
||||||
popl %edi
|
popl %edi
|
||||||
popl %esi
|
popl %esi
|
||||||
ret
|
ret
|
||||||
3: movl %eax,%esi / from + count*4 - 4
|
4: movl %eax,%esi / from + count*4 - 4
|
||||||
rep; smovl
|
rep; smovl
|
||||||
cld
|
cld
|
||||||
popl %edi
|
popl %edi
|
||||||
|
@ -404,7 +404,7 @@ void CodeSection::expand_locs(int new_capacity) {
|
|||||||
locs_start = REALLOC_RESOURCE_ARRAY(relocInfo, _locs_start, old_capacity, new_capacity);
|
locs_start = REALLOC_RESOURCE_ARRAY(relocInfo, _locs_start, old_capacity, new_capacity);
|
||||||
} else {
|
} else {
|
||||||
locs_start = NEW_RESOURCE_ARRAY(relocInfo, new_capacity);
|
locs_start = NEW_RESOURCE_ARRAY(relocInfo, new_capacity);
|
||||||
Copy::conjoint_bytes(_locs_start, locs_start, old_capacity * sizeof(relocInfo));
|
Copy::conjoint_jbytes(_locs_start, locs_start, old_capacity * sizeof(relocInfo));
|
||||||
_locs_own = true;
|
_locs_own = true;
|
||||||
}
|
}
|
||||||
_locs_start = locs_start;
|
_locs_start = locs_start;
|
||||||
@ -581,7 +581,7 @@ csize_t CodeBuffer::copy_relocations_to(CodeBlob* dest) const {
|
|||||||
(HeapWord*)(buf+buf_offset),
|
(HeapWord*)(buf+buf_offset),
|
||||||
(lsize + HeapWordSize-1) / HeapWordSize);
|
(lsize + HeapWordSize-1) / HeapWordSize);
|
||||||
} else {
|
} else {
|
||||||
Copy::conjoint_bytes(lstart, buf+buf_offset, lsize);
|
Copy::conjoint_jbytes(lstart, buf+buf_offset, lsize);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
buf_offset += lsize;
|
buf_offset += lsize;
|
||||||
|
@ -242,10 +242,10 @@ void Compilation::setup_code_buffer(CodeBuffer* code, int call_stub_estimate) {
|
|||||||
code->insts()->initialize_shared_locs((relocInfo*)locs_buffer,
|
code->insts()->initialize_shared_locs((relocInfo*)locs_buffer,
|
||||||
locs_buffer_size / sizeof(relocInfo));
|
locs_buffer_size / sizeof(relocInfo));
|
||||||
code->initialize_consts_size(Compilation::desired_max_constant_size());
|
code->initialize_consts_size(Compilation::desired_max_constant_size());
|
||||||
// Call stubs + deopt/exception handler
|
// Call stubs + two deopt handlers (regular and MH) + exception handler
|
||||||
code->initialize_stubs_size((call_stub_estimate * LIR_Assembler::call_stub_size) +
|
code->initialize_stubs_size((call_stub_estimate * LIR_Assembler::call_stub_size) +
|
||||||
LIR_Assembler::exception_handler_size +
|
LIR_Assembler::exception_handler_size +
|
||||||
LIR_Assembler::deopt_handler_size);
|
2 * LIR_Assembler::deopt_handler_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -878,15 +878,12 @@ void GraphBuilder::load_constant() {
|
|||||||
case T_OBJECT :
|
case T_OBJECT :
|
||||||
{
|
{
|
||||||
ciObject* obj = con.as_object();
|
ciObject* obj = con.as_object();
|
||||||
if (obj->is_klass()) {
|
if (!obj->is_loaded()
|
||||||
ciKlass* klass = obj->as_klass();
|
|| (PatchALot && obj->klass() != ciEnv::current()->String_klass())) {
|
||||||
if (!klass->is_loaded() || PatchALot) {
|
patch_state = state()->copy();
|
||||||
patch_state = state()->copy();
|
t = new ObjectConstant(obj);
|
||||||
t = new ObjectConstant(obj);
|
|
||||||
} else {
|
|
||||||
t = new InstanceConstant(klass->java_mirror());
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
|
assert(!obj->is_klass(), "must be java_mirror of klass");
|
||||||
t = new InstanceConstant(obj->as_instance());
|
t = new InstanceConstant(obj->as_instance());
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -601,7 +601,7 @@ JRT_END
|
|||||||
|
|
||||||
|
|
||||||
static klassOop resolve_field_return_klass(methodHandle caller, int bci, TRAPS) {
|
static klassOop resolve_field_return_klass(methodHandle caller, int bci, TRAPS) {
|
||||||
Bytecode_field* field_access = Bytecode_field_at(caller(), caller->bcp_from(bci));
|
Bytecode_field* field_access = Bytecode_field_at(caller, bci);
|
||||||
// This can be static or non-static field access
|
// This can be static or non-static field access
|
||||||
Bytecodes::Code code = field_access->code();
|
Bytecodes::Code code = field_access->code();
|
||||||
|
|
||||||
@ -721,7 +721,7 @@ JRT_ENTRY(void, Runtime1::patch_code(JavaThread* thread, Runtime1::StubID stub_i
|
|||||||
Handle load_klass(THREAD, NULL); // oop needed by load_klass_patching code
|
Handle load_klass(THREAD, NULL); // oop needed by load_klass_patching code
|
||||||
if (stub_id == Runtime1::access_field_patching_id) {
|
if (stub_id == Runtime1::access_field_patching_id) {
|
||||||
|
|
||||||
Bytecode_field* field_access = Bytecode_field_at(caller_method(), caller_method->bcp_from(bci));
|
Bytecode_field* field_access = Bytecode_field_at(caller_method, bci);
|
||||||
FieldAccessInfo result; // initialize class if needed
|
FieldAccessInfo result; // initialize class if needed
|
||||||
Bytecodes::Code code = field_access->code();
|
Bytecodes::Code code = field_access->code();
|
||||||
constantPoolHandle constants(THREAD, caller_method->constants());
|
constantPoolHandle constants(THREAD, caller_method->constants());
|
||||||
@ -781,11 +781,9 @@ JRT_ENTRY(void, Runtime1::patch_code(JavaThread* thread, Runtime1::StubID stub_i
|
|||||||
case Bytecodes::_ldc:
|
case Bytecodes::_ldc:
|
||||||
case Bytecodes::_ldc_w:
|
case Bytecodes::_ldc_w:
|
||||||
{
|
{
|
||||||
Bytecode_loadconstant* cc = Bytecode_loadconstant_at(caller_method(),
|
Bytecode_loadconstant* cc = Bytecode_loadconstant_at(caller_method, bci);
|
||||||
caller_method->bcp_from(bci));
|
k = cc->resolve_constant(CHECK);
|
||||||
klassOop resolved = caller_method->constants()->klass_at(cc->index(), CHECK);
|
assert(k != NULL && !k->is_klass(), "must be class mirror or other Java constant");
|
||||||
// ldc wants the java mirror.
|
|
||||||
k = resolved->klass_part()->java_mirror();
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default: Unimplemented();
|
default: Unimplemented();
|
||||||
@ -816,6 +814,15 @@ JRT_ENTRY(void, Runtime1::patch_code(JavaThread* thread, Runtime1::StubID stub_i
|
|||||||
// Return to the now deoptimized frame.
|
// Return to the now deoptimized frame.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If we are patching in a non-perm oop, make sure the nmethod
|
||||||
|
// is on the right list.
|
||||||
|
if (ScavengeRootsInCode && load_klass.not_null() && load_klass->is_scavengable()) {
|
||||||
|
MutexLockerEx ml_code (CodeCache_lock, Mutex::_no_safepoint_check_flag);
|
||||||
|
nmethod* nm = CodeCache::find_nmethod(caller_frame.pc());
|
||||||
|
guarantee(nm != NULL, "only nmethods can contain non-perm oops");
|
||||||
|
if (!nm->on_scavenge_root_list())
|
||||||
|
CodeCache::add_scavenge_root_nmethod(nm);
|
||||||
|
}
|
||||||
|
|
||||||
// Now copy code back
|
// Now copy code back
|
||||||
|
|
||||||
@ -1115,7 +1122,7 @@ JRT_LEAF(void, Runtime1::primitive_arraycopy(HeapWord* src, HeapWord* dst, int l
|
|||||||
if (length == 0) return;
|
if (length == 0) return;
|
||||||
// Not guaranteed to be word atomic, but that doesn't matter
|
// Not guaranteed to be word atomic, but that doesn't matter
|
||||||
// for anything but an oop array, which is covered by oop_arraycopy.
|
// for anything but an oop array, which is covered by oop_arraycopy.
|
||||||
Copy::conjoint_bytes(src, dst, length);
|
Copy::conjoint_jbytes(src, dst, length);
|
||||||
JRT_END
|
JRT_END
|
||||||
|
|
||||||
JRT_LEAF(void, Runtime1::oop_arraycopy(HeapWord* src, HeapWord* dst, int num))
|
JRT_LEAF(void, Runtime1::oop_arraycopy(HeapWord* src, HeapWord* dst, int num))
|
||||||
|
@ -44,12 +44,22 @@ size_t ciCPCache::get_f1_offset(int index) {
|
|||||||
// ciCPCache::is_f1_null_at
|
// ciCPCache::is_f1_null_at
|
||||||
bool ciCPCache::is_f1_null_at(int index) {
|
bool ciCPCache::is_f1_null_at(int index) {
|
||||||
VM_ENTRY_MARK;
|
VM_ENTRY_MARK;
|
||||||
constantPoolCacheOop cpcache = (constantPoolCacheOop) get_oop();
|
oop f1 = entry_at(index)->f1();
|
||||||
oop f1 = cpcache->secondary_entry_at(index)->f1();
|
|
||||||
return (f1 == NULL);
|
return (f1 == NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------
|
||||||
|
// ciCPCache::get_pool_index
|
||||||
|
int ciCPCache::get_pool_index(int index) {
|
||||||
|
VM_ENTRY_MARK;
|
||||||
|
ConstantPoolCacheEntry* e = entry_at(index);
|
||||||
|
if (e->is_secondary_entry())
|
||||||
|
e = entry_at(e->main_entry_index());
|
||||||
|
return e->constant_pool_index();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------
|
// ------------------------------------------------------------------
|
||||||
// ciCPCache::print
|
// ciCPCache::print
|
||||||
//
|
//
|
||||||
|
@ -29,6 +29,18 @@
|
|||||||
// Note: This class is called ciCPCache as ciConstantPoolCache is used
|
// Note: This class is called ciCPCache as ciConstantPoolCache is used
|
||||||
// for something different.
|
// for something different.
|
||||||
class ciCPCache : public ciObject {
|
class ciCPCache : public ciObject {
|
||||||
|
private:
|
||||||
|
constantPoolCacheOop get_cpCacheOop() { // must be called inside a VM_ENTRY_MARK
|
||||||
|
return (constantPoolCacheOop) get_oop();
|
||||||
|
}
|
||||||
|
|
||||||
|
ConstantPoolCacheEntry* entry_at(int i) {
|
||||||
|
int raw_index = i;
|
||||||
|
if (constantPoolCacheOopDesc::is_secondary_index(i))
|
||||||
|
raw_index = constantPoolCacheOopDesc::decode_secondary_index(i);
|
||||||
|
return get_cpCacheOop()->entry_at(raw_index);
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ciCPCache(constantPoolCacheHandle cpcache) : ciObject(cpcache) {}
|
ciCPCache(constantPoolCacheHandle cpcache) : ciObject(cpcache) {}
|
||||||
|
|
||||||
@ -41,5 +53,7 @@ public:
|
|||||||
|
|
||||||
bool is_f1_null_at(int index);
|
bool is_f1_null_at(int index);
|
||||||
|
|
||||||
|
int get_pool_index(int index);
|
||||||
|
|
||||||
void print();
|
void print();
|
||||||
};
|
};
|
||||||
|
@ -85,6 +85,7 @@ friend class ciCallSite; \
|
|||||||
friend class ciConstantPoolCache; \
|
friend class ciConstantPoolCache; \
|
||||||
friend class ciField; \
|
friend class ciField; \
|
||||||
friend class ciConstant; \
|
friend class ciConstant; \
|
||||||
|
friend class ciCPCache; \
|
||||||
friend class ciFlags; \
|
friend class ciFlags; \
|
||||||
friend class ciExceptionHandler; \
|
friend class ciExceptionHandler; \
|
||||||
friend class ciCallProfile; \
|
friend class ciCallProfile; \
|
||||||
|
@ -511,9 +511,22 @@ ciKlass* ciEnv::get_klass_by_index(constantPoolHandle cpool,
|
|||||||
//
|
//
|
||||||
// Implementation of get_constant_by_index().
|
// Implementation of get_constant_by_index().
|
||||||
ciConstant ciEnv::get_constant_by_index_impl(constantPoolHandle cpool,
|
ciConstant ciEnv::get_constant_by_index_impl(constantPoolHandle cpool,
|
||||||
int index,
|
int pool_index, int cache_index,
|
||||||
ciInstanceKlass* accessor) {
|
ciInstanceKlass* accessor) {
|
||||||
|
bool ignore_will_link;
|
||||||
EXCEPTION_CONTEXT;
|
EXCEPTION_CONTEXT;
|
||||||
|
int index = pool_index;
|
||||||
|
if (cache_index >= 0) {
|
||||||
|
assert(index < 0, "only one kind of index at a time");
|
||||||
|
ConstantPoolCacheEntry* cpc_entry = cpool->cache()->entry_at(cache_index);
|
||||||
|
index = cpc_entry->constant_pool_index();
|
||||||
|
oop obj = cpc_entry->f1();
|
||||||
|
if (obj != NULL) {
|
||||||
|
assert(obj->is_instance(), "must be an instance");
|
||||||
|
ciObject* ciobj = get_object(obj);
|
||||||
|
return ciConstant(T_OBJECT, ciobj);
|
||||||
|
}
|
||||||
|
}
|
||||||
constantTag tag = cpool->tag_at(index);
|
constantTag tag = cpool->tag_at(index);
|
||||||
if (tag.is_int()) {
|
if (tag.is_int()) {
|
||||||
return ciConstant(T_INT, (jint)cpool->int_at(index));
|
return ciConstant(T_INT, (jint)cpool->int_at(index));
|
||||||
@ -540,8 +553,7 @@ ciConstant ciEnv::get_constant_by_index_impl(constantPoolHandle cpool,
|
|||||||
return ciConstant(T_OBJECT, constant);
|
return ciConstant(T_OBJECT, constant);
|
||||||
} else if (tag.is_klass() || tag.is_unresolved_klass()) {
|
} else if (tag.is_klass() || tag.is_unresolved_klass()) {
|
||||||
// 4881222: allow ldc to take a class type
|
// 4881222: allow ldc to take a class type
|
||||||
bool ignore;
|
ciKlass* klass = get_klass_by_index_impl(cpool, index, ignore_will_link, accessor);
|
||||||
ciKlass* klass = get_klass_by_index_impl(cpool, index, ignore, accessor);
|
|
||||||
if (HAS_PENDING_EXCEPTION) {
|
if (HAS_PENDING_EXCEPTION) {
|
||||||
CLEAR_PENDING_EXCEPTION;
|
CLEAR_PENDING_EXCEPTION;
|
||||||
record_out_of_memory_failure();
|
record_out_of_memory_failure();
|
||||||
@ -549,42 +561,32 @@ ciConstant ciEnv::get_constant_by_index_impl(constantPoolHandle cpool,
|
|||||||
}
|
}
|
||||||
assert (klass->is_instance_klass() || klass->is_array_klass(),
|
assert (klass->is_instance_klass() || klass->is_array_klass(),
|
||||||
"must be an instance or array klass ");
|
"must be an instance or array klass ");
|
||||||
return ciConstant(T_OBJECT, klass);
|
return ciConstant(T_OBJECT, klass->java_mirror());
|
||||||
} else if (tag.is_object()) {
|
} else if (tag.is_object()) {
|
||||||
oop obj = cpool->object_at(index);
|
oop obj = cpool->object_at(index);
|
||||||
assert(obj->is_instance(), "must be an instance");
|
assert(obj->is_instance(), "must be an instance");
|
||||||
ciObject* ciobj = get_object(obj);
|
ciObject* ciobj = get_object(obj);
|
||||||
return ciConstant(T_OBJECT, ciobj);
|
return ciConstant(T_OBJECT, ciobj);
|
||||||
|
} else if (tag.is_method_type()) {
|
||||||
|
// must execute Java code to link this CP entry into cache[i].f1
|
||||||
|
ciSymbol* signature = get_object(cpool->method_type_signature_at(index))->as_symbol();
|
||||||
|
ciObject* ciobj = get_unloaded_method_type_constant(signature);
|
||||||
|
return ciConstant(T_OBJECT, ciobj);
|
||||||
|
} else if (tag.is_method_handle()) {
|
||||||
|
// must execute Java code to link this CP entry into cache[i].f1
|
||||||
|
int ref_kind = cpool->method_handle_ref_kind_at(index);
|
||||||
|
int callee_index = cpool->method_handle_klass_index_at(index);
|
||||||
|
ciKlass* callee = get_klass_by_index_impl(cpool, callee_index, ignore_will_link, accessor);
|
||||||
|
ciSymbol* name = get_object(cpool->method_handle_name_ref_at(index))->as_symbol();
|
||||||
|
ciSymbol* signature = get_object(cpool->method_handle_signature_ref_at(index))->as_symbol();
|
||||||
|
ciObject* ciobj = get_unloaded_method_handle_constant(callee, name, signature, ref_kind);
|
||||||
|
return ciConstant(T_OBJECT, ciobj);
|
||||||
} else {
|
} else {
|
||||||
ShouldNotReachHere();
|
ShouldNotReachHere();
|
||||||
return ciConstant();
|
return ciConstant();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------
|
|
||||||
// ciEnv::is_unresolved_string_impl
|
|
||||||
//
|
|
||||||
// Implementation of is_unresolved_string().
|
|
||||||
bool ciEnv::is_unresolved_string_impl(instanceKlass* accessor, int index) const {
|
|
||||||
EXCEPTION_CONTEXT;
|
|
||||||
assert(accessor->is_linked(), "must be linked before accessing constant pool");
|
|
||||||
constantPoolOop cpool = accessor->constants();
|
|
||||||
constantTag tag = cpool->tag_at(index);
|
|
||||||
return tag.is_unresolved_string();
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------
|
|
||||||
// ciEnv::is_unresolved_klass_impl
|
|
||||||
//
|
|
||||||
// Implementation of is_unresolved_klass().
|
|
||||||
bool ciEnv::is_unresolved_klass_impl(instanceKlass* accessor, int index) const {
|
|
||||||
EXCEPTION_CONTEXT;
|
|
||||||
assert(accessor->is_linked(), "must be linked before accessing constant pool");
|
|
||||||
constantPoolOop cpool = accessor->constants();
|
|
||||||
constantTag tag = cpool->tag_at(index);
|
|
||||||
return tag.is_unresolved_klass();
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------
|
// ------------------------------------------------------------------
|
||||||
// ciEnv::get_constant_by_index
|
// ciEnv::get_constant_by_index
|
||||||
//
|
//
|
||||||
@ -592,31 +594,9 @@ bool ciEnv::is_unresolved_klass_impl(instanceKlass* accessor, int index) const {
|
|||||||
//
|
//
|
||||||
// Implementation note: this query is currently in no way cached.
|
// Implementation note: this query is currently in no way cached.
|
||||||
ciConstant ciEnv::get_constant_by_index(constantPoolHandle cpool,
|
ciConstant ciEnv::get_constant_by_index(constantPoolHandle cpool,
|
||||||
int index,
|
int pool_index, int cache_index,
|
||||||
ciInstanceKlass* accessor) {
|
ciInstanceKlass* accessor) {
|
||||||
GUARDED_VM_ENTRY(return get_constant_by_index_impl(cpool, index, accessor);)
|
GUARDED_VM_ENTRY(return get_constant_by_index_impl(cpool, pool_index, cache_index, accessor);)
|
||||||
}
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------
|
|
||||||
// ciEnv::is_unresolved_string
|
|
||||||
//
|
|
||||||
// Check constant pool
|
|
||||||
//
|
|
||||||
// Implementation note: this query is currently in no way cached.
|
|
||||||
bool ciEnv::is_unresolved_string(ciInstanceKlass* accessor,
|
|
||||||
int index) const {
|
|
||||||
GUARDED_VM_ENTRY(return is_unresolved_string_impl(accessor->get_instanceKlass(), index); )
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------
|
|
||||||
// ciEnv::is_unresolved_klass
|
|
||||||
//
|
|
||||||
// Check constant pool
|
|
||||||
//
|
|
||||||
// Implementation note: this query is currently in no way cached.
|
|
||||||
bool ciEnv::is_unresolved_klass(ciInstanceKlass* accessor,
|
|
||||||
int index) const {
|
|
||||||
GUARDED_VM_ENTRY(return is_unresolved_klass_impl(accessor->get_instanceKlass(), index); )
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------
|
// ------------------------------------------------------------------
|
||||||
|
@ -116,12 +116,8 @@ private:
|
|||||||
bool& is_accessible,
|
bool& is_accessible,
|
||||||
ciInstanceKlass* loading_klass);
|
ciInstanceKlass* loading_klass);
|
||||||
ciConstant get_constant_by_index(constantPoolHandle cpool,
|
ciConstant get_constant_by_index(constantPoolHandle cpool,
|
||||||
int constant_index,
|
int pool_index, int cache_index,
|
||||||
ciInstanceKlass* accessor);
|
ciInstanceKlass* accessor);
|
||||||
bool is_unresolved_string(ciInstanceKlass* loading_klass,
|
|
||||||
int constant_index) const;
|
|
||||||
bool is_unresolved_klass(ciInstanceKlass* loading_klass,
|
|
||||||
int constant_index) const;
|
|
||||||
ciField* get_field_by_index(ciInstanceKlass* loading_klass,
|
ciField* get_field_by_index(ciInstanceKlass* loading_klass,
|
||||||
int field_index);
|
int field_index);
|
||||||
ciMethod* get_method_by_index(constantPoolHandle cpool,
|
ciMethod* get_method_by_index(constantPoolHandle cpool,
|
||||||
@ -137,12 +133,8 @@ private:
|
|||||||
bool& is_accessible,
|
bool& is_accessible,
|
||||||
ciInstanceKlass* loading_klass);
|
ciInstanceKlass* loading_klass);
|
||||||
ciConstant get_constant_by_index_impl(constantPoolHandle cpool,
|
ciConstant get_constant_by_index_impl(constantPoolHandle cpool,
|
||||||
int constant_index,
|
int pool_index, int cache_index,
|
||||||
ciInstanceKlass* loading_klass);
|
ciInstanceKlass* loading_klass);
|
||||||
bool is_unresolved_string_impl (instanceKlass* loading_klass,
|
|
||||||
int constant_index) const;
|
|
||||||
bool is_unresolved_klass_impl (instanceKlass* loading_klass,
|
|
||||||
int constant_index) const;
|
|
||||||
ciField* get_field_by_index_impl(ciInstanceKlass* loading_klass,
|
ciField* get_field_by_index_impl(ciInstanceKlass* loading_klass,
|
||||||
int field_index);
|
int field_index);
|
||||||
ciMethod* get_method_by_index_impl(constantPoolHandle cpool,
|
ciMethod* get_method_by_index_impl(constantPoolHandle cpool,
|
||||||
@ -190,6 +182,25 @@ private:
|
|||||||
return _factory->get_unloaded_klass(accessing_klass, name, true);
|
return _factory->get_unloaded_klass(accessing_klass, name, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get a ciKlass representing an unloaded klass mirror.
|
||||||
|
// Result is not necessarily unique, but will be unloaded.
|
||||||
|
ciInstance* get_unloaded_klass_mirror(ciKlass* type) {
|
||||||
|
return _factory->get_unloaded_klass_mirror(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get a ciInstance representing an unresolved method handle constant.
|
||||||
|
ciInstance* get_unloaded_method_handle_constant(ciKlass* holder,
|
||||||
|
ciSymbol* name,
|
||||||
|
ciSymbol* signature,
|
||||||
|
int ref_kind) {
|
||||||
|
return _factory->get_unloaded_method_handle_constant(holder, name, signature, ref_kind);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get a ciInstance representing an unresolved method type constant.
|
||||||
|
ciInstance* get_unloaded_method_type_constant(ciSymbol* signature) {
|
||||||
|
return _factory->get_unloaded_method_type_constant(signature);
|
||||||
|
}
|
||||||
|
|
||||||
// See if we already have an unloaded klass for the given name
|
// See if we already have an unloaded klass for the given name
|
||||||
// or return NULL if not.
|
// or return NULL if not.
|
||||||
ciKlass *check_get_unloaded_klass(ciKlass* accessing_klass, ciSymbol* name) {
|
ciKlass *check_get_unloaded_klass(ciKlass* accessing_klass, ciSymbol* name) {
|
||||||
|
@ -323,8 +323,8 @@ ciInstanceKlass* ciInstanceKlass::super() {
|
|||||||
// ciInstanceKlass::java_mirror
|
// ciInstanceKlass::java_mirror
|
||||||
//
|
//
|
||||||
// Get the instance of java.lang.Class corresponding to this klass.
|
// Get the instance of java.lang.Class corresponding to this klass.
|
||||||
|
// Cache it on this->_java_mirror.
|
||||||
ciInstance* ciInstanceKlass::java_mirror() {
|
ciInstance* ciInstanceKlass::java_mirror() {
|
||||||
assert(is_loaded(), "must be loaded");
|
|
||||||
if (_java_mirror == NULL) {
|
if (_java_mirror == NULL) {
|
||||||
_java_mirror = ciKlass::java_mirror();
|
_java_mirror = ciKlass::java_mirror();
|
||||||
}
|
}
|
||||||
|
@ -192,8 +192,14 @@ ciKlass* ciKlass::find_klass(ciSymbol* klass_name) {
|
|||||||
|
|
||||||
// ------------------------------------------------------------------
|
// ------------------------------------------------------------------
|
||||||
// ciKlass::java_mirror
|
// ciKlass::java_mirror
|
||||||
|
//
|
||||||
|
// Get the instance of java.lang.Class corresponding to this klass.
|
||||||
|
// If it is an unloaded instance or array klass, return an unloaded
|
||||||
|
// mirror object of type Class.
|
||||||
ciInstance* ciKlass::java_mirror() {
|
ciInstance* ciKlass::java_mirror() {
|
||||||
GUARDED_VM_ENTRY(
|
GUARDED_VM_ENTRY(
|
||||||
|
if (!is_loaded())
|
||||||
|
return ciEnv::current()->get_unloaded_klass_mirror(this);
|
||||||
oop java_mirror = get_Klass()->java_mirror();
|
oop java_mirror = get_Klass()->java_mirror();
|
||||||
return CURRENT_ENV->get_object(java_mirror)->as_instance();
|
return CURRENT_ENV->get_object(java_mirror)->as_instance();
|
||||||
)
|
)
|
||||||
|
@ -70,6 +70,7 @@ ciObjectFactory::ciObjectFactory(Arena* arena,
|
|||||||
|
|
||||||
_unloaded_methods = new (arena) GrowableArray<ciMethod*>(arena, 4, 0, NULL);
|
_unloaded_methods = new (arena) GrowableArray<ciMethod*>(arena, 4, 0, NULL);
|
||||||
_unloaded_klasses = new (arena) GrowableArray<ciKlass*>(arena, 8, 0, NULL);
|
_unloaded_klasses = new (arena) GrowableArray<ciKlass*>(arena, 8, 0, NULL);
|
||||||
|
_unloaded_instances = new (arena) GrowableArray<ciInstance*>(arena, 4, 0, NULL);
|
||||||
_return_addresses =
|
_return_addresses =
|
||||||
new (arena) GrowableArray<ciReturnAddress*>(arena, 8, 0, NULL);
|
new (arena) GrowableArray<ciReturnAddress*>(arena, 8, 0, NULL);
|
||||||
}
|
}
|
||||||
@ -443,6 +444,74 @@ ciKlass* ciObjectFactory::get_unloaded_klass(ciKlass* accessing_klass,
|
|||||||
return new_klass;
|
return new_klass;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//------------------------------------------------------------------
|
||||||
|
// ciObjectFactory::get_unloaded_instance
|
||||||
|
//
|
||||||
|
// Get a ciInstance representing an as-yet undetermined instance of a given class.
|
||||||
|
//
|
||||||
|
ciInstance* ciObjectFactory::get_unloaded_instance(ciInstanceKlass* instance_klass) {
|
||||||
|
for (int i=0; i<_unloaded_instances->length(); i++) {
|
||||||
|
ciInstance* entry = _unloaded_instances->at(i);
|
||||||
|
if (entry->klass()->equals(instance_klass)) {
|
||||||
|
// We've found a match.
|
||||||
|
return entry;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is a new unloaded instance. Create it and stick it in
|
||||||
|
// the cache.
|
||||||
|
ciInstance* new_instance = new (arena()) ciInstance(instance_klass);
|
||||||
|
|
||||||
|
init_ident_of(new_instance);
|
||||||
|
_unloaded_instances->append(new_instance);
|
||||||
|
|
||||||
|
// make sure it looks the way we want:
|
||||||
|
assert(!new_instance->is_loaded(), "");
|
||||||
|
assert(new_instance->klass() == instance_klass, "");
|
||||||
|
|
||||||
|
return new_instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//------------------------------------------------------------------
|
||||||
|
// ciObjectFactory::get_unloaded_klass_mirror
|
||||||
|
//
|
||||||
|
// Get a ciInstance representing an unresolved klass mirror.
|
||||||
|
//
|
||||||
|
// Currently, this ignores the parameters and returns a unique unloaded instance.
|
||||||
|
ciInstance* ciObjectFactory::get_unloaded_klass_mirror(ciKlass* type) {
|
||||||
|
assert(ciEnv::_Class_klass != NULL, "");
|
||||||
|
return get_unloaded_instance(ciEnv::_Class_klass->as_instance_klass());
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------
|
||||||
|
// ciObjectFactory::get_unloaded_method_handle_constant
|
||||||
|
//
|
||||||
|
// Get a ciInstance representing an unresolved method handle constant.
|
||||||
|
//
|
||||||
|
// Currently, this ignores the parameters and returns a unique unloaded instance.
|
||||||
|
ciInstance* ciObjectFactory::get_unloaded_method_handle_constant(ciKlass* holder,
|
||||||
|
ciSymbol* name,
|
||||||
|
ciSymbol* signature,
|
||||||
|
int ref_kind) {
|
||||||
|
if (ciEnv::_MethodHandle_klass == NULL) return NULL;
|
||||||
|
return get_unloaded_instance(ciEnv::_MethodHandle_klass->as_instance_klass());
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------
|
||||||
|
// ciObjectFactory::get_unloaded_method_type_constant
|
||||||
|
//
|
||||||
|
// Get a ciInstance representing an unresolved method type constant.
|
||||||
|
//
|
||||||
|
// Currently, this ignores the parameters and returns a unique unloaded instance.
|
||||||
|
ciInstance* ciObjectFactory::get_unloaded_method_type_constant(ciSymbol* signature) {
|
||||||
|
if (ciEnv::_MethodType_klass == NULL) return NULL;
|
||||||
|
return get_unloaded_instance(ciEnv::_MethodType_klass->as_instance_klass());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//------------------------------------------------------------------
|
//------------------------------------------------------------------
|
||||||
// ciObjectFactory::get_empty_methodData
|
// ciObjectFactory::get_empty_methodData
|
||||||
//
|
//
|
||||||
@ -637,7 +706,8 @@ void ciObjectFactory::print_contents() {
|
|||||||
//
|
//
|
||||||
// Print debugging information about the object factory
|
// Print debugging information about the object factory
|
||||||
void ciObjectFactory::print() {
|
void ciObjectFactory::print() {
|
||||||
tty->print("<ciObjectFactory oops=%d unloaded_methods=%d unloaded_klasses=%d>",
|
tty->print("<ciObjectFactory oops=%d unloaded_methods=%d unloaded_instances=%d unloaded_klasses=%d>",
|
||||||
_ci_objects->length(), _unloaded_methods->length(),
|
_ci_objects->length(), _unloaded_methods->length(),
|
||||||
|
_unloaded_instances->length(),
|
||||||
_unloaded_klasses->length());
|
_unloaded_klasses->length());
|
||||||
}
|
}
|
||||||
|
@ -39,6 +39,7 @@ private:
|
|||||||
GrowableArray<ciObject*>* _ci_objects;
|
GrowableArray<ciObject*>* _ci_objects;
|
||||||
GrowableArray<ciMethod*>* _unloaded_methods;
|
GrowableArray<ciMethod*>* _unloaded_methods;
|
||||||
GrowableArray<ciKlass*>* _unloaded_klasses;
|
GrowableArray<ciKlass*>* _unloaded_klasses;
|
||||||
|
GrowableArray<ciInstance*>* _unloaded_instances;
|
||||||
GrowableArray<ciReturnAddress*>* _return_addresses;
|
GrowableArray<ciReturnAddress*>* _return_addresses;
|
||||||
int _next_ident;
|
int _next_ident;
|
||||||
|
|
||||||
@ -73,6 +74,8 @@ private:
|
|||||||
|
|
||||||
void print_contents_impl();
|
void print_contents_impl();
|
||||||
|
|
||||||
|
ciInstance* get_unloaded_instance(ciInstanceKlass* klass);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static bool is_initialized() { return _initialized; }
|
static bool is_initialized() { return _initialized; }
|
||||||
|
|
||||||
@ -98,6 +101,18 @@ public:
|
|||||||
ciSymbol* name,
|
ciSymbol* name,
|
||||||
bool create_if_not_found);
|
bool create_if_not_found);
|
||||||
|
|
||||||
|
// Get a ciInstance representing an unresolved klass mirror.
|
||||||
|
ciInstance* get_unloaded_klass_mirror(ciKlass* type);
|
||||||
|
|
||||||
|
// Get a ciInstance representing an unresolved method handle constant.
|
||||||
|
ciInstance* get_unloaded_method_handle_constant(ciKlass* holder,
|
||||||
|
ciSymbol* name,
|
||||||
|
ciSymbol* signature,
|
||||||
|
int ref_kind);
|
||||||
|
|
||||||
|
// Get a ciInstance representing an unresolved method type constant.
|
||||||
|
ciInstance* get_unloaded_method_type_constant(ciSymbol* signature);
|
||||||
|
|
||||||
|
|
||||||
// Get the ciMethodData representing the methodData for a method
|
// Get the ciMethodData representing the methodData for a method
|
||||||
// with none.
|
// with none.
|
||||||
|
@ -186,12 +186,13 @@ ciKlass* ciBytecodeStream::get_klass(bool& will_link) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------
|
// ------------------------------------------------------------------
|
||||||
// ciBytecodeStream::get_constant_index
|
// ciBytecodeStream::get_constant_raw_index
|
||||||
//
|
//
|
||||||
// If this bytecode is one of the ldc variants, get the index of the
|
// If this bytecode is one of the ldc variants, get the index of the
|
||||||
// referenced constant.
|
// referenced constant.
|
||||||
int ciBytecodeStream::get_constant_index() const {
|
int ciBytecodeStream::get_constant_raw_index() const {
|
||||||
switch(cur_bc()) {
|
// work-alike for Bytecode_loadconstant::raw_index()
|
||||||
|
switch (cur_bc()) {
|
||||||
case Bytecodes::_ldc:
|
case Bytecodes::_ldc:
|
||||||
return get_index_u1();
|
return get_index_u1();
|
||||||
case Bytecodes::_ldc_w:
|
case Bytecodes::_ldc_w:
|
||||||
@ -202,25 +203,52 @@ int ciBytecodeStream::get_constant_index() const {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------
|
||||||
|
// ciBytecodeStream::get_constant_pool_index
|
||||||
|
// Decode any CP cache index into a regular pool index.
|
||||||
|
int ciBytecodeStream::get_constant_pool_index() const {
|
||||||
|
// work-alike for Bytecode_loadconstant::pool_index()
|
||||||
|
int index = get_constant_raw_index();
|
||||||
|
if (has_cache_index()) {
|
||||||
|
return get_cpcache()->get_pool_index(index);
|
||||||
|
}
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------
|
||||||
|
// ciBytecodeStream::get_constant_cache_index
|
||||||
|
// Return the CP cache index, or -1 if there isn't any.
|
||||||
|
int ciBytecodeStream::get_constant_cache_index() const {
|
||||||
|
// work-alike for Bytecode_loadconstant::cache_index()
|
||||||
|
return has_cache_index() ? get_constant_raw_index() : -1;
|
||||||
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------
|
// ------------------------------------------------------------------
|
||||||
// ciBytecodeStream::get_constant
|
// ciBytecodeStream::get_constant
|
||||||
//
|
//
|
||||||
// If this bytecode is one of the ldc variants, get the referenced
|
// If this bytecode is one of the ldc variants, get the referenced
|
||||||
// constant.
|
// constant.
|
||||||
ciConstant ciBytecodeStream::get_constant() {
|
ciConstant ciBytecodeStream::get_constant() {
|
||||||
|
int pool_index = get_constant_raw_index();
|
||||||
|
int cache_index = -1;
|
||||||
|
if (has_cache_index()) {
|
||||||
|
cache_index = pool_index;
|
||||||
|
pool_index = -1;
|
||||||
|
}
|
||||||
VM_ENTRY_MARK;
|
VM_ENTRY_MARK;
|
||||||
constantPoolHandle cpool(_method->get_methodOop()->constants());
|
constantPoolHandle cpool(_method->get_methodOop()->constants());
|
||||||
return CURRENT_ENV->get_constant_by_index(cpool, get_constant_index(), _holder);
|
return CURRENT_ENV->get_constant_by_index(cpool, pool_index, cache_index, _holder);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------
|
// ------------------------------------------------------------------
|
||||||
bool ciBytecodeStream::is_unresolved_string() const {
|
// ciBytecodeStream::get_constant_pool_tag
|
||||||
return CURRENT_ENV->is_unresolved_string(_holder, get_constant_index());
|
//
|
||||||
}
|
// If this bytecode is one of the ldc variants, get the referenced
|
||||||
|
// constant.
|
||||||
// ------------------------------------------------------------------
|
constantTag ciBytecodeStream::get_constant_pool_tag(int index) const {
|
||||||
bool ciBytecodeStream::is_unresolved_klass() const {
|
VM_ENTRY_MARK;
|
||||||
return CURRENT_ENV->is_unresolved_klass(_holder, get_klass_index());
|
return _method->get_methodOop()->constants()->tag_at(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------
|
// ------------------------------------------------------------------
|
||||||
@ -378,13 +406,16 @@ int ciBytecodeStream::get_method_signature_index() {
|
|||||||
|
|
||||||
// ------------------------------------------------------------------
|
// ------------------------------------------------------------------
|
||||||
// ciBytecodeStream::get_cpcache
|
// ciBytecodeStream::get_cpcache
|
||||||
ciCPCache* ciBytecodeStream::get_cpcache() {
|
ciCPCache* ciBytecodeStream::get_cpcache() const {
|
||||||
VM_ENTRY_MARK;
|
if (_cpcache == NULL) {
|
||||||
// Get the constant pool.
|
VM_ENTRY_MARK;
|
||||||
constantPoolOop cpool = _holder->get_instanceKlass()->constants();
|
// Get the constant pool.
|
||||||
constantPoolCacheOop cpcache = cpool->cache();
|
constantPoolOop cpool = _holder->get_instanceKlass()->constants();
|
||||||
|
constantPoolCacheOop cpcache = cpool->cache();
|
||||||
|
|
||||||
return CURRENT_ENV->get_object(cpcache)->as_cpcache();
|
*(ciCPCache**)&_cpcache = CURRENT_ENV->get_object(cpcache)->as_cpcache();
|
||||||
|
}
|
||||||
|
return _cpcache;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------
|
// ------------------------------------------------------------------
|
||||||
|
@ -46,6 +46,7 @@ private:
|
|||||||
|
|
||||||
ciMethod* _method; // the method
|
ciMethod* _method; // the method
|
||||||
ciInstanceKlass* _holder;
|
ciInstanceKlass* _holder;
|
||||||
|
ciCPCache* _cpcache;
|
||||||
address _bc_start; // Start of current bytecode for table
|
address _bc_start; // Start of current bytecode for table
|
||||||
address _was_wide; // Address past last wide bytecode
|
address _was_wide; // Address past last wide bytecode
|
||||||
jint* _table_base; // Aligned start of last table or switch
|
jint* _table_base; // Aligned start of last table or switch
|
||||||
@ -58,7 +59,9 @@ private:
|
|||||||
|
|
||||||
void reset( address base, unsigned int size ) {
|
void reset( address base, unsigned int size ) {
|
||||||
_bc_start =_was_wide = 0;
|
_bc_start =_was_wide = 0;
|
||||||
_start = _pc = base; _end = base + size; }
|
_start = _pc = base; _end = base + size;
|
||||||
|
_cpcache = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
void assert_wide(bool require_wide) const {
|
void assert_wide(bool require_wide) const {
|
||||||
if (require_wide)
|
if (require_wide)
|
||||||
@ -136,15 +139,20 @@ public:
|
|||||||
bool is_wide() const { return ( _pc == _was_wide ); }
|
bool is_wide() const { return ( _pc == _was_wide ); }
|
||||||
|
|
||||||
// Does this instruction contain an index which refes into the CP cache?
|
// Does this instruction contain an index which refes into the CP cache?
|
||||||
bool uses_cp_cache() const { return Bytecodes::uses_cp_cache(cur_bc_raw()); }
|
bool has_cache_index() const { return Bytecodes::uses_cp_cache(cur_bc_raw()); }
|
||||||
|
|
||||||
int get_index_u1() const {
|
int get_index_u1() const {
|
||||||
return bytecode()->get_index_u1(cur_bc_raw());
|
return bytecode()->get_index_u1(cur_bc_raw());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int get_index_u1_cpcache() const {
|
||||||
|
return bytecode()->get_index_u1_cpcache(cur_bc_raw());
|
||||||
|
}
|
||||||
|
|
||||||
// Get a byte index following this bytecode.
|
// Get a byte index following this bytecode.
|
||||||
// If prefixed with a wide bytecode, get a wide index.
|
// If prefixed with a wide bytecode, get a wide index.
|
||||||
int get_index() const {
|
int get_index() const {
|
||||||
|
assert(!has_cache_index(), "else use cpcache variant");
|
||||||
return (_pc == _was_wide) // was widened?
|
return (_pc == _was_wide) // was widened?
|
||||||
? get_index_u2(true) // yes, return wide index
|
? get_index_u2(true) // yes, return wide index
|
||||||
: get_index_u1(); // no, return narrow index
|
: get_index_u1(); // no, return narrow index
|
||||||
@ -207,7 +215,9 @@ public:
|
|||||||
return cur_bci() + get_int_table(index); }
|
return cur_bci() + get_int_table(index); }
|
||||||
|
|
||||||
// --- Constant pool access ---
|
// --- Constant pool access ---
|
||||||
int get_constant_index() const;
|
int get_constant_raw_index() const;
|
||||||
|
int get_constant_pool_index() const;
|
||||||
|
int get_constant_cache_index() const;
|
||||||
int get_field_index();
|
int get_field_index();
|
||||||
int get_method_index();
|
int get_method_index();
|
||||||
|
|
||||||
@ -217,12 +227,17 @@ public:
|
|||||||
int get_klass_index() const;
|
int get_klass_index() const;
|
||||||
|
|
||||||
// If this bytecode is one of the ldc variants, get the referenced
|
// If this bytecode is one of the ldc variants, get the referenced
|
||||||
// constant
|
// constant. Do not attempt to resolve it, since that would require
|
||||||
|
// execution of Java code. If it is not resolved, return an unloaded
|
||||||
|
// object (ciConstant.as_object()->is_loaded() == false).
|
||||||
ciConstant get_constant();
|
ciConstant get_constant();
|
||||||
// True if the ldc variant points to an unresolved string
|
constantTag get_constant_pool_tag(int index) const;
|
||||||
bool is_unresolved_string() const;
|
|
||||||
// True if the ldc variant points to an unresolved klass
|
// True if the klass-using bytecode points to an unresolved klass
|
||||||
bool is_unresolved_klass() const;
|
bool is_unresolved_klass() const {
|
||||||
|
constantTag tag = get_constant_pool_tag(get_klass_index());
|
||||||
|
return tag.is_unresolved_klass();
|
||||||
|
}
|
||||||
|
|
||||||
// If this bytecode is one of get_field, get_static, put_field,
|
// If this bytecode is one of get_field, get_static, put_field,
|
||||||
// or put_static, get the referenced field.
|
// or put_static, get the referenced field.
|
||||||
@ -238,7 +253,7 @@ public:
|
|||||||
int get_method_holder_index();
|
int get_method_holder_index();
|
||||||
int get_method_signature_index();
|
int get_method_signature_index();
|
||||||
|
|
||||||
ciCPCache* get_cpcache();
|
ciCPCache* get_cpcache() const;
|
||||||
ciCallSite* get_call_site();
|
ciCallSite* get_call_site();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -712,10 +712,8 @@ void ciTypeFlow::StateVector::do_ldc(ciBytecodeStream* str) {
|
|||||||
ciObject* obj = con.as_object();
|
ciObject* obj = con.as_object();
|
||||||
if (obj->is_null_object()) {
|
if (obj->is_null_object()) {
|
||||||
push_null();
|
push_null();
|
||||||
} else if (obj->is_klass()) {
|
|
||||||
// The type of ldc <class> is java.lang.Class
|
|
||||||
push_object(outer()->env()->Class_klass());
|
|
||||||
} else {
|
} else {
|
||||||
|
assert(!obj->is_klass(), "must be java_mirror of klass");
|
||||||
push_object(obj->klass());
|
push_object(obj->klass());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -117,6 +117,29 @@ void ClassFileParser::parse_constant_pool_entries(constantPoolHandle cp, int len
|
|||||||
cp->string_index_at_put(index, string_index);
|
cp->string_index_at_put(index, string_index);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case JVM_CONSTANT_MethodHandle :
|
||||||
|
case JVM_CONSTANT_MethodType :
|
||||||
|
if (!EnableMethodHandles ||
|
||||||
|
_major_version < Verifier::INVOKEDYNAMIC_MAJOR_VERSION) {
|
||||||
|
classfile_parse_error(
|
||||||
|
(!EnableInvokeDynamic ?
|
||||||
|
"This JVM does not support constant tag %u in class file %s" :
|
||||||
|
"Class file version does not support constant tag %u in class file %s"),
|
||||||
|
tag, CHECK);
|
||||||
|
}
|
||||||
|
if (tag == JVM_CONSTANT_MethodHandle) {
|
||||||
|
cfs->guarantee_more(4, CHECK); // ref_kind, method_index, tag/access_flags
|
||||||
|
u1 ref_kind = cfs->get_u1_fast();
|
||||||
|
u2 method_index = cfs->get_u2_fast();
|
||||||
|
cp->method_handle_index_at_put(index, ref_kind, method_index);
|
||||||
|
} else if (tag == JVM_CONSTANT_MethodType) {
|
||||||
|
cfs->guarantee_more(3, CHECK); // signature_index, tag/access_flags
|
||||||
|
u2 signature_index = cfs->get_u2_fast();
|
||||||
|
cp->method_type_index_at_put(index, signature_index);
|
||||||
|
} else {
|
||||||
|
ShouldNotReachHere();
|
||||||
|
}
|
||||||
|
break;
|
||||||
case JVM_CONSTANT_Integer :
|
case JVM_CONSTANT_Integer :
|
||||||
{
|
{
|
||||||
cfs->guarantee_more(5, CHECK); // bytes, tag/access_flags
|
cfs->guarantee_more(5, CHECK); // bytes, tag/access_flags
|
||||||
@ -337,6 +360,60 @@ constantPoolHandle ClassFileParser::parse_constant_pool(TRAPS) {
|
|||||||
cp->unresolved_string_at_put(index, sym);
|
cp->unresolved_string_at_put(index, sym);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case JVM_CONSTANT_MethodHandle :
|
||||||
|
{
|
||||||
|
int ref_index = cp->method_handle_index_at(index);
|
||||||
|
check_property(
|
||||||
|
valid_cp_range(ref_index, length) &&
|
||||||
|
EnableMethodHandles,
|
||||||
|
"Invalid constant pool index %u in class file %s",
|
||||||
|
ref_index, CHECK_(nullHandle));
|
||||||
|
constantTag tag = cp->tag_at(ref_index);
|
||||||
|
int ref_kind = cp->method_handle_ref_kind_at(index);
|
||||||
|
switch (ref_kind) {
|
||||||
|
case JVM_REF_getField:
|
||||||
|
case JVM_REF_getStatic:
|
||||||
|
case JVM_REF_putField:
|
||||||
|
case JVM_REF_putStatic:
|
||||||
|
check_property(
|
||||||
|
tag.is_field(),
|
||||||
|
"Invalid constant pool index %u in class file %s (not a field)",
|
||||||
|
ref_index, CHECK_(nullHandle));
|
||||||
|
break;
|
||||||
|
case JVM_REF_invokeVirtual:
|
||||||
|
case JVM_REF_invokeStatic:
|
||||||
|
case JVM_REF_invokeSpecial:
|
||||||
|
case JVM_REF_newInvokeSpecial:
|
||||||
|
check_property(
|
||||||
|
tag.is_method(),
|
||||||
|
"Invalid constant pool index %u in class file %s (not a method)",
|
||||||
|
ref_index, CHECK_(nullHandle));
|
||||||
|
break;
|
||||||
|
case JVM_REF_invokeInterface:
|
||||||
|
check_property(
|
||||||
|
tag.is_interface_method(),
|
||||||
|
"Invalid constant pool index %u in class file %s (not an interface method)",
|
||||||
|
ref_index, CHECK_(nullHandle));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
classfile_parse_error(
|
||||||
|
"Bad method handle kind at constant pool index %u in class file %s",
|
||||||
|
index, CHECK_(nullHandle));
|
||||||
|
}
|
||||||
|
// Keep the ref_index unchanged. It will be indirected at link-time.
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case JVM_CONSTANT_MethodType :
|
||||||
|
{
|
||||||
|
int ref_index = cp->method_type_index_at(index);
|
||||||
|
check_property(
|
||||||
|
valid_cp_range(ref_index, length) &&
|
||||||
|
cp->tag_at(ref_index).is_utf8() &&
|
||||||
|
EnableMethodHandles,
|
||||||
|
"Invalid constant pool index %u in class file %s",
|
||||||
|
ref_index, CHECK_(nullHandle));
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
fatal(err_msg("bad constant pool tag value %u",
|
fatal(err_msg("bad constant pool tag value %u",
|
||||||
cp->tag_at(index).value()));
|
cp->tag_at(index).value()));
|
||||||
@ -452,6 +529,43 @@ constantPoolHandle ClassFileParser::parse_constant_pool(TRAPS) {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case JVM_CONSTANT_MethodHandle: {
|
||||||
|
int ref_index = cp->method_handle_index_at(index);
|
||||||
|
int ref_kind = cp->method_handle_ref_kind_at(index);
|
||||||
|
switch (ref_kind) {
|
||||||
|
case JVM_REF_invokeVirtual:
|
||||||
|
case JVM_REF_invokeStatic:
|
||||||
|
case JVM_REF_invokeSpecial:
|
||||||
|
case JVM_REF_newInvokeSpecial:
|
||||||
|
{
|
||||||
|
int name_and_type_ref_index = cp->name_and_type_ref_index_at(ref_index);
|
||||||
|
int name_ref_index = cp->name_ref_index_at(name_and_type_ref_index);
|
||||||
|
symbolHandle name(THREAD, cp->symbol_at(name_ref_index));
|
||||||
|
if (ref_kind == JVM_REF_newInvokeSpecial) {
|
||||||
|
if (name() != vmSymbols::object_initializer_name()) {
|
||||||
|
classfile_parse_error(
|
||||||
|
"Bad constructor name at constant pool index %u in class file %s",
|
||||||
|
name_ref_index, CHECK_(nullHandle));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (name() == vmSymbols::object_initializer_name()) {
|
||||||
|
classfile_parse_error(
|
||||||
|
"Bad method name at constant pool index %u in class file %s",
|
||||||
|
name_ref_index, CHECK_(nullHandle));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
// Other ref_kinds are already fully checked in previous pass.
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case JVM_CONSTANT_MethodType: {
|
||||||
|
symbolHandle no_name = vmSymbolHandles::type_name(); // place holder
|
||||||
|
symbolHandle signature(THREAD, cp->method_type_signature_at(index));
|
||||||
|
verify_legal_method_signature(no_name, signature, CHECK_(nullHandle));
|
||||||
|
break;
|
||||||
|
}
|
||||||
} // end of switch
|
} // end of switch
|
||||||
} // end of for
|
} // end of for
|
||||||
|
|
||||||
@ -467,7 +581,7 @@ void ClassFileParser::patch_constant_pool(constantPoolHandle cp, int index, Hand
|
|||||||
case JVM_CONSTANT_UnresolvedClass :
|
case JVM_CONSTANT_UnresolvedClass :
|
||||||
// Patching a class means pre-resolving it.
|
// Patching a class means pre-resolving it.
|
||||||
// The name in the constant pool is ignored.
|
// The name in the constant pool is ignored.
|
||||||
if (patch->klass() == SystemDictionary::Class_klass()) { // %%% java_lang_Class::is_instance
|
if (java_lang_Class::is_instance(patch())) {
|
||||||
guarantee_property(!java_lang_Class::is_primitive(patch()),
|
guarantee_property(!java_lang_Class::is_primitive(patch()),
|
||||||
"Illegal class patch at %d in class file %s",
|
"Illegal class patch at %d in class file %s",
|
||||||
index, CHECK);
|
index, CHECK);
|
||||||
|
@ -2454,6 +2454,48 @@ Handle SystemDictionary::find_method_handle_type(symbolHandle signature,
|
|||||||
return Handle(THREAD, (oop) result.get_jobject());
|
return Handle(THREAD, (oop) result.get_jobject());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ask Java code to find or construct a method handle constant.
|
||||||
|
Handle SystemDictionary::link_method_handle_constant(KlassHandle caller,
|
||||||
|
int ref_kind, //e.g., JVM_REF_invokeVirtual
|
||||||
|
KlassHandle callee,
|
||||||
|
symbolHandle name_sym,
|
||||||
|
symbolHandle signature,
|
||||||
|
TRAPS) {
|
||||||
|
Handle empty;
|
||||||
|
Handle name = java_lang_String::create_from_symbol(name_sym(), CHECK_(empty));
|
||||||
|
Handle type;
|
||||||
|
if (signature->utf8_length() > 0 && signature->byte_at(0) == '(') {
|
||||||
|
bool ignore_is_on_bcp = false;
|
||||||
|
type = find_method_handle_type(signature, caller, ignore_is_on_bcp, CHECK_(empty));
|
||||||
|
} else {
|
||||||
|
SignatureStream ss(signature(), false);
|
||||||
|
if (!ss.is_done()) {
|
||||||
|
oop mirror = ss.as_java_mirror(caller->class_loader(), caller->protection_domain(),
|
||||||
|
SignatureStream::NCDFError, CHECK_(empty));
|
||||||
|
type = Handle(THREAD, mirror);
|
||||||
|
ss.next();
|
||||||
|
if (!ss.is_done()) type = Handle(); // error!
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (type.is_null()) {
|
||||||
|
THROW_MSG_(vmSymbols::java_lang_LinkageError(), "bad signature", empty);
|
||||||
|
}
|
||||||
|
|
||||||
|
// call sun.dyn.MethodHandleNatives::linkMethodHandleConstant(Class caller, int refKind, Class callee, String name, Object type) -> MethodHandle
|
||||||
|
JavaCallArguments args;
|
||||||
|
args.push_oop(caller->java_mirror()); // the referring class
|
||||||
|
args.push_int(ref_kind);
|
||||||
|
args.push_oop(callee->java_mirror()); // the target class
|
||||||
|
args.push_oop(name());
|
||||||
|
args.push_oop(type());
|
||||||
|
JavaValue result(T_OBJECT);
|
||||||
|
JavaCalls::call_static(&result,
|
||||||
|
SystemDictionary::MethodHandleNatives_klass(),
|
||||||
|
vmSymbols::linkMethodHandleConstant_name(),
|
||||||
|
vmSymbols::linkMethodHandleConstant_signature(),
|
||||||
|
&args, CHECK_(empty));
|
||||||
|
return Handle(THREAD, (oop) result.get_jobject());
|
||||||
|
}
|
||||||
|
|
||||||
// Ask Java code to find or construct a java.dyn.CallSite for the given
|
// Ask Java code to find or construct a java.dyn.CallSite for the given
|
||||||
// name and signature, as interpreted relative to the given class loader.
|
// name and signature, as interpreted relative to the given class loader.
|
||||||
|
@ -473,6 +473,13 @@ public:
|
|||||||
KlassHandle accessing_klass,
|
KlassHandle accessing_klass,
|
||||||
bool& return_bcp_flag,
|
bool& return_bcp_flag,
|
||||||
TRAPS);
|
TRAPS);
|
||||||
|
// ask Java to compute a java.dyn.MethodHandle object for a given CP entry
|
||||||
|
static Handle link_method_handle_constant(KlassHandle caller,
|
||||||
|
int ref_kind, //e.g., JVM_REF_invokeVirtual
|
||||||
|
KlassHandle callee,
|
||||||
|
symbolHandle name,
|
||||||
|
symbolHandle signature,
|
||||||
|
TRAPS);
|
||||||
// ask Java to create a dynamic call site, while linking an invokedynamic op
|
// ask Java to create a dynamic call site, while linking an invokedynamic op
|
||||||
static Handle make_dynamic_call_site(Handle bootstrap_method,
|
static Handle make_dynamic_call_site(Handle bootstrap_method,
|
||||||
// Callee information:
|
// Callee information:
|
||||||
|
@ -1598,7 +1598,10 @@ void ClassVerifier::verify_ldc(
|
|||||||
if (opcode == Bytecodes::_ldc || opcode == Bytecodes::_ldc_w) {
|
if (opcode == Bytecodes::_ldc || opcode == Bytecodes::_ldc_w) {
|
||||||
if (!tag.is_unresolved_string() && !tag.is_unresolved_klass()) {
|
if (!tag.is_unresolved_string() && !tag.is_unresolved_klass()) {
|
||||||
types = (1 << JVM_CONSTANT_Integer) | (1 << JVM_CONSTANT_Float)
|
types = (1 << JVM_CONSTANT_Integer) | (1 << JVM_CONSTANT_Float)
|
||||||
| (1 << JVM_CONSTANT_String) | (1 << JVM_CONSTANT_Class);
|
| (1 << JVM_CONSTANT_String) | (1 << JVM_CONSTANT_Class)
|
||||||
|
| (1 << JVM_CONSTANT_MethodHandle) | (1 << JVM_CONSTANT_MethodType);
|
||||||
|
// Note: The class file parser already verified the legality of
|
||||||
|
// MethodHandle and MethodType constants.
|
||||||
verify_cp_type(index, cp, types, CHECK_VERIFY(this));
|
verify_cp_type(index, cp, types, CHECK_VERIFY(this));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -1632,6 +1635,14 @@ void ClassVerifier::verify_ldc(
|
|||||||
current_frame->push_stack_2(
|
current_frame->push_stack_2(
|
||||||
VerificationType::long_type(),
|
VerificationType::long_type(),
|
||||||
VerificationType::long2_type(), CHECK_VERIFY(this));
|
VerificationType::long2_type(), CHECK_VERIFY(this));
|
||||||
|
} else if (tag.is_method_handle()) {
|
||||||
|
current_frame->push_stack(
|
||||||
|
VerificationType::reference_type(
|
||||||
|
vmSymbols::java_dyn_MethodHandle()), CHECK_VERIFY(this));
|
||||||
|
} else if (tag.is_method_type()) {
|
||||||
|
current_frame->push_stack(
|
||||||
|
VerificationType::reference_type(
|
||||||
|
vmSymbols::java_dyn_MethodType()), CHECK_VERIFY(this));
|
||||||
} else {
|
} else {
|
||||||
verify_error(bci, "Invalid index in ldc");
|
verify_error(bci, "Invalid index in ldc");
|
||||||
return;
|
return;
|
||||||
@ -1920,9 +1931,12 @@ void ClassVerifier::verify_invoke_instructions(
|
|||||||
// Get referenced class type
|
// Get referenced class type
|
||||||
VerificationType ref_class_type;
|
VerificationType ref_class_type;
|
||||||
if (opcode == Bytecodes::_invokedynamic) {
|
if (opcode == Bytecodes::_invokedynamic) {
|
||||||
if (!EnableInvokeDynamic) {
|
if (!EnableInvokeDynamic ||
|
||||||
|
_klass->major_version() < Verifier::INVOKEDYNAMIC_MAJOR_VERSION) {
|
||||||
class_format_error(
|
class_format_error(
|
||||||
"invokedynamic instructions not enabled on this JVM",
|
(!EnableInvokeDynamic ?
|
||||||
|
"invokedynamic instructions not enabled in this JVM" :
|
||||||
|
"invokedynamic instructions not supported by this class file version"),
|
||||||
_klass->external_name());
|
_klass->external_name());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,10 @@
|
|||||||
// The verifier class
|
// The verifier class
|
||||||
class Verifier : AllStatic {
|
class Verifier : AllStatic {
|
||||||
public:
|
public:
|
||||||
enum { STACKMAP_ATTRIBUTE_MAJOR_VERSION = 50 };
|
enum {
|
||||||
|
STACKMAP_ATTRIBUTE_MAJOR_VERSION = 50,
|
||||||
|
INVOKEDYNAMIC_MAJOR_VERSION = 51
|
||||||
|
};
|
||||||
typedef enum { ThrowException, NoException } Mode;
|
typedef enum { ThrowException, NoException } Mode;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -246,6 +246,8 @@
|
|||||||
/* internal up-calls made only by the JVM, via class sun.dyn.MethodHandleNatives: */ \
|
/* internal up-calls made only by the JVM, via class sun.dyn.MethodHandleNatives: */ \
|
||||||
template(findMethodHandleType_name, "findMethodHandleType") \
|
template(findMethodHandleType_name, "findMethodHandleType") \
|
||||||
template(findMethodHandleType_signature, "(Ljava/lang/Class;[Ljava/lang/Class;)Ljava/dyn/MethodType;") \
|
template(findMethodHandleType_signature, "(Ljava/lang/Class;[Ljava/lang/Class;)Ljava/dyn/MethodType;") \
|
||||||
|
template(linkMethodHandleConstant_name, "linkMethodHandleConstant") \
|
||||||
|
template(linkMethodHandleConstant_signature, "(Ljava/lang/Class;ILjava/lang/Class;Ljava/lang/String;Ljava/lang/Object;)Ljava/dyn/MethodHandle;") \
|
||||||
template(makeDynamicCallSite_name, "makeDynamicCallSite") \
|
template(makeDynamicCallSite_name, "makeDynamicCallSite") \
|
||||||
template(makeDynamicCallSite_signature, "(Ljava/dyn/MethodHandle;Ljava/lang/String;Ljava/dyn/MethodType;Ljava/lang/Object;Lsun/dyn/MemberName;I)Ljava/dyn/CallSite;") \
|
template(makeDynamicCallSite_signature, "(Ljava/dyn/MethodHandle;Ljava/lang/String;Ljava/dyn/MethodType;Ljava/lang/Object;Lsun/dyn/MemberName;I)Ljava/dyn/CallSite;") \
|
||||||
NOT_LP64( do_alias(machine_word_signature, int_signature) ) \
|
NOT_LP64( do_alias(machine_word_signature, int_signature) ) \
|
||||||
|
@ -584,6 +584,7 @@ nmethod::nmethod(
|
|||||||
_oops_do_mark_link = NULL;
|
_oops_do_mark_link = NULL;
|
||||||
_method = method;
|
_method = method;
|
||||||
_entry_bci = InvocationEntryBci;
|
_entry_bci = InvocationEntryBci;
|
||||||
|
_jmethod_id = NULL;
|
||||||
_osr_link = NULL;
|
_osr_link = NULL;
|
||||||
_scavenge_root_link = NULL;
|
_scavenge_root_link = NULL;
|
||||||
_scavenge_root_state = 0;
|
_scavenge_root_state = 0;
|
||||||
@ -677,6 +678,7 @@ nmethod::nmethod(
|
|||||||
_oops_do_mark_link = NULL;
|
_oops_do_mark_link = NULL;
|
||||||
_method = method;
|
_method = method;
|
||||||
_entry_bci = InvocationEntryBci;
|
_entry_bci = InvocationEntryBci;
|
||||||
|
_jmethod_id = NULL;
|
||||||
_osr_link = NULL;
|
_osr_link = NULL;
|
||||||
_scavenge_root_link = NULL;
|
_scavenge_root_link = NULL;
|
||||||
_scavenge_root_state = 0;
|
_scavenge_root_state = 0;
|
||||||
@ -784,6 +786,7 @@ nmethod::nmethod(
|
|||||||
NOT_PRODUCT(_has_debug_info = false);
|
NOT_PRODUCT(_has_debug_info = false);
|
||||||
_oops_do_mark_link = NULL;
|
_oops_do_mark_link = NULL;
|
||||||
_method = method;
|
_method = method;
|
||||||
|
_jmethod_id = NULL;
|
||||||
_compile_id = compile_id;
|
_compile_id = compile_id;
|
||||||
_comp_level = comp_level;
|
_comp_level = comp_level;
|
||||||
_entry_bci = entry_bci;
|
_entry_bci = entry_bci;
|
||||||
@ -1488,11 +1491,25 @@ void nmethod::post_compiled_method_load_event() {
|
|||||||
moop->signature()->utf8_length(),
|
moop->signature()->utf8_length(),
|
||||||
code_begin(), code_size());
|
code_begin(), code_size());
|
||||||
|
|
||||||
|
if (JvmtiExport::should_post_compiled_method_load() ||
|
||||||
|
JvmtiExport::should_post_compiled_method_unload()) {
|
||||||
|
get_and_cache_jmethod_id();
|
||||||
|
}
|
||||||
|
|
||||||
if (JvmtiExport::should_post_compiled_method_load()) {
|
if (JvmtiExport::should_post_compiled_method_load()) {
|
||||||
JvmtiExport::post_compiled_method_load(this);
|
JvmtiExport::post_compiled_method_load(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
jmethodID nmethod::get_and_cache_jmethod_id() {
|
||||||
|
if (_jmethod_id == NULL) {
|
||||||
|
// Cache the jmethod_id since it can no longer be looked up once the
|
||||||
|
// method itself has been marked for unloading.
|
||||||
|
_jmethod_id = method()->jmethod_id();
|
||||||
|
}
|
||||||
|
return _jmethod_id;
|
||||||
|
}
|
||||||
|
|
||||||
void nmethod::post_compiled_method_unload() {
|
void nmethod::post_compiled_method_unload() {
|
||||||
if (unload_reported()) {
|
if (unload_reported()) {
|
||||||
// During unloading we transition to unloaded and then to zombie
|
// During unloading we transition to unloaded and then to zombie
|
||||||
@ -1504,12 +1521,17 @@ void nmethod::post_compiled_method_unload() {
|
|||||||
DTRACE_METHOD_UNLOAD_PROBE(method());
|
DTRACE_METHOD_UNLOAD_PROBE(method());
|
||||||
|
|
||||||
// If a JVMTI agent has enabled the CompiledMethodUnload event then
|
// If a JVMTI agent has enabled the CompiledMethodUnload event then
|
||||||
// post the event. Sometime later this nmethod will be made a zombie by
|
// post the event. Sometime later this nmethod will be made a zombie
|
||||||
// the sweeper but the methodOop will not be valid at that point.
|
// by the sweeper but the methodOop will not be valid at that point.
|
||||||
if (JvmtiExport::should_post_compiled_method_unload()) {
|
// If the _jmethod_id is null then no load event was ever requested
|
||||||
|
// so don't bother posting the unload. The main reason for this is
|
||||||
|
// that the jmethodID is a weak reference to the methodOop so if
|
||||||
|
// it's being unloaded there's no way to look it up since the weak
|
||||||
|
// ref will have been cleared.
|
||||||
|
if (_jmethod_id != NULL && JvmtiExport::should_post_compiled_method_unload()) {
|
||||||
assert(!unload_reported(), "already unloaded");
|
assert(!unload_reported(), "already unloaded");
|
||||||
HandleMark hm;
|
HandleMark hm;
|
||||||
JvmtiExport::post_compiled_method_unload(method()->jmethod_id(), code_begin());
|
JvmtiExport::post_compiled_method_unload(_jmethod_id, code_begin());
|
||||||
}
|
}
|
||||||
|
|
||||||
// The JVMTI CompiledMethodUnload event can be enabled or disabled at
|
// The JVMTI CompiledMethodUnload event can be enabled or disabled at
|
||||||
@ -2659,13 +2681,10 @@ void nmethod::print_code_comment_on(outputStream* st, int column, u_char* begin,
|
|||||||
case Bytecodes::_getstatic:
|
case Bytecodes::_getstatic:
|
||||||
case Bytecodes::_putstatic:
|
case Bytecodes::_putstatic:
|
||||||
{
|
{
|
||||||
methodHandle sdm = sd->method();
|
Bytecode_field* field = Bytecode_field_at(sd->method(), sd->bci());
|
||||||
Bytecode_field* field = Bytecode_field_at(sdm(), sdm->bcp_from(sd->bci()));
|
|
||||||
constantPoolOop sdmc = sdm->constants();
|
|
||||||
symbolOop name = sdmc->name_ref_at(field->index());
|
|
||||||
st->print(" ");
|
st->print(" ");
|
||||||
if (name != NULL)
|
if (field->name() != NULL)
|
||||||
name->print_symbol_on(st);
|
field->name()->print_symbol_on(st);
|
||||||
else
|
else
|
||||||
st->print("<UNKNOWN>");
|
st->print("<UNKNOWN>");
|
||||||
}
|
}
|
||||||
|
@ -135,6 +135,7 @@ class nmethod : public CodeBlob {
|
|||||||
|
|
||||||
methodOop _method;
|
methodOop _method;
|
||||||
int _entry_bci; // != InvocationEntryBci if this nmethod is an on-stack replacement method
|
int _entry_bci; // != InvocationEntryBci if this nmethod is an on-stack replacement method
|
||||||
|
jmethodID _jmethod_id; // Cache of method()->jmethod_id()
|
||||||
|
|
||||||
// To support simple linked-list chaining of nmethods:
|
// To support simple linked-list chaining of nmethods:
|
||||||
nmethod* _osr_link; // from instanceKlass::osr_nmethods_head
|
nmethod* _osr_link; // from instanceKlass::osr_nmethods_head
|
||||||
@ -599,6 +600,7 @@ public:
|
|||||||
|
|
||||||
// jvmti support:
|
// jvmti support:
|
||||||
void post_compiled_method_load_event();
|
void post_compiled_method_load_event();
|
||||||
|
jmethodID get_and_cache_jmethod_id();
|
||||||
|
|
||||||
// verify operations
|
// verify operations
|
||||||
void verify();
|
void verify();
|
||||||
|
@ -3972,6 +3972,10 @@ public:
|
|||||||
|
|
||||||
void work(int i) {
|
void work(int i) {
|
||||||
if (i >= _n_workers) return; // no work needed this round
|
if (i >= _n_workers) return; // no work needed this round
|
||||||
|
|
||||||
|
double start_time_ms = os::elapsedTime() * 1000.0;
|
||||||
|
_g1h->g1_policy()->record_gc_worker_start_time(i, start_time_ms);
|
||||||
|
|
||||||
ResourceMark rm;
|
ResourceMark rm;
|
||||||
HandleMark hm;
|
HandleMark hm;
|
||||||
|
|
||||||
@ -4019,7 +4023,7 @@ public:
|
|||||||
double elapsed_ms = (os::elapsedTime()-start)*1000.0;
|
double elapsed_ms = (os::elapsedTime()-start)*1000.0;
|
||||||
double term_ms = pss.term_time()*1000.0;
|
double term_ms = pss.term_time()*1000.0;
|
||||||
_g1h->g1_policy()->record_obj_copy_time(i, elapsed_ms-term_ms);
|
_g1h->g1_policy()->record_obj_copy_time(i, elapsed_ms-term_ms);
|
||||||
_g1h->g1_policy()->record_termination_time(i, term_ms);
|
_g1h->g1_policy()->record_termination(i, term_ms, pss.term_attempts());
|
||||||
}
|
}
|
||||||
_g1h->g1_policy()->record_thread_age_table(pss.age_table());
|
_g1h->g1_policy()->record_thread_age_table(pss.age_table());
|
||||||
_g1h->update_surviving_young_words(pss.surviving_young_words()+1);
|
_g1h->update_surviving_young_words(pss.surviving_young_words()+1);
|
||||||
@ -4043,7 +4047,8 @@ public:
|
|||||||
double term = pss.term_time();
|
double term = pss.term_time();
|
||||||
gclog_or_tty->print(" Elapsed: %7.2f ms.\n"
|
gclog_or_tty->print(" Elapsed: %7.2f ms.\n"
|
||||||
" Strong roots: %7.2f ms (%6.2f%%)\n"
|
" Strong roots: %7.2f ms (%6.2f%%)\n"
|
||||||
" Termination: %7.2f ms (%6.2f%%) (in %d entries)\n",
|
" Termination: %7.2f ms (%6.2f%%) "
|
||||||
|
"(in "SIZE_FORMAT" entries)\n",
|
||||||
elapsed * 1000.0,
|
elapsed * 1000.0,
|
||||||
strong_roots * 1000.0, (strong_roots*100.0/elapsed),
|
strong_roots * 1000.0, (strong_roots*100.0/elapsed),
|
||||||
term * 1000.0, (term*100.0/elapsed),
|
term * 1000.0, (term*100.0/elapsed),
|
||||||
@ -4059,6 +4064,8 @@ public:
|
|||||||
|
|
||||||
assert(pss.refs_to_scan() == 0, "Task queue should be empty");
|
assert(pss.refs_to_scan() == 0, "Task queue should be empty");
|
||||||
assert(pss.overflowed_refs_to_scan() == 0, "Overflow queue should be empty");
|
assert(pss.overflowed_refs_to_scan() == 0, "Overflow queue should be empty");
|
||||||
|
double end_time_ms = os::elapsedTime() * 1000.0;
|
||||||
|
_g1h->g1_policy()->record_gc_worker_end_time(i, end_time_ms);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1549,7 +1549,7 @@ protected:
|
|||||||
int _hash_seed;
|
int _hash_seed;
|
||||||
int _queue_num;
|
int _queue_num;
|
||||||
|
|
||||||
int _term_attempts;
|
size_t _term_attempts;
|
||||||
#if G1_DETAILED_STATS
|
#if G1_DETAILED_STATS
|
||||||
int _pushes, _pops, _steals, _steal_attempts;
|
int _pushes, _pops, _steals, _steal_attempts;
|
||||||
int _overflow_pushes;
|
int _overflow_pushes;
|
||||||
@ -1727,8 +1727,8 @@ public:
|
|||||||
int* hash_seed() { return &_hash_seed; }
|
int* hash_seed() { return &_hash_seed; }
|
||||||
int queue_num() { return _queue_num; }
|
int queue_num() { return _queue_num; }
|
||||||
|
|
||||||
int term_attempts() { return _term_attempts; }
|
size_t term_attempts() { return _term_attempts; }
|
||||||
void note_term_attempt() { _term_attempts++; }
|
void note_term_attempt() { _term_attempts++; }
|
||||||
|
|
||||||
#if G1_DETAILED_STATS
|
#if G1_DETAILED_STATS
|
||||||
int pushes() { return _pushes; }
|
int pushes() { return _pushes; }
|
||||||
|
@ -231,20 +231,21 @@ G1CollectorPolicy::G1CollectorPolicy() :
|
|||||||
_recent_prev_end_times_for_all_gcs_sec->add(os::elapsedTime());
|
_recent_prev_end_times_for_all_gcs_sec->add(os::elapsedTime());
|
||||||
_prev_collection_pause_end_ms = os::elapsedTime() * 1000.0;
|
_prev_collection_pause_end_ms = os::elapsedTime() * 1000.0;
|
||||||
|
|
||||||
|
_par_last_gc_worker_start_times_ms = new double[_parallel_gc_threads];
|
||||||
_par_last_ext_root_scan_times_ms = new double[_parallel_gc_threads];
|
_par_last_ext_root_scan_times_ms = new double[_parallel_gc_threads];
|
||||||
_par_last_mark_stack_scan_times_ms = new double[_parallel_gc_threads];
|
_par_last_mark_stack_scan_times_ms = new double[_parallel_gc_threads];
|
||||||
|
|
||||||
_par_last_update_rs_start_times_ms = new double[_parallel_gc_threads];
|
|
||||||
_par_last_update_rs_times_ms = new double[_parallel_gc_threads];
|
_par_last_update_rs_times_ms = new double[_parallel_gc_threads];
|
||||||
_par_last_update_rs_processed_buffers = new double[_parallel_gc_threads];
|
_par_last_update_rs_processed_buffers = new double[_parallel_gc_threads];
|
||||||
|
|
||||||
_par_last_scan_rs_start_times_ms = new double[_parallel_gc_threads];
|
|
||||||
_par_last_scan_rs_times_ms = new double[_parallel_gc_threads];
|
_par_last_scan_rs_times_ms = new double[_parallel_gc_threads];
|
||||||
_par_last_scan_new_refs_times_ms = new double[_parallel_gc_threads];
|
_par_last_scan_new_refs_times_ms = new double[_parallel_gc_threads];
|
||||||
|
|
||||||
_par_last_obj_copy_times_ms = new double[_parallel_gc_threads];
|
_par_last_obj_copy_times_ms = new double[_parallel_gc_threads];
|
||||||
|
|
||||||
_par_last_termination_times_ms = new double[_parallel_gc_threads];
|
_par_last_termination_times_ms = new double[_parallel_gc_threads];
|
||||||
|
_par_last_termination_attempts = new double[_parallel_gc_threads];
|
||||||
|
_par_last_gc_worker_end_times_ms = new double[_parallel_gc_threads];
|
||||||
|
|
||||||
// start conservatively
|
// start conservatively
|
||||||
_expensive_region_limit_ms = 0.5 * (double) MaxGCPauseMillis;
|
_expensive_region_limit_ms = 0.5 * (double) MaxGCPauseMillis;
|
||||||
@ -274,10 +275,64 @@ G1CollectorPolicy::G1CollectorPolicy() :
|
|||||||
|
|
||||||
// </NEW PREDICTION>
|
// </NEW PREDICTION>
|
||||||
|
|
||||||
double time_slice = (double) GCPauseIntervalMillis / 1000.0;
|
// Below, we might need to calculate the pause time target based on
|
||||||
|
// the pause interval. When we do so we are going to give G1 maximum
|
||||||
|
// flexibility and allow it to do pauses when it needs to. So, we'll
|
||||||
|
// arrange that the pause interval to be pause time target + 1 to
|
||||||
|
// ensure that a) the pause time target is maximized with respect to
|
||||||
|
// the pause interval and b) we maintain the invariant that pause
|
||||||
|
// time target < pause interval. If the user does not want this
|
||||||
|
// maximum flexibility, they will have to set the pause interval
|
||||||
|
// explicitly.
|
||||||
|
|
||||||
|
// First make sure that, if either parameter is set, its value is
|
||||||
|
// reasonable.
|
||||||
|
if (!FLAG_IS_DEFAULT(MaxGCPauseMillis)) {
|
||||||
|
if (MaxGCPauseMillis < 1) {
|
||||||
|
vm_exit_during_initialization("MaxGCPauseMillis should be "
|
||||||
|
"greater than 0");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!FLAG_IS_DEFAULT(GCPauseIntervalMillis)) {
|
||||||
|
if (GCPauseIntervalMillis < 1) {
|
||||||
|
vm_exit_during_initialization("GCPauseIntervalMillis should be "
|
||||||
|
"greater than 0");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Then, if the pause time target parameter was not set, set it to
|
||||||
|
// the default value.
|
||||||
|
if (FLAG_IS_DEFAULT(MaxGCPauseMillis)) {
|
||||||
|
if (FLAG_IS_DEFAULT(GCPauseIntervalMillis)) {
|
||||||
|
// The default pause time target in G1 is 200ms
|
||||||
|
FLAG_SET_DEFAULT(MaxGCPauseMillis, 200);
|
||||||
|
} else {
|
||||||
|
// We do not allow the pause interval to be set without the
|
||||||
|
// pause time target
|
||||||
|
vm_exit_during_initialization("GCPauseIntervalMillis cannot be set "
|
||||||
|
"without setting MaxGCPauseMillis");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Then, if the interval parameter was not set, set it according to
|
||||||
|
// the pause time target (this will also deal with the case when the
|
||||||
|
// pause time target is the default value).
|
||||||
|
if (FLAG_IS_DEFAULT(GCPauseIntervalMillis)) {
|
||||||
|
FLAG_SET_DEFAULT(GCPauseIntervalMillis, MaxGCPauseMillis + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Finally, make sure that the two parameters are consistent.
|
||||||
|
if (MaxGCPauseMillis >= GCPauseIntervalMillis) {
|
||||||
|
char buffer[256];
|
||||||
|
jio_snprintf(buffer, 256,
|
||||||
|
"MaxGCPauseMillis (%u) should be less than "
|
||||||
|
"GCPauseIntervalMillis (%u)",
|
||||||
|
MaxGCPauseMillis, GCPauseIntervalMillis);
|
||||||
|
vm_exit_during_initialization(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
double max_gc_time = (double) MaxGCPauseMillis / 1000.0;
|
double max_gc_time = (double) MaxGCPauseMillis / 1000.0;
|
||||||
guarantee(max_gc_time < time_slice,
|
double time_slice = (double) GCPauseIntervalMillis / 1000.0;
|
||||||
"Max GC time should not be greater than the time slice");
|
|
||||||
_mmu_tracker = new G1MMUTrackerQueue(time_slice, max_gc_time);
|
_mmu_tracker = new G1MMUTrackerQueue(time_slice, max_gc_time);
|
||||||
_sigma = (double) G1ConfidencePercent / 100.0;
|
_sigma = (double) G1ConfidencePercent / 100.0;
|
||||||
|
|
||||||
@ -782,16 +837,17 @@ void G1CollectorPolicy::record_collection_pause_start(double start_time_sec,
|
|||||||
// if they are not set properly
|
// if they are not set properly
|
||||||
|
|
||||||
for (int i = 0; i < _parallel_gc_threads; ++i) {
|
for (int i = 0; i < _parallel_gc_threads; ++i) {
|
||||||
_par_last_ext_root_scan_times_ms[i] = -666.0;
|
_par_last_gc_worker_start_times_ms[i] = -1234.0;
|
||||||
_par_last_mark_stack_scan_times_ms[i] = -666.0;
|
_par_last_ext_root_scan_times_ms[i] = -1234.0;
|
||||||
_par_last_update_rs_start_times_ms[i] = -666.0;
|
_par_last_mark_stack_scan_times_ms[i] = -1234.0;
|
||||||
_par_last_update_rs_times_ms[i] = -666.0;
|
_par_last_update_rs_times_ms[i] = -1234.0;
|
||||||
_par_last_update_rs_processed_buffers[i] = -666.0;
|
_par_last_update_rs_processed_buffers[i] = -1234.0;
|
||||||
_par_last_scan_rs_start_times_ms[i] = -666.0;
|
_par_last_scan_rs_times_ms[i] = -1234.0;
|
||||||
_par_last_scan_rs_times_ms[i] = -666.0;
|
_par_last_scan_new_refs_times_ms[i] = -1234.0;
|
||||||
_par_last_scan_new_refs_times_ms[i] = -666.0;
|
_par_last_obj_copy_times_ms[i] = -1234.0;
|
||||||
_par_last_obj_copy_times_ms[i] = -666.0;
|
_par_last_termination_times_ms[i] = -1234.0;
|
||||||
_par_last_termination_times_ms[i] = -666.0;
|
_par_last_termination_attempts[i] = -1234.0;
|
||||||
|
_par_last_gc_worker_end_times_ms[i] = -1234.0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -942,9 +998,9 @@ T sum_of(T* sum_arr, int start, int n, int N) {
|
|||||||
return sum;
|
return sum;
|
||||||
}
|
}
|
||||||
|
|
||||||
void G1CollectorPolicy::print_par_stats (int level,
|
void G1CollectorPolicy::print_par_stats(int level,
|
||||||
const char* str,
|
const char* str,
|
||||||
double* data,
|
double* data,
|
||||||
bool summary) {
|
bool summary) {
|
||||||
double min = data[0], max = data[0];
|
double min = data[0], max = data[0];
|
||||||
double total = 0.0;
|
double total = 0.0;
|
||||||
@ -973,10 +1029,10 @@ void G1CollectorPolicy::print_par_stats (int level,
|
|||||||
gclog_or_tty->print_cr("]");
|
gclog_or_tty->print_cr("]");
|
||||||
}
|
}
|
||||||
|
|
||||||
void G1CollectorPolicy::print_par_buffers (int level,
|
void G1CollectorPolicy::print_par_sizes(int level,
|
||||||
const char* str,
|
const char* str,
|
||||||
double* data,
|
double* data,
|
||||||
bool summary) {
|
bool summary) {
|
||||||
double min = data[0], max = data[0];
|
double min = data[0], max = data[0];
|
||||||
double total = 0.0;
|
double total = 0.0;
|
||||||
int j;
|
int j;
|
||||||
@ -1321,15 +1377,22 @@ void G1CollectorPolicy::record_collection_pause_end(bool abandoned) {
|
|||||||
}
|
}
|
||||||
if (parallel) {
|
if (parallel) {
|
||||||
print_stats(1, "Parallel Time", _cur_collection_par_time_ms);
|
print_stats(1, "Parallel Time", _cur_collection_par_time_ms);
|
||||||
print_par_stats(2, "Update RS (Start)", _par_last_update_rs_start_times_ms, false);
|
print_par_stats(2, "GC Worker Start Time",
|
||||||
|
_par_last_gc_worker_start_times_ms, false);
|
||||||
print_par_stats(2, "Update RS", _par_last_update_rs_times_ms);
|
print_par_stats(2, "Update RS", _par_last_update_rs_times_ms);
|
||||||
print_par_buffers(3, "Processed Buffers",
|
print_par_sizes(3, "Processed Buffers",
|
||||||
_par_last_update_rs_processed_buffers, true);
|
_par_last_update_rs_processed_buffers, true);
|
||||||
print_par_stats(2, "Ext Root Scanning", _par_last_ext_root_scan_times_ms);
|
print_par_stats(2, "Ext Root Scanning",
|
||||||
print_par_stats(2, "Mark Stack Scanning", _par_last_mark_stack_scan_times_ms);
|
_par_last_ext_root_scan_times_ms);
|
||||||
|
print_par_stats(2, "Mark Stack Scanning",
|
||||||
|
_par_last_mark_stack_scan_times_ms);
|
||||||
print_par_stats(2, "Scan RS", _par_last_scan_rs_times_ms);
|
print_par_stats(2, "Scan RS", _par_last_scan_rs_times_ms);
|
||||||
print_par_stats(2, "Object Copy", _par_last_obj_copy_times_ms);
|
print_par_stats(2, "Object Copy", _par_last_obj_copy_times_ms);
|
||||||
print_par_stats(2, "Termination", _par_last_termination_times_ms);
|
print_par_stats(2, "Termination", _par_last_termination_times_ms);
|
||||||
|
print_par_sizes(3, "Termination Attempts",
|
||||||
|
_par_last_termination_attempts, true);
|
||||||
|
print_par_stats(2, "GC Worker End Time",
|
||||||
|
_par_last_gc_worker_end_times_ms, false);
|
||||||
print_stats(2, "Other", parallel_other_time);
|
print_stats(2, "Other", parallel_other_time);
|
||||||
print_stats(1, "Clear CT", _cur_clear_ct_time_ms);
|
print_stats(1, "Clear CT", _cur_clear_ct_time_ms);
|
||||||
} else {
|
} else {
|
||||||
|
@ -171,16 +171,17 @@ protected:
|
|||||||
double* _cur_aux_times_ms;
|
double* _cur_aux_times_ms;
|
||||||
bool* _cur_aux_times_set;
|
bool* _cur_aux_times_set;
|
||||||
|
|
||||||
|
double* _par_last_gc_worker_start_times_ms;
|
||||||
double* _par_last_ext_root_scan_times_ms;
|
double* _par_last_ext_root_scan_times_ms;
|
||||||
double* _par_last_mark_stack_scan_times_ms;
|
double* _par_last_mark_stack_scan_times_ms;
|
||||||
double* _par_last_update_rs_start_times_ms;
|
|
||||||
double* _par_last_update_rs_times_ms;
|
double* _par_last_update_rs_times_ms;
|
||||||
double* _par_last_update_rs_processed_buffers;
|
double* _par_last_update_rs_processed_buffers;
|
||||||
double* _par_last_scan_rs_start_times_ms;
|
|
||||||
double* _par_last_scan_rs_times_ms;
|
double* _par_last_scan_rs_times_ms;
|
||||||
double* _par_last_scan_new_refs_times_ms;
|
double* _par_last_scan_new_refs_times_ms;
|
||||||
double* _par_last_obj_copy_times_ms;
|
double* _par_last_obj_copy_times_ms;
|
||||||
double* _par_last_termination_times_ms;
|
double* _par_last_termination_times_ms;
|
||||||
|
double* _par_last_termination_attempts;
|
||||||
|
double* _par_last_gc_worker_end_times_ms;
|
||||||
|
|
||||||
// indicates that we are in young GC mode
|
// indicates that we are in young GC mode
|
||||||
bool _in_young_gc_mode;
|
bool _in_young_gc_mode;
|
||||||
@ -559,13 +560,14 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void print_stats (int level, const char* str, double value);
|
void print_stats(int level, const char* str, double value);
|
||||||
void print_stats (int level, const char* str, int value);
|
void print_stats(int level, const char* str, int value);
|
||||||
void print_par_stats (int level, const char* str, double* data) {
|
|
||||||
|
void print_par_stats(int level, const char* str, double* data) {
|
||||||
print_par_stats(level, str, data, true);
|
print_par_stats(level, str, data, true);
|
||||||
}
|
}
|
||||||
void print_par_stats (int level, const char* str, double* data, bool summary);
|
void print_par_stats(int level, const char* str, double* data, bool summary);
|
||||||
void print_par_buffers (int level, const char* str, double* data, bool summary);
|
void print_par_sizes(int level, const char* str, double* data, bool summary);
|
||||||
|
|
||||||
void check_other_times(int level,
|
void check_other_times(int level,
|
||||||
NumberSeq* other_times_ms,
|
NumberSeq* other_times_ms,
|
||||||
@ -891,6 +893,10 @@ public:
|
|||||||
virtual void record_full_collection_start();
|
virtual void record_full_collection_start();
|
||||||
virtual void record_full_collection_end();
|
virtual void record_full_collection_end();
|
||||||
|
|
||||||
|
void record_gc_worker_start_time(int worker_i, double ms) {
|
||||||
|
_par_last_gc_worker_start_times_ms[worker_i] = ms;
|
||||||
|
}
|
||||||
|
|
||||||
void record_ext_root_scan_time(int worker_i, double ms) {
|
void record_ext_root_scan_time(int worker_i, double ms) {
|
||||||
_par_last_ext_root_scan_times_ms[worker_i] = ms;
|
_par_last_ext_root_scan_times_ms[worker_i] = ms;
|
||||||
}
|
}
|
||||||
@ -912,10 +918,6 @@ public:
|
|||||||
_all_mod_union_times_ms->add(ms);
|
_all_mod_union_times_ms->add(ms);
|
||||||
}
|
}
|
||||||
|
|
||||||
void record_update_rs_start_time(int thread, double ms) {
|
|
||||||
_par_last_update_rs_start_times_ms[thread] = ms;
|
|
||||||
}
|
|
||||||
|
|
||||||
void record_update_rs_time(int thread, double ms) {
|
void record_update_rs_time(int thread, double ms) {
|
||||||
_par_last_update_rs_times_ms[thread] = ms;
|
_par_last_update_rs_times_ms[thread] = ms;
|
||||||
}
|
}
|
||||||
@ -925,10 +927,6 @@ public:
|
|||||||
_par_last_update_rs_processed_buffers[thread] = processed_buffers;
|
_par_last_update_rs_processed_buffers[thread] = processed_buffers;
|
||||||
}
|
}
|
||||||
|
|
||||||
void record_scan_rs_start_time(int thread, double ms) {
|
|
||||||
_par_last_scan_rs_start_times_ms[thread] = ms;
|
|
||||||
}
|
|
||||||
|
|
||||||
void record_scan_rs_time(int thread, double ms) {
|
void record_scan_rs_time(int thread, double ms) {
|
||||||
_par_last_scan_rs_times_ms[thread] = ms;
|
_par_last_scan_rs_times_ms[thread] = ms;
|
||||||
}
|
}
|
||||||
@ -953,16 +951,13 @@ public:
|
|||||||
_par_last_obj_copy_times_ms[thread] += ms;
|
_par_last_obj_copy_times_ms[thread] += ms;
|
||||||
}
|
}
|
||||||
|
|
||||||
void record_obj_copy_time(double ms) {
|
void record_termination(int thread, double ms, size_t attempts) {
|
||||||
record_obj_copy_time(0, ms);
|
|
||||||
}
|
|
||||||
|
|
||||||
void record_termination_time(int thread, double ms) {
|
|
||||||
_par_last_termination_times_ms[thread] = ms;
|
_par_last_termination_times_ms[thread] = ms;
|
||||||
|
_par_last_termination_attempts[thread] = (double) attempts;
|
||||||
}
|
}
|
||||||
|
|
||||||
void record_termination_time(double ms) {
|
void record_gc_worker_end_time(int worker_i, double ms) {
|
||||||
record_termination_time(0, ms);
|
_par_last_gc_worker_end_times_ms[worker_i] = ms;
|
||||||
}
|
}
|
||||||
|
|
||||||
void record_pause_time_ms(double ms) {
|
void record_pause_time_ms(double ms) {
|
||||||
|
@ -303,7 +303,6 @@ void HRInto_G1RemSet::scanRS(OopsInHeapRegionClosure* oc, int worker_i) {
|
|||||||
assert( _cards_scanned != NULL, "invariant" );
|
assert( _cards_scanned != NULL, "invariant" );
|
||||||
_cards_scanned[worker_i] = scanRScl.cards_done();
|
_cards_scanned[worker_i] = scanRScl.cards_done();
|
||||||
|
|
||||||
_g1p->record_scan_rs_start_time(worker_i, rs_time_start * 1000.0);
|
|
||||||
_g1p->record_scan_rs_time(worker_i, scan_rs_time_sec * 1000.0);
|
_g1p->record_scan_rs_time(worker_i, scan_rs_time_sec * 1000.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -311,8 +310,6 @@ void HRInto_G1RemSet::updateRS(int worker_i) {
|
|||||||
ConcurrentG1Refine* cg1r = _g1->concurrent_g1_refine();
|
ConcurrentG1Refine* cg1r = _g1->concurrent_g1_refine();
|
||||||
|
|
||||||
double start = os::elapsedTime();
|
double start = os::elapsedTime();
|
||||||
_g1p->record_update_rs_start_time(worker_i, start * 1000.0);
|
|
||||||
|
|
||||||
// Apply the appropriate closure to all remaining log entries.
|
// Apply the appropriate closure to all remaining log entries.
|
||||||
_g1->iterate_dirty_card_closure(false, worker_i);
|
_g1->iterate_dirty_card_closure(false, worker_i);
|
||||||
// Now there should be no dirty cards.
|
// Now there should be no dirty cards.
|
||||||
@ -471,7 +468,6 @@ HRInto_G1RemSet::oops_into_collection_set_do(OopsInHeapRegionClosure* oc,
|
|||||||
updateRS(worker_i);
|
updateRS(worker_i);
|
||||||
scanNewRefsRS(oc, worker_i);
|
scanNewRefsRS(oc, worker_i);
|
||||||
} else {
|
} else {
|
||||||
_g1p->record_update_rs_start_time(worker_i, os::elapsedTime() * 1000.0);
|
|
||||||
_g1p->record_update_rs_processed_buffers(worker_i, 0.0);
|
_g1p->record_update_rs_processed_buffers(worker_i, 0.0);
|
||||||
_g1p->record_update_rs_time(worker_i, 0.0);
|
_g1p->record_update_rs_time(worker_i, 0.0);
|
||||||
_g1p->record_scan_new_refs_time(worker_i, 0.0);
|
_g1p->record_scan_new_refs_time(worker_i, 0.0);
|
||||||
@ -479,7 +475,6 @@ HRInto_G1RemSet::oops_into_collection_set_do(OopsInHeapRegionClosure* oc,
|
|||||||
if (G1UseParallelRSetScanning || (worker_i == 0)) {
|
if (G1UseParallelRSetScanning || (worker_i == 0)) {
|
||||||
scanRS(oc, worker_i);
|
scanRS(oc, worker_i);
|
||||||
} else {
|
} else {
|
||||||
_g1p->record_scan_rs_start_time(worker_i, os::elapsedTime() * 1000.0);
|
|
||||||
_g1p->record_scan_rs_time(worker_i, 0.0);
|
_g1p->record_scan_rs_time(worker_i, 0.0);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2001, 2008, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -566,14 +566,14 @@ void CardTableExtension::resize_covered_region_by_end(int changed_region,
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Commit new or uncommit old pages, if necessary.
|
// Commit new or uncommit old pages, if necessary.
|
||||||
resize_commit_uncommit(changed_region, new_region);
|
if (resize_commit_uncommit(changed_region, new_region)) {
|
||||||
|
// Set the new start of the committed region
|
||||||
|
resize_update_committed_table(changed_region, new_region);
|
||||||
|
}
|
||||||
|
|
||||||
// Update card table entries
|
// Update card table entries
|
||||||
resize_update_card_table_entries(changed_region, new_region);
|
resize_update_card_table_entries(changed_region, new_region);
|
||||||
|
|
||||||
// Set the new start of the committed region
|
|
||||||
resize_update_committed_table(changed_region, new_region);
|
|
||||||
|
|
||||||
// Update the covered region
|
// Update the covered region
|
||||||
resize_update_covered_table(changed_region, new_region);
|
resize_update_covered_table(changed_region, new_region);
|
||||||
|
|
||||||
@ -604,8 +604,9 @@ void CardTableExtension::resize_covered_region_by_end(int changed_region,
|
|||||||
debug_only(verify_guard();)
|
debug_only(verify_guard();)
|
||||||
}
|
}
|
||||||
|
|
||||||
void CardTableExtension::resize_commit_uncommit(int changed_region,
|
bool CardTableExtension::resize_commit_uncommit(int changed_region,
|
||||||
MemRegion new_region) {
|
MemRegion new_region) {
|
||||||
|
bool result = false;
|
||||||
// Commit new or uncommit old pages, if necessary.
|
// Commit new or uncommit old pages, if necessary.
|
||||||
MemRegion cur_committed = _committed[changed_region];
|
MemRegion cur_committed = _committed[changed_region];
|
||||||
assert(_covered[changed_region].end() == new_region.end(),
|
assert(_covered[changed_region].end() == new_region.end(),
|
||||||
@ -675,20 +676,31 @@ void CardTableExtension::resize_commit_uncommit(int changed_region,
|
|||||||
"card table expansion");
|
"card table expansion");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
result = true;
|
||||||
} else if (new_start_aligned > cur_committed.start()) {
|
} else if (new_start_aligned > cur_committed.start()) {
|
||||||
// Shrink the committed region
|
// Shrink the committed region
|
||||||
|
#if 0 // uncommitting space is currently unsafe because of the interactions
|
||||||
|
// of growing and shrinking regions. One region A can uncommit space
|
||||||
|
// that it owns but which is being used by another region B (maybe).
|
||||||
|
// Region B has not committed the space because it was already
|
||||||
|
// committed by region A.
|
||||||
MemRegion uncommit_region = committed_unique_to_self(changed_region,
|
MemRegion uncommit_region = committed_unique_to_self(changed_region,
|
||||||
MemRegion(cur_committed.start(), new_start_aligned));
|
MemRegion(cur_committed.start(), new_start_aligned));
|
||||||
if (!uncommit_region.is_empty()) {
|
if (!uncommit_region.is_empty()) {
|
||||||
if (!os::uncommit_memory((char*)uncommit_region.start(),
|
if (!os::uncommit_memory((char*)uncommit_region.start(),
|
||||||
uncommit_region.byte_size())) {
|
uncommit_region.byte_size())) {
|
||||||
vm_exit_out_of_memory(uncommit_region.byte_size(),
|
// If the uncommit fails, ignore it. Let the
|
||||||
"card table contraction");
|
// committed table resizing go even though the committed
|
||||||
|
// table will over state the committed space.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
assert(!result, "Should be false with current workaround");
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
assert(_committed[changed_region].end() == cur_committed.end(),
|
assert(_committed[changed_region].end() == cur_committed.end(),
|
||||||
"end should not change");
|
"end should not change");
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CardTableExtension::resize_update_committed_table(int changed_region,
|
void CardTableExtension::resize_update_committed_table(int changed_region,
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2001, 2008, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -30,7 +30,9 @@ class GCTaskQueue;
|
|||||||
class CardTableExtension : public CardTableModRefBS {
|
class CardTableExtension : public CardTableModRefBS {
|
||||||
private:
|
private:
|
||||||
// Support methods for resizing the card table.
|
// Support methods for resizing the card table.
|
||||||
void resize_commit_uncommit(int changed_region, MemRegion new_region);
|
// resize_commit_uncommit() returns true if the pages were committed or
|
||||||
|
// uncommitted
|
||||||
|
bool resize_commit_uncommit(int changed_region, MemRegion new_region);
|
||||||
void resize_update_card_table_entries(int changed_region,
|
void resize_update_card_table_entries(int changed_region,
|
||||||
MemRegion new_region);
|
MemRegion new_region);
|
||||||
void resize_update_committed_table(int changed_region, MemRegion new_region);
|
void resize_update_committed_table(int changed_region, MemRegion new_region);
|
||||||
|
@ -545,6 +545,7 @@ ciCPCache.cpp ciUtilities.hpp
|
|||||||
|
|
||||||
ciCPCache.hpp ciClassList.hpp
|
ciCPCache.hpp ciClassList.hpp
|
||||||
ciCPCache.hpp ciObject.hpp
|
ciCPCache.hpp ciObject.hpp
|
||||||
|
ciCPCache.hpp cpCacheOop.hpp
|
||||||
|
|
||||||
ciEnv.cpp allocation.inline.hpp
|
ciEnv.cpp allocation.inline.hpp
|
||||||
ciEnv.cpp ciConstant.hpp
|
ciEnv.cpp ciConstant.hpp
|
||||||
@ -823,6 +824,7 @@ ciSignature.hpp growableArray.hpp
|
|||||||
|
|
||||||
ciStreams.cpp ciCallSite.hpp
|
ciStreams.cpp ciCallSite.hpp
|
||||||
ciStreams.cpp ciConstant.hpp
|
ciStreams.cpp ciConstant.hpp
|
||||||
|
ciStreams.cpp ciCPCache.hpp
|
||||||
ciStreams.cpp ciField.hpp
|
ciStreams.cpp ciField.hpp
|
||||||
ciStreams.cpp ciStreams.hpp
|
ciStreams.cpp ciStreams.hpp
|
||||||
ciStreams.cpp ciUtilities.hpp
|
ciStreams.cpp ciUtilities.hpp
|
||||||
|
@ -136,25 +136,24 @@ int Bytecode_tableswitch::dest_offset_at(int i) const {
|
|||||||
// Implementation of Bytecode_invoke
|
// Implementation of Bytecode_invoke
|
||||||
|
|
||||||
void Bytecode_invoke::verify() const {
|
void Bytecode_invoke::verify() const {
|
||||||
Bytecodes::Code bc = adjusted_invoke_code();
|
|
||||||
assert(is_valid(), "check invoke");
|
assert(is_valid(), "check invoke");
|
||||||
assert(method()->constants()->cache() != NULL, "do not call this from verifier or rewriter");
|
assert(method()->constants()->cache() != NULL, "do not call this from verifier or rewriter");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
symbolOop Bytecode_invoke::signature() const {
|
symbolOop Bytecode_member_ref::signature() const {
|
||||||
constantPoolOop constants = method()->constants();
|
constantPoolOop constants = method()->constants();
|
||||||
return constants->signature_ref_at(index());
|
return constants->signature_ref_at(index());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
symbolOop Bytecode_invoke::name() const {
|
symbolOop Bytecode_member_ref::name() const {
|
||||||
constantPoolOop constants = method()->constants();
|
constantPoolOop constants = method()->constants();
|
||||||
return constants->name_ref_at(index());
|
return constants->name_ref_at(index());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
BasicType Bytecode_invoke::result_type(Thread *thread) const {
|
BasicType Bytecode_member_ref::result_type(Thread *thread) const {
|
||||||
symbolHandle sh(thread, signature());
|
symbolHandle sh(thread, signature());
|
||||||
ResultTypeFinder rts(sh);
|
ResultTypeFinder rts(sh);
|
||||||
rts.iterate();
|
rts.iterate();
|
||||||
@ -167,9 +166,9 @@ methodHandle Bytecode_invoke::static_target(TRAPS) {
|
|||||||
KlassHandle resolved_klass;
|
KlassHandle resolved_klass;
|
||||||
constantPoolHandle constants(THREAD, _method->constants());
|
constantPoolHandle constants(THREAD, _method->constants());
|
||||||
|
|
||||||
if (adjusted_invoke_code() == Bytecodes::_invokedynamic) {
|
if (java_code() == Bytecodes::_invokedynamic) {
|
||||||
LinkResolver::resolve_dynamic_method(m, resolved_klass, constants, index(), CHECK_(methodHandle()));
|
LinkResolver::resolve_dynamic_method(m, resolved_klass, constants, index(), CHECK_(methodHandle()));
|
||||||
} else if (adjusted_invoke_code() != Bytecodes::_invokeinterface) {
|
} else if (java_code() != Bytecodes::_invokeinterface) {
|
||||||
LinkResolver::resolve_method(m, resolved_klass, constants, index(), CHECK_(methodHandle()));
|
LinkResolver::resolve_method(m, resolved_klass, constants, index(), CHECK_(methodHandle()));
|
||||||
} else {
|
} else {
|
||||||
LinkResolver::resolve_interface_method(m, resolved_klass, constants, index(), CHECK_(methodHandle()));
|
LinkResolver::resolve_interface_method(m, resolved_klass, constants, index(), CHECK_(methodHandle()));
|
||||||
@ -178,51 +177,68 @@ methodHandle Bytecode_invoke::static_target(TRAPS) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int Bytecode_invoke::index() const {
|
int Bytecode_member_ref::index() const {
|
||||||
// Note: Rewriter::rewrite changes the Java_u2 of an invokedynamic to a native_u4,
|
// Note: Rewriter::rewrite changes the Java_u2 of an invokedynamic to a native_u4,
|
||||||
// at the same time it allocates per-call-site CP cache entries.
|
// at the same time it allocates per-call-site CP cache entries.
|
||||||
Bytecodes::Code stdc = Bytecodes::java_code(code());
|
Bytecodes::Code rawc = code();
|
||||||
Bytecode* invoke = Bytecode_at(bcp());
|
Bytecode* invoke = bytecode();
|
||||||
if (invoke->has_index_u4(stdc))
|
if (invoke->has_index_u4(rawc))
|
||||||
return invoke->get_index_u4(stdc);
|
return invoke->get_index_u4(rawc);
|
||||||
else
|
else
|
||||||
return invoke->get_index_u2_cpcache(stdc);
|
return invoke->get_index_u2_cpcache(rawc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int Bytecode_member_ref::pool_index() const {
|
||||||
|
int index = this->index();
|
||||||
|
DEBUG_ONLY({
|
||||||
|
if (!bytecode()->has_index_u4(code()))
|
||||||
|
index -= constantPoolOopDesc::CPCACHE_INDEX_TAG;
|
||||||
|
});
|
||||||
|
return _method->constants()->cache()->entry_at(index)->constant_pool_index();
|
||||||
|
}
|
||||||
|
|
||||||
// Implementation of Bytecode_field
|
// Implementation of Bytecode_field
|
||||||
|
|
||||||
void Bytecode_field::verify() const {
|
void Bytecode_field::verify() const {
|
||||||
Bytecodes::Code stdc = Bytecodes::java_code(code());
|
assert(is_valid(), "check field");
|
||||||
assert(stdc == Bytecodes::_putstatic || stdc == Bytecodes::_getstatic ||
|
|
||||||
stdc == Bytecodes::_putfield || stdc == Bytecodes::_getfield, "check field");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool Bytecode_field::is_static() const {
|
// Implementation of Bytecode_loadconstant
|
||||||
Bytecodes::Code stdc = Bytecodes::java_code(code());
|
|
||||||
return stdc == Bytecodes::_putstatic || stdc == Bytecodes::_getstatic;
|
int Bytecode_loadconstant::raw_index() const {
|
||||||
|
Bytecode* bcp = bytecode();
|
||||||
|
Bytecodes::Code rawc = bcp->code();
|
||||||
|
assert(rawc != Bytecodes::_wide, "verifier prevents this");
|
||||||
|
if (Bytecodes::java_code(rawc) == Bytecodes::_ldc)
|
||||||
|
return bcp->get_index_u1(rawc);
|
||||||
|
else
|
||||||
|
return bcp->get_index_u2(rawc, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int Bytecode_loadconstant::pool_index() const {
|
||||||
int Bytecode_field::index() const {
|
int index = raw_index();
|
||||||
Bytecode* invoke = Bytecode_at(bcp());
|
if (has_cache_index()) {
|
||||||
return invoke->get_index_u2_cpcache(Bytecodes::_getfield);
|
return _method->constants()->cache()->entry_at(index)->constant_pool_index();
|
||||||
}
|
}
|
||||||
|
return index;
|
||||||
|
}
|
||||||
// Implementation of Bytecodes loac constant
|
|
||||||
|
BasicType Bytecode_loadconstant::result_type() const {
|
||||||
int Bytecode_loadconstant::index() const {
|
int index = pool_index();
|
||||||
Bytecodes::Code stdc = Bytecodes::java_code(code());
|
constantTag tag = _method->constants()->tag_at(index);
|
||||||
if (stdc != Bytecodes::_wide) {
|
return tag.basic_type();
|
||||||
if (Bytecodes::java_code(stdc) == Bytecodes::_ldc)
|
}
|
||||||
return get_index_u1(stdc);
|
|
||||||
else
|
oop Bytecode_loadconstant::resolve_constant(TRAPS) const {
|
||||||
return get_index_u2(stdc, false);
|
assert(_method.not_null(), "must supply method to resolve constant");
|
||||||
|
int index = raw_index();
|
||||||
|
constantPoolOop constants = _method->constants();
|
||||||
|
if (has_cache_index()) {
|
||||||
|
return constants->resolve_cached_constant_at(index, THREAD);
|
||||||
|
} else {
|
||||||
|
return constants->resolve_constant_at(index, THREAD);
|
||||||
}
|
}
|
||||||
stdc = Bytecodes::code_at(addr_at(1));
|
|
||||||
return get_index_u2(stdc, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
@ -76,9 +76,13 @@ class Bytecode: public ThisRelativeObj {
|
|||||||
return Bytes::get_native_u2(p);
|
return Bytes::get_native_u2(p);
|
||||||
else return Bytes::get_Java_u2(p);
|
else return Bytes::get_Java_u2(p);
|
||||||
}
|
}
|
||||||
|
int get_index_u1_cpcache(Bytecodes::Code bc) const {
|
||||||
|
assert_same_format_as(bc); assert_index_size(1, bc);
|
||||||
|
return *(jubyte*)addr_at(1) + constantPoolOopDesc::CPCACHE_INDEX_TAG;
|
||||||
|
}
|
||||||
int get_index_u2_cpcache(Bytecodes::Code bc) const {
|
int get_index_u2_cpcache(Bytecodes::Code bc) const {
|
||||||
assert_same_format_as(bc); assert_index_size(2, bc); assert_native_index(bc);
|
assert_same_format_as(bc); assert_index_size(2, bc); assert_native_index(bc);
|
||||||
return Bytes::get_native_u2(addr_at(1)) DEBUG_ONLY(+ constantPoolOopDesc::CPCACHE_INDEX_TAG);
|
return Bytes::get_native_u2(addr_at(1)) + constantPoolOopDesc::CPCACHE_INDEX_TAG;
|
||||||
}
|
}
|
||||||
int get_index_u4(Bytecodes::Code bc) const {
|
int get_index_u4(Bytecodes::Code bc) const {
|
||||||
assert_same_format_as(bc); assert_index_size(4, bc);
|
assert_same_format_as(bc); assert_index_size(4, bc);
|
||||||
@ -152,7 +156,7 @@ class Bytecode_lookupswitch: public Bytecode {
|
|||||||
|
|
||||||
inline Bytecode_lookupswitch* Bytecode_lookupswitch_at(address bcp) {
|
inline Bytecode_lookupswitch* Bytecode_lookupswitch_at(address bcp) {
|
||||||
Bytecode_lookupswitch* b = (Bytecode_lookupswitch*)bcp;
|
Bytecode_lookupswitch* b = (Bytecode_lookupswitch*)bcp;
|
||||||
debug_only(b->verify());
|
DEBUG_ONLY(b->verify());
|
||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -174,44 +178,56 @@ class Bytecode_tableswitch: public Bytecode {
|
|||||||
|
|
||||||
inline Bytecode_tableswitch* Bytecode_tableswitch_at(address bcp) {
|
inline Bytecode_tableswitch* Bytecode_tableswitch_at(address bcp) {
|
||||||
Bytecode_tableswitch* b = (Bytecode_tableswitch*)bcp;
|
Bytecode_tableswitch* b = (Bytecode_tableswitch*)bcp;
|
||||||
debug_only(b->verify());
|
DEBUG_ONLY(b->verify());
|
||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Abstraction for invoke_{virtual, static, interface, special}
|
// Common code for decoding invokes and field references.
|
||||||
|
|
||||||
class Bytecode_invoke: public ResourceObj {
|
class Bytecode_member_ref: public ResourceObj {
|
||||||
protected:
|
protected:
|
||||||
methodHandle _method; // method containing the bytecode
|
methodHandle _method; // method containing the bytecode
|
||||||
int _bci; // position of the bytecode
|
int _bci; // position of the bytecode
|
||||||
|
|
||||||
Bytecode_invoke(methodHandle method, int bci) : _method(method), _bci(bci) {}
|
Bytecode_member_ref(methodHandle method, int bci) : _method(method), _bci(bci) {}
|
||||||
|
|
||||||
|
public:
|
||||||
|
// Attributes
|
||||||
|
methodHandle method() const { return _method; }
|
||||||
|
int bci() const { return _bci; }
|
||||||
|
address bcp() const { return _method->bcp_from(bci()); }
|
||||||
|
Bytecode* bytecode() const { return Bytecode_at(bcp()); }
|
||||||
|
|
||||||
|
int index() const; // cache index (loaded from instruction)
|
||||||
|
int pool_index() const; // constant pool index
|
||||||
|
symbolOop name() const; // returns the name of the method or field
|
||||||
|
symbolOop signature() const; // returns the signature of the method or field
|
||||||
|
|
||||||
|
BasicType result_type(Thread* thread) const; // returns the result type of the getfield or invoke
|
||||||
|
|
||||||
|
Bytecodes::Code code() const { return Bytecodes::code_at(bcp(), _method()); }
|
||||||
|
Bytecodes::Code java_code() const { return Bytecodes::java_code(code()); }
|
||||||
|
};
|
||||||
|
|
||||||
|
// Abstraction for invoke_{virtual, static, interface, special}
|
||||||
|
|
||||||
|
class Bytecode_invoke: public Bytecode_member_ref {
|
||||||
|
protected:
|
||||||
|
Bytecode_invoke(methodHandle method, int bci) : Bytecode_member_ref(method, bci) {}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void verify() const;
|
void verify() const;
|
||||||
|
|
||||||
// Attributes
|
// Attributes
|
||||||
methodHandle method() const { return _method; }
|
|
||||||
int bci() const { return _bci; }
|
|
||||||
address bcp() const { return _method->bcp_from(bci()); }
|
|
||||||
|
|
||||||
int index() const; // the constant pool index for the invoke
|
|
||||||
symbolOop name() const; // returns the name of the invoked method
|
|
||||||
symbolOop signature() const; // returns the signature of the invoked method
|
|
||||||
BasicType result_type(Thread *thread) const; // returns the result type of the invoke
|
|
||||||
|
|
||||||
Bytecodes::Code code() const { return Bytecodes::code_at(bcp(), _method()); }
|
|
||||||
Bytecodes::Code adjusted_invoke_code() const { return Bytecodes::java_code(code()); }
|
|
||||||
|
|
||||||
methodHandle static_target(TRAPS); // "specified" method (from constant pool)
|
methodHandle static_target(TRAPS); // "specified" method (from constant pool)
|
||||||
|
|
||||||
// Testers
|
// Testers
|
||||||
bool is_invokeinterface() const { return adjusted_invoke_code() == Bytecodes::_invokeinterface; }
|
bool is_invokeinterface() const { return java_code() == Bytecodes::_invokeinterface; }
|
||||||
bool is_invokevirtual() const { return adjusted_invoke_code() == Bytecodes::_invokevirtual; }
|
bool is_invokevirtual() const { return java_code() == Bytecodes::_invokevirtual; }
|
||||||
bool is_invokestatic() const { return adjusted_invoke_code() == Bytecodes::_invokestatic; }
|
bool is_invokestatic() const { return java_code() == Bytecodes::_invokestatic; }
|
||||||
bool is_invokespecial() const { return adjusted_invoke_code() == Bytecodes::_invokespecial; }
|
bool is_invokespecial() const { return java_code() == Bytecodes::_invokespecial; }
|
||||||
bool is_invokedynamic() const { return adjusted_invoke_code() == Bytecodes::_invokedynamic; }
|
bool is_invokedynamic() const { return java_code() == Bytecodes::_invokedynamic; }
|
||||||
|
|
||||||
bool has_receiver() const { return !is_invokestatic() && !is_invokedynamic(); }
|
bool has_receiver() const { return !is_invokestatic() && !is_invokedynamic(); }
|
||||||
|
|
||||||
@ -230,7 +246,7 @@ class Bytecode_invoke: public ResourceObj {
|
|||||||
|
|
||||||
inline Bytecode_invoke* Bytecode_invoke_at(methodHandle method, int bci) {
|
inline Bytecode_invoke* Bytecode_invoke_at(methodHandle method, int bci) {
|
||||||
Bytecode_invoke* b = new Bytecode_invoke(method, bci);
|
Bytecode_invoke* b = new Bytecode_invoke(method, bci);
|
||||||
debug_only(b->verify());
|
DEBUG_ONLY(b->verify());
|
||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -240,21 +256,34 @@ inline Bytecode_invoke* Bytecode_invoke_at_check(methodHandle method, int bci) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Abstraction for all field accesses (put/get field/static_
|
// Abstraction for all field accesses (put/get field/static)
|
||||||
class Bytecode_field: public Bytecode {
|
class Bytecode_field: public Bytecode_member_ref {
|
||||||
public:
|
protected:
|
||||||
|
Bytecode_field(methodHandle method, int bci) : Bytecode_member_ref(method, bci) {}
|
||||||
|
|
||||||
|
public:
|
||||||
|
// Testers
|
||||||
|
bool is_getfield() const { return java_code() == Bytecodes::_getfield; }
|
||||||
|
bool is_putfield() const { return java_code() == Bytecodes::_putfield; }
|
||||||
|
bool is_getstatic() const { return java_code() == Bytecodes::_getstatic; }
|
||||||
|
bool is_putstatic() const { return java_code() == Bytecodes::_putstatic; }
|
||||||
|
|
||||||
|
bool is_getter() const { return is_getfield() || is_getstatic(); }
|
||||||
|
bool is_static() const { return is_getstatic() || is_putstatic(); }
|
||||||
|
|
||||||
|
bool is_valid() const { return is_getfield() ||
|
||||||
|
is_putfield() ||
|
||||||
|
is_getstatic() ||
|
||||||
|
is_putstatic(); }
|
||||||
void verify() const;
|
void verify() const;
|
||||||
|
|
||||||
int index() const;
|
|
||||||
bool is_static() const;
|
|
||||||
|
|
||||||
// Creation
|
// Creation
|
||||||
inline friend Bytecode_field* Bytecode_field_at(const methodOop method, address bcp);
|
inline friend Bytecode_field* Bytecode_field_at(methodHandle method, int bci);
|
||||||
};
|
};
|
||||||
|
|
||||||
inline Bytecode_field* Bytecode_field_at(const methodOop method, address bcp) {
|
inline Bytecode_field* Bytecode_field_at(methodHandle method, int bci) {
|
||||||
Bytecode_field* b = (Bytecode_field*)bcp;
|
Bytecode_field* b = new Bytecode_field(method, bci);
|
||||||
debug_only(b->verify());
|
DEBUG_ONLY(b->verify());
|
||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -274,7 +303,7 @@ class Bytecode_checkcast: public Bytecode {
|
|||||||
|
|
||||||
inline Bytecode_checkcast* Bytecode_checkcast_at(address bcp) {
|
inline Bytecode_checkcast* Bytecode_checkcast_at(address bcp) {
|
||||||
Bytecode_checkcast* b = (Bytecode_checkcast*)bcp;
|
Bytecode_checkcast* b = (Bytecode_checkcast*)bcp;
|
||||||
debug_only(b->verify());
|
DEBUG_ONLY(b->verify());
|
||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -294,7 +323,7 @@ class Bytecode_instanceof: public Bytecode {
|
|||||||
|
|
||||||
inline Bytecode_instanceof* Bytecode_instanceof_at(address bcp) {
|
inline Bytecode_instanceof* Bytecode_instanceof_at(address bcp) {
|
||||||
Bytecode_instanceof* b = (Bytecode_instanceof*)bcp;
|
Bytecode_instanceof* b = (Bytecode_instanceof*)bcp;
|
||||||
debug_only(b->verify());
|
DEBUG_ONLY(b->verify());
|
||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -312,7 +341,7 @@ class Bytecode_new: public Bytecode {
|
|||||||
|
|
||||||
inline Bytecode_new* Bytecode_new_at(address bcp) {
|
inline Bytecode_new* Bytecode_new_at(address bcp) {
|
||||||
Bytecode_new* b = (Bytecode_new*)bcp;
|
Bytecode_new* b = (Bytecode_new*)bcp;
|
||||||
debug_only(b->verify());
|
DEBUG_ONLY(b->verify());
|
||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -330,7 +359,7 @@ class Bytecode_multianewarray: public Bytecode {
|
|||||||
|
|
||||||
inline Bytecode_multianewarray* Bytecode_multianewarray_at(address bcp) {
|
inline Bytecode_multianewarray* Bytecode_multianewarray_at(address bcp) {
|
||||||
Bytecode_multianewarray* b = (Bytecode_multianewarray*)bcp;
|
Bytecode_multianewarray* b = (Bytecode_multianewarray*)bcp;
|
||||||
debug_only(b->verify());
|
DEBUG_ONLY(b->verify());
|
||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -348,29 +377,57 @@ class Bytecode_anewarray: public Bytecode {
|
|||||||
|
|
||||||
inline Bytecode_anewarray* Bytecode_anewarray_at(address bcp) {
|
inline Bytecode_anewarray* Bytecode_anewarray_at(address bcp) {
|
||||||
Bytecode_anewarray* b = (Bytecode_anewarray*)bcp;
|
Bytecode_anewarray* b = (Bytecode_anewarray*)bcp;
|
||||||
debug_only(b->verify());
|
DEBUG_ONLY(b->verify());
|
||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Abstraction for ldc, ldc_w and ldc2_w
|
// Abstraction for ldc, ldc_w and ldc2_w
|
||||||
|
|
||||||
class Bytecode_loadconstant: public Bytecode {
|
class Bytecode_loadconstant: public ResourceObj {
|
||||||
|
private:
|
||||||
|
int _bci;
|
||||||
|
methodHandle _method;
|
||||||
|
|
||||||
|
Bytecodes::Code code() const { return bytecode()->code(); }
|
||||||
|
|
||||||
|
int raw_index() const;
|
||||||
|
|
||||||
|
Bytecode_loadconstant(methodHandle method, int bci) : _method(method), _bci(bci) {}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
// Attributes
|
||||||
|
methodHandle method() const { return _method; }
|
||||||
|
int bci() const { return _bci; }
|
||||||
|
address bcp() const { return _method->bcp_from(bci()); }
|
||||||
|
Bytecode* bytecode() const { return Bytecode_at(bcp()); }
|
||||||
|
|
||||||
void verify() const {
|
void verify() const {
|
||||||
|
assert(_method.not_null(), "must supply method");
|
||||||
Bytecodes::Code stdc = Bytecodes::java_code(code());
|
Bytecodes::Code stdc = Bytecodes::java_code(code());
|
||||||
assert(stdc == Bytecodes::_ldc ||
|
assert(stdc == Bytecodes::_ldc ||
|
||||||
stdc == Bytecodes::_ldc_w ||
|
stdc == Bytecodes::_ldc_w ||
|
||||||
stdc == Bytecodes::_ldc2_w, "load constant");
|
stdc == Bytecodes::_ldc2_w, "load constant");
|
||||||
}
|
}
|
||||||
|
|
||||||
int index() const;
|
// Only non-standard bytecodes (fast_aldc) have CP cache indexes.
|
||||||
|
bool has_cache_index() const { return code() >= Bytecodes::number_of_java_codes; }
|
||||||
|
|
||||||
inline friend Bytecode_loadconstant* Bytecode_loadconstant_at(const methodOop method, address bcp);
|
int pool_index() const; // index into constant pool
|
||||||
|
int cache_index() const { // index into CP cache (or -1 if none)
|
||||||
|
return has_cache_index() ? raw_index() : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
BasicType result_type() const; // returns the result type of the ldc
|
||||||
|
|
||||||
|
oop resolve_constant(TRAPS) const;
|
||||||
|
|
||||||
|
// Creation
|
||||||
|
inline friend Bytecode_loadconstant* Bytecode_loadconstant_at(methodHandle method, int bci);
|
||||||
};
|
};
|
||||||
|
|
||||||
inline Bytecode_loadconstant* Bytecode_loadconstant_at(const methodOop method, address bcp) {
|
inline Bytecode_loadconstant* Bytecode_loadconstant_at(methodHandle method, int bci) {
|
||||||
Bytecode_loadconstant* b = (Bytecode_loadconstant*)bcp;
|
Bytecode_loadconstant* b = new Bytecode_loadconstant(method, bci);
|
||||||
debug_only(b->verify());
|
DEBUG_ONLY(b->verify());
|
||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
|
@ -49,6 +49,7 @@ class BytecodePrinter: public BytecodeClosure {
|
|||||||
|
|
||||||
int get_index_u1() { return *(address)_next_pc++; }
|
int get_index_u1() { return *(address)_next_pc++; }
|
||||||
int get_index_u2() { int i=Bytes::get_Java_u2(_next_pc); _next_pc+=2; return i; }
|
int get_index_u2() { int i=Bytes::get_Java_u2(_next_pc); _next_pc+=2; return i; }
|
||||||
|
int get_index_u1_cpcache() { return get_index_u1() + constantPoolOopDesc::CPCACHE_INDEX_TAG; }
|
||||||
int get_index_u2_cpcache() { int i=Bytes::get_native_u2(_next_pc); _next_pc+=2; return i + constantPoolOopDesc::CPCACHE_INDEX_TAG; }
|
int get_index_u2_cpcache() { int i=Bytes::get_native_u2(_next_pc); _next_pc+=2; return i + constantPoolOopDesc::CPCACHE_INDEX_TAG; }
|
||||||
int get_index_u4() { int i=Bytes::get_native_u4(_next_pc); _next_pc+=4; return i; }
|
int get_index_u4() { int i=Bytes::get_native_u4(_next_pc); _next_pc+=4; return i; }
|
||||||
int get_index_special() { return (is_wide()) ? get_index_u2() : get_index_u1(); }
|
int get_index_special() { return (is_wide()) ? get_index_u2() : get_index_u1(); }
|
||||||
@ -60,6 +61,7 @@ class BytecodePrinter: public BytecodeClosure {
|
|||||||
bool check_index(int i, int& cp_index, outputStream* st = tty);
|
bool check_index(int i, int& cp_index, outputStream* st = tty);
|
||||||
void print_constant(int i, outputStream* st = tty);
|
void print_constant(int i, outputStream* st = tty);
|
||||||
void print_field_or_method(int i, outputStream* st = tty);
|
void print_field_or_method(int i, outputStream* st = tty);
|
||||||
|
void print_field_or_method(int orig_i, int i, outputStream* st = tty);
|
||||||
void print_attributes(int bci, outputStream* st = tty);
|
void print_attributes(int bci, outputStream* st = tty);
|
||||||
void bytecode_epilog(int bci, outputStream* st = tty);
|
void bytecode_epilog(int bci, outputStream* st = tty);
|
||||||
|
|
||||||
@ -177,18 +179,29 @@ void BytecodeTracer::trace(methodHandle method, address bcp, outputStream* st) {
|
|||||||
_closure->trace(method, bcp, st);
|
_closure->trace(method, bcp, st);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void print_symbol(symbolOop sym, outputStream* st) {
|
||||||
|
char buf[40];
|
||||||
|
int len = sym->utf8_length();
|
||||||
|
if (len >= (int)sizeof(buf)) {
|
||||||
|
st->print_cr(" %s...[%d]", sym->as_C_string(buf, sizeof(buf)), len);
|
||||||
|
} else {
|
||||||
|
st->print(" ");
|
||||||
|
sym->print_on(st); st->cr();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void print_oop(oop value, outputStream* st) {
|
void print_oop(oop value, outputStream* st) {
|
||||||
if (value == NULL) {
|
if (value == NULL) {
|
||||||
st->print_cr(" NULL");
|
st->print_cr(" NULL");
|
||||||
} else {
|
} else if (java_lang_String::is_instance(value)) {
|
||||||
EXCEPTION_MARK;
|
EXCEPTION_MARK;
|
||||||
Handle h_value (THREAD, value);
|
Handle h_value (THREAD, value);
|
||||||
symbolHandle sym = java_lang_String::as_symbol(h_value, CATCH);
|
symbolHandle sym = java_lang_String::as_symbol(h_value, CATCH);
|
||||||
if (sym->utf8_length() > 32) {
|
print_symbol(sym(), st);
|
||||||
st->print_cr(" ....");
|
} else if (value->is_symbol()) {
|
||||||
} else {
|
print_symbol(symbolOop(value), st);
|
||||||
sym->print_on(st); st->cr();
|
} else {
|
||||||
}
|
st->print_cr(" " PTR_FORMAT, (intptr_t) value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -279,16 +292,27 @@ void BytecodePrinter::print_constant(int i, outputStream* st) {
|
|||||||
} else if (tag.is_double()) {
|
} else if (tag.is_double()) {
|
||||||
st->print_cr(" %f", constants->double_at(i));
|
st->print_cr(" %f", constants->double_at(i));
|
||||||
} else if (tag.is_string()) {
|
} else if (tag.is_string()) {
|
||||||
oop string = constants->resolved_string_at(i);
|
oop string = constants->pseudo_string_at(i);
|
||||||
print_oop(string, st);
|
print_oop(string, st);
|
||||||
} else if (tag.is_unresolved_string()) {
|
} else if (tag.is_unresolved_string()) {
|
||||||
st->print_cr(" <unresolved string at %d>", i);
|
const char* string = constants->string_at_noresolve(i);
|
||||||
|
st->print_cr(" %s", string);
|
||||||
} else if (tag.is_klass()) {
|
} else if (tag.is_klass()) {
|
||||||
st->print_cr(" %s", constants->resolved_klass_at(i)->klass_part()->external_name());
|
st->print_cr(" %s", constants->resolved_klass_at(i)->klass_part()->external_name());
|
||||||
} else if (tag.is_unresolved_klass()) {
|
} else if (tag.is_unresolved_klass()) {
|
||||||
st->print_cr(" <unresolved klass at %d>", i);
|
st->print_cr(" <unresolved klass at %d>", i);
|
||||||
} else if (tag.is_object()) {
|
} else if (tag.is_object()) {
|
||||||
st->print_cr(" " PTR_FORMAT, constants->object_at(i));
|
st->print(" <Object>");
|
||||||
|
print_oop(constants->object_at(i), st);
|
||||||
|
} else if (tag.is_method_type()) {
|
||||||
|
int i2 = constants->method_type_index_at(i);
|
||||||
|
st->print(" <MethodType> %d", i2);
|
||||||
|
print_oop(constants->symbol_at(i2), st);
|
||||||
|
} else if (tag.is_method_handle()) {
|
||||||
|
int kind = constants->method_handle_ref_kind_at(i);
|
||||||
|
int i2 = constants->method_handle_index_at(i);
|
||||||
|
st->print(" <MethodHandle of kind %d>", kind, i2);
|
||||||
|
print_field_or_method(-i, i2, st);
|
||||||
} else {
|
} else {
|
||||||
st->print_cr(" bad tag=%d at %d", tag.value(), i);
|
st->print_cr(" bad tag=%d at %d", tag.value(), i);
|
||||||
}
|
}
|
||||||
@ -297,7 +321,10 @@ void BytecodePrinter::print_constant(int i, outputStream* st) {
|
|||||||
void BytecodePrinter::print_field_or_method(int i, outputStream* st) {
|
void BytecodePrinter::print_field_or_method(int i, outputStream* st) {
|
||||||
int orig_i = i;
|
int orig_i = i;
|
||||||
if (!check_index(orig_i, i, st)) return;
|
if (!check_index(orig_i, i, st)) return;
|
||||||
|
print_field_or_method(orig_i, i, st);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BytecodePrinter::print_field_or_method(int orig_i, int i, outputStream* st) {
|
||||||
constantPoolOop constants = method()->constants();
|
constantPoolOop constants = method()->constants();
|
||||||
constantTag tag = constants->tag_at(i);
|
constantTag tag = constants->tag_at(i);
|
||||||
|
|
||||||
@ -314,9 +341,11 @@ void BytecodePrinter::print_field_or_method(int i, outputStream* st) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
symbolOop klass = constants->klass_name_at(constants->uncached_klass_ref_index_at(i));
|
||||||
symbolOop name = constants->uncached_name_ref_at(i);
|
symbolOop name = constants->uncached_name_ref_at(i);
|
||||||
symbolOop signature = constants->uncached_signature_ref_at(i);
|
symbolOop signature = constants->uncached_signature_ref_at(i);
|
||||||
st->print_cr(" %d <%s> <%s> ", i, name->as_C_string(), signature->as_C_string());
|
const char* sep = (tag.is_field() ? "/" : "");
|
||||||
|
st->print_cr(" %d <%s.%s%s%s> ", i, klass->as_C_string(), name->as_C_string(), sep, signature->as_C_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -340,12 +369,20 @@ void BytecodePrinter::print_attributes(int bci, outputStream* st) {
|
|||||||
st->print_cr(" " INT32_FORMAT, get_short());
|
st->print_cr(" " INT32_FORMAT, get_short());
|
||||||
break;
|
break;
|
||||||
case Bytecodes::_ldc:
|
case Bytecodes::_ldc:
|
||||||
print_constant(get_index_u1(), st);
|
if (Bytecodes::uses_cp_cache(raw_code())) {
|
||||||
|
print_constant(get_index_u1_cpcache(), st);
|
||||||
|
} else {
|
||||||
|
print_constant(get_index_u1(), st);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Bytecodes::_ldc_w:
|
case Bytecodes::_ldc_w:
|
||||||
case Bytecodes::_ldc2_w:
|
case Bytecodes::_ldc2_w:
|
||||||
print_constant(get_index_u2(), st);
|
if (Bytecodes::uses_cp_cache(raw_code())) {
|
||||||
|
print_constant(get_index_u2_cpcache(), st);
|
||||||
|
} else {
|
||||||
|
print_constant(get_index_u2(), st);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Bytecodes::_iload:
|
case Bytecodes::_iload:
|
||||||
|
@ -489,6 +489,9 @@ void Bytecodes::initialize() {
|
|||||||
|
|
||||||
def(_return_register_finalizer , "return_register_finalizer" , "b" , NULL , T_VOID , 0, true, _return);
|
def(_return_register_finalizer , "return_register_finalizer" , "b" , NULL , T_VOID , 0, true, _return);
|
||||||
|
|
||||||
|
def(_fast_aldc , "fast_aldc" , "bj" , NULL , T_OBJECT, 1, true, _ldc );
|
||||||
|
def(_fast_aldc_w , "fast_aldc_w" , "bJJ" , NULL , T_OBJECT, 1, true, _ldc_w );
|
||||||
|
|
||||||
def(_shouldnotreachhere , "_shouldnotreachhere" , "b" , NULL , T_VOID , 0, false);
|
def(_shouldnotreachhere , "_shouldnotreachhere" , "b" , NULL , T_VOID , 0, false);
|
||||||
|
|
||||||
// platform specific JVM bytecodes
|
// platform specific JVM bytecodes
|
||||||
|
@ -270,6 +270,10 @@ class Bytecodes: AllStatic {
|
|||||||
_fast_linearswitch ,
|
_fast_linearswitch ,
|
||||||
_fast_binaryswitch ,
|
_fast_binaryswitch ,
|
||||||
|
|
||||||
|
// special handling of oop constants:
|
||||||
|
_fast_aldc ,
|
||||||
|
_fast_aldc_w ,
|
||||||
|
|
||||||
_return_register_finalizer ,
|
_return_register_finalizer ,
|
||||||
|
|
||||||
_shouldnotreachhere, // For debugging
|
_shouldnotreachhere, // For debugging
|
||||||
|
@ -267,20 +267,6 @@ void AbstractInterpreter::print_method_kind(MethodKind kind) {
|
|||||||
}
|
}
|
||||||
#endif // PRODUCT
|
#endif // PRODUCT
|
||||||
|
|
||||||
static BasicType constant_pool_type(methodOop method, int index) {
|
|
||||||
constantTag tag = method->constants()->tag_at(index);
|
|
||||||
if (tag.is_int ()) return T_INT;
|
|
||||||
else if (tag.is_float ()) return T_FLOAT;
|
|
||||||
else if (tag.is_long ()) return T_LONG;
|
|
||||||
else if (tag.is_double ()) return T_DOUBLE;
|
|
||||||
else if (tag.is_string ()) return T_OBJECT;
|
|
||||||
else if (tag.is_unresolved_string()) return T_OBJECT;
|
|
||||||
else if (tag.is_klass ()) return T_OBJECT;
|
|
||||||
else if (tag.is_unresolved_klass ()) return T_OBJECT;
|
|
||||||
ShouldNotReachHere();
|
|
||||||
return T_ILLEGAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------------------------------------------
|
||||||
// Deoptimization support
|
// Deoptimization support
|
||||||
@ -330,13 +316,15 @@ address AbstractInterpreter::deopt_continue_after_entry(methodOop method, addres
|
|||||||
}
|
}
|
||||||
|
|
||||||
case Bytecodes::_ldc :
|
case Bytecodes::_ldc :
|
||||||
type = constant_pool_type( method, *(bcp+1) );
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Bytecodes::_ldc_w : // fall through
|
case Bytecodes::_ldc_w : // fall through
|
||||||
case Bytecodes::_ldc2_w:
|
case Bytecodes::_ldc2_w:
|
||||||
type = constant_pool_type( method, Bytes::get_Java_u2(bcp+1) );
|
{
|
||||||
break;
|
Thread *thread = Thread::current();
|
||||||
|
ResourceMark rm(thread);
|
||||||
|
methodHandle mh(thread, method);
|
||||||
|
type = Bytecode_loadconstant_at(mh, bci)->result_type();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
type = Bytecodes::result_type(code);
|
type = Bytecodes::result_type(code);
|
||||||
|
@ -83,6 +83,18 @@ IRT_ENTRY(void, InterpreterRuntime::ldc(JavaThread* thread, bool wide))
|
|||||||
}
|
}
|
||||||
IRT_END
|
IRT_END
|
||||||
|
|
||||||
|
IRT_ENTRY(void, InterpreterRuntime::resolve_ldc(JavaThread* thread, Bytecodes::Code bytecode)) {
|
||||||
|
assert(bytecode == Bytecodes::_fast_aldc ||
|
||||||
|
bytecode == Bytecodes::_fast_aldc_w, "wrong bc");
|
||||||
|
ResourceMark rm(thread);
|
||||||
|
methodHandle m (thread, method(thread));
|
||||||
|
Bytecode_loadconstant* ldc = Bytecode_loadconstant_at(m, bci(thread));
|
||||||
|
oop result = ldc->resolve_constant(THREAD);
|
||||||
|
DEBUG_ONLY(ConstantPoolCacheEntry* cpce = m->constants()->cache()->entry_at(ldc->cache_index()));
|
||||||
|
assert(result == cpce->f1(), "expected result for assembly code");
|
||||||
|
}
|
||||||
|
IRT_END
|
||||||
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------------------------------------------
|
||||||
// Allocation
|
// Allocation
|
||||||
@ -328,7 +340,7 @@ IRT_ENTRY(address, InterpreterRuntime::exception_handler_for_exception(JavaThrea
|
|||||||
typeArrayHandle h_extable (thread, h_method->exception_table());
|
typeArrayHandle h_extable (thread, h_method->exception_table());
|
||||||
bool should_repeat;
|
bool should_repeat;
|
||||||
int handler_bci;
|
int handler_bci;
|
||||||
int current_bci = bcp(thread) - h_method->code_base();
|
int current_bci = bci(thread);
|
||||||
|
|
||||||
// Need to do this check first since when _do_not_unlock_if_synchronized
|
// Need to do this check first since when _do_not_unlock_if_synchronized
|
||||||
// is set, we don't want to trigger any classloading which may make calls
|
// is set, we don't want to trigger any classloading which may make calls
|
||||||
@ -615,8 +627,7 @@ IRT_ENTRY(void, InterpreterRuntime::resolve_invoke(JavaThread* thread, Bytecodes
|
|||||||
if (bytecode == Bytecodes::_invokevirtual || bytecode == Bytecodes::_invokeinterface) {
|
if (bytecode == Bytecodes::_invokevirtual || bytecode == Bytecodes::_invokeinterface) {
|
||||||
ResourceMark rm(thread);
|
ResourceMark rm(thread);
|
||||||
methodHandle m (thread, method(thread));
|
methodHandle m (thread, method(thread));
|
||||||
int bci = m->bci_from(bcp(thread));
|
Bytecode_invoke* call = Bytecode_invoke_at(m, bci(thread));
|
||||||
Bytecode_invoke* call = Bytecode_invoke_at(m, bci);
|
|
||||||
symbolHandle signature (thread, call->signature());
|
symbolHandle signature (thread, call->signature());
|
||||||
receiver = Handle(thread,
|
receiver = Handle(thread,
|
||||||
thread->last_frame().interpreter_callee_receiver(signature));
|
thread->last_frame().interpreter_callee_receiver(signature));
|
||||||
@ -1257,7 +1268,7 @@ IRT_LEAF(void, InterpreterRuntime::popframe_move_outgoing_args(JavaThread* threa
|
|||||||
Bytecode_invoke* invoke = Bytecode_invoke_at(mh, bci);
|
Bytecode_invoke* invoke = Bytecode_invoke_at(mh, bci);
|
||||||
ArgumentSizeComputer asc(invoke->signature());
|
ArgumentSizeComputer asc(invoke->signature());
|
||||||
int size_of_arguments = (asc.size() + (invoke->has_receiver() ? 1 : 0)); // receiver
|
int size_of_arguments = (asc.size() + (invoke->has_receiver() ? 1 : 0)); // receiver
|
||||||
Copy::conjoint_bytes(src_address, dest_address,
|
Copy::conjoint_jbytes(src_address, dest_address,
|
||||||
size_of_arguments * Interpreter::stackElementSize);
|
size_of_arguments * Interpreter::stackElementSize);
|
||||||
IRT_END
|
IRT_END
|
||||||
#endif
|
#endif
|
||||||
|
@ -34,6 +34,7 @@ class InterpreterRuntime: AllStatic {
|
|||||||
static frame last_frame(JavaThread *thread) { return thread->last_frame(); }
|
static frame last_frame(JavaThread *thread) { return thread->last_frame(); }
|
||||||
static methodOop method(JavaThread *thread) { return last_frame(thread).interpreter_frame_method(); }
|
static methodOop method(JavaThread *thread) { return last_frame(thread).interpreter_frame_method(); }
|
||||||
static address bcp(JavaThread *thread) { return last_frame(thread).interpreter_frame_bcp(); }
|
static address bcp(JavaThread *thread) { return last_frame(thread).interpreter_frame_bcp(); }
|
||||||
|
static int bci(JavaThread *thread) { return last_frame(thread).interpreter_frame_bci(); }
|
||||||
static void set_bcp_and_mdp(address bcp, JavaThread*thread);
|
static void set_bcp_and_mdp(address bcp, JavaThread*thread);
|
||||||
static Bytecodes::Code code(JavaThread *thread) {
|
static Bytecodes::Code code(JavaThread *thread) {
|
||||||
// pass method to avoid calling unsafe bcp_to_method (partial fix 4926272)
|
// pass method to avoid calling unsafe bcp_to_method (partial fix 4926272)
|
||||||
@ -59,6 +60,7 @@ class InterpreterRuntime: AllStatic {
|
|||||||
public:
|
public:
|
||||||
// Constants
|
// Constants
|
||||||
static void ldc (JavaThread* thread, bool wide);
|
static void ldc (JavaThread* thread, bool wide);
|
||||||
|
static void resolve_ldc (JavaThread* thread, Bytecodes::Code bytecode);
|
||||||
|
|
||||||
// Allocation
|
// Allocation
|
||||||
static void _new (JavaThread* thread, constantPoolOopDesc* pool, int index);
|
static void _new (JavaThread* thread, constantPoolOopDesc* pool, int index);
|
||||||
|
@ -38,6 +38,8 @@ void Rewriter::compute_index_maps() {
|
|||||||
case JVM_CONSTANT_InterfaceMethodref:
|
case JVM_CONSTANT_InterfaceMethodref:
|
||||||
case JVM_CONSTANT_Fieldref : // fall through
|
case JVM_CONSTANT_Fieldref : // fall through
|
||||||
case JVM_CONSTANT_Methodref : // fall through
|
case JVM_CONSTANT_Methodref : // fall through
|
||||||
|
case JVM_CONSTANT_MethodHandle : // fall through
|
||||||
|
case JVM_CONSTANT_MethodType : // fall through
|
||||||
add_cp_cache_entry(i);
|
add_cp_cache_entry(i);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -131,6 +133,27 @@ void Rewriter::rewrite_invokedynamic(address bcp, int offset) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Rewrite some ldc bytecodes to _fast_aldc
|
||||||
|
void Rewriter::maybe_rewrite_ldc(address bcp, int offset, bool is_wide) {
|
||||||
|
assert((*bcp) == (is_wide ? Bytecodes::_ldc_w : Bytecodes::_ldc), "");
|
||||||
|
address p = bcp + offset;
|
||||||
|
int cp_index = is_wide ? Bytes::get_Java_u2(p) : (u1)(*p);
|
||||||
|
constantTag tag = _pool->tag_at(cp_index).value();
|
||||||
|
if (tag.is_method_handle() || tag.is_method_type()) {
|
||||||
|
int cache_index = cp_entry_to_cp_cache(cp_index);
|
||||||
|
if (is_wide) {
|
||||||
|
(*bcp) = Bytecodes::_fast_aldc_w;
|
||||||
|
assert(cache_index == (u2)cache_index, "");
|
||||||
|
Bytes::put_native_u2(p, cache_index);
|
||||||
|
} else {
|
||||||
|
(*bcp) = Bytecodes::_fast_aldc;
|
||||||
|
assert(cache_index == (u1)cache_index, "");
|
||||||
|
(*p) = (u1)cache_index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Rewrites a method given the index_map information
|
// Rewrites a method given the index_map information
|
||||||
void Rewriter::scan_method(methodOop method) {
|
void Rewriter::scan_method(methodOop method) {
|
||||||
|
|
||||||
@ -198,6 +221,12 @@ void Rewriter::scan_method(methodOop method) {
|
|||||||
case Bytecodes::_invokedynamic:
|
case Bytecodes::_invokedynamic:
|
||||||
rewrite_invokedynamic(bcp, prefix_length+1);
|
rewrite_invokedynamic(bcp, prefix_length+1);
|
||||||
break;
|
break;
|
||||||
|
case Bytecodes::_ldc:
|
||||||
|
maybe_rewrite_ldc(bcp, prefix_length+1, false);
|
||||||
|
break;
|
||||||
|
case Bytecodes::_ldc_w:
|
||||||
|
maybe_rewrite_ldc(bcp, prefix_length+1, true);
|
||||||
|
break;
|
||||||
case Bytecodes::_jsr : // fall through
|
case Bytecodes::_jsr : // fall through
|
||||||
case Bytecodes::_jsr_w : nof_jsrs++; break;
|
case Bytecodes::_jsr_w : nof_jsrs++; break;
|
||||||
case Bytecodes::_monitorenter : // fall through
|
case Bytecodes::_monitorenter : // fall through
|
||||||
|
@ -66,6 +66,7 @@ class Rewriter: public StackObj {
|
|||||||
void rewrite_Object_init(methodHandle m, TRAPS);
|
void rewrite_Object_init(methodHandle m, TRAPS);
|
||||||
void rewrite_member_reference(address bcp, int offset);
|
void rewrite_member_reference(address bcp, int offset);
|
||||||
void rewrite_invokedynamic(address bcp, int offset);
|
void rewrite_invokedynamic(address bcp, int offset);
|
||||||
|
void maybe_rewrite_ldc(address bcp, int offset, bool is_wide);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Driver routine:
|
// Driver routine:
|
||||||
|
@ -507,6 +507,9 @@ void TemplateTable::initialize() {
|
|||||||
def(Bytecodes::_fast_linearswitch , ubcp|disp|____|____, itos, vtos, fast_linearswitch , _ );
|
def(Bytecodes::_fast_linearswitch , ubcp|disp|____|____, itos, vtos, fast_linearswitch , _ );
|
||||||
def(Bytecodes::_fast_binaryswitch , ubcp|disp|____|____, itos, vtos, fast_binaryswitch , _ );
|
def(Bytecodes::_fast_binaryswitch , ubcp|disp|____|____, itos, vtos, fast_binaryswitch , _ );
|
||||||
|
|
||||||
|
def(Bytecodes::_fast_aldc , ubcp|____|clvm|____, vtos, atos, fast_aldc , false );
|
||||||
|
def(Bytecodes::_fast_aldc_w , ubcp|____|clvm|____, vtos, atos, fast_aldc , true );
|
||||||
|
|
||||||
def(Bytecodes::_return_register_finalizer , ____|disp|clvm|____, vtos, vtos, _return , vtos );
|
def(Bytecodes::_return_register_finalizer , ____|disp|clvm|____, vtos, vtos, _return , vtos );
|
||||||
|
|
||||||
def(Bytecodes::_shouldnotreachhere , ____|____|____|____, vtos, vtos, shouldnotreachhere , _ );
|
def(Bytecodes::_shouldnotreachhere , ____|____|____|____, vtos, vtos, shouldnotreachhere , _ );
|
||||||
|
@ -123,6 +123,7 @@ class TemplateTable: AllStatic {
|
|||||||
static void sipush();
|
static void sipush();
|
||||||
static void ldc(bool wide);
|
static void ldc(bool wide);
|
||||||
static void ldc2_w();
|
static void ldc2_w();
|
||||||
|
static void fast_aldc(bool wide);
|
||||||
|
|
||||||
static void locals_index(Register reg, int offset = 1);
|
static void locals_index(Register reg, int offset = 1);
|
||||||
static void iload();
|
static void iload();
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2000, 2009, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -284,12 +284,19 @@ void CardTableModRefBS::resize_covered_region(MemRegion new_region) {
|
|||||||
committed_unique_to_self(ind, MemRegion(new_end_aligned,
|
committed_unique_to_self(ind, MemRegion(new_end_aligned,
|
||||||
cur_committed.end()));
|
cur_committed.end()));
|
||||||
if (!uncommit_region.is_empty()) {
|
if (!uncommit_region.is_empty()) {
|
||||||
if (!os::uncommit_memory((char*)uncommit_region.start(),
|
// It is not safe to uncommit cards if the boundary between
|
||||||
uncommit_region.byte_size())) {
|
// the generations is moving. A shrink can uncommit cards
|
||||||
assert(false, "Card table contraction failed");
|
// owned by generation A but being used by generation B.
|
||||||
// The call failed so don't change the end of the
|
if (!UseAdaptiveGCBoundary) {
|
||||||
// committed region. This is better than taking the
|
if (!os::uncommit_memory((char*)uncommit_region.start(),
|
||||||
// VM down.
|
uncommit_region.byte_size())) {
|
||||||
|
assert(false, "Card table contraction failed");
|
||||||
|
// The call failed so don't change the end of the
|
||||||
|
// committed region. This is better than taking the
|
||||||
|
// VM down.
|
||||||
|
new_end_aligned = _committed[ind].end();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
new_end_aligned = _committed[ind].end();
|
new_end_aligned = _committed[ind].end();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -297,6 +304,19 @@ void CardTableModRefBS::resize_covered_region(MemRegion new_region) {
|
|||||||
// In any case, we can reset the end of the current committed entry.
|
// In any case, we can reset the end of the current committed entry.
|
||||||
_committed[ind].set_end(new_end_aligned);
|
_committed[ind].set_end(new_end_aligned);
|
||||||
|
|
||||||
|
#ifdef ASSERT
|
||||||
|
// Check that the last card in the new region is committed according
|
||||||
|
// to the tables.
|
||||||
|
bool covered = false;
|
||||||
|
for (int cr = 0; cr < _cur_covered_regions; cr++) {
|
||||||
|
if (_committed[cr].contains(new_end - 1)) {
|
||||||
|
covered = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert(covered, "Card for end of new region not committed");
|
||||||
|
#endif
|
||||||
|
|
||||||
// The default of 0 is not necessarily clean cards.
|
// The default of 0 is not necessarily clean cards.
|
||||||
jbyte* entry;
|
jbyte* entry;
|
||||||
if (old_region.last() < _whole_heap.start()) {
|
if (old_region.last() < _whole_heap.start()) {
|
||||||
@ -354,6 +374,9 @@ void CardTableModRefBS::resize_covered_region(MemRegion new_region) {
|
|||||||
addr_for((jbyte*) _committed[ind].start()),
|
addr_for((jbyte*) _committed[ind].start()),
|
||||||
addr_for((jbyte*) _committed[ind].last()));
|
addr_for((jbyte*) _committed[ind].last()));
|
||||||
}
|
}
|
||||||
|
// Touch the last card of the covered region to show that it
|
||||||
|
// is committed (or SEGV).
|
||||||
|
debug_only(*byte_for(_covered[ind].last());)
|
||||||
debug_only(verify_guard();)
|
debug_only(verify_guard();)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -179,9 +179,14 @@ char* GenCollectedHeap::allocate(size_t alignment,
|
|||||||
}
|
}
|
||||||
n_covered_regions += _gen_specs[i]->n_covered_regions();
|
n_covered_regions += _gen_specs[i]->n_covered_regions();
|
||||||
}
|
}
|
||||||
assert(total_reserved % pageSize == 0, "Gen size");
|
assert(total_reserved % pageSize == 0,
|
||||||
|
err_msg("Gen size; total_reserved=" SIZE_FORMAT ", pageSize="
|
||||||
|
SIZE_FORMAT, total_reserved, pageSize));
|
||||||
total_reserved += perm_gen_spec->max_size();
|
total_reserved += perm_gen_spec->max_size();
|
||||||
assert(total_reserved % pageSize == 0, "Perm Gen size");
|
assert(total_reserved % pageSize == 0,
|
||||||
|
err_msg("Perm size; total_reserved=" SIZE_FORMAT ", pageSize="
|
||||||
|
SIZE_FORMAT ", perm gen max=" SIZE_FORMAT, total_reserved,
|
||||||
|
pageSize, perm_gen_spec->max_size()));
|
||||||
|
|
||||||
if (total_reserved < perm_gen_spec->max_size()) {
|
if (total_reserved < perm_gen_spec->max_size()) {
|
||||||
vm_exit_during_initialization(overflow_msg);
|
vm_exit_during_initialization(overflow_msg);
|
||||||
|
@ -372,6 +372,13 @@ void constantPoolKlass::oop_print_on(oop obj, outputStream* st) {
|
|||||||
entry->print_value_on(st);
|
entry->print_value_on(st);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case JVM_CONSTANT_MethodHandle :
|
||||||
|
st->print("ref_kind=%d", cp->method_handle_ref_kind_at(index));
|
||||||
|
st->print(" ref_index=%d", cp->method_handle_index_at(index));
|
||||||
|
break;
|
||||||
|
case JVM_CONSTANT_MethodType :
|
||||||
|
st->print("signature_index=%d", cp->method_type_index_at(index));
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
ShouldNotReachHere();
|
ShouldNotReachHere();
|
||||||
break;
|
break;
|
||||||
@ -437,6 +444,7 @@ void constantPoolKlass::oop_verify_on(oop obj, outputStream* st) {
|
|||||||
// can be non-perm, can be non-instance (array)
|
// can be non-perm, can be non-instance (array)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// FIXME: verify JSR 292 tags JVM_CONSTANT_MethodHandle, etc.
|
||||||
base++;
|
base++;
|
||||||
}
|
}
|
||||||
guarantee(cp->tags()->is_perm(), "should be in permspace");
|
guarantee(cp->tags()->is_perm(), "should be in permspace");
|
||||||
|
@ -358,6 +358,11 @@ symbolOop constantPoolOopDesc::klass_ref_at_noresolve(int which) {
|
|||||||
return klass_at_noresolve(ref_index);
|
return klass_at_noresolve(ref_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
symbolOop constantPoolOopDesc::uncached_klass_ref_at_noresolve(int which) {
|
||||||
|
jint ref_index = uncached_klass_ref_index_at(which);
|
||||||
|
return klass_at_noresolve(ref_index);
|
||||||
|
}
|
||||||
|
|
||||||
char* constantPoolOopDesc::string_at_noresolve(int which) {
|
char* constantPoolOopDesc::string_at_noresolve(int which) {
|
||||||
// Test entry type in case string is resolved while in here.
|
// Test entry type in case string is resolved while in here.
|
||||||
oop entry = *(obj_at_addr(which));
|
oop entry = *(obj_at_addr(which));
|
||||||
@ -384,6 +389,119 @@ void constantPoolOopDesc::resolve_string_constants_impl(constantPoolHandle this_
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
oop constantPoolOopDesc::resolve_constant_at_impl(constantPoolHandle this_oop, int index, int cache_index, TRAPS) {
|
||||||
|
oop result_oop = NULL;
|
||||||
|
if (cache_index >= 0) {
|
||||||
|
assert(index < 0, "only one kind of index at a time");
|
||||||
|
ConstantPoolCacheEntry* cpc_entry = this_oop->cache()->entry_at(cache_index);
|
||||||
|
result_oop = cpc_entry->f1();
|
||||||
|
if (result_oop != NULL) {
|
||||||
|
return result_oop; // that was easy...
|
||||||
|
}
|
||||||
|
index = cpc_entry->constant_pool_index();
|
||||||
|
}
|
||||||
|
|
||||||
|
int tag_value = this_oop->tag_at(index).value();
|
||||||
|
switch (tag_value) {
|
||||||
|
|
||||||
|
case JVM_CONSTANT_UnresolvedClass:
|
||||||
|
case JVM_CONSTANT_UnresolvedClassInError:
|
||||||
|
case JVM_CONSTANT_Class:
|
||||||
|
{
|
||||||
|
klassOop resolved = klass_at_impl(this_oop, index, CHECK_NULL);
|
||||||
|
// ldc wants the java mirror.
|
||||||
|
result_oop = resolved->klass_part()->java_mirror();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case JVM_CONSTANT_String:
|
||||||
|
case JVM_CONSTANT_UnresolvedString:
|
||||||
|
if (this_oop->is_pseudo_string_at(index)) {
|
||||||
|
result_oop = this_oop->pseudo_string_at(index);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
result_oop = string_at_impl(this_oop, index, CHECK_NULL);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case JVM_CONSTANT_Object:
|
||||||
|
result_oop = this_oop->object_at(index);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case JVM_CONSTANT_MethodHandle:
|
||||||
|
{
|
||||||
|
int ref_kind = this_oop->method_handle_ref_kind_at(index);
|
||||||
|
int callee_index = this_oop->method_handle_klass_index_at(index);
|
||||||
|
symbolHandle name(THREAD, this_oop->method_handle_name_ref_at(index));
|
||||||
|
symbolHandle signature(THREAD, this_oop->method_handle_signature_ref_at(index));
|
||||||
|
if (PrintMiscellaneous)
|
||||||
|
tty->print_cr("resolve JVM_CONSTANT_MethodHandle:%d [%d/%d/%d] %s.%s",
|
||||||
|
ref_kind, index, this_oop->method_handle_index_at(index),
|
||||||
|
callee_index, name->as_C_string(), signature->as_C_string());
|
||||||
|
KlassHandle callee;
|
||||||
|
{ klassOop k = klass_at_impl(this_oop, callee_index, CHECK_NULL);
|
||||||
|
callee = KlassHandle(THREAD, k);
|
||||||
|
}
|
||||||
|
KlassHandle klass(THREAD, this_oop->pool_holder());
|
||||||
|
Handle value = SystemDictionary::link_method_handle_constant(klass, ref_kind,
|
||||||
|
callee, name, signature,
|
||||||
|
CHECK_NULL);
|
||||||
|
result_oop = value();
|
||||||
|
// FIXME: Uniquify errors, using SystemDictionary::find_resolution_error.
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case JVM_CONSTANT_MethodType:
|
||||||
|
{
|
||||||
|
symbolHandle signature(THREAD, this_oop->method_type_signature_at(index));
|
||||||
|
if (PrintMiscellaneous)
|
||||||
|
tty->print_cr("resolve JVM_CONSTANT_MethodType [%d/%d] %s",
|
||||||
|
index, this_oop->method_type_index_at(index),
|
||||||
|
signature->as_C_string());
|
||||||
|
KlassHandle klass(THREAD, this_oop->pool_holder());
|
||||||
|
bool ignore_is_on_bcp = false;
|
||||||
|
Handle value = SystemDictionary::find_method_handle_type(signature,
|
||||||
|
klass,
|
||||||
|
ignore_is_on_bcp,
|
||||||
|
CHECK_NULL);
|
||||||
|
result_oop = value();
|
||||||
|
// FIXME: Uniquify errors, using SystemDictionary::find_resolution_error.
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* maybe some day
|
||||||
|
case JVM_CONSTANT_Integer:
|
||||||
|
case JVM_CONSTANT_Float:
|
||||||
|
case JVM_CONSTANT_Long:
|
||||||
|
case JVM_CONSTANT_Double:
|
||||||
|
result_oop = java_lang_boxing_object::create(...);
|
||||||
|
break;
|
||||||
|
*/
|
||||||
|
|
||||||
|
default:
|
||||||
|
DEBUG_ONLY( tty->print_cr("*** %p: tag at CP[%d/%d] = %d",
|
||||||
|
this_oop(), index, cache_index, tag_value) );
|
||||||
|
assert(false, "unexpected constant tag");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cache_index >= 0) {
|
||||||
|
// Cache the oop here also.
|
||||||
|
Handle result(THREAD, result_oop);
|
||||||
|
result_oop = NULL; // safety
|
||||||
|
ObjectLocker ol(this_oop, THREAD);
|
||||||
|
ConstantPoolCacheEntry* cpc_entry = this_oop->cache()->entry_at(cache_index);
|
||||||
|
oop result_oop2 = cpc_entry->f1();
|
||||||
|
if (result_oop2 != NULL) {
|
||||||
|
// Race condition: May already be filled in while we were trying to lock.
|
||||||
|
return result_oop2;
|
||||||
|
}
|
||||||
|
cpc_entry->set_f1(result());
|
||||||
|
return result();
|
||||||
|
} else {
|
||||||
|
return result_oop;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
oop constantPoolOopDesc::string_at_impl(constantPoolHandle this_oop, int which, TRAPS) {
|
oop constantPoolOopDesc::string_at_impl(constantPoolHandle this_oop, int which, TRAPS) {
|
||||||
oop entry = *(this_oop->obj_at_addr(which));
|
oop entry = *(this_oop->obj_at_addr(which));
|
||||||
if (entry->is_symbol()) {
|
if (entry->is_symbol()) {
|
||||||
@ -690,6 +808,28 @@ bool constantPoolOopDesc::compare_entry_to(int index1, constantPoolHandle cp2,
|
|||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
case JVM_CONSTANT_MethodType:
|
||||||
|
{
|
||||||
|
int k1 = method_type_index_at(index1);
|
||||||
|
int k2 = cp2->method_type_index_at(index2);
|
||||||
|
if (k1 == k2) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case JVM_CONSTANT_MethodHandle:
|
||||||
|
{
|
||||||
|
int k1 = method_handle_ref_kind_at(index1);
|
||||||
|
int k2 = cp2->method_handle_ref_kind_at(index2);
|
||||||
|
if (k1 == k2) {
|
||||||
|
int i1 = method_handle_index_at(index1);
|
||||||
|
int i2 = cp2->method_handle_index_at(index2);
|
||||||
|
if (i1 == i2) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
|
||||||
case JVM_CONSTANT_UnresolvedString:
|
case JVM_CONSTANT_UnresolvedString:
|
||||||
{
|
{
|
||||||
symbolOop s1 = unresolved_string_at(index1);
|
symbolOop s1 = unresolved_string_at(index1);
|
||||||
@ -863,6 +1003,19 @@ void constantPoolOopDesc::copy_entry_to(int from_i, constantPoolHandle to_cp,
|
|||||||
to_cp->symbol_at_put(to_i, s);
|
to_cp->symbol_at_put(to_i, s);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
case JVM_CONSTANT_MethodType:
|
||||||
|
{
|
||||||
|
jint k = method_type_index_at(from_i);
|
||||||
|
to_cp->method_type_index_at_put(to_i, k);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case JVM_CONSTANT_MethodHandle:
|
||||||
|
{
|
||||||
|
int k1 = method_handle_ref_kind_at(from_i);
|
||||||
|
int k2 = method_handle_index_at(from_i);
|
||||||
|
to_cp->method_handle_index_at_put(to_i, k1, k2);
|
||||||
|
} break;
|
||||||
|
|
||||||
// Invalid is used as the tag for the second constant pool entry
|
// Invalid is used as the tag for the second constant pool entry
|
||||||
// occupied by JVM_CONSTANT_Double or JVM_CONSTANT_Long. It should
|
// occupied by JVM_CONSTANT_Double or JVM_CONSTANT_Long. It should
|
||||||
// not be seen by itself.
|
// not be seen by itself.
|
||||||
@ -1066,8 +1219,12 @@ jint constantPoolOopDesc::cpool_entry_size(jint idx) {
|
|||||||
case JVM_CONSTANT_UnresolvedClassInError:
|
case JVM_CONSTANT_UnresolvedClassInError:
|
||||||
case JVM_CONSTANT_StringIndex:
|
case JVM_CONSTANT_StringIndex:
|
||||||
case JVM_CONSTANT_UnresolvedString:
|
case JVM_CONSTANT_UnresolvedString:
|
||||||
|
case JVM_CONSTANT_MethodType:
|
||||||
return 3;
|
return 3;
|
||||||
|
|
||||||
|
case JVM_CONSTANT_MethodHandle:
|
||||||
|
return 4; //tag, ref_kind, ref_index
|
||||||
|
|
||||||
case JVM_CONSTANT_Integer:
|
case JVM_CONSTANT_Integer:
|
||||||
case JVM_CONSTANT_Float:
|
case JVM_CONSTANT_Float:
|
||||||
case JVM_CONSTANT_Fieldref:
|
case JVM_CONSTANT_Fieldref:
|
||||||
@ -1271,6 +1428,22 @@ int constantPoolOopDesc::copy_cpool_bytes(int cpool_size,
|
|||||||
DBG(printf("JVM_CONSTANT_StringIndex: %hd", idx1));
|
DBG(printf("JVM_CONSTANT_StringIndex: %hd", idx1));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case JVM_CONSTANT_MethodHandle: {
|
||||||
|
*bytes = JVM_CONSTANT_MethodHandle;
|
||||||
|
int kind = method_handle_ref_kind_at(idx);
|
||||||
|
idx1 = method_handle_index_at(idx);
|
||||||
|
*(bytes+1) = (unsigned char) kind;
|
||||||
|
Bytes::put_Java_u2((address) (bytes+2), idx1);
|
||||||
|
DBG(printf("JVM_CONSTANT_MethodHandle: %d %hd", kind, idx1));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case JVM_CONSTANT_MethodType: {
|
||||||
|
*bytes = JVM_CONSTANT_MethodType;
|
||||||
|
idx1 = method_type_index_at(idx);
|
||||||
|
Bytes::put_Java_u2((address) (bytes+1), idx1);
|
||||||
|
DBG(printf("JVM_CONSTANT_MethodType: %hd", idx1));
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
DBG(printf("\n"));
|
DBG(printf("\n"));
|
||||||
bytes += ent_size;
|
bytes += ent_size;
|
||||||
|
@ -146,6 +146,16 @@ class constantPoolOopDesc : public oopDesc {
|
|||||||
oop_store_without_check(obj_at_addr(which), oop(s));
|
oop_store_without_check(obj_at_addr(which), oop(s));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void method_handle_index_at_put(int which, int ref_kind, int ref_index) {
|
||||||
|
tag_at_put(which, JVM_CONSTANT_MethodHandle);
|
||||||
|
*int_at_addr(which) = ((jint) ref_index<<16) | ref_kind;
|
||||||
|
}
|
||||||
|
|
||||||
|
void method_type_index_at_put(int which, int ref_index) {
|
||||||
|
tag_at_put(which, JVM_CONSTANT_MethodType);
|
||||||
|
*int_at_addr(which) = ref_index;
|
||||||
|
}
|
||||||
|
|
||||||
// Temporary until actual use
|
// Temporary until actual use
|
||||||
void unresolved_string_at_put(int which, symbolOop s) {
|
void unresolved_string_at_put(int which, symbolOop s) {
|
||||||
*obj_at_addr(which) = NULL;
|
*obj_at_addr(which) = NULL;
|
||||||
@ -357,6 +367,36 @@ class constantPoolOopDesc : public oopDesc {
|
|||||||
return *int_at_addr(which);
|
return *int_at_addr(which);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int method_handle_ref_kind_at(int which) {
|
||||||
|
assert(tag_at(which).is_method_handle(), "Corrupted constant pool");
|
||||||
|
return extract_low_short_from_int(*int_at_addr(which)); // mask out unwanted ref_index bits
|
||||||
|
}
|
||||||
|
int method_handle_index_at(int which) {
|
||||||
|
assert(tag_at(which).is_method_handle(), "Corrupted constant pool");
|
||||||
|
return extract_high_short_from_int(*int_at_addr(which)); // shift out unwanted ref_kind bits
|
||||||
|
}
|
||||||
|
int method_type_index_at(int which) {
|
||||||
|
assert(tag_at(which).is_method_type(), "Corrupted constant pool");
|
||||||
|
return *int_at_addr(which);
|
||||||
|
}
|
||||||
|
// Derived queries:
|
||||||
|
symbolOop method_handle_name_ref_at(int which) {
|
||||||
|
int member = method_handle_index_at(which);
|
||||||
|
return impl_name_ref_at(member, true);
|
||||||
|
}
|
||||||
|
symbolOop method_handle_signature_ref_at(int which) {
|
||||||
|
int member = method_handle_index_at(which);
|
||||||
|
return impl_signature_ref_at(member, true);
|
||||||
|
}
|
||||||
|
int method_handle_klass_index_at(int which) {
|
||||||
|
int member = method_handle_index_at(which);
|
||||||
|
return impl_klass_ref_index_at(member, true);
|
||||||
|
}
|
||||||
|
symbolOop method_type_signature_at(int which) {
|
||||||
|
int sym = method_type_index_at(which);
|
||||||
|
return symbol_at(sym);
|
||||||
|
}
|
||||||
|
|
||||||
// The following methods (name/signature/klass_ref_at, klass_ref_at_noresolve,
|
// The following methods (name/signature/klass_ref_at, klass_ref_at_noresolve,
|
||||||
// name_and_type_ref_index_at) all expect to be passed indices obtained
|
// name_and_type_ref_index_at) all expect to be passed indices obtained
|
||||||
// directly from the bytecode, and extracted according to java byte order.
|
// directly from the bytecode, and extracted according to java byte order.
|
||||||
@ -388,6 +428,17 @@ class constantPoolOopDesc : public oopDesc {
|
|||||||
resolve_string_constants_impl(h_this, CHECK);
|
resolve_string_constants_impl(h_this, CHECK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Resolve late bound constants.
|
||||||
|
oop resolve_constant_at(int index, TRAPS) {
|
||||||
|
constantPoolHandle h_this(THREAD, this);
|
||||||
|
return resolve_constant_at_impl(h_this, index, -1, THREAD);
|
||||||
|
}
|
||||||
|
|
||||||
|
oop resolve_cached_constant_at(int cache_index, TRAPS) {
|
||||||
|
constantPoolHandle h_this(THREAD, this);
|
||||||
|
return resolve_constant_at_impl(h_this, -1, cache_index, THREAD);
|
||||||
|
}
|
||||||
|
|
||||||
// Klass name matches name at offset
|
// Klass name matches name at offset
|
||||||
bool klass_name_at_matches(instanceKlassHandle k, int which);
|
bool klass_name_at_matches(instanceKlassHandle k, int which);
|
||||||
|
|
||||||
@ -420,6 +471,7 @@ class constantPoolOopDesc : public oopDesc {
|
|||||||
// Routines currently used for annotations (only called by jvm.cpp) but which might be used in the
|
// Routines currently used for annotations (only called by jvm.cpp) but which might be used in the
|
||||||
// future by other Java code. These take constant pool indices rather than possibly-byte-swapped
|
// future by other Java code. These take constant pool indices rather than possibly-byte-swapped
|
||||||
// constant pool cache indices as do the peer methods above.
|
// constant pool cache indices as do the peer methods above.
|
||||||
|
symbolOop uncached_klass_ref_at_noresolve(int which);
|
||||||
symbolOop uncached_name_ref_at(int which) { return impl_name_ref_at(which, true); }
|
symbolOop uncached_name_ref_at(int which) { return impl_name_ref_at(which, true); }
|
||||||
symbolOop uncached_signature_ref_at(int which) { return impl_signature_ref_at(which, true); }
|
symbolOop uncached_signature_ref_at(int which) { return impl_signature_ref_at(which, true); }
|
||||||
int uncached_klass_ref_index_at(int which) { return impl_klass_ref_index_at(which, true); }
|
int uncached_klass_ref_index_at(int which) { return impl_klass_ref_index_at(which, true); }
|
||||||
@ -436,6 +488,8 @@ class constantPoolOopDesc : public oopDesc {
|
|||||||
|
|
||||||
#ifdef ASSERT
|
#ifdef ASSERT
|
||||||
enum { CPCACHE_INDEX_TAG = 0x10000 }; // helps keep CP cache indices distinct from CP indices
|
enum { CPCACHE_INDEX_TAG = 0x10000 }; // helps keep CP cache indices distinct from CP indices
|
||||||
|
#else
|
||||||
|
enum { CPCACHE_INDEX_TAG = 0 }; // in product mode, this zero value is a no-op
|
||||||
#endif //ASSERT
|
#endif //ASSERT
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -469,6 +523,8 @@ class constantPoolOopDesc : public oopDesc {
|
|||||||
// Resolve string constants (to prevent allocation during compilation)
|
// Resolve string constants (to prevent allocation during compilation)
|
||||||
static void resolve_string_constants_impl(constantPoolHandle this_oop, TRAPS);
|
static void resolve_string_constants_impl(constantPoolHandle this_oop, TRAPS);
|
||||||
|
|
||||||
|
static oop resolve_constant_at_impl(constantPoolHandle this_oop, int index, int cache_index, TRAPS);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Merging constantPoolOop support:
|
// Merging constantPoolOop support:
|
||||||
bool compare_entry_to(int index1, constantPoolHandle cp2, int index2, TRAPS);
|
bool compare_entry_to(int index1, constantPoolHandle cp2, int index2, TRAPS);
|
||||||
|
@ -110,6 +110,7 @@
|
|||||||
class ConstantPoolCacheEntry VALUE_OBJ_CLASS_SPEC {
|
class ConstantPoolCacheEntry VALUE_OBJ_CLASS_SPEC {
|
||||||
friend class VMStructs;
|
friend class VMStructs;
|
||||||
friend class constantPoolCacheKlass;
|
friend class constantPoolCacheKlass;
|
||||||
|
friend class constantPoolOopDesc; //resolve_constant_at_impl => set_f1
|
||||||
|
|
||||||
private:
|
private:
|
||||||
volatile intx _indices; // constant pool index & rewrite bytecodes
|
volatile intx _indices; // constant pool index & rewrite bytecodes
|
||||||
|
@ -472,9 +472,7 @@ Node *RegionNode::Ideal(PhaseGVN *phase, bool can_reshape) {
|
|||||||
assert( n->req() == 2 && n->in(1) != NULL, "Only one data input expected" );
|
assert( n->req() == 2 && n->in(1) != NULL, "Only one data input expected" );
|
||||||
// Break dead loop data path.
|
// Break dead loop data path.
|
||||||
// Eagerly replace phis with top to avoid phis copies generation.
|
// Eagerly replace phis with top to avoid phis copies generation.
|
||||||
igvn->add_users_to_worklist(n);
|
igvn->replace_node(n, top);
|
||||||
igvn->hash_delete(n); // Yank from hash before hacking edges
|
|
||||||
igvn->subsume_node(n, top);
|
|
||||||
if( max != outcnt() ) {
|
if( max != outcnt() ) {
|
||||||
progress = true;
|
progress = true;
|
||||||
j = refresh_out_pos(j);
|
j = refresh_out_pos(j);
|
||||||
@ -518,18 +516,17 @@ Node *RegionNode::Ideal(PhaseGVN *phase, bool can_reshape) {
|
|||||||
igvn->hash_delete(n); // Remove from worklist before modifying edges
|
igvn->hash_delete(n); // Remove from worklist before modifying edges
|
||||||
if( n->is_Phi() ) { // Collapse all Phis
|
if( n->is_Phi() ) { // Collapse all Phis
|
||||||
// Eagerly replace phis to avoid copies generation.
|
// Eagerly replace phis to avoid copies generation.
|
||||||
igvn->add_users_to_worklist(n);
|
Node* in;
|
||||||
igvn->hash_delete(n); // Yank from hash before hacking edges
|
|
||||||
if( cnt == 0 ) {
|
if( cnt == 0 ) {
|
||||||
assert( n->req() == 1, "No data inputs expected" );
|
assert( n->req() == 1, "No data inputs expected" );
|
||||||
igvn->subsume_node(n, parent_ctrl); // replaced by top
|
in = parent_ctrl; // replaced by top
|
||||||
} else {
|
} else {
|
||||||
assert( n->req() == 2 && n->in(1) != NULL, "Only one data input expected" );
|
assert( n->req() == 2 && n->in(1) != NULL, "Only one data input expected" );
|
||||||
Node* in1 = n->in(1); // replaced by unique input
|
in = n->in(1); // replaced by unique input
|
||||||
if( n->as_Phi()->is_unsafe_data_reference(in1) )
|
if( n->as_Phi()->is_unsafe_data_reference(in) )
|
||||||
in1 = phase->C->top(); // replaced by top
|
in = phase->C->top(); // replaced by top
|
||||||
igvn->subsume_node(n, in1);
|
|
||||||
}
|
}
|
||||||
|
igvn->replace_node(n, in);
|
||||||
}
|
}
|
||||||
else if( n->is_Region() ) { // Update all incoming edges
|
else if( n->is_Region() ) { // Update all incoming edges
|
||||||
assert( !igvn->eqv(n, this), "Must be removed from DefUse edges");
|
assert( !igvn->eqv(n, this), "Must be removed from DefUse edges");
|
||||||
@ -2127,7 +2124,7 @@ Node *NeverBranchNode::Ideal(PhaseGVN *phase, bool can_reshape) {
|
|||||||
// if it's not there, there's nothing to do.
|
// if it's not there, there's nothing to do.
|
||||||
Node* fallthru = proj_out(0);
|
Node* fallthru = proj_out(0);
|
||||||
if (fallthru != NULL) {
|
if (fallthru != NULL) {
|
||||||
phase->is_IterGVN()->subsume_node(fallthru, in(0));
|
phase->is_IterGVN()->replace_node(fallthru, in(0));
|
||||||
}
|
}
|
||||||
return phase->C->top();
|
return phase->C->top();
|
||||||
}
|
}
|
||||||
|
@ -2000,6 +2000,17 @@ static void final_graph_reshaping_impl( Node *n, Final_Reshape_Counts &frc ) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef ASSERT
|
||||||
|
if( n->is_Mem() ) {
|
||||||
|
Compile* C = Compile::current();
|
||||||
|
int alias_idx = C->get_alias_index(n->as_Mem()->adr_type());
|
||||||
|
assert( n->in(0) != NULL || alias_idx != Compile::AliasIdxRaw ||
|
||||||
|
// oop will be recorded in oop map if load crosses safepoint
|
||||||
|
n->is_Load() && (n->as_Load()->bottom_type()->isa_oopptr() ||
|
||||||
|
LoadNode::is_immutable_value(n->in(MemNode::Address))),
|
||||||
|
"raw memory operations should have control edge");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
// Count FPU ops and common calls, implements item (3)
|
// Count FPU ops and common calls, implements item (3)
|
||||||
switch( nop ) {
|
switch( nop ) {
|
||||||
// Count all float operations that may use FPU
|
// Count all float operations that may use FPU
|
||||||
|
@ -1789,9 +1789,10 @@ void GraphKit::increment_counter(address counter_addr) {
|
|||||||
|
|
||||||
void GraphKit::increment_counter(Node* counter_addr) {
|
void GraphKit::increment_counter(Node* counter_addr) {
|
||||||
int adr_type = Compile::AliasIdxRaw;
|
int adr_type = Compile::AliasIdxRaw;
|
||||||
Node* cnt = make_load(NULL, counter_addr, TypeInt::INT, T_INT, adr_type);
|
Node* ctrl = control();
|
||||||
|
Node* cnt = make_load(ctrl, counter_addr, TypeInt::INT, T_INT, adr_type);
|
||||||
Node* incr = _gvn.transform(new (C, 3) AddINode(cnt, _gvn.intcon(1)));
|
Node* incr = _gvn.transform(new (C, 3) AddINode(cnt, _gvn.intcon(1)));
|
||||||
store_to_memory( NULL, counter_addr, incr, T_INT, adr_type );
|
store_to_memory( ctrl, counter_addr, incr, T_INT, adr_type );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -2771,11 +2772,7 @@ FastLockNode* GraphKit::shared_lock(Node* obj) {
|
|||||||
// Update the counter for this lock. Don't bother using an atomic
|
// Update the counter for this lock. Don't bother using an atomic
|
||||||
// operation since we don't require absolute accuracy.
|
// operation since we don't require absolute accuracy.
|
||||||
lock->create_lock_counter(map()->jvms());
|
lock->create_lock_counter(map()->jvms());
|
||||||
int adr_type = Compile::AliasIdxRaw;
|
increment_counter(lock->counter()->addr());
|
||||||
Node* counter_addr = makecon(TypeRawPtr::make(lock->counter()->addr()));
|
|
||||||
Node* cnt = make_load(NULL, counter_addr, TypeInt::INT, T_INT, adr_type);
|
|
||||||
Node* incr = _gvn.transform(new (C, 3) AddINode(cnt, _gvn.intcon(1)));
|
|
||||||
store_to_memory(control(), counter_addr, incr, T_INT, adr_type);
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -1081,11 +1081,9 @@ static IfNode* idealize_test(PhaseGVN* phase, IfNode* iff) {
|
|||||||
|
|
||||||
igvn->register_new_node_with_optimizer(new_if_f);
|
igvn->register_new_node_with_optimizer(new_if_f);
|
||||||
igvn->register_new_node_with_optimizer(new_if_t);
|
igvn->register_new_node_with_optimizer(new_if_t);
|
||||||
igvn->hash_delete(old_if_f);
|
|
||||||
igvn->hash_delete(old_if_t);
|
|
||||||
// Flip test, so flip trailing control
|
// Flip test, so flip trailing control
|
||||||
igvn->subsume_node(old_if_f, new_if_t);
|
igvn->replace_node(old_if_f, new_if_t);
|
||||||
igvn->subsume_node(old_if_t, new_if_f);
|
igvn->replace_node(old_if_t, new_if_f);
|
||||||
|
|
||||||
// Progress
|
// Progress
|
||||||
return iff;
|
return iff;
|
||||||
|
@ -3512,8 +3512,7 @@ bool LibraryCallKit::inline_native_hashcode(bool is_virtual, bool is_static) {
|
|||||||
|
|
||||||
// Get the header out of the object, use LoadMarkNode when available
|
// Get the header out of the object, use LoadMarkNode when available
|
||||||
Node* header_addr = basic_plus_adr(obj, oopDesc::mark_offset_in_bytes());
|
Node* header_addr = basic_plus_adr(obj, oopDesc::mark_offset_in_bytes());
|
||||||
Node* header = make_load(NULL, header_addr, TypeRawPtr::BOTTOM, T_ADDRESS);
|
Node* header = make_load(control(), header_addr, TypeX_X, TypeX_X->basic_type());
|
||||||
header = _gvn.transform( new (C, 2) CastP2XNode(NULL, header) );
|
|
||||||
|
|
||||||
// Test the header to see if it is unlocked.
|
// Test the header to see if it is unlocked.
|
||||||
Node *lock_mask = _gvn.MakeConX(markOopDesc::biased_lock_mask_in_place);
|
Node *lock_mask = _gvn.MakeConX(markOopDesc::biased_lock_mask_in_place);
|
||||||
@ -5202,7 +5201,7 @@ LibraryCallKit::generate_checkcast_arraycopy(const TypePtr* adr_type,
|
|||||||
// super_check_offset, for the desired klass.
|
// super_check_offset, for the desired klass.
|
||||||
int sco_offset = Klass::super_check_offset_offset_in_bytes() + sizeof(oopDesc);
|
int sco_offset = Klass::super_check_offset_offset_in_bytes() + sizeof(oopDesc);
|
||||||
Node* p3 = basic_plus_adr(dest_elem_klass, sco_offset);
|
Node* p3 = basic_plus_adr(dest_elem_klass, sco_offset);
|
||||||
Node* n3 = new(C, 3) LoadINode(NULL, immutable_memory(), p3, TypeRawPtr::BOTTOM);
|
Node* n3 = new(C, 3) LoadINode(NULL, memory(p3), p3, _gvn.type(p3)->is_ptr());
|
||||||
Node* check_offset = _gvn.transform(n3);
|
Node* check_offset = _gvn.transform(n3);
|
||||||
Node* check_value = dest_elem_klass;
|
Node* check_value = dest_elem_klass;
|
||||||
|
|
||||||
|
@ -194,8 +194,7 @@ Node* IdealLoopTree::reassociate_add_sub(Node* n1, PhaseIdealLoop *phase) {
|
|||||||
addx = new (phase->C, 3) AddINode(x, inv);
|
addx = new (phase->C, 3) AddINode(x, inv);
|
||||||
}
|
}
|
||||||
phase->register_new_node(addx, phase->get_ctrl(x));
|
phase->register_new_node(addx, phase->get_ctrl(x));
|
||||||
phase->_igvn.hash_delete(n1);
|
phase->_igvn.replace_node(n1, addx);
|
||||||
phase->_igvn.subsume_node(n1, addx);
|
|
||||||
return addx;
|
return addx;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1586,8 +1585,7 @@ bool IdealLoopTree::policy_do_remove_empty_loop( PhaseIdealLoop *phase ) {
|
|||||||
Node *phi = cl->phi();
|
Node *phi = cl->phi();
|
||||||
Node *final = new (phase->C, 3) SubINode( cl->limit(), cl->stride() );
|
Node *final = new (phase->C, 3) SubINode( cl->limit(), cl->stride() );
|
||||||
phase->register_new_node(final,cl->in(LoopNode::EntryControl));
|
phase->register_new_node(final,cl->in(LoopNode::EntryControl));
|
||||||
phase->_igvn.hash_delete(phi);
|
phase->_igvn.replace_node(phi,final);
|
||||||
phase->_igvn.subsume_node(phi,final);
|
|
||||||
phase->C->set_major_progress();
|
phase->C->set_major_progress();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -400,7 +400,7 @@ Node *PhaseIdealLoop::is_counted_loop( Node *x, IdealLoopTree *loop ) {
|
|||||||
nphi->set_req(LoopNode::LoopBackControl, phi->in(LoopNode::LoopBackControl));
|
nphi->set_req(LoopNode::LoopBackControl, phi->in(LoopNode::LoopBackControl));
|
||||||
nphi = _igvn.register_new_node_with_optimizer(nphi);
|
nphi = _igvn.register_new_node_with_optimizer(nphi);
|
||||||
set_ctrl(nphi, get_ctrl(phi));
|
set_ctrl(nphi, get_ctrl(phi));
|
||||||
_igvn.subsume_node(phi, nphi);
|
_igvn.replace_node(phi, nphi);
|
||||||
phi = nphi->as_Phi();
|
phi = nphi->as_Phi();
|
||||||
}
|
}
|
||||||
cmp = cmp->clone();
|
cmp = cmp->clone();
|
||||||
@ -760,7 +760,7 @@ void IdealLoopTree::split_fall_in( PhaseIdealLoop *phase, int fall_in_cnt ) {
|
|||||||
// which in turn prevents removing an empty loop.
|
// which in turn prevents removing an empty loop.
|
||||||
Node *id_old_phi = old_phi->Identity( &igvn );
|
Node *id_old_phi = old_phi->Identity( &igvn );
|
||||||
if( id_old_phi != old_phi ) { // Found a simple identity?
|
if( id_old_phi != old_phi ) { // Found a simple identity?
|
||||||
// Note that I cannot call 'subsume_node' here, because
|
// Note that I cannot call 'replace_node' here, because
|
||||||
// that will yank the edge from old_phi to the Region and
|
// that will yank the edge from old_phi to the Region and
|
||||||
// I'm mid-iteration over the Region's uses.
|
// I'm mid-iteration over the Region's uses.
|
||||||
for (DUIterator_Last imin, i = old_phi->last_outs(imin); i >= imin; ) {
|
for (DUIterator_Last imin, i = old_phi->last_outs(imin); i >= imin; ) {
|
||||||
@ -1065,11 +1065,9 @@ bool IdealLoopTree::beautify_loops( PhaseIdealLoop *phase ) {
|
|||||||
l = igvn.register_new_node_with_optimizer(l, _head);
|
l = igvn.register_new_node_with_optimizer(l, _head);
|
||||||
phase->set_created_loop_node();
|
phase->set_created_loop_node();
|
||||||
// Go ahead and replace _head
|
// Go ahead and replace _head
|
||||||
phase->_igvn.subsume_node( _head, l );
|
phase->_igvn.replace_node( _head, l );
|
||||||
_head = l;
|
_head = l;
|
||||||
phase->set_loop(_head, this);
|
phase->set_loop(_head, this);
|
||||||
for (DUIterator_Fast imax, i = l->fast_outs(imax); i < imax; i++)
|
|
||||||
phase->_igvn.add_users_to_worklist(l->fast_out(i));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now recursively beautify nested loops
|
// Now recursively beautify nested loops
|
||||||
@ -1329,8 +1327,7 @@ void IdealLoopTree::counted_loop( PhaseIdealLoop *phase ) {
|
|||||||
Node* add = new (C, 3) AddINode(ratio_idx, diff);
|
Node* add = new (C, 3) AddINode(ratio_idx, diff);
|
||||||
phase->_igvn.register_new_node_with_optimizer(add);
|
phase->_igvn.register_new_node_with_optimizer(add);
|
||||||
phase->set_ctrl(add, cl);
|
phase->set_ctrl(add, cl);
|
||||||
phase->_igvn.hash_delete( phi2 );
|
phase->_igvn.replace_node( phi2, add );
|
||||||
phase->_igvn.subsume_node( phi2, add );
|
|
||||||
// Sometimes an induction variable is unused
|
// Sometimes an induction variable is unused
|
||||||
if (add->outcnt() == 0) {
|
if (add->outcnt() == 0) {
|
||||||
phase->_igvn.remove_dead_node(add);
|
phase->_igvn.remove_dead_node(add);
|
||||||
|
@ -626,8 +626,7 @@ public:
|
|||||||
_nodes.map( old_node->_idx, (Node*)((intptr_t)new_node + 1) );
|
_nodes.map( old_node->_idx, (Node*)((intptr_t)new_node + 1) );
|
||||||
}
|
}
|
||||||
void lazy_replace( Node *old_node, Node *new_node ) {
|
void lazy_replace( Node *old_node, Node *new_node ) {
|
||||||
_igvn.hash_delete(old_node);
|
_igvn.replace_node( old_node, new_node );
|
||||||
_igvn.subsume_node( old_node, new_node );
|
|
||||||
lazy_update( old_node, new_node );
|
lazy_update( old_node, new_node );
|
||||||
}
|
}
|
||||||
void lazy_replace_proj( Node *old_node, Node *new_node ) {
|
void lazy_replace_proj( Node *old_node, Node *new_node ) {
|
||||||
|
@ -354,8 +354,7 @@ Node *PhaseIdealLoop::remix_address_expressions( Node *n ) {
|
|||||||
register_new_node( var_scale, n_ctrl );
|
register_new_node( var_scale, n_ctrl );
|
||||||
Node *var_add = new (C, 3) AddINode( var_scale, inv_scale );
|
Node *var_add = new (C, 3) AddINode( var_scale, inv_scale );
|
||||||
register_new_node( var_add, n_ctrl );
|
register_new_node( var_add, n_ctrl );
|
||||||
_igvn.hash_delete( n );
|
_igvn.replace_node( n, var_add );
|
||||||
_igvn.subsume_node( n, var_add );
|
|
||||||
return var_add;
|
return var_add;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -390,8 +389,7 @@ Node *PhaseIdealLoop::remix_address_expressions( Node *n ) {
|
|||||||
register_new_node( add1, n_loop->_head->in(LoopNode::EntryControl) );
|
register_new_node( add1, n_loop->_head->in(LoopNode::EntryControl) );
|
||||||
Node *add2 = new (C, 4) AddPNode( n->in(1), add1, n->in(2)->in(3) );
|
Node *add2 = new (C, 4) AddPNode( n->in(1), add1, n->in(2)->in(3) );
|
||||||
register_new_node( add2, n_ctrl );
|
register_new_node( add2, n_ctrl );
|
||||||
_igvn.hash_delete( n );
|
_igvn.replace_node( n, add2 );
|
||||||
_igvn.subsume_node( n, add2 );
|
|
||||||
return add2;
|
return add2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -412,8 +410,7 @@ Node *PhaseIdealLoop::remix_address_expressions( Node *n ) {
|
|||||||
register_new_node( add1, n_loop->_head->in(LoopNode::EntryControl) );
|
register_new_node( add1, n_loop->_head->in(LoopNode::EntryControl) );
|
||||||
Node *add2 = new (C, 4) AddPNode( n->in(1), add1, V );
|
Node *add2 = new (C, 4) AddPNode( n->in(1), add1, V );
|
||||||
register_new_node( add2, n_ctrl );
|
register_new_node( add2, n_ctrl );
|
||||||
_igvn.hash_delete( n );
|
_igvn.replace_node( n, add2 );
|
||||||
_igvn.subsume_node( n, add2 );
|
|
||||||
return add2;
|
return add2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -555,8 +552,7 @@ Node *PhaseIdealLoop::conditional_move( Node *region ) {
|
|||||||
}
|
}
|
||||||
Node *cmov = CMoveNode::make( C, cmov_ctrl, iff->in(1), phi->in(1+flip), phi->in(2-flip), _igvn.type(phi) );
|
Node *cmov = CMoveNode::make( C, cmov_ctrl, iff->in(1), phi->in(1+flip), phi->in(2-flip), _igvn.type(phi) );
|
||||||
register_new_node( cmov, cmov_ctrl );
|
register_new_node( cmov, cmov_ctrl );
|
||||||
_igvn.hash_delete(phi);
|
_igvn.replace_node( phi, cmov );
|
||||||
_igvn.subsume_node( phi, cmov );
|
|
||||||
#ifndef PRODUCT
|
#ifndef PRODUCT
|
||||||
if( VerifyLoopOptimizations ) verify();
|
if( VerifyLoopOptimizations ) verify();
|
||||||
#endif
|
#endif
|
||||||
@ -642,8 +638,7 @@ Node *PhaseIdealLoop::split_if_with_blocks_pre( Node *n ) {
|
|||||||
|
|
||||||
// Found a Phi to split thru!
|
// Found a Phi to split thru!
|
||||||
// Replace 'n' with the new phi
|
// Replace 'n' with the new phi
|
||||||
_igvn.hash_delete(n);
|
_igvn.replace_node( n, phi );
|
||||||
_igvn.subsume_node( n, phi );
|
|
||||||
// Moved a load around the loop, 'en-registering' something.
|
// Moved a load around the loop, 'en-registering' something.
|
||||||
if( n_blk->Opcode() == Op_Loop && n->is_Load() &&
|
if( n_blk->Opcode() == Op_Loop && n->is_Load() &&
|
||||||
!phi->in(LoopNode::LoopBackControl)->is_Load() )
|
!phi->in(LoopNode::LoopBackControl)->is_Load() )
|
||||||
@ -789,13 +784,11 @@ void PhaseIdealLoop::split_if_with_blocks_post( Node *n ) {
|
|||||||
|
|
||||||
// Found a Phi to split thru!
|
// Found a Phi to split thru!
|
||||||
// Replace 'n' with the new phi
|
// Replace 'n' with the new phi
|
||||||
_igvn.hash_delete(n);
|
_igvn.replace_node( n, phi );
|
||||||
_igvn.subsume_node( n, phi );
|
|
||||||
|
|
||||||
// Now split the bool up thru the phi
|
// Now split the bool up thru the phi
|
||||||
Node *bolphi = split_thru_phi( bol, n_ctrl, -1 );
|
Node *bolphi = split_thru_phi( bol, n_ctrl, -1 );
|
||||||
_igvn.hash_delete(bol);
|
_igvn.replace_node( bol, bolphi );
|
||||||
_igvn.subsume_node( bol, bolphi );
|
|
||||||
assert( iff->in(1) == bolphi, "" );
|
assert( iff->in(1) == bolphi, "" );
|
||||||
if( bolphi->Value(&_igvn)->singleton() )
|
if( bolphi->Value(&_igvn)->singleton() )
|
||||||
return;
|
return;
|
||||||
@ -803,8 +796,7 @@ void PhaseIdealLoop::split_if_with_blocks_post( Node *n ) {
|
|||||||
// Conditional-move? Must split up now
|
// Conditional-move? Must split up now
|
||||||
if( !iff->is_If() ) {
|
if( !iff->is_If() ) {
|
||||||
Node *cmovphi = split_thru_phi( iff, n_ctrl, -1 );
|
Node *cmovphi = split_thru_phi( iff, n_ctrl, -1 );
|
||||||
_igvn.hash_delete(iff);
|
_igvn.replace_node( iff, cmovphi );
|
||||||
_igvn.subsume_node( iff, cmovphi );
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -950,9 +942,7 @@ void PhaseIdealLoop::split_if_with_blocks_post( Node *n ) {
|
|||||||
if( n_op == Op_Opaque2 &&
|
if( n_op == Op_Opaque2 &&
|
||||||
n->in(1) != NULL &&
|
n->in(1) != NULL &&
|
||||||
get_loop(get_ctrl(n)) == get_loop(get_ctrl(n->in(1))) ) {
|
get_loop(get_ctrl(n)) == get_loop(get_ctrl(n->in(1))) ) {
|
||||||
_igvn.add_users_to_worklist(n);
|
_igvn.replace_node( n, n->in(1) );
|
||||||
_igvn.hash_delete(n);
|
|
||||||
_igvn.subsume_node( n, n->in(1) );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1425,7 +1415,7 @@ void PhaseIdealLoop::clone_loop( IdealLoopTree *loop, Node_List &old_new, int dd
|
|||||||
// IGVN does CSE).
|
// IGVN does CSE).
|
||||||
Node *hit = _igvn.hash_find_insert(use);
|
Node *hit = _igvn.hash_find_insert(use);
|
||||||
if( hit ) // Go ahead and re-hash for hits.
|
if( hit ) // Go ahead and re-hash for hits.
|
||||||
_igvn.subsume_node( use, hit );
|
_igvn.replace_node( use, hit );
|
||||||
}
|
}
|
||||||
|
|
||||||
// If 'use' was in the loop-exit block, it now needs to be sunk
|
// If 'use' was in the loop-exit block, it now needs to be sunk
|
||||||
|
@ -135,8 +135,7 @@ CallNode* PhaseMacroExpand::make_slow_call(CallNode *oldcall, const TypeFunc* sl
|
|||||||
if (parm1 != NULL) call->init_req(TypeFunc::Parms+1, parm1);
|
if (parm1 != NULL) call->init_req(TypeFunc::Parms+1, parm1);
|
||||||
copy_call_debug_info(oldcall, call);
|
copy_call_debug_info(oldcall, call);
|
||||||
call->set_cnt(PROB_UNLIKELY_MAG(4)); // Same effect as RC_UNCOMMON.
|
call->set_cnt(PROB_UNLIKELY_MAG(4)); // Same effect as RC_UNCOMMON.
|
||||||
_igvn.hash_delete(oldcall);
|
_igvn.replace_node(oldcall, call);
|
||||||
_igvn.subsume_node(oldcall, call);
|
|
||||||
transform_later(call);
|
transform_later(call);
|
||||||
|
|
||||||
return call;
|
return call;
|
||||||
@ -523,8 +522,7 @@ Node *PhaseMacroExpand::value_from_mem(Node *sfpt_mem, BasicType ft, const Type
|
|||||||
// Kill all new Phis
|
// Kill all new Phis
|
||||||
while(value_phis.is_nonempty()) {
|
while(value_phis.is_nonempty()) {
|
||||||
Node* n = value_phis.node();
|
Node* n = value_phis.node();
|
||||||
_igvn.hash_delete(n);
|
_igvn.replace_node(n, C->top());
|
||||||
_igvn.subsume_node(n, C->top());
|
|
||||||
value_phis.pop();
|
value_phis.pop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1311,8 +1309,7 @@ void PhaseMacroExpand::expand_allocate_common(
|
|||||||
if (!always_slow) {
|
if (!always_slow) {
|
||||||
call->set_cnt(PROB_UNLIKELY_MAG(4)); // Same effect as RC_UNCOMMON.
|
call->set_cnt(PROB_UNLIKELY_MAG(4)); // Same effect as RC_UNCOMMON.
|
||||||
}
|
}
|
||||||
_igvn.hash_delete(alloc);
|
_igvn.replace_node(alloc, call);
|
||||||
_igvn.subsume_node(alloc, call);
|
|
||||||
transform_later(call);
|
transform_later(call);
|
||||||
|
|
||||||
// Identify the output projections from the allocate node and
|
// Identify the output projections from the allocate node and
|
||||||
@ -1431,7 +1428,7 @@ PhaseMacroExpand::initialize_object(AllocateNode* alloc,
|
|||||||
Node* mark_node = NULL;
|
Node* mark_node = NULL;
|
||||||
// For now only enable fast locking for non-array types
|
// For now only enable fast locking for non-array types
|
||||||
if (UseBiasedLocking && (length == NULL)) {
|
if (UseBiasedLocking && (length == NULL)) {
|
||||||
mark_node = make_load(NULL, rawmem, klass_node, Klass::prototype_header_offset_in_bytes() + sizeof(oopDesc), TypeRawPtr::BOTTOM, T_ADDRESS);
|
mark_node = make_load(control, rawmem, klass_node, Klass::prototype_header_offset_in_bytes() + sizeof(oopDesc), TypeRawPtr::BOTTOM, T_ADDRESS);
|
||||||
} else {
|
} else {
|
||||||
mark_node = makecon(TypeRawPtr::make((address)markOopDesc::prototype()));
|
mark_node = makecon(TypeRawPtr::make((address)markOopDesc::prototype()));
|
||||||
}
|
}
|
||||||
|
@ -815,6 +815,16 @@ void LoadNode::dump_spec(outputStream *st) const {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef ASSERT
|
||||||
|
//----------------------------is_immutable_value-------------------------------
|
||||||
|
// Helper function to allow a raw load without control edge for some cases
|
||||||
|
bool LoadNode::is_immutable_value(Node* adr) {
|
||||||
|
return (adr->is_AddP() && adr->in(AddPNode::Base)->is_top() &&
|
||||||
|
adr->in(AddPNode::Address)->Opcode() == Op_ThreadLocal &&
|
||||||
|
(adr->in(AddPNode::Offset)->find_intptr_t_con(-1) ==
|
||||||
|
in_bytes(JavaThread::osthread_offset())));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
//----------------------------LoadNode::make-----------------------------------
|
//----------------------------LoadNode::make-----------------------------------
|
||||||
// Polymorphic factory method:
|
// Polymorphic factory method:
|
||||||
@ -828,6 +838,11 @@ Node *LoadNode::make( PhaseGVN& gvn, Node *ctl, Node *mem, Node *adr, const Type
|
|||||||
assert(!(adr_type->isa_aryptr() &&
|
assert(!(adr_type->isa_aryptr() &&
|
||||||
adr_type->offset() == arrayOopDesc::length_offset_in_bytes()),
|
adr_type->offset() == arrayOopDesc::length_offset_in_bytes()),
|
||||||
"use LoadRangeNode instead");
|
"use LoadRangeNode instead");
|
||||||
|
// Check control edge of raw loads
|
||||||
|
assert( ctl != NULL || C->get_alias_index(adr_type) != Compile::AliasIdxRaw ||
|
||||||
|
// oop will be recorded in oop map if load crosses safepoint
|
||||||
|
rt->isa_oopptr() || is_immutable_value(adr),
|
||||||
|
"raw memory operations should have control edge");
|
||||||
switch (bt) {
|
switch (bt) {
|
||||||
case T_BOOLEAN: return new (C, 3) LoadUBNode(ctl, mem, adr, adr_type, rt->is_int() );
|
case T_BOOLEAN: return new (C, 3) LoadUBNode(ctl, mem, adr, adr_type, rt->is_int() );
|
||||||
case T_BYTE: return new (C, 3) LoadBNode (ctl, mem, adr, adr_type, rt->is_int() );
|
case T_BYTE: return new (C, 3) LoadBNode (ctl, mem, adr, adr_type, rt->is_int() );
|
||||||
@ -2064,6 +2079,8 @@ Node* LoadRangeNode::Identity( PhaseTransform *phase ) {
|
|||||||
// Polymorphic factory method:
|
// Polymorphic factory method:
|
||||||
StoreNode* StoreNode::make( PhaseGVN& gvn, Node* ctl, Node* mem, Node* adr, const TypePtr* adr_type, Node* val, BasicType bt ) {
|
StoreNode* StoreNode::make( PhaseGVN& gvn, Node* ctl, Node* mem, Node* adr, const TypePtr* adr_type, Node* val, BasicType bt ) {
|
||||||
Compile* C = gvn.C;
|
Compile* C = gvn.C;
|
||||||
|
assert( C->get_alias_index(adr_type) != Compile::AliasIdxRaw ||
|
||||||
|
ctl != NULL, "raw memory operations should have control edge");
|
||||||
|
|
||||||
switch (bt) {
|
switch (bt) {
|
||||||
case T_BOOLEAN:
|
case T_BOOLEAN:
|
||||||
|
@ -189,6 +189,10 @@ public:
|
|||||||
#ifndef PRODUCT
|
#ifndef PRODUCT
|
||||||
virtual void dump_spec(outputStream *st) const;
|
virtual void dump_spec(outputStream *st) const;
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef ASSERT
|
||||||
|
// Helper function to allow a raw load without control edge for some cases
|
||||||
|
static bool is_immutable_value(Node* adr);
|
||||||
|
#endif
|
||||||
protected:
|
protected:
|
||||||
const Type* load_array_final_field(const TypeKlassPtr *tkls,
|
const Type* load_array_final_field(const TypeKlassPtr *tkls,
|
||||||
ciKlass* klass) const;
|
ciKlass* klass) const;
|
||||||
|
@ -88,15 +88,16 @@ Node *Parse::fetch_interpreter_state(int index,
|
|||||||
Node *local_addrs_base) {
|
Node *local_addrs_base) {
|
||||||
Node *mem = memory(Compile::AliasIdxRaw);
|
Node *mem = memory(Compile::AliasIdxRaw);
|
||||||
Node *adr = basic_plus_adr( local_addrs_base, local_addrs, -index*wordSize );
|
Node *adr = basic_plus_adr( local_addrs_base, local_addrs, -index*wordSize );
|
||||||
|
Node *ctl = control();
|
||||||
|
|
||||||
// Very similar to LoadNode::make, except we handle un-aligned longs and
|
// Very similar to LoadNode::make, except we handle un-aligned longs and
|
||||||
// doubles on Sparc. Intel can handle them just fine directly.
|
// doubles on Sparc. Intel can handle them just fine directly.
|
||||||
Node *l;
|
Node *l;
|
||||||
switch( bt ) { // Signature is flattened
|
switch( bt ) { // Signature is flattened
|
||||||
case T_INT: l = new (C, 3) LoadINode( 0, mem, adr, TypeRawPtr::BOTTOM ); break;
|
case T_INT: l = new (C, 3) LoadINode( ctl, mem, adr, TypeRawPtr::BOTTOM ); break;
|
||||||
case T_FLOAT: l = new (C, 3) LoadFNode( 0, mem, adr, TypeRawPtr::BOTTOM ); break;
|
case T_FLOAT: l = new (C, 3) LoadFNode( ctl, mem, adr, TypeRawPtr::BOTTOM ); break;
|
||||||
case T_ADDRESS: l = new (C, 3) LoadPNode( 0, mem, adr, TypeRawPtr::BOTTOM, TypeRawPtr::BOTTOM ); break;
|
case T_ADDRESS: l = new (C, 3) LoadPNode( ctl, mem, adr, TypeRawPtr::BOTTOM, TypeRawPtr::BOTTOM ); break;
|
||||||
case T_OBJECT: l = new (C, 3) LoadPNode( 0, mem, adr, TypeRawPtr::BOTTOM, TypeInstPtr::BOTTOM ); break;
|
case T_OBJECT: l = new (C, 3) LoadPNode( ctl, mem, adr, TypeRawPtr::BOTTOM, TypeInstPtr::BOTTOM ); break;
|
||||||
case T_LONG:
|
case T_LONG:
|
||||||
case T_DOUBLE: {
|
case T_DOUBLE: {
|
||||||
// Since arguments are in reverse order, the argument address 'adr'
|
// Since arguments are in reverse order, the argument address 'adr'
|
||||||
@ -104,12 +105,12 @@ Node *Parse::fetch_interpreter_state(int index,
|
|||||||
adr = basic_plus_adr( local_addrs_base, local_addrs, -(index+1)*wordSize );
|
adr = basic_plus_adr( local_addrs_base, local_addrs, -(index+1)*wordSize );
|
||||||
if( Matcher::misaligned_doubles_ok ) {
|
if( Matcher::misaligned_doubles_ok ) {
|
||||||
l = (bt == T_DOUBLE)
|
l = (bt == T_DOUBLE)
|
||||||
? (Node*)new (C, 3) LoadDNode( 0, mem, adr, TypeRawPtr::BOTTOM )
|
? (Node*)new (C, 3) LoadDNode( ctl, mem, adr, TypeRawPtr::BOTTOM )
|
||||||
: (Node*)new (C, 3) LoadLNode( 0, mem, adr, TypeRawPtr::BOTTOM );
|
: (Node*)new (C, 3) LoadLNode( ctl, mem, adr, TypeRawPtr::BOTTOM );
|
||||||
} else {
|
} else {
|
||||||
l = (bt == T_DOUBLE)
|
l = (bt == T_DOUBLE)
|
||||||
? (Node*)new (C, 3) LoadD_unalignedNode( 0, mem, adr, TypeRawPtr::BOTTOM )
|
? (Node*)new (C, 3) LoadD_unalignedNode( ctl, mem, adr, TypeRawPtr::BOTTOM )
|
||||||
: (Node*)new (C, 3) LoadL_unalignedNode( 0, mem, adr, TypeRawPtr::BOTTOM );
|
: (Node*)new (C, 3) LoadL_unalignedNode( ctl, mem, adr, TypeRawPtr::BOTTOM );
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1324,33 +1324,21 @@ void Parse::do_one_bytecode() {
|
|||||||
case Bytecodes::_ldc_w:
|
case Bytecodes::_ldc_w:
|
||||||
case Bytecodes::_ldc2_w:
|
case Bytecodes::_ldc2_w:
|
||||||
// If the constant is unresolved, run this BC once in the interpreter.
|
// If the constant is unresolved, run this BC once in the interpreter.
|
||||||
if (iter().is_unresolved_string()) {
|
{
|
||||||
uncommon_trap(Deoptimization::make_trap_request
|
|
||||||
(Deoptimization::Reason_unloaded,
|
|
||||||
Deoptimization::Action_reinterpret,
|
|
||||||
iter().get_constant_index()),
|
|
||||||
NULL, "unresolved_string");
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
ciConstant constant = iter().get_constant();
|
ciConstant constant = iter().get_constant();
|
||||||
if (constant.basic_type() == T_OBJECT) {
|
if (constant.basic_type() == T_OBJECT &&
|
||||||
ciObject* c = constant.as_object();
|
!constant.as_object()->is_loaded()) {
|
||||||
if (c->is_klass()) {
|
int index = iter().get_constant_pool_index();
|
||||||
// The constant returned for a klass is the ciKlass for the
|
constantTag tag = iter().get_constant_pool_tag(index);
|
||||||
// entry. We want the java_mirror so get it.
|
uncommon_trap(Deoptimization::make_trap_request
|
||||||
ciKlass* klass = c->as_klass();
|
(Deoptimization::Reason_unloaded,
|
||||||
if (klass->is_loaded()) {
|
Deoptimization::Action_reinterpret,
|
||||||
constant = ciConstant(T_OBJECT, klass->java_mirror());
|
index),
|
||||||
} else {
|
NULL, tag.internal_name());
|
||||||
uncommon_trap(Deoptimization::make_trap_request
|
break;
|
||||||
(Deoptimization::Reason_unloaded,
|
|
||||||
Deoptimization::Action_reinterpret,
|
|
||||||
iter().get_constant_index()),
|
|
||||||
NULL, "unresolved_klass");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
assert(constant.basic_type() != T_OBJECT || !constant.as_object()->is_klass(),
|
||||||
|
"must be java_mirror of klass");
|
||||||
bool pushed = push_constant(constant, true);
|
bool pushed = push_constant(constant, true);
|
||||||
guarantee(pushed, "must be possible to push this constant");
|
guarantee(pushed, "must be possible to push this constant");
|
||||||
}
|
}
|
||||||
|
@ -1447,16 +1447,12 @@ Node *PhaseCCP::transform_once( Node *n ) {
|
|||||||
Node* m = n->out(i);
|
Node* m = n->out(i);
|
||||||
if( m->is_Phi() ) {
|
if( m->is_Phi() ) {
|
||||||
assert(type(m) == Type::TOP, "Unreachable region should not have live phis.");
|
assert(type(m) == Type::TOP, "Unreachable region should not have live phis.");
|
||||||
add_users_to_worklist(m);
|
replace_node(m, nn);
|
||||||
hash_delete(m); // Yank from hash before hacking edges
|
|
||||||
subsume_node(m, nn);
|
|
||||||
--i; // deleted this phi; rescan starting with next position
|
--i; // deleted this phi; rescan starting with next position
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
add_users_to_worklist(n); // Users of about-to-be-constant 'n'
|
replace_node(n,nn); // Update DefUse edges for new constant
|
||||||
hash_delete(n); // Removed 'n' from table before subsuming it
|
|
||||||
subsume_node(n,nn); // Update DefUse edges for new constant
|
|
||||||
}
|
}
|
||||||
return nn;
|
return nn;
|
||||||
}
|
}
|
||||||
|
@ -393,6 +393,10 @@ class PhaseIterGVN : public PhaseGVN {
|
|||||||
|
|
||||||
// Idealize old Node 'n' with respect to its inputs and its value
|
// Idealize old Node 'n' with respect to its inputs and its value
|
||||||
virtual Node *transform_old( Node *a_node );
|
virtual Node *transform_old( Node *a_node );
|
||||||
|
|
||||||
|
// Subsume users of node 'old' into node 'nn'
|
||||||
|
void subsume_node( Node *old, Node *nn );
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
// Idealize new Node 'n' with respect to its inputs and its value
|
// Idealize new Node 'n' with respect to its inputs and its value
|
||||||
@ -439,10 +443,6 @@ public:
|
|||||||
remove_globally_dead_node(dead);
|
remove_globally_dead_node(dead);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Subsume users of node 'old' into node 'nn'
|
|
||||||
// If no Def-Use info existed for 'nn' it will after call.
|
|
||||||
void subsume_node( Node *old, Node *nn );
|
|
||||||
|
|
||||||
// Add users of 'n' to worklist
|
// Add users of 'n' to worklist
|
||||||
void add_users_to_worklist0( Node *n );
|
void add_users_to_worklist0( Node *n );
|
||||||
void add_users_to_worklist ( Node *n );
|
void add_users_to_worklist ( Node *n );
|
||||||
@ -450,7 +450,7 @@ public:
|
|||||||
// Replace old node with new one.
|
// Replace old node with new one.
|
||||||
void replace_node( Node *old, Node *nn ) {
|
void replace_node( Node *old, Node *nn ) {
|
||||||
add_users_to_worklist(old);
|
add_users_to_worklist(old);
|
||||||
hash_delete(old);
|
hash_delete(old); // Yank from hash before hacking edges
|
||||||
subsume_node(old, nn);
|
subsume_node(old, nn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -217,8 +217,7 @@ bool PhaseIdealLoop::split_up( Node *n, Node *blk1, Node *blk2 ) {
|
|||||||
register_new_node(phi, blk1);
|
register_new_node(phi, blk1);
|
||||||
|
|
||||||
// Remove cloned-up value from optimizer; use phi instead
|
// Remove cloned-up value from optimizer; use phi instead
|
||||||
_igvn.hash_delete(n);
|
_igvn.replace_node( n, phi );
|
||||||
_igvn.subsume_node( n, phi );
|
|
||||||
|
|
||||||
// (There used to be a self-recursive call to split_up() here,
|
// (There used to be a self-recursive call to split_up() here,
|
||||||
// but it is not needed. All necessary forward walking is done
|
// but it is not needed. All necessary forward walking is done
|
||||||
@ -352,8 +351,7 @@ Node *PhaseIdealLoop::find_use_block( Node *use, Node *def, Node *old_false, Nod
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (use_blk == NULL) { // He's dead, Jim
|
if (use_blk == NULL) { // He's dead, Jim
|
||||||
_igvn.hash_delete(use);
|
_igvn.replace_node(use, C->top());
|
||||||
_igvn.subsume_node(use, C->top());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return use_blk;
|
return use_blk;
|
||||||
|
@ -1172,8 +1172,7 @@ void SuperWord::output() {
|
|||||||
_phase->set_ctrl(vn, _phase->get_ctrl(p->at(0)));
|
_phase->set_ctrl(vn, _phase->get_ctrl(p->at(0)));
|
||||||
for (uint j = 0; j < p->size(); j++) {
|
for (uint j = 0; j < p->size(); j++) {
|
||||||
Node* pm = p->at(j);
|
Node* pm = p->at(j);
|
||||||
_igvn.hash_delete(pm);
|
_igvn.replace_node(pm, vn);
|
||||||
_igvn.subsume_node(pm, vn);
|
|
||||||
}
|
}
|
||||||
_igvn._worklist.push(vn);
|
_igvn._worklist.push(vn);
|
||||||
}
|
}
|
||||||
|
@ -182,6 +182,8 @@ int Type::uhash( const Type *const t ) {
|
|||||||
return t->hash();
|
return t->hash();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define SMALLINT ((juint)3) // a value too insignificant to consider widening
|
||||||
|
|
||||||
//--------------------------Initialize_shared----------------------------------
|
//--------------------------Initialize_shared----------------------------------
|
||||||
void Type::Initialize_shared(Compile* current) {
|
void Type::Initialize_shared(Compile* current) {
|
||||||
// This method does not need to be locked because the first system
|
// This method does not need to be locked because the first system
|
||||||
@ -240,6 +242,7 @@ void Type::Initialize_shared(Compile* current) {
|
|||||||
assert( TypeInt::CC_GT == TypeInt::ONE, "types must match for CmpL to work" );
|
assert( TypeInt::CC_GT == TypeInt::ONE, "types must match for CmpL to work" );
|
||||||
assert( TypeInt::CC_EQ == TypeInt::ZERO, "types must match for CmpL to work" );
|
assert( TypeInt::CC_EQ == TypeInt::ZERO, "types must match for CmpL to work" );
|
||||||
assert( TypeInt::CC_GE == TypeInt::BOOL, "types must match for CmpL to work" );
|
assert( TypeInt::CC_GE == TypeInt::BOOL, "types must match for CmpL to work" );
|
||||||
|
assert( (juint)(TypeInt::CC->_hi - TypeInt::CC->_lo) <= SMALLINT, "CC is truly small");
|
||||||
|
|
||||||
TypeLong::MINUS_1 = TypeLong::make(-1); // -1
|
TypeLong::MINUS_1 = TypeLong::make(-1); // -1
|
||||||
TypeLong::ZERO = TypeLong::make( 0); // 0
|
TypeLong::ZERO = TypeLong::make( 0); // 0
|
||||||
@ -1054,16 +1057,21 @@ const TypeInt *TypeInt::make( jint lo ) {
|
|||||||
return (TypeInt*)(new TypeInt(lo,lo,WidenMin))->hashcons();
|
return (TypeInt*)(new TypeInt(lo,lo,WidenMin))->hashcons();
|
||||||
}
|
}
|
||||||
|
|
||||||
#define SMALLINT ((juint)3) // a value too insignificant to consider widening
|
static int normalize_int_widen( jint lo, jint hi, int w ) {
|
||||||
|
|
||||||
const TypeInt *TypeInt::make( jint lo, jint hi, int w ) {
|
|
||||||
// Certain normalizations keep us sane when comparing types.
|
// Certain normalizations keep us sane when comparing types.
|
||||||
// The 'SMALLINT' covers constants and also CC and its relatives.
|
// The 'SMALLINT' covers constants and also CC and its relatives.
|
||||||
assert(CC == NULL || (juint)(CC->_hi - CC->_lo) <= SMALLINT, "CC is truly small");
|
|
||||||
if (lo <= hi) {
|
if (lo <= hi) {
|
||||||
if ((juint)(hi - lo) <= SMALLINT) w = Type::WidenMin;
|
if ((juint)(hi - lo) <= SMALLINT) w = Type::WidenMin;
|
||||||
if ((juint)(hi - lo) >= max_juint) w = Type::WidenMax; // plain int
|
if ((juint)(hi - lo) >= max_juint) w = Type::WidenMax; // TypeInt::INT
|
||||||
|
} else {
|
||||||
|
if ((juint)(lo - hi) <= SMALLINT) w = Type::WidenMin;
|
||||||
|
if ((juint)(lo - hi) >= max_juint) w = Type::WidenMin; // dual TypeInt::INT
|
||||||
}
|
}
|
||||||
|
return w;
|
||||||
|
}
|
||||||
|
|
||||||
|
const TypeInt *TypeInt::make( jint lo, jint hi, int w ) {
|
||||||
|
w = normalize_int_widen(lo, hi, w);
|
||||||
return (TypeInt*)(new TypeInt(lo,hi,w))->hashcons();
|
return (TypeInt*)(new TypeInt(lo,hi,w))->hashcons();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1103,14 +1111,14 @@ const Type *TypeInt::xmeet( const Type *t ) const {
|
|||||||
|
|
||||||
// Expand covered set
|
// Expand covered set
|
||||||
const TypeInt *r = t->is_int();
|
const TypeInt *r = t->is_int();
|
||||||
// (Avoid TypeInt::make, to avoid the argument normalizations it enforces.)
|
return make( MIN2(_lo,r->_lo), MAX2(_hi,r->_hi), MAX2(_widen,r->_widen) );
|
||||||
return (new TypeInt( MIN2(_lo,r->_lo), MAX2(_hi,r->_hi), MAX2(_widen,r->_widen) ))->hashcons();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------xdual------------------------------------------
|
//------------------------------xdual------------------------------------------
|
||||||
// Dual: reverse hi & lo; flip widen
|
// Dual: reverse hi & lo; flip widen
|
||||||
const Type *TypeInt::xdual() const {
|
const Type *TypeInt::xdual() const {
|
||||||
return new TypeInt(_hi,_lo,WidenMax-_widen);
|
int w = normalize_int_widen(_hi,_lo, WidenMax-_widen);
|
||||||
|
return new TypeInt(_hi,_lo,w);
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------widen------------------------------------------
|
//------------------------------widen------------------------------------------
|
||||||
@ -1202,7 +1210,7 @@ const Type *TypeInt::narrow( const Type *old ) const {
|
|||||||
//-----------------------------filter------------------------------------------
|
//-----------------------------filter------------------------------------------
|
||||||
const Type *TypeInt::filter( const Type *kills ) const {
|
const Type *TypeInt::filter( const Type *kills ) const {
|
||||||
const TypeInt* ft = join(kills)->isa_int();
|
const TypeInt* ft = join(kills)->isa_int();
|
||||||
if (ft == NULL || ft->_lo > ft->_hi)
|
if (ft == NULL || ft->empty())
|
||||||
return Type::TOP; // Canonical empty value
|
return Type::TOP; // Canonical empty value
|
||||||
if (ft->_widen < this->_widen) {
|
if (ft->_widen < this->_widen) {
|
||||||
// Do not allow the value of kill->_widen to affect the outcome.
|
// Do not allow the value of kill->_widen to affect the outcome.
|
||||||
@ -1304,13 +1312,21 @@ const TypeLong *TypeLong::make( jlong lo ) {
|
|||||||
return (TypeLong*)(new TypeLong(lo,lo,WidenMin))->hashcons();
|
return (TypeLong*)(new TypeLong(lo,lo,WidenMin))->hashcons();
|
||||||
}
|
}
|
||||||
|
|
||||||
const TypeLong *TypeLong::make( jlong lo, jlong hi, int w ) {
|
static int normalize_long_widen( jlong lo, jlong hi, int w ) {
|
||||||
// Certain normalizations keep us sane when comparing types.
|
// Certain normalizations keep us sane when comparing types.
|
||||||
// The '1' covers constants.
|
// The 'SMALLINT' covers constants.
|
||||||
if (lo <= hi) {
|
if (lo <= hi) {
|
||||||
if ((julong)(hi - lo) <= SMALLINT) w = Type::WidenMin;
|
if ((julong)(hi - lo) <= SMALLINT) w = Type::WidenMin;
|
||||||
if ((julong)(hi - lo) >= max_julong) w = Type::WidenMax; // plain long
|
if ((julong)(hi - lo) >= max_julong) w = Type::WidenMax; // TypeLong::LONG
|
||||||
|
} else {
|
||||||
|
if ((julong)(lo - hi) <= SMALLINT) w = Type::WidenMin;
|
||||||
|
if ((julong)(lo - hi) >= max_julong) w = Type::WidenMin; // dual TypeLong::LONG
|
||||||
}
|
}
|
||||||
|
return w;
|
||||||
|
}
|
||||||
|
|
||||||
|
const TypeLong *TypeLong::make( jlong lo, jlong hi, int w ) {
|
||||||
|
w = normalize_long_widen(lo, hi, w);
|
||||||
return (TypeLong*)(new TypeLong(lo,hi,w))->hashcons();
|
return (TypeLong*)(new TypeLong(lo,hi,w))->hashcons();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1351,14 +1367,14 @@ const Type *TypeLong::xmeet( const Type *t ) const {
|
|||||||
|
|
||||||
// Expand covered set
|
// Expand covered set
|
||||||
const TypeLong *r = t->is_long(); // Turn into a TypeLong
|
const TypeLong *r = t->is_long(); // Turn into a TypeLong
|
||||||
// (Avoid TypeLong::make, to avoid the argument normalizations it enforces.)
|
return make( MIN2(_lo,r->_lo), MAX2(_hi,r->_hi), MAX2(_widen,r->_widen) );
|
||||||
return (new TypeLong( MIN2(_lo,r->_lo), MAX2(_hi,r->_hi), MAX2(_widen,r->_widen) ))->hashcons();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------xdual------------------------------------------
|
//------------------------------xdual------------------------------------------
|
||||||
// Dual: reverse hi & lo; flip widen
|
// Dual: reverse hi & lo; flip widen
|
||||||
const Type *TypeLong::xdual() const {
|
const Type *TypeLong::xdual() const {
|
||||||
return new TypeLong(_hi,_lo,WidenMax-_widen);
|
int w = normalize_long_widen(_hi,_lo, WidenMax-_widen);
|
||||||
|
return new TypeLong(_hi,_lo,w);
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------widen------------------------------------------
|
//------------------------------widen------------------------------------------
|
||||||
@ -1453,7 +1469,7 @@ const Type *TypeLong::narrow( const Type *old ) const {
|
|||||||
//-----------------------------filter------------------------------------------
|
//-----------------------------filter------------------------------------------
|
||||||
const Type *TypeLong::filter( const Type *kills ) const {
|
const Type *TypeLong::filter( const Type *kills ) const {
|
||||||
const TypeLong* ft = join(kills)->isa_long();
|
const TypeLong* ft = join(kills)->isa_long();
|
||||||
if (ft == NULL || ft->_lo > ft->_hi)
|
if (ft == NULL || ft->empty())
|
||||||
return Type::TOP; // Canonical empty value
|
return Type::TOP; // Canonical empty value
|
||||||
if (ft->_widen < this->_widen) {
|
if (ft->_widen < this->_widen) {
|
||||||
// Do not allow the value of kill->_widen to affect the outcome.
|
// Do not allow the value of kill->_widen to affect the outcome.
|
||||||
|
@ -1044,7 +1044,22 @@ enum {
|
|||||||
JVM_CONSTANT_Fieldref,
|
JVM_CONSTANT_Fieldref,
|
||||||
JVM_CONSTANT_Methodref,
|
JVM_CONSTANT_Methodref,
|
||||||
JVM_CONSTANT_InterfaceMethodref,
|
JVM_CONSTANT_InterfaceMethodref,
|
||||||
JVM_CONSTANT_NameAndType
|
JVM_CONSTANT_NameAndType,
|
||||||
|
JVM_CONSTANT_MethodHandle = 15, // JSR 292
|
||||||
|
JVM_CONSTANT_MethodType = 16 // JSR 292
|
||||||
|
};
|
||||||
|
|
||||||
|
/* JVM_CONSTANT_MethodHandle subtypes */
|
||||||
|
enum {
|
||||||
|
JVM_REF_getField = 1,
|
||||||
|
JVM_REF_getStatic = 2,
|
||||||
|
JVM_REF_putField = 3,
|
||||||
|
JVM_REF_putStatic = 4,
|
||||||
|
JVM_REF_invokeVirtual = 5,
|
||||||
|
JVM_REF_invokeStatic = 6,
|
||||||
|
JVM_REF_invokeSpecial = 7,
|
||||||
|
JVM_REF_newInvokeSpecial = 8,
|
||||||
|
JVM_REF_invokeInterface = 9
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Used in the newarray instruction. */
|
/* Used in the newarray instruction. */
|
||||||
|
@ -217,21 +217,21 @@ jvmtiError JvmtiCodeBlobEvents::generate_dynamic_code_events(JvmtiEnv* env) {
|
|||||||
|
|
||||||
class nmethodDesc: public CHeapObj {
|
class nmethodDesc: public CHeapObj {
|
||||||
private:
|
private:
|
||||||
methodHandle _method;
|
jmethodID _jmethod_id;
|
||||||
address _code_begin;
|
address _code_begin;
|
||||||
address _code_end;
|
address _code_end;
|
||||||
jvmtiAddrLocationMap* _map;
|
jvmtiAddrLocationMap* _map;
|
||||||
jint _map_length;
|
jint _map_length;
|
||||||
public:
|
public:
|
||||||
nmethodDesc(methodHandle method, address code_begin, address code_end,
|
nmethodDesc(jmethodID jmethod_id, address code_begin, address code_end,
|
||||||
jvmtiAddrLocationMap* map, jint map_length) {
|
jvmtiAddrLocationMap* map, jint map_length) {
|
||||||
_method = method;
|
_jmethod_id = jmethod_id;
|
||||||
_code_begin = code_begin;
|
_code_begin = code_begin;
|
||||||
_code_end = code_end;
|
_code_end = code_end;
|
||||||
_map = map;
|
_map = map;
|
||||||
_map_length = map_length;
|
_map_length = map_length;
|
||||||
}
|
}
|
||||||
methodHandle method() const { return _method; }
|
jmethodID jmethod_id() const { return _jmethod_id; }
|
||||||
address code_begin() const { return _code_begin; }
|
address code_begin() const { return _code_begin; }
|
||||||
address code_end() const { return _code_end; }
|
address code_end() const { return _code_end; }
|
||||||
jvmtiAddrLocationMap* map() const { return _map; }
|
jvmtiAddrLocationMap* map() const { return _map; }
|
||||||
@ -323,8 +323,7 @@ void nmethodCollector::do_nmethod(nmethod* nm) {
|
|||||||
JvmtiCodeBlobEvents::build_jvmti_addr_location_map(nm, &map, &map_length);
|
JvmtiCodeBlobEvents::build_jvmti_addr_location_map(nm, &map, &map_length);
|
||||||
|
|
||||||
// record the nmethod details
|
// record the nmethod details
|
||||||
methodHandle mh(nm->method());
|
nmethodDesc* snm = new nmethodDesc(nm->get_and_cache_jmethod_id(),
|
||||||
nmethodDesc* snm = new nmethodDesc(mh,
|
|
||||||
nm->code_begin(),
|
nm->code_begin(),
|
||||||
nm->code_end(),
|
nm->code_end(),
|
||||||
map,
|
map,
|
||||||
@ -367,8 +366,7 @@ jvmtiError JvmtiCodeBlobEvents::generate_compiled_method_load_events(JvmtiEnv* e
|
|||||||
// iterate over the list and post an event for each nmethod
|
// iterate over the list and post an event for each nmethod
|
||||||
nmethodDesc* nm_desc = collector.first();
|
nmethodDesc* nm_desc = collector.first();
|
||||||
while (nm_desc != NULL) {
|
while (nm_desc != NULL) {
|
||||||
methodOop method = nm_desc->method()();
|
jmethodID mid = nm_desc->jmethod_id();
|
||||||
jmethodID mid = method->jmethod_id();
|
|
||||||
assert(mid != NULL, "checking");
|
assert(mid != NULL, "checking");
|
||||||
JvmtiExport::post_compiled_method_load(env, mid,
|
JvmtiExport::post_compiled_method_load(env, mid,
|
||||||
(jint)(nm_desc->code_end() - nm_desc->code_begin()),
|
(jint)(nm_desc->code_end() - nm_desc->code_begin()),
|
||||||
|
@ -163,10 +163,10 @@ bool MethodComparator::args_same(Bytecodes::Code c_old, Bytecodes::Code c_new) {
|
|||||||
|
|
||||||
case Bytecodes::_ldc : // fall through
|
case Bytecodes::_ldc : // fall through
|
||||||
case Bytecodes::_ldc_w : {
|
case Bytecodes::_ldc_w : {
|
||||||
Bytecode_loadconstant* ldc_old = Bytecode_loadconstant_at(_s_old->method()(), _s_old->bcp());
|
Bytecode_loadconstant* ldc_old = Bytecode_loadconstant_at(_s_old->method(), _s_old->bci());
|
||||||
Bytecode_loadconstant* ldc_new = Bytecode_loadconstant_at(_s_new->method()(), _s_new->bcp());
|
Bytecode_loadconstant* ldc_new = Bytecode_loadconstant_at(_s_new->method(), _s_new->bci());
|
||||||
int cpi_old = ldc_old->index();
|
int cpi_old = ldc_old->pool_index();
|
||||||
int cpi_new = ldc_new->index();
|
int cpi_new = ldc_new->pool_index();
|
||||||
constantTag tag_old = _old_cp->tag_at(cpi_old);
|
constantTag tag_old = _old_cp->tag_at(cpi_old);
|
||||||
constantTag tag_new = _new_cp->tag_at(cpi_new);
|
constantTag tag_new = _new_cp->tag_at(cpi_new);
|
||||||
if (tag_old.is_int() || tag_old.is_float()) {
|
if (tag_old.is_int() || tag_old.is_float()) {
|
||||||
@ -187,12 +187,30 @@ bool MethodComparator::args_same(Bytecodes::Code c_old, Bytecodes::Code c_new) {
|
|||||||
if (strcmp(_old_cp->string_at_noresolve(cpi_old),
|
if (strcmp(_old_cp->string_at_noresolve(cpi_old),
|
||||||
_new_cp->string_at_noresolve(cpi_new)) != 0)
|
_new_cp->string_at_noresolve(cpi_new)) != 0)
|
||||||
return false;
|
return false;
|
||||||
} else { // tag_old should be klass - 4881222
|
} else if (tag_old.is_klass() || tag_old.is_unresolved_klass()) {
|
||||||
|
// tag_old should be klass - 4881222
|
||||||
if (! (tag_new.is_unresolved_klass() || tag_new.is_klass()))
|
if (! (tag_new.is_unresolved_klass() || tag_new.is_klass()))
|
||||||
return false;
|
return false;
|
||||||
if (_old_cp->klass_at_noresolve(cpi_old) !=
|
if (_old_cp->klass_at_noresolve(cpi_old) !=
|
||||||
_new_cp->klass_at_noresolve(cpi_new))
|
_new_cp->klass_at_noresolve(cpi_new))
|
||||||
return false;
|
return false;
|
||||||
|
} else if (tag_old.is_method_type() && tag_new.is_method_type()) {
|
||||||
|
int mti_old = _old_cp->method_type_index_at(cpi_old);
|
||||||
|
int mti_new = _new_cp->method_type_index_at(cpi_new);
|
||||||
|
if ((_old_cp->symbol_at(mti_old) != _new_cp->symbol_at(mti_new)))
|
||||||
|
return false;
|
||||||
|
} else if (tag_old.is_method_handle() && tag_new.is_method_handle()) {
|
||||||
|
if (_old_cp->method_handle_ref_kind_at(cpi_old) !=
|
||||||
|
_new_cp->method_handle_ref_kind_at(cpi_new))
|
||||||
|
return false;
|
||||||
|
int mhi_old = _old_cp->method_handle_index_at(cpi_old);
|
||||||
|
int mhi_new = _new_cp->method_handle_index_at(cpi_new);
|
||||||
|
if ((_old_cp->uncached_klass_ref_at_noresolve(mhi_old) != _new_cp->uncached_klass_ref_at_noresolve(mhi_new)) ||
|
||||||
|
(_old_cp->uncached_name_ref_at(mhi_old) != _new_cp->uncached_name_ref_at(mhi_new)) ||
|
||||||
|
(_old_cp->uncached_signature_ref_at(mhi_old) != _new_cp->uncached_signature_ref_at(mhi_new)))
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
return false; // unknown tag
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1376,11 +1376,6 @@ void Arguments::set_g1_gc_flags() {
|
|||||||
}
|
}
|
||||||
no_shared_spaces();
|
no_shared_spaces();
|
||||||
|
|
||||||
// Set the maximum pause time goal to be a reasonable default.
|
|
||||||
if (FLAG_IS_DEFAULT(MaxGCPauseMillis)) {
|
|
||||||
FLAG_SET_DEFAULT(MaxGCPauseMillis, 200);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (FLAG_IS_DEFAULT(MarkStackSize)) {
|
if (FLAG_IS_DEFAULT(MarkStackSize)) {
|
||||||
FLAG_SET_DEFAULT(MarkStackSize, 128 * TASKQUEUE_SIZE);
|
FLAG_SET_DEFAULT(MarkStackSize, 128 * TASKQUEUE_SIZE);
|
||||||
}
|
}
|
||||||
@ -1513,6 +1508,9 @@ void Arguments::set_aggressive_opts_flags() {
|
|||||||
if (AggressiveOpts && FLAG_IS_DEFAULT(BiasedLockingStartupDelay)) {
|
if (AggressiveOpts && FLAG_IS_DEFAULT(BiasedLockingStartupDelay)) {
|
||||||
FLAG_SET_DEFAULT(BiasedLockingStartupDelay, 500);
|
FLAG_SET_DEFAULT(BiasedLockingStartupDelay, 500);
|
||||||
}
|
}
|
||||||
|
if (AggressiveOpts && FLAG_IS_DEFAULT(OptimizeStringConcat)) {
|
||||||
|
FLAG_SET_DEFAULT(OptimizeStringConcat, true);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (AggressiveOpts) {
|
if (AggressiveOpts) {
|
||||||
@ -1697,20 +1695,21 @@ bool Arguments::check_vm_args_consistency() {
|
|||||||
|
|
||||||
status = status && verify_percentage(GCHeapFreeLimit, "GCHeapFreeLimit");
|
status = status && verify_percentage(GCHeapFreeLimit, "GCHeapFreeLimit");
|
||||||
|
|
||||||
// Check user specified sharing option conflict with Parallel GC
|
// Check whether user-specified sharing option conflicts with GC or page size.
|
||||||
bool cannot_share = ((UseConcMarkSweepGC || CMSIncrementalMode) || UseG1GC || UseParNewGC ||
|
// Both sharing and large pages are enabled by default on some platforms;
|
||||||
UseParallelGC || UseParallelOldGC ||
|
// large pages override sharing only if explicitly set on the command line.
|
||||||
SOLARIS_ONLY(UseISM) NOT_SOLARIS(UseLargePages));
|
const bool cannot_share = UseConcMarkSweepGC || CMSIncrementalMode ||
|
||||||
|
UseG1GC || UseParNewGC || UseParallelGC || UseParallelOldGC ||
|
||||||
|
UseLargePages && FLAG_IS_CMDLINE(UseLargePages);
|
||||||
if (cannot_share) {
|
if (cannot_share) {
|
||||||
// Either force sharing on by forcing the other options off, or
|
// Either force sharing on by forcing the other options off, or
|
||||||
// force sharing off.
|
// force sharing off.
|
||||||
if (DumpSharedSpaces || ForceSharedSpaces) {
|
if (DumpSharedSpaces || ForceSharedSpaces) {
|
||||||
jio_fprintf(defaultStream::error_stream(),
|
jio_fprintf(defaultStream::error_stream(),
|
||||||
"Reverting to Serial GC because of %s\n",
|
"Using Serial GC and default page size because of %s\n",
|
||||||
ForceSharedSpaces ? " -Xshare:on" : "-Xshare:dump");
|
ForceSharedSpaces ? "-Xshare:on" : "-Xshare:dump");
|
||||||
force_serial_gc();
|
force_serial_gc();
|
||||||
FLAG_SET_DEFAULT(SOLARIS_ONLY(UseISM) NOT_SOLARIS(UseLargePages), false);
|
FLAG_SET_DEFAULT(UseLargePages, false);
|
||||||
} else {
|
} else {
|
||||||
if (UseSharedSpaces && Verbose) {
|
if (UseSharedSpaces && Verbose) {
|
||||||
jio_fprintf(defaultStream::error_stream(),
|
jio_fprintf(defaultStream::error_stream(),
|
||||||
@ -1719,6 +1718,8 @@ bool Arguments::check_vm_args_consistency() {
|
|||||||
}
|
}
|
||||||
no_shared_spaces();
|
no_shared_spaces();
|
||||||
}
|
}
|
||||||
|
} else if (UseLargePages && (UseSharedSpaces || DumpSharedSpaces)) {
|
||||||
|
FLAG_SET_DEFAULT(UseLargePages, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
status = status && check_gc_consistency();
|
status = status && check_gc_consistency();
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user