Merge
This commit is contained in:
commit
d1b22548f7
.hgtags-top-repo
hotspot
.hgtags
agent/src/share/classes/sun/jvm/hotspot
runtime
tools/jcore
make
src
cpu
sparc/vm
assembler_sparc.cppassembler_sparc.hppassembler_sparc.inline.hppcppInterpreter_sparc.cppinterpreterGenerator_sparc.hppinterpreter_sparc.cppmethodHandles_sparc.cppregister_definitions_sparc.cppsharedRuntime_sparc.cpptemplateInterpreter_sparc.cppvtableStubs_sparc.cpp
x86/vm
assembler_x86.cppassembler_x86.hppcppInterpreter_x86.cppinterp_masm_x86_32.cppinterp_masm_x86_32.hppinterp_masm_x86_64.cppinterp_masm_x86_64.hppinterpreterGenerator_x86.hppinterpreter_x86_32.cppinterpreter_x86_64.cppmethodHandles_x86.cppstubGenerator_x86_32.cpptemplateInterpreter_x86_32.cpptemplateInterpreter_x86_64.cppvtableStubs_x86_32.cppvtableStubs_x86_64.cpp
share/vm
ci
classfile
classFileParser.cppclassFileParser.hppdictionary.cppdictionary.hppjavaClasses.cppjavaClasses.hppsystemDictionary.cppsystemDictionary.hppvmSymbols.hpp
code
includeDB_coreincludeDB_gc_parallelinterpreter
abstractInterpreter.hppcppInterpreter.cppinterpreter.cppinterpreterRuntime.cppinterpreterRuntime.hpplinkResolver.cpplinkResolver.hpptemplateInterpreter.cpptemplateInterpreter.hpptemplateInterpreterGenerator.hpp
memory
oops
opto
prims
runtime
arguments.cppglobals.hppjavaCalls.cppsharedRuntime.cppsharedRuntime.hppsynchronizer.cppthread.cppthread.hppvmStructs.cpp
utilities
test/compiler
@ -29,3 +29,4 @@ aee93a8992d2389121eb610c00a86196f3e2b9b0 jdk7-b49
|
|||||||
4264c2fe66493e57c411045a1b61377796641e45 jdk7-b52
|
4264c2fe66493e57c411045a1b61377796641e45 jdk7-b52
|
||||||
c235f4a8559d196879c56af80159f67ee5d0e720 jdk7-b53
|
c235f4a8559d196879c56af80159f67ee5d0e720 jdk7-b53
|
||||||
2ef382b1bbd58a68e668391c6145a4b2066c5b96 jdk7-b54
|
2ef382b1bbd58a68e668391c6145a4b2066c5b96 jdk7-b54
|
||||||
|
aea0ace7a1e43619800931d42bbf69c579361c2d jdk7-b55
|
||||||
|
@ -29,3 +29,4 @@ dae503d9f04c1a11e182dbf7f770509c28dc0609 jdk7-b50
|
|||||||
1b1e8f1a4fe8cebc01c022484f78148e17b62a0d jdk7-b52
|
1b1e8f1a4fe8cebc01c022484f78148e17b62a0d jdk7-b52
|
||||||
032c6af894dae8d939b3dd31d82042549e7793e0 jdk7-b53
|
032c6af894dae8d939b3dd31d82042549e7793e0 jdk7-b53
|
||||||
fafab5d5349c7c066d677538db67a1ee0fb33bd2 jdk7-b54
|
fafab5d5349c7c066d677538db67a1ee0fb33bd2 jdk7-b54
|
||||||
|
f8e839c086152da70d6ec5913ba6f9f509282e8d jdk7-b55
|
||||||
|
@ -147,6 +147,7 @@ public interface ClassConstants
|
|||||||
JVM_ACC_INTERFACE |
|
JVM_ACC_INTERFACE |
|
||||||
JVM_ACC_ABSTRACT |
|
JVM_ACC_ABSTRACT |
|
||||||
JVM_ACC_ANNOTATION |
|
JVM_ACC_ANNOTATION |
|
||||||
|
JVM_ACC_ENUM |
|
||||||
JVM_ACC_SYNTHETIC);
|
JVM_ACC_SYNTHETIC);
|
||||||
|
|
||||||
|
|
||||||
|
@ -48,6 +48,8 @@ public class JavaThread extends Thread {
|
|||||||
private static AddressField lastJavaPCField;
|
private static AddressField lastJavaPCField;
|
||||||
private static CIntegerField threadStateField;
|
private static CIntegerField threadStateField;
|
||||||
private static AddressField osThreadField;
|
private static AddressField osThreadField;
|
||||||
|
private static AddressField stackBaseField;
|
||||||
|
private static CIntegerField stackSizeField;
|
||||||
|
|
||||||
private static JavaThreadPDAccess access;
|
private static JavaThreadPDAccess access;
|
||||||
|
|
||||||
@ -83,6 +85,8 @@ public class JavaThread extends Thread {
|
|||||||
lastJavaPCField = anchorType.getAddressField("_last_Java_pc");
|
lastJavaPCField = anchorType.getAddressField("_last_Java_pc");
|
||||||
threadStateField = type.getCIntegerField("_thread_state");
|
threadStateField = type.getCIntegerField("_thread_state");
|
||||||
osThreadField = type.getAddressField("_osthread");
|
osThreadField = type.getAddressField("_osthread");
|
||||||
|
stackBaseField = type.getAddressField("_stack_base");
|
||||||
|
stackSizeField = type.getCIntegerField("_stack_size");
|
||||||
|
|
||||||
UNINITIALIZED = db.lookupIntConstant("_thread_uninitialized").intValue();
|
UNINITIALIZED = db.lookupIntConstant("_thread_uninitialized").intValue();
|
||||||
NEW = db.lookupIntConstant("_thread_new").intValue();
|
NEW = db.lookupIntConstant("_thread_new").intValue();
|
||||||
@ -312,6 +316,14 @@ public class JavaThread extends Thread {
|
|||||||
return (OSThread) VMObjectFactory.newObject(OSThread.class, osThreadField.getValue(addr));
|
return (OSThread) VMObjectFactory.newObject(OSThread.class, osThreadField.getValue(addr));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Address getStackBase() {
|
||||||
|
return stackBaseField.getValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getStackSize() {
|
||||||
|
return stackSizeField.getValue();
|
||||||
|
}
|
||||||
|
|
||||||
/** Gets the Java-side thread object for this JavaThread */
|
/** Gets the Java-side thread object for this JavaThread */
|
||||||
public Oop getThreadObj() {
|
public Oop getThreadObj() {
|
||||||
return VM.getVM().getObjectHeap().newOop(threadObjField.getValue(addr));
|
return VM.getVM().getObjectHeap().newOop(threadObjField.getValue(addr));
|
||||||
@ -345,11 +357,18 @@ public class JavaThread extends Thread {
|
|||||||
if (Assert.ASSERTS_ENABLED) {
|
if (Assert.ASSERTS_ENABLED) {
|
||||||
Assert.that(VM.getVM().isDebugging(), "Not yet implemented for non-debugging system");
|
Assert.that(VM.getVM().isDebugging(), "Not yet implemented for non-debugging system");
|
||||||
}
|
}
|
||||||
Address highest = highestLock();
|
|
||||||
Address sp = lastSPDbg();
|
Address sp = lastSPDbg();
|
||||||
|
Address stackBase = getStackBase();
|
||||||
// Be robust
|
// Be robust
|
||||||
if ((highest == null) || (sp == null)) return false;
|
if (sp == null) return false;
|
||||||
return (highest.greaterThanOrEqual(a) && sp.lessThanOrEqual(a));
|
return stackBase.greaterThanOrEqual(a) && sp.lessThanOrEqual(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isLockOwned(Address a) {
|
||||||
|
Address stackBase = getStackBase();
|
||||||
|
Address stackLimit = stackBase.addOffsetTo(-getStackSize());
|
||||||
|
|
||||||
|
return stackBase.greaterThanOrEqual(a) && stackLimit.lessThanOrEqual(a);
|
||||||
|
|
||||||
// FIXME: should traverse MonitorArray/MonitorChunks as in VM
|
// FIXME: should traverse MonitorArray/MonitorChunks as in VM
|
||||||
}
|
}
|
||||||
|
@ -38,7 +38,6 @@ public class Thread extends VMObject {
|
|||||||
private static int HAS_ASYNC_EXCEPTION;
|
private static int HAS_ASYNC_EXCEPTION;
|
||||||
|
|
||||||
private static AddressField activeHandlesField;
|
private static AddressField activeHandlesField;
|
||||||
private static AddressField highestLockField;
|
|
||||||
private static AddressField currentPendingMonitorField;
|
private static AddressField currentPendingMonitorField;
|
||||||
private static AddressField currentWaitingMonitorField;
|
private static AddressField currentWaitingMonitorField;
|
||||||
|
|
||||||
@ -60,7 +59,6 @@ public class Thread extends VMObject {
|
|||||||
|
|
||||||
tlabFieldOffset = type.getField("_tlab").getOffset();
|
tlabFieldOffset = type.getField("_tlab").getOffset();
|
||||||
activeHandlesField = type.getAddressField("_active_handles");
|
activeHandlesField = type.getAddressField("_active_handles");
|
||||||
highestLockField = type.getAddressField("_highest_lock");
|
|
||||||
currentPendingMonitorField = type.getAddressField("_current_pending_monitor");
|
currentPendingMonitorField = type.getAddressField("_current_pending_monitor");
|
||||||
currentWaitingMonitorField = type.getAddressField("_current_waiting_monitor");
|
currentWaitingMonitorField = type.getAddressField("_current_waiting_monitor");
|
||||||
}
|
}
|
||||||
@ -121,10 +119,6 @@ public class Thread extends VMObject {
|
|||||||
// pending exception
|
// pending exception
|
||||||
}
|
}
|
||||||
|
|
||||||
public Address highestLock() {
|
|
||||||
return highestLockField.getValue(addr);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ObjectMonitor getCurrentPendingMonitor() {
|
public ObjectMonitor getCurrentPendingMonitor() {
|
||||||
Address monitorAddr = currentPendingMonitorField.getValue(addr);
|
Address monitorAddr = currentPendingMonitorField.getValue(addr);
|
||||||
if (monitorAddr == null) {
|
if (monitorAddr == null) {
|
||||||
|
@ -164,20 +164,11 @@ public class Threads {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
long leastDiff = 0;
|
|
||||||
boolean leastDiffInitialized = false;
|
|
||||||
JavaThread theOwner = null;
|
|
||||||
for (JavaThread thread = first(); thread != null; thread = thread.next()) {
|
for (JavaThread thread = first(); thread != null; thread = thread.next()) {
|
||||||
Address addr = thread.highestLock();
|
if (thread.isLockOwned(o))
|
||||||
if (addr == null || addr.lessThan(o)) continue;
|
return thread;
|
||||||
long diff = addr.minus(o);
|
|
||||||
if (!leastDiffInitialized || diff < leastDiff) {
|
|
||||||
leastDiffInitialized = true;
|
|
||||||
leastDiff = diff;
|
|
||||||
theOwner = thread;
|
|
||||||
}
|
}
|
||||||
}
|
return null;
|
||||||
return theOwner;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public JavaThread owningThreadFromMonitor(ObjectMonitor monitor) {
|
public JavaThread owningThreadFromMonitor(ObjectMonitor monitor) {
|
||||||
|
@ -89,29 +89,6 @@ public class ByteCodeRewriter
|
|||||||
// update the code buffer hotspot specific bytecode with the jvm bytecode
|
// update the code buffer hotspot specific bytecode with the jvm bytecode
|
||||||
code[bci] = (byte) (0xFF & bytecode);
|
code[bci] = (byte) (0xFF & bytecode);
|
||||||
|
|
||||||
// RewriteFrequentPairs
|
|
||||||
if(hotspotcode == Bytecodes._fast_iaccess_0 ||
|
|
||||||
hotspotcode == Bytecodes._fast_aaccess_0 ||
|
|
||||||
hotspotcode == Bytecodes._fast_faccess_0) {
|
|
||||||
// rewrite next bytecode as _getfield
|
|
||||||
bci++;
|
|
||||||
code[bci] = (byte) (0xFF & Bytecodes._getfield);
|
|
||||||
bytecode = Bytecodes._getfield;
|
|
||||||
hotspotcode = Bytecodes._getfield;
|
|
||||||
} else if (hotspotcode == Bytecodes._fast_iload2) {
|
|
||||||
// rewrite next bytecode as _iload
|
|
||||||
bci++;
|
|
||||||
code[bci] = (byte) (0xFF & Bytecodes._iload);
|
|
||||||
bytecode = Bytecodes._iload;
|
|
||||||
hotspotcode = Bytecodes._iload;
|
|
||||||
} else if (hotspotcode == Bytecodes._fast_icaload) {
|
|
||||||
// rewrite next bytecode as _caload
|
|
||||||
bci++;
|
|
||||||
code[bci] = (byte) (0xFF & Bytecodes._caload);
|
|
||||||
bytecode = Bytecodes._caload;
|
|
||||||
bytecode = Bytecodes._caload;
|
|
||||||
}
|
|
||||||
|
|
||||||
short cpoolIndex = 0;
|
short cpoolIndex = 0;
|
||||||
switch (bytecode) {
|
switch (bytecode) {
|
||||||
// bytecodes with ConstantPoolCache index
|
// bytecodes with ConstantPoolCache index
|
||||||
|
@ -59,8 +59,14 @@ public class ClassDump extends Tool {
|
|||||||
SystemDictionary dict = VM.getVM().getSystemDictionary();
|
SystemDictionary dict = VM.getVM().getSystemDictionary();
|
||||||
dict.classesDo(new SystemDictionary.ClassVisitor() {
|
dict.classesDo(new SystemDictionary.ClassVisitor() {
|
||||||
public void visit(Klass k) {
|
public void visit(Klass k) {
|
||||||
if (k instanceof InstanceKlass)
|
if (k instanceof InstanceKlass) {
|
||||||
|
try {
|
||||||
dumpKlass((InstanceKlass) k);
|
dumpKlass((InstanceKlass) k);
|
||||||
|
} catch (Exception e) {
|
||||||
|
System.out.println(k.getName().asString());
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -40,7 +40,6 @@ public class ClassWriter implements /* imports */ ClassConstants
|
|||||||
protected InstanceKlass klass;
|
protected InstanceKlass klass;
|
||||||
protected DataOutputStream dos;
|
protected DataOutputStream dos;
|
||||||
protected ConstantPool cpool;
|
protected ConstantPool cpool;
|
||||||
protected boolean is15Format;
|
|
||||||
|
|
||||||
// Map between class name to index of type CONSTANT_Class
|
// Map between class name to index of type CONSTANT_Class
|
||||||
protected Map classToIndex = new HashMap();
|
protected Map classToIndex = new HashMap();
|
||||||
@ -73,7 +72,6 @@ public class ClassWriter implements /* imports */ ClassConstants
|
|||||||
klass = kls;
|
klass = kls;
|
||||||
dos = new DataOutputStream(os);
|
dos = new DataOutputStream(os);
|
||||||
cpool = klass.getConstants();
|
cpool = klass.getConstants();
|
||||||
is15Format = is15ClassFile();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void write() throws IOException {
|
public void write() throws IOException {
|
||||||
@ -82,7 +80,7 @@ public class ClassWriter implements /* imports */ ClassConstants
|
|||||||
// write magic
|
// write magic
|
||||||
dos.writeInt(0xCAFEBABE);
|
dos.writeInt(0xCAFEBABE);
|
||||||
|
|
||||||
writeVersion(is15Format);
|
writeVersion();
|
||||||
writeConstantPool();
|
writeConstantPool();
|
||||||
writeClassAccessFlags();
|
writeClassAccessFlags();
|
||||||
writeThisClass();
|
writeThisClass();
|
||||||
@ -96,43 +94,14 @@ public class ClassWriter implements /* imports */ ClassConstants
|
|||||||
dos.flush();
|
dos.flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected boolean is15ClassFile() {
|
protected void writeVersion() throws IOException {
|
||||||
// if klass has generic signature, then it is 1.5 class file.
|
dos.writeShort((short)klass.minorVersion());
|
||||||
if (klass.getGenericSignature() != null) {
|
dos.writeShort((short)klass.majorVersion());
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// if atleast one method has generic signature
|
protected void writeIndex(int index) throws IOException {
|
||||||
// , then we have 1.5 class file.
|
if (index == 0) throw new InternalError();
|
||||||
ObjArray methods = klass.getMethods();
|
dos.writeShort(index);
|
||||||
final int numMethods = (int) methods.getLength();
|
|
||||||
for (int m = 0; m < numMethods; m++) {
|
|
||||||
Method curMethod = (Method) methods.getObjAt(m);
|
|
||||||
if (curMethod.getGenericSignature() != null) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// if atleast one field has non-zero generic signature index, then we have
|
|
||||||
// 1.5 class file
|
|
||||||
TypeArray fields = klass.getFields();
|
|
||||||
final int numFields = (int) fields.getLength();
|
|
||||||
for (int f = 0; f < numFields; f += InstanceKlass.NEXT_OFFSET) {
|
|
||||||
short genSigIndex = fields.getShortAt(f + InstanceKlass.GENERIC_SIGNATURE_INDEX_OFFSET);
|
|
||||||
if (genSigIndex != (short)0) return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void writeVersion(boolean is15Format) throws IOException {
|
|
||||||
if (is15Format) {
|
|
||||||
dos.writeShort(MINOR_VERSION);
|
|
||||||
dos.writeShort(MAJOR_VERSION);
|
|
||||||
} else {
|
|
||||||
dos.writeShort(MINOR_VERSION_OLD);
|
|
||||||
dos.writeShort(MAJOR_VERSION_OLD);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void writeConstantPool() throws IOException {
|
protected void writeConstantPool() throws IOException {
|
||||||
@ -392,8 +361,8 @@ public class ClassWriter implements /* imports */ ClassConstants
|
|||||||
if (DEBUG) debugMessage("\tfield name = " + nameIndex + ", signature = " + signatureIndex);
|
if (DEBUG) debugMessage("\tfield name = " + nameIndex + ", signature = " + signatureIndex);
|
||||||
|
|
||||||
short fieldAttributeCount = 0;
|
short fieldAttributeCount = 0;
|
||||||
boolean isSyn = isSynthetic(accessFlags);
|
boolean hasSyn = hasSyntheticAttribute(accessFlags);
|
||||||
if (isSyn)
|
if (hasSyn)
|
||||||
fieldAttributeCount++;
|
fieldAttributeCount++;
|
||||||
|
|
||||||
short initvalIndex = fields.getShortAt(index + InstanceKlass.INITVAL_INDEX_OFFSET);
|
short initvalIndex = fields.getShortAt(index + InstanceKlass.INITVAL_INDEX_OFFSET);
|
||||||
@ -407,18 +376,18 @@ public class ClassWriter implements /* imports */ ClassConstants
|
|||||||
dos.writeShort(fieldAttributeCount);
|
dos.writeShort(fieldAttributeCount);
|
||||||
|
|
||||||
// write synthetic, if applicable
|
// write synthetic, if applicable
|
||||||
if (isSyn)
|
if (hasSyn)
|
||||||
writeSynthetic();
|
writeSynthetic();
|
||||||
|
|
||||||
if (initvalIndex != 0) {
|
if (initvalIndex != 0) {
|
||||||
dos.writeShort(_constantValueIndex);
|
writeIndex(_constantValueIndex);
|
||||||
dos.writeInt(2);
|
dos.writeInt(2);
|
||||||
dos.writeShort(initvalIndex);
|
dos.writeShort(initvalIndex);
|
||||||
if (DEBUG) debugMessage("\tfield init value = " + initvalIndex);
|
if (DEBUG) debugMessage("\tfield init value = " + initvalIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (genSigIndex != 0) {
|
if (genSigIndex != 0) {
|
||||||
dos.writeShort(_signatureIndex);
|
writeIndex(_signatureIndex);
|
||||||
dos.writeInt(2);
|
dos.writeInt(2);
|
||||||
dos.writeShort(genSigIndex);
|
dos.writeShort(genSigIndex);
|
||||||
if (DEBUG) debugMessage("\tfield generic signature index " + genSigIndex);
|
if (DEBUG) debugMessage("\tfield generic signature index " + genSigIndex);
|
||||||
@ -430,8 +399,13 @@ public class ClassWriter implements /* imports */ ClassConstants
|
|||||||
return (accessFlags & (short) JVM_ACC_SYNTHETIC) != 0;
|
return (accessFlags & (short) JVM_ACC_SYNTHETIC) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected boolean hasSyntheticAttribute(short accessFlags) {
|
||||||
|
// Check if flags have the attribute and if the constant pool contains an entry for it.
|
||||||
|
return isSynthetic(accessFlags) && _syntheticIndex != 0;
|
||||||
|
}
|
||||||
|
|
||||||
protected void writeSynthetic() throws IOException {
|
protected void writeSynthetic() throws IOException {
|
||||||
dos.writeShort(_syntheticIndex);
|
writeIndex(_syntheticIndex);
|
||||||
dos.writeInt(0);
|
dos.writeInt(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -459,8 +433,8 @@ public class ClassWriter implements /* imports */ ClassConstants
|
|||||||
|
|
||||||
short methodAttributeCount = 0;
|
short methodAttributeCount = 0;
|
||||||
|
|
||||||
final boolean isSyn = isSynthetic((short)accessFlags);
|
final boolean hasSyn = hasSyntheticAttribute((short)accessFlags);
|
||||||
if (isSyn)
|
if (hasSyn)
|
||||||
methodAttributeCount++;
|
methodAttributeCount++;
|
||||||
|
|
||||||
final boolean hasCheckedExceptions = m.hasCheckedExceptions();
|
final boolean hasCheckedExceptions = m.hasCheckedExceptions();
|
||||||
@ -478,27 +452,11 @@ public class ClassWriter implements /* imports */ ClassConstants
|
|||||||
dos.writeShort(methodAttributeCount);
|
dos.writeShort(methodAttributeCount);
|
||||||
if (DEBUG) debugMessage("\tmethod attribute count = " + methodAttributeCount);
|
if (DEBUG) debugMessage("\tmethod attribute count = " + methodAttributeCount);
|
||||||
|
|
||||||
if (isSyn) {
|
if (hasSyn) {
|
||||||
if (DEBUG) debugMessage("\tmethod is synthetic");
|
if (DEBUG) debugMessage("\tmethod is synthetic");
|
||||||
writeSynthetic();
|
writeSynthetic();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasCheckedExceptions) {
|
|
||||||
CheckedExceptionElement[] exceptions = m.getCheckedExceptions();
|
|
||||||
dos.writeShort(_exceptionsIndex);
|
|
||||||
|
|
||||||
int attrSize = 2 /* number_of_exceptions */ +
|
|
||||||
exceptions.length * 2 /* exception_index */;
|
|
||||||
dos.writeInt(attrSize);
|
|
||||||
dos.writeShort(exceptions.length);
|
|
||||||
if (DEBUG) debugMessage("\tmethod has " + exceptions.length
|
|
||||||
+ " checked exception(s)");
|
|
||||||
for (int e = 0; e < exceptions.length; e++) {
|
|
||||||
short cpIndex = (short) exceptions[e].getClassCPIndex();
|
|
||||||
dos.writeShort(cpIndex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isCodeAvailable) {
|
if (isCodeAvailable) {
|
||||||
byte[] code = m.getByteCode();
|
byte[] code = m.getByteCode();
|
||||||
short codeAttrCount = 0;
|
short codeAttrCount = 0;
|
||||||
@ -574,7 +532,7 @@ public class ClassWriter implements /* imports */ ClassConstants
|
|||||||
|
|
||||||
// start writing Code
|
// start writing Code
|
||||||
|
|
||||||
dos.writeShort(_codeIndex);
|
writeIndex(_codeIndex);
|
||||||
|
|
||||||
dos.writeInt(codeSize);
|
dos.writeInt(codeSize);
|
||||||
if (DEBUG) debugMessage("\tcode attribute length = " + codeSize);
|
if (DEBUG) debugMessage("\tcode attribute length = " + codeSize);
|
||||||
@ -608,7 +566,7 @@ public class ClassWriter implements /* imports */ ClassConstants
|
|||||||
|
|
||||||
// write LineNumberTable, if available.
|
// write LineNumberTable, if available.
|
||||||
if (hasLineNumberTable) {
|
if (hasLineNumberTable) {
|
||||||
dos.writeShort(_lineNumberTableIndex);
|
writeIndex(_lineNumberTableIndex);
|
||||||
dos.writeInt(lineNumberAttrLen);
|
dos.writeInt(lineNumberAttrLen);
|
||||||
dos.writeShort((short) lineNumberTable.length);
|
dos.writeShort((short) lineNumberTable.length);
|
||||||
for (int l = 0; l < lineNumberTable.length; l++) {
|
for (int l = 0; l < lineNumberTable.length; l++) {
|
||||||
@ -619,7 +577,7 @@ public class ClassWriter implements /* imports */ ClassConstants
|
|||||||
|
|
||||||
// write LocalVariableTable, if available.
|
// write LocalVariableTable, if available.
|
||||||
if (hasLocalVariableTable) {
|
if (hasLocalVariableTable) {
|
||||||
dos.writeShort((short) _localVariableTableIndex);
|
writeIndex((short) _localVariableTableIndex);
|
||||||
dos.writeInt(localVarAttrLen);
|
dos.writeInt(localVarAttrLen);
|
||||||
dos.writeShort((short) localVariableTable.length);
|
dos.writeShort((short) localVariableTable.length);
|
||||||
for (int l = 0; l < localVariableTable.length; l++) {
|
for (int l = 0; l < localVariableTable.length; l++) {
|
||||||
@ -632,6 +590,22 @@ public class ClassWriter implements /* imports */ ClassConstants
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (hasCheckedExceptions) {
|
||||||
|
CheckedExceptionElement[] exceptions = m.getCheckedExceptions();
|
||||||
|
writeIndex(_exceptionsIndex);
|
||||||
|
|
||||||
|
int attrSize = 2 /* number_of_exceptions */ +
|
||||||
|
exceptions.length * 2 /* exception_index */;
|
||||||
|
dos.writeInt(attrSize);
|
||||||
|
dos.writeShort(exceptions.length);
|
||||||
|
if (DEBUG) debugMessage("\tmethod has " + exceptions.length
|
||||||
|
+ " checked exception(s)");
|
||||||
|
for (int e = 0; e < exceptions.length; e++) {
|
||||||
|
short cpIndex = (short) exceptions[e].getClassCPIndex();
|
||||||
|
dos.writeShort(cpIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (isGeneric) {
|
if (isGeneric) {
|
||||||
writeGenericSignature(m.getGenericSignature().asString());
|
writeGenericSignature(m.getGenericSignature().asString());
|
||||||
}
|
}
|
||||||
@ -643,7 +617,7 @@ public class ClassWriter implements /* imports */ ClassConstants
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected void writeGenericSignature(String signature) throws IOException {
|
protected void writeGenericSignature(String signature) throws IOException {
|
||||||
dos.writeShort(_signatureIndex);
|
writeIndex(_signatureIndex);
|
||||||
if (DEBUG) debugMessage("signature attribute = " + _signatureIndex);
|
if (DEBUG) debugMessage("signature attribute = " + _signatureIndex);
|
||||||
dos.writeInt(2);
|
dos.writeInt(2);
|
||||||
Short index = (Short) utf8ToIndex.get(signature);
|
Short index = (Short) utf8ToIndex.get(signature);
|
||||||
@ -653,12 +627,12 @@ public class ClassWriter implements /* imports */ ClassConstants
|
|||||||
|
|
||||||
protected void writeClassAttributes() throws IOException {
|
protected void writeClassAttributes() throws IOException {
|
||||||
final long flags = klass.getAccessFlags();
|
final long flags = klass.getAccessFlags();
|
||||||
final boolean isSyn = isSynthetic((short) flags);
|
final boolean hasSyn = hasSyntheticAttribute((short) flags);
|
||||||
|
|
||||||
// check for source file
|
// check for source file
|
||||||
short classAttributeCount = 0;
|
short classAttributeCount = 0;
|
||||||
|
|
||||||
if (isSyn)
|
if (hasSyn)
|
||||||
classAttributeCount++;
|
classAttributeCount++;
|
||||||
|
|
||||||
Symbol sourceFileName = klass.getSourceFileName();
|
Symbol sourceFileName = klass.getSourceFileName();
|
||||||
@ -677,12 +651,12 @@ public class ClassWriter implements /* imports */ ClassConstants
|
|||||||
dos.writeShort(classAttributeCount);
|
dos.writeShort(classAttributeCount);
|
||||||
if (DEBUG) debugMessage("class attribute count = " + classAttributeCount);
|
if (DEBUG) debugMessage("class attribute count = " + classAttributeCount);
|
||||||
|
|
||||||
if (isSyn)
|
if (hasSyn)
|
||||||
writeSynthetic();
|
writeSynthetic();
|
||||||
|
|
||||||
// write SourceFile, if any
|
// write SourceFile, if any
|
||||||
if (sourceFileName != null) {
|
if (sourceFileName != null) {
|
||||||
dos.writeShort(_sourceFileIndex);
|
writeIndex(_sourceFileIndex);
|
||||||
if (DEBUG) debugMessage("source file attribute = " + _sourceFileIndex);
|
if (DEBUG) debugMessage("source file attribute = " + _sourceFileIndex);
|
||||||
dos.writeInt(2);
|
dos.writeInt(2);
|
||||||
Short index = (Short) utf8ToIndex.get(sourceFileName.asString());
|
Short index = (Short) utf8ToIndex.get(sourceFileName.asString());
|
||||||
@ -697,7 +671,7 @@ public class ClassWriter implements /* imports */ ClassConstants
|
|||||||
|
|
||||||
// write inner classes, if any
|
// write inner classes, if any
|
||||||
if (numInnerClasses != 0) {
|
if (numInnerClasses != 0) {
|
||||||
dos.writeShort(_innerClassesIndex);
|
writeIndex(_innerClassesIndex);
|
||||||
final int innerAttrLen = 2 /* number_of_inner_classes */ +
|
final int innerAttrLen = 2 /* number_of_inner_classes */ +
|
||||||
numInnerClasses * (
|
numInnerClasses * (
|
||||||
2 /* inner_class_info_index */ +
|
2 /* inner_class_info_index */ +
|
||||||
|
@ -33,9 +33,9 @@
|
|||||||
# Don't put quotes (fail windows build).
|
# Don't put quotes (fail windows build).
|
||||||
HOTSPOT_VM_COPYRIGHT=Copyright 2009
|
HOTSPOT_VM_COPYRIGHT=Copyright 2009
|
||||||
|
|
||||||
HS_MAJOR_VER=15
|
HS_MAJOR_VER=16
|
||||||
HS_MINOR_VER=0
|
HS_MINOR_VER=0
|
||||||
HS_BUILD_NUMBER=05
|
HS_BUILD_NUMBER=01
|
||||||
|
|
||||||
JDK_MAJOR_VER=1
|
JDK_MAJOR_VER=1
|
||||||
JDK_MINOR_VER=7
|
JDK_MINOR_VER=7
|
||||||
|
@ -73,6 +73,7 @@ if [ "${osname}" = SunOS ] ; then
|
|||||||
else
|
else
|
||||||
if [ "${JPRT_JOB_PRODUCT_RELEASE}" = "jdk6" -o \
|
if [ "${JPRT_JOB_PRODUCT_RELEASE}" = "jdk6" -o \
|
||||||
"${JPRT_JOB_PRODUCT_RELEASE}" = "jdk6u10" -o \
|
"${JPRT_JOB_PRODUCT_RELEASE}" = "jdk6u10" -o \
|
||||||
|
"${JPRT_JOB_PRODUCT_RELEASE}" = "jdk6u14" -o \
|
||||||
"${JPRT_JOB_PRODUCT_RELEASE}" = "jdk6perf" ] ; then
|
"${JPRT_JOB_PRODUCT_RELEASE}" = "jdk6perf" ] ; then
|
||||||
# All jdk6 builds use SS11
|
# All jdk6 builds use SS11
|
||||||
compiler_name=SS11
|
compiler_name=SS11
|
||||||
|
@ -3029,6 +3029,58 @@ void MacroAssembler::check_klass_subtype_slow_path(Register sub_klass,
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void MacroAssembler::check_method_handle_type(Register mtype_reg, Register mh_reg,
|
||||||
|
Register temp_reg,
|
||||||
|
Label& wrong_method_type) {
|
||||||
|
assert_different_registers(mtype_reg, mh_reg, temp_reg);
|
||||||
|
// compare method type against that of the receiver
|
||||||
|
RegisterOrConstant mhtype_offset = delayed_value(java_dyn_MethodHandle::type_offset_in_bytes, temp_reg);
|
||||||
|
ld_ptr(mh_reg, mhtype_offset, temp_reg);
|
||||||
|
cmp(temp_reg, mtype_reg);
|
||||||
|
br(Assembler::notEqual, false, Assembler::pn, wrong_method_type);
|
||||||
|
delayed()->nop();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void MacroAssembler::jump_to_method_handle_entry(Register mh_reg, Register temp_reg) {
|
||||||
|
assert(mh_reg == G3_method_handle, "caller must put MH object in G3");
|
||||||
|
assert_different_registers(mh_reg, temp_reg);
|
||||||
|
|
||||||
|
// pick out the interpreted side of the handler
|
||||||
|
ld_ptr(mh_reg, delayed_value(java_dyn_MethodHandle::vmentry_offset_in_bytes, temp_reg), temp_reg);
|
||||||
|
|
||||||
|
// off we go...
|
||||||
|
ld_ptr(temp_reg, MethodHandleEntry::from_interpreted_entry_offset_in_bytes(), temp_reg);
|
||||||
|
jmp(temp_reg, 0);
|
||||||
|
|
||||||
|
// for the various stubs which take control at this point,
|
||||||
|
// see MethodHandles::generate_method_handle_stub
|
||||||
|
|
||||||
|
// (Can any caller use this delay slot? If so, add an option for supression.)
|
||||||
|
delayed()->nop();
|
||||||
|
}
|
||||||
|
|
||||||
|
RegisterOrConstant MacroAssembler::argument_offset(RegisterOrConstant arg_slot,
|
||||||
|
int extra_slot_offset) {
|
||||||
|
// cf. TemplateTable::prepare_invoke(), if (load_receiver).
|
||||||
|
int stackElementSize = Interpreter::stackElementWords() * wordSize;
|
||||||
|
int offset = Interpreter::expr_offset_in_bytes(extra_slot_offset+0);
|
||||||
|
int offset1 = Interpreter::expr_offset_in_bytes(extra_slot_offset+1);
|
||||||
|
assert(offset1 - offset == stackElementSize, "correct arithmetic");
|
||||||
|
if (arg_slot.is_constant()) {
|
||||||
|
offset += arg_slot.as_constant() * stackElementSize;
|
||||||
|
return offset;
|
||||||
|
} else {
|
||||||
|
Register temp = arg_slot.as_register();
|
||||||
|
sll_ptr(temp, exact_log2(stackElementSize), temp);
|
||||||
|
if (offset != 0)
|
||||||
|
add(temp, offset, temp);
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void MacroAssembler::biased_locking_enter(Register obj_reg, Register mark_reg,
|
void MacroAssembler::biased_locking_enter(Register obj_reg, Register mark_reg,
|
||||||
Register temp_reg,
|
Register temp_reg,
|
||||||
Label& done, Label* slow_case,
|
Label& done, Label* slow_case,
|
||||||
|
@ -84,6 +84,10 @@ REGISTER_DECLARATION(Register, G4_scratch , G4);
|
|||||||
|
|
||||||
REGISTER_DECLARATION(Register, Gtemp , G5);
|
REGISTER_DECLARATION(Register, Gtemp , G5);
|
||||||
|
|
||||||
|
// JSR 292 fixed register usages:
|
||||||
|
REGISTER_DECLARATION(Register, G5_method_type , G5);
|
||||||
|
REGISTER_DECLARATION(Register, G3_method_handle , G3);
|
||||||
|
|
||||||
// The compiler requires that G5_megamorphic_method is G5_inline_cache_klass,
|
// The compiler requires that G5_megamorphic_method is G5_inline_cache_klass,
|
||||||
// because a single patchable "set" instruction (NativeMovConstReg,
|
// because a single patchable "set" instruction (NativeMovConstReg,
|
||||||
// or NativeMovConstPatching for compiler1) instruction
|
// or NativeMovConstPatching for compiler1) instruction
|
||||||
@ -91,9 +95,13 @@ REGISTER_DECLARATION(Register, Gtemp , G5);
|
|||||||
// call site is an inline cache or is megamorphic. See the function
|
// call site is an inline cache or is megamorphic. See the function
|
||||||
// CompiledIC::set_to_megamorphic.
|
// CompiledIC::set_to_megamorphic.
|
||||||
//
|
//
|
||||||
// On the other hand, G5_inline_cache_klass must differ from G5_method,
|
// If a inline cache targets an interpreted method, then the
|
||||||
// because both registers are needed for an inline cache that calls
|
// G5 register will be used twice during the call. First,
|
||||||
// an interpreted method.
|
// the call site will be patched to load a compiledICHolder
|
||||||
|
// into G5. (This is an ordered pair of ic_klass, method.)
|
||||||
|
// The c2i adapter will first check the ic_klass, then load
|
||||||
|
// G5_method with the method part of the pair just before
|
||||||
|
// jumping into the interpreter.
|
||||||
//
|
//
|
||||||
// Note that G5_method is only the method-self for the interpreter,
|
// Note that G5_method is only the method-self for the interpreter,
|
||||||
// and is logically unrelated to G5_megamorphic_method.
|
// and is logically unrelated to G5_megamorphic_method.
|
||||||
@ -1931,6 +1939,7 @@ class MacroAssembler: public Assembler {
|
|||||||
inline void store_ptr_contents( Register s, Address& a, int offset = 0 );
|
inline void store_ptr_contents( Register s, Address& a, int offset = 0 );
|
||||||
inline void jumpl_to( Address& a, Register d, int offset = 0 );
|
inline void jumpl_to( Address& a, Register d, int offset = 0 );
|
||||||
inline void jump_to( Address& a, int offset = 0 );
|
inline void jump_to( Address& a, int offset = 0 );
|
||||||
|
inline void jump_indirect_to( Address& a, Register temp, int ld_offset = 0, int jmp_offset = 0 );
|
||||||
|
|
||||||
// ring buffer traceable jumps
|
// ring buffer traceable jumps
|
||||||
|
|
||||||
@ -2366,6 +2375,16 @@ class MacroAssembler: public Assembler {
|
|||||||
Register temp2_reg,
|
Register temp2_reg,
|
||||||
Label& L_success);
|
Label& L_success);
|
||||||
|
|
||||||
|
// method handles (JSR 292)
|
||||||
|
void check_method_handle_type(Register mtype_reg, Register mh_reg,
|
||||||
|
Register temp_reg,
|
||||||
|
Label& wrong_method_type);
|
||||||
|
void jump_to_method_handle_entry(Register mh_reg, Register temp_reg);
|
||||||
|
// offset relative to Gargs of argument at tos[arg_slot].
|
||||||
|
// (arg_slot == 0 means the last argument, not the first).
|
||||||
|
RegisterOrConstant argument_offset(RegisterOrConstant arg_slot,
|
||||||
|
int extra_slot_offset = 0);
|
||||||
|
|
||||||
|
|
||||||
// Stack overflow checking
|
// Stack overflow checking
|
||||||
|
|
||||||
|
@ -671,6 +671,15 @@ inline void MacroAssembler::jump_to( Address& a, int offset ) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline void MacroAssembler::jump_indirect_to( Address& a, Register temp,
|
||||||
|
int ld_offset, int jmp_offset ) {
|
||||||
|
assert_not_delayed();
|
||||||
|
//sethi(a); // sethi is caller responsibility for this one
|
||||||
|
ld_ptr(a, temp, ld_offset);
|
||||||
|
jmp(temp, jmp_offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
inline void MacroAssembler::set_oop( jobject obj, Register d ) {
|
inline void MacroAssembler::set_oop( jobject obj, Register d ) {
|
||||||
set_oop(allocate_oop_address(obj, d));
|
set_oop(allocate_oop_address(obj, d));
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved.
|
* Copyright 2007-2009 Sun Microsystems, Inc. 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
|
||||||
@ -1017,6 +1017,7 @@ void CppInterpreterGenerator::generate_compute_interpreter_state(const Register
|
|||||||
const int slop_factor = 2*wordSize;
|
const int slop_factor = 2*wordSize;
|
||||||
|
|
||||||
const int fixed_size = ((sizeof(BytecodeInterpreter) + slop_factor) >> LogBytesPerWord) + // what is the slop factor?
|
const int fixed_size = ((sizeof(BytecodeInterpreter) + slop_factor) >> LogBytesPerWord) + // what is the slop factor?
|
||||||
|
//6815692//methodOopDesc::extra_stack_words() + // extra push slots for MH adapters
|
||||||
frame::memory_parameter_word_sp_offset + // register save area + param window
|
frame::memory_parameter_word_sp_offset + // register save area + param window
|
||||||
(native ? frame::interpreter_frame_extra_outgoing_argument_words : 0); // JNI, class
|
(native ? frame::interpreter_frame_extra_outgoing_argument_words : 0); // JNI, class
|
||||||
|
|
||||||
@ -1163,6 +1164,9 @@ void CppInterpreterGenerator::generate_compute_interpreter_state(const Register
|
|||||||
__ st_ptr(O2, XXX_STATE(_stack)); // PREPUSH
|
__ st_ptr(O2, XXX_STATE(_stack)); // PREPUSH
|
||||||
|
|
||||||
__ lduh(max_stack, O3); // Full size expression stack
|
__ lduh(max_stack, O3); // Full size expression stack
|
||||||
|
guarantee(!EnableMethodHandles, "no support yet for java.dyn.MethodHandle"); //6815692
|
||||||
|
//6815692//if (EnableMethodHandles)
|
||||||
|
//6815692// __ inc(O3, methodOopDesc::extra_stack_entries());
|
||||||
__ sll(O3, LogBytesPerWord, O3);
|
__ sll(O3, LogBytesPerWord, O3);
|
||||||
__ sub(O2, O3, O3);
|
__ sub(O2, O3, O3);
|
||||||
// __ sub(O3, wordSize, O3); // so prepush doesn't look out of bounds
|
// __ sub(O3, wordSize, O3); // so prepush doesn't look out of bounds
|
||||||
@ -2017,7 +2021,9 @@ static int size_activation_helper(int callee_extra_locals, int max_stack, int mo
|
|||||||
|
|
||||||
const int fixed_size = sizeof(BytecodeInterpreter)/wordSize + // interpreter state object
|
const int fixed_size = sizeof(BytecodeInterpreter)/wordSize + // interpreter state object
|
||||||
frame::memory_parameter_word_sp_offset; // register save area + param window
|
frame::memory_parameter_word_sp_offset; // register save area + param window
|
||||||
|
const int extra_stack = 0; //6815692//methodOopDesc::extra_stack_entries();
|
||||||
return (round_to(max_stack +
|
return (round_to(max_stack +
|
||||||
|
extra_stack +
|
||||||
slop_factor +
|
slop_factor +
|
||||||
fixed_size +
|
fixed_size +
|
||||||
monitor_size +
|
monitor_size +
|
||||||
@ -2104,7 +2110,8 @@ void BytecodeInterpreter::layout_interpreterState(interpreterState to_fill,
|
|||||||
// Need +1 here because stack_base points to the word just above the first expr stack entry
|
// Need +1 here because stack_base points to the word just above the first expr stack entry
|
||||||
// and stack_limit is supposed to point to the word just below the last expr stack entry.
|
// and stack_limit is supposed to point to the word just below the last expr stack entry.
|
||||||
// See generate_compute_interpreter_state.
|
// See generate_compute_interpreter_state.
|
||||||
to_fill->_stack_limit = stack_base - (method->max_stack() + 1);
|
int extra_stack = 0; //6815692//methodOopDesc::extra_stack_entries();
|
||||||
|
to_fill->_stack_limit = stack_base - (method->max_stack() + 1 + extra_stack);
|
||||||
to_fill->_monitor_base = (BasicObjectLock*) monitor_base;
|
to_fill->_monitor_base = (BasicObjectLock*) monitor_base;
|
||||||
|
|
||||||
// sparc specific
|
// sparc specific
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved.
|
* Copyright 1997-2009 Sun Microsystems, Inc. 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
|
||||||
@ -29,6 +29,7 @@
|
|||||||
address generate_normal_entry(bool synchronized);
|
address generate_normal_entry(bool synchronized);
|
||||||
address generate_native_entry(bool synchronized);
|
address generate_native_entry(bool synchronized);
|
||||||
address generate_abstract_entry(void);
|
address generate_abstract_entry(void);
|
||||||
|
address generate_method_handle_entry(void);
|
||||||
address generate_math_entry(AbstractInterpreter::MethodKind kind);
|
address generate_math_entry(AbstractInterpreter::MethodKind kind);
|
||||||
address generate_empty_entry(void);
|
address generate_empty_entry(void);
|
||||||
address generate_accessor_entry(void);
|
address generate_accessor_entry(void);
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved.
|
* Copyright 1997-2009 Sun Microsystems, Inc. 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
|
||||||
@ -235,6 +235,19 @@ address InterpreterGenerator::generate_abstract_entry(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Method handle invoker
|
||||||
|
// Dispatch a method of the form java.dyn.MethodHandles::invoke(...)
|
||||||
|
address InterpreterGenerator::generate_method_handle_entry(void) {
|
||||||
|
if (!EnableMethodHandles) {
|
||||||
|
return generate_abstract_entry();
|
||||||
|
}
|
||||||
|
return generate_abstract_entry(); //6815692//
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
// Entry points & stack frame layout
|
// Entry points & stack frame layout
|
||||||
//
|
//
|
||||||
@ -364,6 +377,7 @@ address AbstractInterpreterGenerator::generate_method_entry(AbstractInterpreter:
|
|||||||
case Interpreter::empty : entry_point = ((InterpreterGenerator*)this)->generate_empty_entry(); break;
|
case Interpreter::empty : entry_point = ((InterpreterGenerator*)this)->generate_empty_entry(); break;
|
||||||
case Interpreter::accessor : entry_point = ((InterpreterGenerator*)this)->generate_accessor_entry(); break;
|
case Interpreter::accessor : entry_point = ((InterpreterGenerator*)this)->generate_accessor_entry(); break;
|
||||||
case Interpreter::abstract : entry_point = ((InterpreterGenerator*)this)->generate_abstract_entry(); break;
|
case Interpreter::abstract : entry_point = ((InterpreterGenerator*)this)->generate_abstract_entry(); break;
|
||||||
|
case Interpreter::method_handle : entry_point = ((InterpreterGenerator*)this)->generate_method_handle_entry(); break;
|
||||||
case Interpreter::java_lang_math_sin : break;
|
case Interpreter::java_lang_math_sin : break;
|
||||||
case Interpreter::java_lang_math_cos : break;
|
case Interpreter::java_lang_math_cos : break;
|
||||||
case Interpreter::java_lang_math_tan : break;
|
case Interpreter::java_lang_math_tan : break;
|
||||||
|
70
hotspot/src/cpu/sparc/vm/methodHandles_sparc.cpp
Normal file
70
hotspot/src/cpu/sparc/vm/methodHandles_sparc.cpp
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
||||||
|
* CA 95054 USA or visit www.sun.com if you need additional information or
|
||||||
|
* have any questions.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "incls/_precompiled.incl"
|
||||||
|
#include "incls/_methodHandles_sparc.cpp.incl"
|
||||||
|
|
||||||
|
#define __ _masm->
|
||||||
|
|
||||||
|
address MethodHandleEntry::start_compiled_entry(MacroAssembler* _masm,
|
||||||
|
address interpreted_entry) {
|
||||||
|
__ align(wordSize);
|
||||||
|
address target = __ pc() + sizeof(Data);
|
||||||
|
while (__ pc() < target) {
|
||||||
|
__ nop();
|
||||||
|
__ align(wordSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
MethodHandleEntry* me = (MethodHandleEntry*) __ pc();
|
||||||
|
me->set_end_address(__ pc()); // set a temporary end_address
|
||||||
|
me->set_from_interpreted_entry(interpreted_entry);
|
||||||
|
me->set_type_checking_entry(NULL);
|
||||||
|
|
||||||
|
return (address) me;
|
||||||
|
}
|
||||||
|
|
||||||
|
MethodHandleEntry* MethodHandleEntry::finish_compiled_entry(MacroAssembler* _masm,
|
||||||
|
address start_addr) {
|
||||||
|
MethodHandleEntry* me = (MethodHandleEntry*) start_addr;
|
||||||
|
assert(me->end_address() == start_addr, "valid ME");
|
||||||
|
|
||||||
|
// Fill in the real end_address:
|
||||||
|
__ align(wordSize);
|
||||||
|
me->set_end_address(__ pc());
|
||||||
|
|
||||||
|
return me;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Code generation
|
||||||
|
address MethodHandles::generate_method_handle_interpreter_entry(MacroAssembler* _masm) {
|
||||||
|
ShouldNotReachHere(); //NYI, 6815692
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate an "entry" field for a method handle.
|
||||||
|
// This determines how the method handle will respond to calls.
|
||||||
|
void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHandles::EntryKind ek) {
|
||||||
|
ShouldNotReachHere(); //NYI, 6815692
|
||||||
|
}
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2002-2008 Sun Microsystems, Inc. All Rights Reserved.
|
* Copyright 2002-2009 Sun Microsystems, Inc. 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
|
||||||
@ -142,6 +142,8 @@ REGISTER_DEFINITION(Register, G1_scratch);
|
|||||||
REGISTER_DEFINITION(Register, G3_scratch);
|
REGISTER_DEFINITION(Register, G3_scratch);
|
||||||
REGISTER_DEFINITION(Register, G4_scratch);
|
REGISTER_DEFINITION(Register, G4_scratch);
|
||||||
REGISTER_DEFINITION(Register, Gtemp);
|
REGISTER_DEFINITION(Register, Gtemp);
|
||||||
|
REGISTER_DEFINITION(Register, G5_method_type);
|
||||||
|
REGISTER_DEFINITION(Register, G3_method_handle);
|
||||||
REGISTER_DEFINITION(Register, Lentry_args);
|
REGISTER_DEFINITION(Register, Lentry_args);
|
||||||
|
|
||||||
#ifdef CC_INTERP
|
#ifdef CC_INTERP
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved.
|
* Copyright 2003-2009 Sun Microsystems, Inc. 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
|
||||||
@ -937,9 +937,9 @@ void AdapterGenerator::gen_i2c_adapter(
|
|||||||
// Inputs:
|
// Inputs:
|
||||||
// G2_thread - TLS
|
// G2_thread - TLS
|
||||||
// G5_method - Method oop
|
// G5_method - Method oop
|
||||||
// O0 - Flag telling us to restore SP from O5
|
// G4 (Gargs) - Pointer to interpreter's args
|
||||||
// O4_args - Pointer to interpreter's args
|
// O0..O4 - free for scratch
|
||||||
// O5 - Caller's saved SP, to be restored if needed
|
// O5_savedSP - Caller's saved SP, to be restored if needed
|
||||||
// O6 - Current SP!
|
// O6 - Current SP!
|
||||||
// O7 - Valid return address
|
// O7 - Valid return address
|
||||||
// L0-L7, I0-I7 - Caller's temps (no frame pushed yet)
|
// L0-L7, I0-I7 - Caller's temps (no frame pushed yet)
|
||||||
@ -954,7 +954,7 @@ void AdapterGenerator::gen_i2c_adapter(
|
|||||||
// F0-F7 - more outgoing args
|
// F0-F7 - more outgoing args
|
||||||
|
|
||||||
|
|
||||||
// O4 is about to get loaded up with compiled callee's args
|
// Gargs is the incoming argument base, and also an outgoing argument.
|
||||||
__ sub(Gargs, BytesPerWord, Gargs);
|
__ sub(Gargs, BytesPerWord, Gargs);
|
||||||
|
|
||||||
#ifdef ASSERT
|
#ifdef ASSERT
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved.
|
* Copyright 1997-2009 Sun Microsystems, Inc. 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
|
||||||
@ -108,6 +108,24 @@ address TemplateInterpreterGenerator::generate_ClassCastException_handler() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Arguments are: required type in G5_method_type, and
|
||||||
|
// failing object (or NULL) in G3_method_handle.
|
||||||
|
address TemplateInterpreterGenerator::generate_WrongMethodType_handler() {
|
||||||
|
address entry = __ pc();
|
||||||
|
// expression stack must be empty before entering the VM if an exception
|
||||||
|
// happened
|
||||||
|
__ empty_expression_stack();
|
||||||
|
// load exception object
|
||||||
|
__ call_VM(Oexception,
|
||||||
|
CAST_FROM_FN_PTR(address,
|
||||||
|
InterpreterRuntime::throw_WrongMethodTypeException),
|
||||||
|
G5_method_type, // required
|
||||||
|
G3_method_handle); // actual
|
||||||
|
__ should_not_reach_here();
|
||||||
|
return entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
address TemplateInterpreterGenerator::generate_ArrayIndexOutOfBounds_handler(const char* name) {
|
address TemplateInterpreterGenerator::generate_ArrayIndexOutOfBounds_handler(const char* name) {
|
||||||
address entry = __ pc();
|
address entry = __ pc();
|
||||||
// expression stack must be empty before entering the VM if an exception happened
|
// expression stack must be empty before entering the VM if an exception happened
|
||||||
@ -448,6 +466,7 @@ void TemplateInterpreterGenerator::generate_fixed_frame(bool native_call) {
|
|||||||
|
|
||||||
const int extra_space =
|
const int extra_space =
|
||||||
rounded_vm_local_words + // frame local scratch space
|
rounded_vm_local_words + // frame local scratch space
|
||||||
|
//6815692//methodOopDesc::extra_stack_words() + // extra push slots for MH adapters
|
||||||
frame::memory_parameter_word_sp_offset + // register save area
|
frame::memory_parameter_word_sp_offset + // register save area
|
||||||
(native_call ? frame::interpreter_frame_extra_outgoing_argument_words : 0);
|
(native_call ? frame::interpreter_frame_extra_outgoing_argument_words : 0);
|
||||||
|
|
||||||
@ -1447,6 +1466,7 @@ static int size_activation_helper(int callee_extra_locals, int max_stack, int mo
|
|||||||
round_to(callee_extra_locals * Interpreter::stackElementWords(), WordsPerLong);
|
round_to(callee_extra_locals * Interpreter::stackElementWords(), WordsPerLong);
|
||||||
const int max_stack_words = max_stack * Interpreter::stackElementWords();
|
const int max_stack_words = max_stack * Interpreter::stackElementWords();
|
||||||
return (round_to((max_stack_words
|
return (round_to((max_stack_words
|
||||||
|
//6815692//+ methodOopDesc::extra_stack_words()
|
||||||
+ rounded_vm_local_words
|
+ rounded_vm_local_words
|
||||||
+ frame::memory_parameter_word_sp_offset), WordsPerLong)
|
+ frame::memory_parameter_word_sp_offset), WordsPerLong)
|
||||||
// already rounded
|
// already rounded
|
||||||
|
@ -114,6 +114,9 @@ VtableStub* VtableStubs::create_vtable_stub(int vtable_index) {
|
|||||||
(int)(s->code_end() - __ pc()));
|
(int)(s->code_end() - __ pc()));
|
||||||
}
|
}
|
||||||
guarantee(__ pc() <= s->code_end(), "overflowed buffer");
|
guarantee(__ pc() <= s->code_end(), "overflowed buffer");
|
||||||
|
// shut the door on sizing bugs
|
||||||
|
int slop = 2*BytesPerInstWord; // 32-bit offset is this much larger than a 13-bit one
|
||||||
|
assert(vtable_index > 10 || __ pc() + slop <= s->code_end(), "room for sethi;add");
|
||||||
|
|
||||||
s->set_exception_points(npe_addr, ame_addr);
|
s->set_exception_points(npe_addr, ame_addr);
|
||||||
return s;
|
return s;
|
||||||
@ -208,6 +211,9 @@ VtableStub* VtableStubs::create_itable_stub(int itable_index) {
|
|||||||
(int)(s->code_end() - __ pc()));
|
(int)(s->code_end() - __ pc()));
|
||||||
}
|
}
|
||||||
guarantee(__ pc() <= s->code_end(), "overflowed buffer");
|
guarantee(__ pc() <= s->code_end(), "overflowed buffer");
|
||||||
|
// shut the door on sizing bugs
|
||||||
|
int slop = 2*BytesPerInstWord; // 32-bit offset is this much larger than a 13-bit one
|
||||||
|
assert(itable_index > 10 || __ pc() + slop <= s->code_end(), "room for sethi;add");
|
||||||
|
|
||||||
s->set_exception_points(npe_addr, ame_addr);
|
s->set_exception_points(npe_addr, ame_addr);
|
||||||
return s;
|
return s;
|
||||||
@ -233,6 +239,50 @@ int VtableStub::pd_code_size_limit(bool is_vtable_stub) {
|
|||||||
return (basic + slop);
|
return (basic + slop);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// In order to tune these parameters, run the JVM with VM options
|
||||||
|
// +PrintMiscellaneous and +WizardMode to see information about
|
||||||
|
// actual itable stubs. Look for lines like this:
|
||||||
|
// itable #1 at 0x5551212[116] left over: 8
|
||||||
|
// Reduce the constants so that the "left over" number is 8
|
||||||
|
// Do not aim at a left-over number of zero, because a very
|
||||||
|
// large vtable or itable offset (> 4K) will require an extra
|
||||||
|
// sethi/or pair of instructions.
|
||||||
|
//
|
||||||
|
// The JVM98 app. _202_jess has a megamorphic interface call.
|
||||||
|
// The itable code looks like this:
|
||||||
|
// Decoding VtableStub itbl[1]@16
|
||||||
|
// ld [ %o0 + 4 ], %g3
|
||||||
|
// save %sp, -64, %sp
|
||||||
|
// ld [ %g3 + 0xe8 ], %l2
|
||||||
|
// sll %l2, 2, %l2
|
||||||
|
// add %l2, 0x134, %l2
|
||||||
|
// and %l2, -8, %l2 ! NOT_LP64 only
|
||||||
|
// add %g3, %l2, %l2
|
||||||
|
// add %g3, 4, %g3
|
||||||
|
// ld [ %l2 ], %l5
|
||||||
|
// brz,pn %l5, throw_icce
|
||||||
|
// cmp %l5, %g5
|
||||||
|
// be %icc, success
|
||||||
|
// add %l2, 8, %l2
|
||||||
|
// loop:
|
||||||
|
// ld [ %l2 ], %l5
|
||||||
|
// brz,pn %l5, throw_icce
|
||||||
|
// cmp %l5, %g5
|
||||||
|
// bne,pn %icc, loop
|
||||||
|
// add %l2, 8, %l2
|
||||||
|
// success:
|
||||||
|
// ld [ %l2 + -4 ], %l2
|
||||||
|
// ld [ %g3 + %l2 ], %l5
|
||||||
|
// restore %l5, 0, %g5
|
||||||
|
// ld [ %g5 + 0x44 ], %g3
|
||||||
|
// jmp %g3
|
||||||
|
// nop
|
||||||
|
// throw_icce:
|
||||||
|
// sethi %hi(throw_ICCE_entry), %g3
|
||||||
|
// ! 5 more instructions here, LP64_ONLY
|
||||||
|
// jmp %g3 + %lo(throw_ICCE_entry)
|
||||||
|
// restore
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -7609,6 +7609,83 @@ RegisterOrConstant MacroAssembler::delayed_value_impl(intptr_t* delayed_value_ad
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// registers on entry:
|
||||||
|
// - rax ('check' register): required MethodType
|
||||||
|
// - rcx: method handle
|
||||||
|
// - rdx, rsi, or ?: killable temp
|
||||||
|
void MacroAssembler::check_method_handle_type(Register mtype_reg, Register mh_reg,
|
||||||
|
Register temp_reg,
|
||||||
|
Label& wrong_method_type) {
|
||||||
|
if (UseCompressedOops) unimplemented(); // field accesses must decode
|
||||||
|
// compare method type against that of the receiver
|
||||||
|
cmpptr(mtype_reg, Address(mh_reg, delayed_value(java_dyn_MethodHandle::type_offset_in_bytes, temp_reg)));
|
||||||
|
jcc(Assembler::notEqual, wrong_method_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// A method handle has a "vmslots" field which gives the size of its
|
||||||
|
// argument list in JVM stack slots. This field is either located directly
|
||||||
|
// in every method handle, or else is indirectly accessed through the
|
||||||
|
// method handle's MethodType. This macro hides the distinction.
|
||||||
|
void MacroAssembler::load_method_handle_vmslots(Register vmslots_reg, Register mh_reg,
|
||||||
|
Register temp_reg) {
|
||||||
|
if (UseCompressedOops) unimplemented(); // field accesses must decode
|
||||||
|
// load mh.type.form.vmslots
|
||||||
|
if (java_dyn_MethodHandle::vmslots_offset_in_bytes() != 0) {
|
||||||
|
// hoist vmslots into every mh to avoid dependent load chain
|
||||||
|
movl(vmslots_reg, Address(mh_reg, delayed_value(java_dyn_MethodHandle::vmslots_offset_in_bytes, temp_reg)));
|
||||||
|
} else {
|
||||||
|
Register temp2_reg = vmslots_reg;
|
||||||
|
movptr(temp2_reg, Address(mh_reg, delayed_value(java_dyn_MethodHandle::type_offset_in_bytes, temp_reg)));
|
||||||
|
movptr(temp2_reg, Address(temp2_reg, delayed_value(java_dyn_MethodType::form_offset_in_bytes, temp_reg)));
|
||||||
|
movl(vmslots_reg, Address(temp2_reg, delayed_value(java_dyn_MethodTypeForm::vmslots_offset_in_bytes, temp_reg)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// registers on entry:
|
||||||
|
// - rcx: method handle
|
||||||
|
// - rdx: killable temp (interpreted only)
|
||||||
|
// - rax: killable temp (compiled only)
|
||||||
|
void MacroAssembler::jump_to_method_handle_entry(Register mh_reg, Register temp_reg) {
|
||||||
|
assert(mh_reg == rcx, "caller must put MH object in rcx");
|
||||||
|
assert_different_registers(mh_reg, temp_reg);
|
||||||
|
|
||||||
|
if (UseCompressedOops) unimplemented(); // field accesses must decode
|
||||||
|
|
||||||
|
// pick out the interpreted side of the handler
|
||||||
|
movptr(temp_reg, Address(mh_reg, delayed_value(java_dyn_MethodHandle::vmentry_offset_in_bytes, temp_reg)));
|
||||||
|
|
||||||
|
// off we go...
|
||||||
|
jmp(Address(temp_reg, MethodHandleEntry::from_interpreted_entry_offset_in_bytes()));
|
||||||
|
|
||||||
|
// for the various stubs which take control at this point,
|
||||||
|
// see MethodHandles::generate_method_handle_stub
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Address MacroAssembler::argument_address(RegisterOrConstant arg_slot,
|
||||||
|
int extra_slot_offset) {
|
||||||
|
// cf. TemplateTable::prepare_invoke(), if (load_receiver).
|
||||||
|
int stackElementSize = Interpreter::stackElementSize();
|
||||||
|
int offset = Interpreter::expr_offset_in_bytes(extra_slot_offset+0);
|
||||||
|
#ifdef ASSERT
|
||||||
|
int offset1 = Interpreter::expr_offset_in_bytes(extra_slot_offset+1);
|
||||||
|
assert(offset1 - offset == stackElementSize, "correct arithmetic");
|
||||||
|
#endif
|
||||||
|
Register scale_reg = noreg;
|
||||||
|
Address::ScaleFactor scale_factor = Address::no_scale;
|
||||||
|
if (arg_slot.is_constant()) {
|
||||||
|
offset += arg_slot.as_constant() * stackElementSize;
|
||||||
|
} else {
|
||||||
|
scale_reg = arg_slot.as_register();
|
||||||
|
scale_factor = Address::times(stackElementSize);
|
||||||
|
}
|
||||||
|
offset += wordSize; // return PC is on stack
|
||||||
|
return Address(rsp, scale_reg, scale_factor, offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void MacroAssembler::verify_oop_addr(Address addr, const char* s) {
|
void MacroAssembler::verify_oop_addr(Address addr, const char* s) {
|
||||||
if (!VerifyOops) return;
|
if (!VerifyOops) return;
|
||||||
|
|
||||||
|
@ -1857,6 +1857,16 @@ class MacroAssembler: public Assembler {
|
|||||||
Register temp_reg,
|
Register temp_reg,
|
||||||
Label& L_success);
|
Label& L_success);
|
||||||
|
|
||||||
|
// method handles (JSR 292)
|
||||||
|
void check_method_handle_type(Register mtype_reg, Register mh_reg,
|
||||||
|
Register temp_reg,
|
||||||
|
Label& wrong_method_type);
|
||||||
|
void load_method_handle_vmslots(Register vmslots_reg, Register mh_reg,
|
||||||
|
Register temp_reg);
|
||||||
|
void jump_to_method_handle_entry(Register mh_reg, Register temp_reg);
|
||||||
|
Address argument_address(RegisterOrConstant arg_slot, int extra_slot_offset = 0);
|
||||||
|
|
||||||
|
|
||||||
//----
|
//----
|
||||||
void set_word_if_not_zero(Register reg); // sets reg to 1 if not zero, otherwise 0
|
void set_word_if_not_zero(Register reg); // sets reg to 1 if not zero, otherwise 0
|
||||||
|
|
||||||
|
@ -513,10 +513,11 @@ void CppInterpreterGenerator::generate_compute_interpreter_state(const Register
|
|||||||
// compute full expression stack limit
|
// compute full expression stack limit
|
||||||
|
|
||||||
const Address size_of_stack (rbx, methodOopDesc::max_stack_offset());
|
const Address size_of_stack (rbx, methodOopDesc::max_stack_offset());
|
||||||
|
const int extra_stack = 0; //6815692//methodOopDesc::extra_stack_words();
|
||||||
__ load_unsigned_short(rdx, size_of_stack); // get size of expression stack in words
|
__ load_unsigned_short(rdx, size_of_stack); // get size of expression stack in words
|
||||||
__ negptr(rdx); // so we can subtract in next step
|
__ negptr(rdx); // so we can subtract in next step
|
||||||
// Allocate expression stack
|
// Allocate expression stack
|
||||||
__ lea(rsp, Address(rsp, rdx, Address::times_ptr));
|
__ lea(rsp, Address(rsp, rdx, Address::times_ptr, -extra_stack));
|
||||||
__ movptr(STATE(_stack_limit), rsp);
|
__ movptr(STATE(_stack_limit), rsp);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -659,8 +660,9 @@ void InterpreterGenerator::generate_stack_overflow_check(void) {
|
|||||||
// Always give one monitor to allow us to start interp if sync method.
|
// Always give one monitor to allow us to start interp if sync method.
|
||||||
// Any additional monitors need a check when moving the expression stack
|
// Any additional monitors need a check when moving the expression stack
|
||||||
const int one_monitor = frame::interpreter_frame_monitor_size() * wordSize;
|
const int one_monitor = frame::interpreter_frame_monitor_size() * wordSize;
|
||||||
|
const int extra_stack = 0; //6815692//methodOopDesc::extra_stack_entries();
|
||||||
__ load_unsigned_short(rax, size_of_stack); // get size of expression stack in words
|
__ load_unsigned_short(rax, size_of_stack); // get size of expression stack in words
|
||||||
__ lea(rax, Address(noreg, rax, Interpreter::stackElementScale(), one_monitor));
|
__ lea(rax, Address(noreg, rax, Interpreter::stackElementScale(), extra_stack + one_monitor));
|
||||||
__ lea(rax, Address(rax, rdx, Interpreter::stackElementScale(), overhead_size));
|
__ lea(rax, Address(rax, rdx, Interpreter::stackElementScale(), overhead_size));
|
||||||
|
|
||||||
#ifdef ASSERT
|
#ifdef ASSERT
|
||||||
@ -2185,6 +2187,7 @@ address AbstractInterpreterGenerator::generate_method_entry(AbstractInterpreter:
|
|||||||
case Interpreter::empty : entry_point = ((InterpreterGenerator*)this)->generate_empty_entry(); break;
|
case Interpreter::empty : entry_point = ((InterpreterGenerator*)this)->generate_empty_entry(); break;
|
||||||
case Interpreter::accessor : entry_point = ((InterpreterGenerator*)this)->generate_accessor_entry(); break;
|
case Interpreter::accessor : entry_point = ((InterpreterGenerator*)this)->generate_accessor_entry(); break;
|
||||||
case Interpreter::abstract : entry_point = ((InterpreterGenerator*)this)->generate_abstract_entry(); break;
|
case Interpreter::abstract : entry_point = ((InterpreterGenerator*)this)->generate_abstract_entry(); break;
|
||||||
|
case Interpreter::method_handle : entry_point = ((InterpreterGenerator*)this)->generate_method_handle_entry(); break;
|
||||||
|
|
||||||
case Interpreter::java_lang_math_sin : // fall thru
|
case Interpreter::java_lang_math_sin : // fall thru
|
||||||
case Interpreter::java_lang_math_cos : // fall thru
|
case Interpreter::java_lang_math_cos : // fall thru
|
||||||
@ -2224,7 +2227,8 @@ int AbstractInterpreter::size_top_interpreter_activation(methodOop method) {
|
|||||||
const int overhead_size = sizeof(BytecodeInterpreter)/wordSize +
|
const int overhead_size = sizeof(BytecodeInterpreter)/wordSize +
|
||||||
( frame::sender_sp_offset - frame::link_offset) + 2;
|
( frame::sender_sp_offset - frame::link_offset) + 2;
|
||||||
|
|
||||||
const int method_stack = (method->max_locals() + method->max_stack()) *
|
const int extra_stack = 0; //6815692//methodOopDesc::extra_stack_entries();
|
||||||
|
const int method_stack = (method->max_locals() + method->max_stack() + extra_stack) *
|
||||||
Interpreter::stackElementWords();
|
Interpreter::stackElementWords();
|
||||||
return overhead_size + method_stack + stub_code;
|
return overhead_size + method_stack + stub_code;
|
||||||
}
|
}
|
||||||
@ -2289,7 +2293,8 @@ void BytecodeInterpreter::layout_interpreterState(interpreterState to_fill,
|
|||||||
// Need +1 here because stack_base points to the word just above the first expr stack entry
|
// Need +1 here because stack_base points to the word just above the first expr stack entry
|
||||||
// and stack_limit is supposed to point to the word just below the last expr stack entry.
|
// and stack_limit is supposed to point to the word just below the last expr stack entry.
|
||||||
// See generate_compute_interpreter_state.
|
// See generate_compute_interpreter_state.
|
||||||
to_fill->_stack_limit = stack_base - (method->max_stack() + 1);
|
int extra_stack = 0; //6815692//methodOopDesc::extra_stack_entries();
|
||||||
|
to_fill->_stack_limit = stack_base - (method->max_stack() + extra_stack + 1);
|
||||||
to_fill->_monitor_base = (BasicObjectLock*) monitor_base;
|
to_fill->_monitor_base = (BasicObjectLock*) monitor_base;
|
||||||
|
|
||||||
to_fill->_self_link = to_fill;
|
to_fill->_self_link = to_fill;
|
||||||
@ -2335,7 +2340,8 @@ int AbstractInterpreter::layout_activation(methodOop method,
|
|||||||
monitor_size);
|
monitor_size);
|
||||||
|
|
||||||
// Now with full size expression stack
|
// Now with full size expression stack
|
||||||
int full_frame_size = short_frame_size + method->max_stack() * BytesPerWord;
|
int extra_stack = 0; //6815692//methodOopDesc::extra_stack_entries();
|
||||||
|
int full_frame_size = short_frame_size + (method->max_stack() + extra_stack) * BytesPerWord;
|
||||||
|
|
||||||
// and now with only live portion of the expression stack
|
// and now with only live portion of the expression stack
|
||||||
short_frame_size = short_frame_size + tempcount * BytesPerWord;
|
short_frame_size = short_frame_size + tempcount * BytesPerWord;
|
||||||
|
@ -555,13 +555,18 @@ void InterpreterMacroAssembler::super_call_VM_leaf(address entry_point, Register
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Jump to from_interpreted entry of a call unless single stepping is possible
|
void InterpreterMacroAssembler::prepare_to_jump_from_interpreted() {
|
||||||
// in this thread in which case we must call the i2i entry
|
|
||||||
void InterpreterMacroAssembler::jump_from_interpreted(Register method, Register temp) {
|
|
||||||
// set sender sp
|
// set sender sp
|
||||||
lea(rsi, Address(rsp, wordSize));
|
lea(rsi, Address(rsp, wordSize));
|
||||||
// record last_sp
|
// record last_sp
|
||||||
movptr(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), rsi);
|
movptr(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), rsi);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Jump to from_interpreted entry of a call unless single stepping is possible
|
||||||
|
// in this thread in which case we must call the i2i entry
|
||||||
|
void InterpreterMacroAssembler::jump_from_interpreted(Register method, Register temp) {
|
||||||
|
prepare_to_jump_from_interpreted();
|
||||||
|
|
||||||
if (JvmtiExport::can_post_interpreter_events()) {
|
if (JvmtiExport::can_post_interpreter_events()) {
|
||||||
Label run_compiled_code;
|
Label run_compiled_code;
|
||||||
|
@ -161,6 +161,7 @@ class InterpreterMacroAssembler: public MacroAssembler {
|
|||||||
|
|
||||||
|
|
||||||
// jump to an invoked target
|
// jump to an invoked target
|
||||||
|
void prepare_to_jump_from_interpreted();
|
||||||
void jump_from_interpreted(Register method, Register temp);
|
void jump_from_interpreted(Register method, Register temp);
|
||||||
|
|
||||||
// Returning from interpreted functions
|
// Returning from interpreted functions
|
||||||
|
@ -551,13 +551,18 @@ void InterpreterMacroAssembler::super_call_VM_leaf(address entry_point,
|
|||||||
MacroAssembler::call_VM_leaf_base(entry_point, 3);
|
MacroAssembler::call_VM_leaf_base(entry_point, 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Jump to from_interpreted entry of a call unless single stepping is possible
|
void InterpreterMacroAssembler::prepare_to_jump_from_interpreted() {
|
||||||
// in this thread in which case we must call the i2i entry
|
|
||||||
void InterpreterMacroAssembler::jump_from_interpreted(Register method, Register temp) {
|
|
||||||
// set sender sp
|
// set sender sp
|
||||||
lea(r13, Address(rsp, wordSize));
|
lea(r13, Address(rsp, wordSize));
|
||||||
// record last_sp
|
// record last_sp
|
||||||
movptr(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), r13);
|
movptr(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), r13);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Jump to from_interpreted entry of a call unless single stepping is possible
|
||||||
|
// in this thread in which case we must call the i2i entry
|
||||||
|
void InterpreterMacroAssembler::jump_from_interpreted(Register method, Register temp) {
|
||||||
|
prepare_to_jump_from_interpreted();
|
||||||
|
|
||||||
if (JvmtiExport::can_post_interpreter_events()) {
|
if (JvmtiExport::can_post_interpreter_events()) {
|
||||||
Label run_compiled_code;
|
Label run_compiled_code;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved.
|
* Copyright 2003-2009 Sun Microsystems, Inc. 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
|
||||||
@ -176,6 +176,7 @@ class InterpreterMacroAssembler: public MacroAssembler {
|
|||||||
void dispatch_via (TosState state, address* table);
|
void dispatch_via (TosState state, address* table);
|
||||||
|
|
||||||
// jump to an invoked target
|
// jump to an invoked target
|
||||||
|
void prepare_to_jump_from_interpreted();
|
||||||
void jump_from_interpreted(Register method, Register temp);
|
void jump_from_interpreted(Register method, Register temp);
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved.
|
* Copyright 1997-2009 Sun Microsystems, Inc. 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
|
||||||
@ -32,6 +32,7 @@
|
|||||||
address generate_normal_entry(bool synchronized);
|
address generate_normal_entry(bool synchronized);
|
||||||
address generate_native_entry(bool synchronized);
|
address generate_native_entry(bool synchronized);
|
||||||
address generate_abstract_entry(void);
|
address generate_abstract_entry(void);
|
||||||
|
address generate_method_handle_entry(void);
|
||||||
address generate_math_entry(AbstractInterpreter::MethodKind kind);
|
address generate_math_entry(AbstractInterpreter::MethodKind kind);
|
||||||
address generate_empty_entry(void);
|
address generate_empty_entry(void);
|
||||||
address generate_accessor_entry(void);
|
address generate_accessor_entry(void);
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved.
|
* Copyright 1997-2009 Sun Microsystems, Inc. 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
|
||||||
@ -201,11 +201,12 @@ address InterpreterGenerator::generate_abstract_entry(void) {
|
|||||||
address entry_point = __ pc();
|
address entry_point = __ pc();
|
||||||
|
|
||||||
// abstract method entry
|
// abstract method entry
|
||||||
// remove return address. Not really needed, since exception handling throws away expression stack
|
|
||||||
__ pop(rbx);
|
|
||||||
|
|
||||||
// adjust stack to what a normal return would do
|
// pop return address, reset last_sp to NULL
|
||||||
__ mov(rsp, rsi);
|
__ empty_expression_stack();
|
||||||
|
__ restore_bcp(); // rsi must be correct for exception handler (was destroyed)
|
||||||
|
__ restore_locals(); // make sure locals pointer is correct as well (was destroyed)
|
||||||
|
|
||||||
// throw exception
|
// throw exception
|
||||||
__ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_AbstractMethodError));
|
__ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_AbstractMethodError));
|
||||||
// the call_VM checks for exception, so we should never return here.
|
// the call_VM checks for exception, so we should never return here.
|
||||||
@ -214,6 +215,20 @@ address InterpreterGenerator::generate_abstract_entry(void) {
|
|||||||
return entry_point;
|
return entry_point;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Method handle invoker
|
||||||
|
// Dispatch a method of the form java.dyn.MethodHandles::invoke(...)
|
||||||
|
address InterpreterGenerator::generate_method_handle_entry(void) {
|
||||||
|
if (!EnableMethodHandles) {
|
||||||
|
return generate_abstract_entry();
|
||||||
|
}
|
||||||
|
|
||||||
|
address entry_point = MethodHandles::generate_method_handle_interpreter_entry(_masm);
|
||||||
|
|
||||||
|
return entry_point;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// This method tells the deoptimizer how big an interpreted frame must be:
|
// This method tells the deoptimizer how big an interpreted frame must be:
|
||||||
int AbstractInterpreter::size_activation(methodOop method,
|
int AbstractInterpreter::size_activation(methodOop method,
|
||||||
int tempcount,
|
int tempcount,
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved.
|
* Copyright 2003-2009 Sun Microsystems, Inc. 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
|
||||||
@ -294,6 +294,16 @@ address InterpreterGenerator::generate_abstract_entry(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Method handle invoker
|
||||||
|
// Dispatch a method of the form java.dyn.MethodHandles::invoke(...)
|
||||||
|
address InterpreterGenerator::generate_method_handle_entry(void) {
|
||||||
|
if (!EnableMethodHandles) {
|
||||||
|
return generate_abstract_entry();
|
||||||
|
}
|
||||||
|
return generate_abstract_entry(); //6815692//
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Empty method, generate a very fast return.
|
// Empty method, generate a very fast return.
|
||||||
|
|
||||||
address InterpreterGenerator::generate_empty_entry(void) {
|
address InterpreterGenerator::generate_empty_entry(void) {
|
||||||
|
1133
hotspot/src/cpu/x86/vm/methodHandles_x86.cpp
Normal file
1133
hotspot/src/cpu/x86/vm/methodHandles_x86.cpp
Normal file
File diff suppressed because it is too large
Load Diff
@ -2219,6 +2219,16 @@ class StubGenerator: public StubCodeGenerator {
|
|||||||
|
|
||||||
// arraycopy stubs used by compilers
|
// arraycopy stubs used by compilers
|
||||||
generate_arraycopy_stubs();
|
generate_arraycopy_stubs();
|
||||||
|
|
||||||
|
// generic method handle stubs
|
||||||
|
if (EnableMethodHandles && SystemDictionary::MethodHandle_klass() != NULL) {
|
||||||
|
for (MethodHandles::EntryKind ek = MethodHandles::_EK_FIRST;
|
||||||
|
ek < MethodHandles::_EK_LIMIT;
|
||||||
|
ek = MethodHandles::EntryKind(1 + (int)ek)) {
|
||||||
|
StubCodeMark mark(this, "MethodHandle", MethodHandles::entry_name(ek));
|
||||||
|
MethodHandles::generate_method_handle_stub(_masm, ek);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -92,6 +92,33 @@ address TemplateInterpreterGenerator::generate_ClassCastException_handler() {
|
|||||||
return entry;
|
return entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Arguments are: required type at TOS+8, failing object (or NULL) at TOS+4.
|
||||||
|
// pc at TOS (just for debugging)
|
||||||
|
address TemplateInterpreterGenerator::generate_WrongMethodType_handler() {
|
||||||
|
address entry = __ pc();
|
||||||
|
|
||||||
|
__ pop(rbx); // actual failing object is at TOS
|
||||||
|
__ pop(rax); // required type is at TOS+4
|
||||||
|
|
||||||
|
__ verify_oop(rbx);
|
||||||
|
__ verify_oop(rax);
|
||||||
|
|
||||||
|
// Various method handle types use interpreter registers as temps.
|
||||||
|
__ restore_bcp();
|
||||||
|
__ restore_locals();
|
||||||
|
|
||||||
|
// Expression stack must be empty before entering the VM for an exception.
|
||||||
|
__ empty_expression_stack();
|
||||||
|
__ empty_FPU_stack();
|
||||||
|
__ call_VM(noreg,
|
||||||
|
CAST_FROM_FN_PTR(address,
|
||||||
|
InterpreterRuntime::throw_WrongMethodTypeException),
|
||||||
|
// pass required type, failing object (or NULL)
|
||||||
|
rax, rbx);
|
||||||
|
return entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
address TemplateInterpreterGenerator::generate_exception_handler_common(const char* name, const char* message, bool pass_oop) {
|
address TemplateInterpreterGenerator::generate_exception_handler_common(const char* name, const char* message, bool pass_oop) {
|
||||||
assert(!pass_oop || message == NULL, "either oop or message but not both");
|
assert(!pass_oop || message == NULL, "either oop or message but not both");
|
||||||
address entry = __ pc();
|
address entry = __ pc();
|
||||||
@ -1370,6 +1397,7 @@ address AbstractInterpreterGenerator::generate_method_entry(AbstractInterpreter:
|
|||||||
case Interpreter::empty : entry_point = ((InterpreterGenerator*)this)->generate_empty_entry(); break;
|
case Interpreter::empty : entry_point = ((InterpreterGenerator*)this)->generate_empty_entry(); break;
|
||||||
case Interpreter::accessor : entry_point = ((InterpreterGenerator*)this)->generate_accessor_entry(); break;
|
case Interpreter::accessor : entry_point = ((InterpreterGenerator*)this)->generate_accessor_entry(); break;
|
||||||
case Interpreter::abstract : entry_point = ((InterpreterGenerator*)this)->generate_abstract_entry(); break;
|
case Interpreter::abstract : entry_point = ((InterpreterGenerator*)this)->generate_abstract_entry(); break;
|
||||||
|
case Interpreter::method_handle : entry_point = ((InterpreterGenerator*)this)->generate_method_handle_entry(); break;
|
||||||
|
|
||||||
case Interpreter::java_lang_math_sin : // fall thru
|
case Interpreter::java_lang_math_sin : // fall thru
|
||||||
case Interpreter::java_lang_math_cos : // fall thru
|
case Interpreter::java_lang_math_cos : // fall thru
|
||||||
@ -1400,7 +1428,8 @@ int AbstractInterpreter::size_top_interpreter_activation(methodOop method) {
|
|||||||
// be sure to change this if you add/subtract anything to/from the overhead area
|
// be sure to change this if you add/subtract anything to/from the overhead area
|
||||||
const int overhead_size = -frame::interpreter_frame_initial_sp_offset;
|
const int overhead_size = -frame::interpreter_frame_initial_sp_offset;
|
||||||
|
|
||||||
const int method_stack = (method->max_locals() + method->max_stack()) *
|
const int extra_stack = methodOopDesc::extra_stack_entries();
|
||||||
|
const int method_stack = (method->max_locals() + method->max_stack() + extra_stack) *
|
||||||
Interpreter::stackElementWords();
|
Interpreter::stackElementWords();
|
||||||
return overhead_size + method_stack + stub_code;
|
return overhead_size + method_stack + stub_code;
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved.
|
* Copyright 2003-2009 Sun Microsystems, Inc. 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
|
||||||
@ -100,6 +100,26 @@ address TemplateInterpreterGenerator::generate_ClassCastException_handler() {
|
|||||||
return entry;
|
return entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Arguments are: required type in rarg1, failing object (or NULL) in rarg2
|
||||||
|
address TemplateInterpreterGenerator::generate_WrongMethodType_handler() {
|
||||||
|
address entry = __ pc();
|
||||||
|
|
||||||
|
__ pop(c_rarg2); // failing object is at TOS
|
||||||
|
__ pop(c_rarg1); // required type is at TOS+8
|
||||||
|
|
||||||
|
// expression stack must be empty before entering the VM if an
|
||||||
|
// exception happened
|
||||||
|
__ empty_expression_stack();
|
||||||
|
|
||||||
|
__ call_VM(noreg,
|
||||||
|
CAST_FROM_FN_PTR(address,
|
||||||
|
InterpreterRuntime::
|
||||||
|
throw_WrongMethodTypeException),
|
||||||
|
// pass required type, failing object (or NULL)
|
||||||
|
c_rarg1, c_rarg2);
|
||||||
|
return entry;
|
||||||
|
}
|
||||||
|
|
||||||
address TemplateInterpreterGenerator::generate_exception_handler_common(
|
address TemplateInterpreterGenerator::generate_exception_handler_common(
|
||||||
const char* name, const char* message, bool pass_oop) {
|
const char* name, const char* message, bool pass_oop) {
|
||||||
assert(!pass_oop || message == NULL, "either oop or message but not both");
|
assert(!pass_oop || message == NULL, "either oop or message but not both");
|
||||||
@ -1393,12 +1413,14 @@ address AbstractInterpreterGenerator::generate_method_entry(
|
|||||||
case Interpreter::empty : entry_point = ((InterpreterGenerator*) this)->generate_empty_entry(); break;
|
case Interpreter::empty : entry_point = ((InterpreterGenerator*) this)->generate_empty_entry(); break;
|
||||||
case Interpreter::accessor : entry_point = ((InterpreterGenerator*) this)->generate_accessor_entry(); break;
|
case Interpreter::accessor : entry_point = ((InterpreterGenerator*) this)->generate_accessor_entry(); break;
|
||||||
case Interpreter::abstract : entry_point = ((InterpreterGenerator*) this)->generate_abstract_entry(); break;
|
case Interpreter::abstract : entry_point = ((InterpreterGenerator*) this)->generate_abstract_entry(); break;
|
||||||
case Interpreter::java_lang_math_sin : break;
|
case Interpreter::method_handle : entry_point = ((InterpreterGenerator*) this)->generate_method_handle_entry();break;
|
||||||
case Interpreter::java_lang_math_cos : break;
|
|
||||||
case Interpreter::java_lang_math_tan : break;
|
case Interpreter::java_lang_math_sin : // fall thru
|
||||||
case Interpreter::java_lang_math_abs : break;
|
case Interpreter::java_lang_math_cos : // fall thru
|
||||||
case Interpreter::java_lang_math_log : break;
|
case Interpreter::java_lang_math_tan : // fall thru
|
||||||
case Interpreter::java_lang_math_log10 : break;
|
case Interpreter::java_lang_math_abs : // fall thru
|
||||||
|
case Interpreter::java_lang_math_log : // fall thru
|
||||||
|
case Interpreter::java_lang_math_log10 : // fall thru
|
||||||
case Interpreter::java_lang_math_sqrt : entry_point = ((InterpreterGenerator*) this)->generate_math_entry(kind); break;
|
case Interpreter::java_lang_math_sqrt : entry_point = ((InterpreterGenerator*) this)->generate_math_entry(kind); break;
|
||||||
default : ShouldNotReachHere(); break;
|
default : ShouldNotReachHere(); break;
|
||||||
}
|
}
|
||||||
@ -1422,7 +1444,8 @@ int AbstractInterpreter::size_top_interpreter_activation(methodOop method) {
|
|||||||
-(frame::interpreter_frame_initial_sp_offset) + entry_size;
|
-(frame::interpreter_frame_initial_sp_offset) + entry_size;
|
||||||
|
|
||||||
const int stub_code = frame::entry_frame_after_call_words;
|
const int stub_code = frame::entry_frame_after_call_words;
|
||||||
const int method_stack = (method->max_locals() + method->max_stack()) *
|
const int extra_stack = methodOopDesc::extra_stack_entries();
|
||||||
|
const int method_stack = (method->max_locals() + method->max_stack() + extra_stack) *
|
||||||
Interpreter::stackElementWords();
|
Interpreter::stackElementWords();
|
||||||
return (overhead_size + method_stack + stub_code);
|
return (overhead_size + method_stack + stub_code);
|
||||||
}
|
}
|
||||||
|
@ -108,6 +108,9 @@ VtableStub* VtableStubs::create_vtable_stub(int vtable_index) {
|
|||||||
(int)(s->code_end() - __ pc()));
|
(int)(s->code_end() - __ pc()));
|
||||||
}
|
}
|
||||||
guarantee(__ pc() <= s->code_end(), "overflowed buffer");
|
guarantee(__ pc() <= s->code_end(), "overflowed buffer");
|
||||||
|
// shut the door on sizing bugs
|
||||||
|
int slop = 3; // 32-bit offset is this much larger than an 8-bit one
|
||||||
|
assert(vtable_index > 10 || __ pc() + slop <= s->code_end(), "room for 32-bit offset");
|
||||||
|
|
||||||
s->set_exception_points(npe_addr, ame_addr);
|
s->set_exception_points(npe_addr, ame_addr);
|
||||||
return s;
|
return s;
|
||||||
@ -181,6 +184,9 @@ VtableStub* VtableStubs::create_itable_stub(int itable_index) {
|
|||||||
(int)(s->code_end() - __ pc()));
|
(int)(s->code_end() - __ pc()));
|
||||||
}
|
}
|
||||||
guarantee(__ pc() <= s->code_end(), "overflowed buffer");
|
guarantee(__ pc() <= s->code_end(), "overflowed buffer");
|
||||||
|
// shut the door on sizing bugs
|
||||||
|
int slop = 3; // 32-bit offset is this much larger than an 8-bit one
|
||||||
|
assert(itable_index > 10 || __ pc() + slop <= s->code_end(), "room for 32-bit offset");
|
||||||
|
|
||||||
s->set_exception_points(npe_addr, ame_addr);
|
s->set_exception_points(npe_addr, ame_addr);
|
||||||
return s;
|
return s;
|
||||||
@ -196,6 +202,41 @@ int VtableStub::pd_code_size_limit(bool is_vtable_stub) {
|
|||||||
// Itable stub size
|
// Itable stub size
|
||||||
return (DebugVtables ? 256 : 66) + (CountCompiledCalls ? 6 : 0);
|
return (DebugVtables ? 256 : 66) + (CountCompiledCalls ? 6 : 0);
|
||||||
}
|
}
|
||||||
|
// In order to tune these parameters, run the JVM with VM options
|
||||||
|
// +PrintMiscellaneous and +WizardMode to see information about
|
||||||
|
// actual itable stubs. Look for lines like this:
|
||||||
|
// itable #1 at 0x5551212[65] left over: 3
|
||||||
|
// Reduce the constants so that the "left over" number is >=3
|
||||||
|
// for the common cases.
|
||||||
|
// Do not aim at a left-over number of zero, because a
|
||||||
|
// large vtable or itable index (> 16) will require a 32-bit
|
||||||
|
// immediate displacement instead of an 8-bit one.
|
||||||
|
//
|
||||||
|
// The JVM98 app. _202_jess has a megamorphic interface call.
|
||||||
|
// The itable code looks like this:
|
||||||
|
// Decoding VtableStub itbl[1]@1
|
||||||
|
// mov 0x4(%ecx),%esi
|
||||||
|
// mov 0xe8(%esi),%edi
|
||||||
|
// lea 0x130(%esi,%edi,4),%edi
|
||||||
|
// add $0x7,%edi
|
||||||
|
// and $0xfffffff8,%edi
|
||||||
|
// lea 0x4(%esi),%esi
|
||||||
|
// mov (%edi),%ebx
|
||||||
|
// cmp %ebx,%eax
|
||||||
|
// je success
|
||||||
|
// loop:
|
||||||
|
// test %ebx,%ebx
|
||||||
|
// je throw_icce
|
||||||
|
// add $0x8,%edi
|
||||||
|
// mov (%edi),%ebx
|
||||||
|
// cmp %ebx,%eax
|
||||||
|
// jne loop
|
||||||
|
// success:
|
||||||
|
// mov 0x4(%edi),%edi
|
||||||
|
// mov (%esi,%edi,1),%ebx
|
||||||
|
// jmp *0x44(%ebx)
|
||||||
|
// throw_icce:
|
||||||
|
// jmp throw_ICCE_entry
|
||||||
}
|
}
|
||||||
|
|
||||||
int VtableStub::pd_code_alignment() {
|
int VtableStub::pd_code_alignment() {
|
||||||
|
@ -106,6 +106,9 @@ VtableStub* VtableStubs::create_vtable_stub(int vtable_index) {
|
|||||||
(int)(s->code_end() - __ pc()));
|
(int)(s->code_end() - __ pc()));
|
||||||
}
|
}
|
||||||
guarantee(__ pc() <= s->code_end(), "overflowed buffer");
|
guarantee(__ pc() <= s->code_end(), "overflowed buffer");
|
||||||
|
// shut the door on sizing bugs
|
||||||
|
int slop = 3; // 32-bit offset is this much larger than an 8-bit one
|
||||||
|
assert(vtable_index > 10 || __ pc() + slop <= s->code_end(), "room for 32-bit offset");
|
||||||
|
|
||||||
s->set_exception_points(npe_addr, ame_addr);
|
s->set_exception_points(npe_addr, ame_addr);
|
||||||
return s;
|
return s;
|
||||||
@ -191,6 +194,9 @@ VtableStub* VtableStubs::create_itable_stub(int itable_index) {
|
|||||||
(int)(s->code_end() - __ pc()));
|
(int)(s->code_end() - __ pc()));
|
||||||
}
|
}
|
||||||
guarantee(__ pc() <= s->code_end(), "overflowed buffer");
|
guarantee(__ pc() <= s->code_end(), "overflowed buffer");
|
||||||
|
// shut the door on sizing bugs
|
||||||
|
int slop = 3; // 32-bit offset is this much larger than an 8-bit one
|
||||||
|
assert(itable_index > 10 || __ pc() + slop <= s->code_end(), "room for 32-bit offset");
|
||||||
|
|
||||||
s->set_exception_points(npe_addr, ame_addr);
|
s->set_exception_points(npe_addr, ame_addr);
|
||||||
return s;
|
return s;
|
||||||
@ -206,6 +212,39 @@ int VtableStub::pd_code_size_limit(bool is_vtable_stub) {
|
|||||||
return (DebugVtables ? 512 : 72) + (CountCompiledCalls ? 13 : 0) +
|
return (DebugVtables ? 512 : 72) + (CountCompiledCalls ? 13 : 0) +
|
||||||
(UseCompressedOops ? 32 : 0); // 2 leaqs
|
(UseCompressedOops ? 32 : 0); // 2 leaqs
|
||||||
}
|
}
|
||||||
|
// In order to tune these parameters, run the JVM with VM options
|
||||||
|
// +PrintMiscellaneous and +WizardMode to see information about
|
||||||
|
// actual itable stubs. Look for lines like this:
|
||||||
|
// itable #1 at 0x5551212[71] left over: 3
|
||||||
|
// Reduce the constants so that the "left over" number is >=3
|
||||||
|
// for the common cases.
|
||||||
|
// Do not aim at a left-over number of zero, because a
|
||||||
|
// large vtable or itable index (>= 32) will require a 32-bit
|
||||||
|
// immediate displacement instead of an 8-bit one.
|
||||||
|
//
|
||||||
|
// The JVM98 app. _202_jess has a megamorphic interface call.
|
||||||
|
// The itable code looks like this:
|
||||||
|
// Decoding VtableStub itbl[1]@12
|
||||||
|
// mov 0x8(%rsi),%r10
|
||||||
|
// mov 0x198(%r10),%r11d
|
||||||
|
// lea 0x218(%r10,%r11,8),%r11
|
||||||
|
// lea 0x8(%r10),%r10
|
||||||
|
// mov (%r11),%rbx
|
||||||
|
// cmp %rbx,%rax
|
||||||
|
// je success
|
||||||
|
// loop:
|
||||||
|
// test %rbx,%rbx
|
||||||
|
// je throw_icce
|
||||||
|
// add $0x10,%r11
|
||||||
|
// mov (%r11),%rbx
|
||||||
|
// cmp %rbx,%rax
|
||||||
|
// jne loop
|
||||||
|
// success:
|
||||||
|
// mov 0x8(%r11),%r11d
|
||||||
|
// mov (%r10,%r11,1),%rbx
|
||||||
|
// jmpq *0x60(%rbx)
|
||||||
|
// throw_icce:
|
||||||
|
// jmpq throw_ICCE_entry
|
||||||
}
|
}
|
||||||
|
|
||||||
int VtableStub::pd_code_alignment() {
|
int VtableStub::pd_code_alignment() {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 1999-2008 Sun Microsystems, Inc. All Rights Reserved.
|
* Copyright 1999-2009 Sun Microsystems, Inc. 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
|
||||||
@ -674,6 +674,30 @@ int ciMethod::scale_count(int count, float prof_factor) {
|
|||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------
|
||||||
|
// invokedynamic support
|
||||||
|
//
|
||||||
|
bool ciMethod::is_method_handle_invoke() {
|
||||||
|
check_is_loaded();
|
||||||
|
bool flag = ((flags().as_int() & JVM_MH_INVOKE_BITS) == JVM_MH_INVOKE_BITS);
|
||||||
|
#ifdef ASSERT
|
||||||
|
{
|
||||||
|
VM_ENTRY_MARK;
|
||||||
|
bool flag2 = get_methodOop()->is_method_handle_invoke();
|
||||||
|
assert(flag == flag2, "consistent");
|
||||||
|
}
|
||||||
|
#endif //ASSERT
|
||||||
|
return flag;
|
||||||
|
}
|
||||||
|
|
||||||
|
ciInstance* ciMethod::method_handle_type() {
|
||||||
|
check_is_loaded();
|
||||||
|
VM_ENTRY_MARK;
|
||||||
|
oop mtype = get_methodOop()->method_handle_type();
|
||||||
|
return CURRENT_THREAD_ENV->get_object(mtype)->as_instance();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------
|
// ------------------------------------------------------------------
|
||||||
// ciMethod::build_method_data
|
// ciMethod::build_method_data
|
||||||
//
|
//
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 1999-2007 Sun Microsystems, Inc. All Rights Reserved.
|
* Copyright 1999-2009 Sun Microsystems, Inc. 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
|
||||||
@ -207,6 +207,8 @@ class ciMethod : public ciObject {
|
|||||||
bool check_call(int refinfo_index, bool is_static) const;
|
bool check_call(int refinfo_index, bool is_static) const;
|
||||||
void build_method_data(); // make sure it exists in the VM also
|
void build_method_data(); // make sure it exists in the VM also
|
||||||
int scale_count(int count, float prof_factor = 1.); // make MDO count commensurate with IIC
|
int scale_count(int count, float prof_factor = 1.); // make MDO count commensurate with IIC
|
||||||
|
bool is_method_handle_invoke();
|
||||||
|
ciInstance* method_handle_type();
|
||||||
|
|
||||||
// What kind of ciObject is this?
|
// What kind of ciObject is this?
|
||||||
bool is_method() { return true; }
|
bool is_method() { return true; }
|
||||||
|
@ -1842,6 +1842,11 @@ methodHandle ClassFileParser::parse_method(constantPoolHandle cp, bool is_interf
|
|||||||
_has_vanilla_constructor = true;
|
_has_vanilla_constructor = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (EnableMethodHandles && m->is_method_handle_invoke()) {
|
||||||
|
THROW_MSG_(vmSymbols::java_lang_VirtualMachineError(),
|
||||||
|
"Method handle invokers must be defined internally to the VM", nullHandle);
|
||||||
|
}
|
||||||
|
|
||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2465,9 +2470,84 @@ void ClassFileParser::java_lang_Class_fix_post(int* next_nonstatic_oop_offset_pt
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Force MethodHandle.vmentry to be an unmanaged pointer.
|
||||||
|
// There is no way for a classfile to express this, so we must help it.
|
||||||
|
void ClassFileParser::java_dyn_MethodHandle_fix_pre(constantPoolHandle cp,
|
||||||
|
typeArrayHandle* fields_ptr,
|
||||||
|
FieldAllocationCount *fac_ptr,
|
||||||
|
TRAPS) {
|
||||||
|
// Add fake fields for java.dyn.MethodHandle instances
|
||||||
|
//
|
||||||
|
// This is not particularly nice, but since there is no way to express
|
||||||
|
// a native wordSize field in Java, we must do it at this level.
|
||||||
|
|
||||||
|
if (!EnableMethodHandles) return;
|
||||||
|
|
||||||
|
int word_sig_index = 0;
|
||||||
|
const int cp_size = cp->length();
|
||||||
|
for (int index = 1; index < cp_size; index++) {
|
||||||
|
if (cp->tag_at(index).is_utf8() &&
|
||||||
|
cp->symbol_at(index) == vmSymbols::machine_word_signature()) {
|
||||||
|
word_sig_index = index;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (word_sig_index == 0)
|
||||||
|
THROW_MSG(vmSymbols::java_lang_VirtualMachineError(),
|
||||||
|
"missing I or J signature (for vmentry) in java.dyn.MethodHandle");
|
||||||
|
|
||||||
|
bool found_vmentry = false;
|
||||||
|
|
||||||
|
const int n = (*fields_ptr)()->length();
|
||||||
|
for (int i = 0; i < n; i += instanceKlass::next_offset) {
|
||||||
|
int name_index = (*fields_ptr)->ushort_at(i + instanceKlass::name_index_offset);
|
||||||
|
int sig_index = (*fields_ptr)->ushort_at(i + instanceKlass::signature_index_offset);
|
||||||
|
int acc_flags = (*fields_ptr)->ushort_at(i + instanceKlass::access_flags_offset);
|
||||||
|
symbolOop f_name = cp->symbol_at(name_index);
|
||||||
|
symbolOop f_sig = cp->symbol_at(sig_index);
|
||||||
|
if (f_sig == vmSymbols::byte_signature() &&
|
||||||
|
f_name == vmSymbols::vmentry_name() &&
|
||||||
|
(acc_flags & JVM_ACC_STATIC) == 0) {
|
||||||
|
// Adjust the field type from byte to an unmanaged pointer.
|
||||||
|
assert(fac_ptr->nonstatic_byte_count > 0, "");
|
||||||
|
fac_ptr->nonstatic_byte_count -= 1;
|
||||||
|
(*fields_ptr)->ushort_at_put(i + instanceKlass::signature_index_offset,
|
||||||
|
word_sig_index);
|
||||||
|
if (wordSize == jintSize) {
|
||||||
|
fac_ptr->nonstatic_word_count += 1;
|
||||||
|
} else {
|
||||||
|
fac_ptr->nonstatic_double_count += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
FieldAllocationType atype = (FieldAllocationType) (*fields_ptr)->ushort_at(i+4);
|
||||||
|
assert(atype == NONSTATIC_BYTE, "");
|
||||||
|
FieldAllocationType new_atype = NONSTATIC_WORD;
|
||||||
|
if (wordSize > jintSize) {
|
||||||
|
if (Universe::field_type_should_be_aligned(T_LONG)) {
|
||||||
|
atype = NONSTATIC_ALIGNED_DOUBLE;
|
||||||
|
} else {
|
||||||
|
atype = NONSTATIC_DOUBLE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(*fields_ptr)->ushort_at_put(i+4, new_atype);
|
||||||
|
|
||||||
|
found_vmentry = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!found_vmentry)
|
||||||
|
THROW_MSG(vmSymbols::java_lang_VirtualMachineError(),
|
||||||
|
"missing vmentry byte field in java.dyn.MethodHandle");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
instanceKlassHandle ClassFileParser::parseClassFile(symbolHandle name,
|
instanceKlassHandle ClassFileParser::parseClassFile(symbolHandle name,
|
||||||
Handle class_loader,
|
Handle class_loader,
|
||||||
Handle protection_domain,
|
Handle protection_domain,
|
||||||
|
KlassHandle host_klass,
|
||||||
GrowableArray<Handle>* cp_patches,
|
GrowableArray<Handle>* cp_patches,
|
||||||
symbolHandle& parsed_name,
|
symbolHandle& parsed_name,
|
||||||
TRAPS) {
|
TRAPS) {
|
||||||
@ -2500,6 +2580,7 @@ instanceKlassHandle ClassFileParser::parseClassFile(symbolHandle name,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_host_klass = host_klass;
|
||||||
_cp_patches = cp_patches;
|
_cp_patches = cp_patches;
|
||||||
|
|
||||||
instanceKlassHandle nullHandle;
|
instanceKlassHandle nullHandle;
|
||||||
@ -2808,6 +2889,11 @@ instanceKlassHandle ClassFileParser::parseClassFile(symbolHandle name,
|
|||||||
java_lang_Class_fix_pre(&methods, &fac, CHECK_(nullHandle));
|
java_lang_Class_fix_pre(&methods, &fac, CHECK_(nullHandle));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// adjust the vmentry field declaration in java.dyn.MethodHandle
|
||||||
|
if (EnableMethodHandles && class_name() == vmSymbols::sun_dyn_MethodHandleImpl() && class_loader.is_null()) {
|
||||||
|
java_dyn_MethodHandle_fix_pre(cp, &fields, &fac, CHECK_(nullHandle));
|
||||||
|
}
|
||||||
|
|
||||||
// Add a fake "discovered" field if it is not present
|
// Add a fake "discovered" field if it is not present
|
||||||
// for compatibility with earlier jdk's.
|
// for compatibility with earlier jdk's.
|
||||||
if (class_name() == vmSymbols::java_lang_ref_Reference()
|
if (class_name() == vmSymbols::java_lang_ref_Reference()
|
||||||
@ -3134,7 +3220,7 @@ instanceKlassHandle ClassFileParser::parseClassFile(symbolHandle name,
|
|||||||
this_klass->set_method_ordering(method_ordering());
|
this_klass->set_method_ordering(method_ordering());
|
||||||
this_klass->set_initial_method_idnum(methods->length());
|
this_klass->set_initial_method_idnum(methods->length());
|
||||||
this_klass->set_name(cp->klass_name_at(this_class_index));
|
this_klass->set_name(cp->klass_name_at(this_class_index));
|
||||||
if (LinkWellKnownClasses) // I am well known to myself
|
if (LinkWellKnownClasses || is_anonymous()) // I am well known to myself
|
||||||
cp->klass_at_put(this_class_index, this_klass()); // eagerly resolve
|
cp->klass_at_put(this_class_index, this_klass()); // eagerly resolve
|
||||||
this_klass->set_protection_domain(protection_domain());
|
this_klass->set_protection_domain(protection_domain());
|
||||||
this_klass->set_fields_annotations(fields_annotations());
|
this_klass->set_fields_annotations(fields_annotations());
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved.
|
* Copyright 1997-2009 Sun Microsystems, Inc. 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
|
||||||
@ -33,6 +33,7 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC {
|
|||||||
u2 _major_version;
|
u2 _major_version;
|
||||||
u2 _minor_version;
|
u2 _minor_version;
|
||||||
symbolHandle _class_name;
|
symbolHandle _class_name;
|
||||||
|
KlassHandle _host_klass;
|
||||||
GrowableArray<Handle>* _cp_patches; // overrides for CP entries
|
GrowableArray<Handle>* _cp_patches; // overrides for CP entries
|
||||||
|
|
||||||
bool _has_finalizer;
|
bool _has_finalizer;
|
||||||
@ -145,6 +146,11 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC {
|
|||||||
// Adjust the next_nonstatic_oop_offset to place the fake fields
|
// Adjust the next_nonstatic_oop_offset to place the fake fields
|
||||||
// before any Java fields.
|
// before any Java fields.
|
||||||
void java_lang_Class_fix_post(int* next_nonstatic_oop_offset);
|
void java_lang_Class_fix_post(int* next_nonstatic_oop_offset);
|
||||||
|
// Adjust the field allocation counts for java.dyn.MethodHandle to add
|
||||||
|
// a fake address (void*) field.
|
||||||
|
void java_dyn_MethodHandle_fix_pre(constantPoolHandle cp,
|
||||||
|
typeArrayHandle* fields_ptr,
|
||||||
|
FieldAllocationCount *fac_ptr, TRAPS);
|
||||||
|
|
||||||
// Format checker methods
|
// Format checker methods
|
||||||
void classfile_parse_error(const char* msg, TRAPS);
|
void classfile_parse_error(const char* msg, TRAPS);
|
||||||
@ -204,6 +210,10 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC {
|
|||||||
char* skip_over_field_name(char* name, bool slash_ok, unsigned int length);
|
char* skip_over_field_name(char* name, bool slash_ok, unsigned int length);
|
||||||
char* skip_over_field_signature(char* signature, bool void_ok, unsigned int length, TRAPS);
|
char* skip_over_field_signature(char* signature, bool void_ok, unsigned int length, TRAPS);
|
||||||
|
|
||||||
|
bool is_anonymous() {
|
||||||
|
assert(AnonymousClasses || _host_klass.is_null(), "");
|
||||||
|
return _host_klass.not_null();
|
||||||
|
}
|
||||||
bool has_cp_patch_at(int index) {
|
bool has_cp_patch_at(int index) {
|
||||||
assert(AnonymousClasses, "");
|
assert(AnonymousClasses, "");
|
||||||
assert(index >= 0, "oob");
|
assert(index >= 0, "oob");
|
||||||
@ -249,11 +259,13 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC {
|
|||||||
Handle protection_domain,
|
Handle protection_domain,
|
||||||
symbolHandle& parsed_name,
|
symbolHandle& parsed_name,
|
||||||
TRAPS) {
|
TRAPS) {
|
||||||
return parseClassFile(name, class_loader, protection_domain, NULL, parsed_name, THREAD);
|
KlassHandle no_host_klass;
|
||||||
|
return parseClassFile(name, class_loader, protection_domain, no_host_klass, NULL, parsed_name, THREAD);
|
||||||
}
|
}
|
||||||
instanceKlassHandle parseClassFile(symbolHandle name,
|
instanceKlassHandle parseClassFile(symbolHandle name,
|
||||||
Handle class_loader,
|
Handle class_loader,
|
||||||
Handle protection_domain,
|
Handle protection_domain,
|
||||||
|
KlassHandle host_klass,
|
||||||
GrowableArray<Handle>* cp_patches,
|
GrowableArray<Handle>* cp_patches,
|
||||||
symbolHandle& parsed_name,
|
symbolHandle& parsed_name,
|
||||||
TRAPS);
|
TRAPS);
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved.
|
* Copyright 2003-2009 Sun Microsystems, Inc. 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
|
||||||
@ -549,6 +549,63 @@ void Dictionary::reorder_dictionary() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SymbolPropertyTable::SymbolPropertyTable(int table_size)
|
||||||
|
: Hashtable(table_size, sizeof(SymbolPropertyEntry))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
SymbolPropertyTable::SymbolPropertyTable(int table_size, HashtableBucket* t,
|
||||||
|
int number_of_entries)
|
||||||
|
: Hashtable(table_size, sizeof(SymbolPropertyEntry), t, number_of_entries)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SymbolPropertyEntry* SymbolPropertyTable::find_entry(int index, unsigned int hash,
|
||||||
|
symbolHandle sym) {
|
||||||
|
assert(index == index_for(sym), "incorrect index?");
|
||||||
|
for (SymbolPropertyEntry* p = bucket(index); p != NULL; p = p->next()) {
|
||||||
|
if (p->hash() == hash && p->symbol() == sym()) {
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SymbolPropertyEntry* SymbolPropertyTable::add_entry(int index, unsigned int hash,
|
||||||
|
symbolHandle sym) {
|
||||||
|
assert_locked_or_safepoint(SystemDictionary_lock);
|
||||||
|
assert(index == index_for(sym), "incorrect index?");
|
||||||
|
assert(find_entry(index, hash, sym) == NULL, "no double entry");
|
||||||
|
|
||||||
|
SymbolPropertyEntry* p = new_entry(hash, sym());
|
||||||
|
Hashtable::add_entry(index, p);
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SymbolPropertyTable::oops_do(OopClosure* f) {
|
||||||
|
for (int index = 0; index < table_size(); index++) {
|
||||||
|
for (SymbolPropertyEntry* p = bucket(index); p != NULL; p = p->next()) {
|
||||||
|
f->do_oop((oop*) p->symbol_addr());
|
||||||
|
if (p->property_oop() != NULL) {
|
||||||
|
f->do_oop(p->property_oop_addr());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SymbolPropertyTable::methods_do(void f(methodOop)) {
|
||||||
|
for (int index = 0; index < table_size(); index++) {
|
||||||
|
for (SymbolPropertyEntry* p = bucket(index); p != NULL; p = p->next()) {
|
||||||
|
oop prop = p->property_oop();
|
||||||
|
if (prop != NULL && prop->is_method()) {
|
||||||
|
f((methodOop)prop);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
#ifndef PRODUCT
|
#ifndef PRODUCT
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2003-2006 Sun Microsystems, Inc. All Rights Reserved.
|
* Copyright 2003-2009 Sun Microsystems, Inc. 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
|
||||||
@ -217,3 +217,112 @@ class DictionaryEntry : public HashtableEntry {
|
|||||||
tty->print_cr("pd set = #%d", count);
|
tty->print_cr("pd set = #%d", count);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Entry in a SymbolPropertyTable, mapping a single symbolOop
|
||||||
|
// to a managed and an unmanaged pointer.
|
||||||
|
class SymbolPropertyEntry : public HashtableEntry {
|
||||||
|
friend class VMStructs;
|
||||||
|
private:
|
||||||
|
oop _property_oop;
|
||||||
|
address _property_data;
|
||||||
|
|
||||||
|
public:
|
||||||
|
symbolOop symbol() const { return (symbolOop) literal(); }
|
||||||
|
|
||||||
|
oop property_oop() const { return _property_oop; }
|
||||||
|
void set_property_oop(oop p) { _property_oop = p; }
|
||||||
|
|
||||||
|
address property_data() const { return _property_data; }
|
||||||
|
void set_property_data(address p) { _property_data = p; }
|
||||||
|
|
||||||
|
SymbolPropertyEntry* next() const {
|
||||||
|
return (SymbolPropertyEntry*)HashtableEntry::next();
|
||||||
|
}
|
||||||
|
|
||||||
|
SymbolPropertyEntry** next_addr() {
|
||||||
|
return (SymbolPropertyEntry**)HashtableEntry::next_addr();
|
||||||
|
}
|
||||||
|
|
||||||
|
oop* symbol_addr() { return literal_addr(); }
|
||||||
|
oop* property_oop_addr() { return &_property_oop; }
|
||||||
|
|
||||||
|
void print_on(outputStream* st) const {
|
||||||
|
symbol()->print_value_on(st);
|
||||||
|
st->print(" -> ");
|
||||||
|
bool printed = false;
|
||||||
|
if (property_oop() != NULL) {
|
||||||
|
property_oop()->print_value_on(st);
|
||||||
|
printed = true;
|
||||||
|
}
|
||||||
|
if (property_data() != NULL) {
|
||||||
|
if (printed) st->print(" and ");
|
||||||
|
st->print(INTPTR_FORMAT, property_data());
|
||||||
|
printed = true;
|
||||||
|
}
|
||||||
|
st->print_cr(printed ? "" : "(empty)");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// A system-internal mapping of symbols to pointers, both managed
|
||||||
|
// and unmanaged. Used to record the auto-generation of each method
|
||||||
|
// MethodHandle.invoke(S)T, for all signatures (S)T.
|
||||||
|
class SymbolPropertyTable : public Hashtable {
|
||||||
|
friend class VMStructs;
|
||||||
|
private:
|
||||||
|
SymbolPropertyEntry* bucket(int i) {
|
||||||
|
return (SymbolPropertyEntry*) Hashtable::bucket(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
// The following method is not MT-safe and must be done under lock.
|
||||||
|
SymbolPropertyEntry** bucket_addr(int i) {
|
||||||
|
return (SymbolPropertyEntry**) Hashtable::bucket_addr(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
void add_entry(int index, SymbolPropertyEntry* new_entry) {
|
||||||
|
ShouldNotReachHere();
|
||||||
|
}
|
||||||
|
void set_entry(int index, SymbolPropertyEntry* new_entry) {
|
||||||
|
ShouldNotReachHere();
|
||||||
|
}
|
||||||
|
|
||||||
|
SymbolPropertyEntry* new_entry(unsigned int hash, symbolOop symbol) {
|
||||||
|
SymbolPropertyEntry* entry = (SymbolPropertyEntry*) Hashtable::new_entry(hash, symbol);
|
||||||
|
entry->set_property_oop(NULL);
|
||||||
|
entry->set_property_data(NULL);
|
||||||
|
return entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
SymbolPropertyTable(int table_size);
|
||||||
|
SymbolPropertyTable(int table_size, HashtableBucket* t, int number_of_entries);
|
||||||
|
|
||||||
|
void free_entry(SymbolPropertyEntry* entry) {
|
||||||
|
Hashtable::free_entry(entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int compute_hash(symbolHandle sym) {
|
||||||
|
// Use the regular identity_hash.
|
||||||
|
return Hashtable::compute_hash(sym);
|
||||||
|
}
|
||||||
|
|
||||||
|
// need not be locked; no state change
|
||||||
|
SymbolPropertyEntry* find_entry(int index, unsigned int hash, symbolHandle name);
|
||||||
|
|
||||||
|
// must be done under SystemDictionary_lock
|
||||||
|
SymbolPropertyEntry* add_entry(int index, unsigned int hash, symbolHandle name);
|
||||||
|
|
||||||
|
// GC support
|
||||||
|
void oops_do(OopClosure* f);
|
||||||
|
void methods_do(void f(methodOop));
|
||||||
|
|
||||||
|
// Sharing support
|
||||||
|
void dump(SerializeOopClosure* soc);
|
||||||
|
void restore(SerializeOopClosure* soc);
|
||||||
|
void reorder_dictionary();
|
||||||
|
|
||||||
|
#ifndef PRODUCT
|
||||||
|
void print();
|
||||||
|
#endif
|
||||||
|
void verify();
|
||||||
|
};
|
||||||
|
|
||||||
|
@ -25,13 +25,24 @@
|
|||||||
# include "incls/_precompiled.incl"
|
# include "incls/_precompiled.incl"
|
||||||
# include "incls/_javaClasses.cpp.incl"
|
# include "incls/_javaClasses.cpp.incl"
|
||||||
|
|
||||||
|
static bool find_field(instanceKlass* ik,
|
||||||
|
symbolOop name_symbol, symbolOop signature_symbol,
|
||||||
|
fieldDescriptor* fd,
|
||||||
|
bool allow_super = false) {
|
||||||
|
if (allow_super)
|
||||||
|
return ik->find_field(name_symbol, signature_symbol, fd) != NULL;
|
||||||
|
else
|
||||||
|
return ik->find_local_field(name_symbol, signature_symbol, fd);
|
||||||
|
}
|
||||||
|
|
||||||
// Helpful routine for computing field offsets at run time rather than hardcoding them
|
// Helpful routine for computing field offsets at run time rather than hardcoding them
|
||||||
static void
|
static void
|
||||||
compute_offset(int &dest_offset,
|
compute_offset(int &dest_offset,
|
||||||
klassOop klass_oop, symbolOop name_symbol, symbolOop signature_symbol) {
|
klassOop klass_oop, symbolOop name_symbol, symbolOop signature_symbol,
|
||||||
|
bool allow_super = false) {
|
||||||
fieldDescriptor fd;
|
fieldDescriptor fd;
|
||||||
instanceKlass* ik = instanceKlass::cast(klass_oop);
|
instanceKlass* ik = instanceKlass::cast(klass_oop);
|
||||||
if (!ik->find_local_field(name_symbol, signature_symbol, &fd)) {
|
if (!find_field(ik, name_symbol, signature_symbol, &fd, allow_super)) {
|
||||||
ResourceMark rm;
|
ResourceMark rm;
|
||||||
tty->print_cr("Invalid layout of %s at %s", ik->external_name(), name_symbol->as_C_string());
|
tty->print_cr("Invalid layout of %s at %s", ik->external_name(), name_symbol->as_C_string());
|
||||||
fatal("Invalid layout of preloaded class");
|
fatal("Invalid layout of preloaded class");
|
||||||
@ -42,14 +53,16 @@ compute_offset(int &dest_offset,
|
|||||||
// Same as above but for "optional" offsets that might not be present in certain JDK versions
|
// Same as above but for "optional" offsets that might not be present in certain JDK versions
|
||||||
static void
|
static void
|
||||||
compute_optional_offset(int& dest_offset,
|
compute_optional_offset(int& dest_offset,
|
||||||
klassOop klass_oop, symbolOop name_symbol, symbolOop signature_symbol) {
|
klassOop klass_oop, symbolOop name_symbol, symbolOop signature_symbol,
|
||||||
|
bool allow_super = false) {
|
||||||
fieldDescriptor fd;
|
fieldDescriptor fd;
|
||||||
instanceKlass* ik = instanceKlass::cast(klass_oop);
|
instanceKlass* ik = instanceKlass::cast(klass_oop);
|
||||||
if (ik->find_local_field(name_symbol, signature_symbol, &fd)) {
|
if (find_field(ik, name_symbol, signature_symbol, &fd, allow_super)) {
|
||||||
dest_offset = fd.offset();
|
dest_offset = fd.offset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Handle java_lang_String::basic_create(int length, bool tenured, TRAPS) {
|
Handle java_lang_String::basic_create(int length, bool tenured, TRAPS) {
|
||||||
// Create the String object first, so there's a chance that the String
|
// Create the String object first, so there's a chance that the String
|
||||||
// and the char array it points to end up in the same cache line.
|
// and the char array it points to end up in the same cache line.
|
||||||
@ -2107,13 +2120,324 @@ void java_lang_ref_SoftReference::set_clock(jlong value) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Support for java_dyn_MethodHandle
|
||||||
|
|
||||||
|
int java_dyn_MethodHandle::_type_offset;
|
||||||
|
int java_dyn_MethodHandle::_vmtarget_offset;
|
||||||
|
int java_dyn_MethodHandle::_vmentry_offset;
|
||||||
|
int java_dyn_MethodHandle::_vmslots_offset;
|
||||||
|
|
||||||
|
int sun_dyn_MemberName::_clazz_offset;
|
||||||
|
int sun_dyn_MemberName::_name_offset;
|
||||||
|
int sun_dyn_MemberName::_type_offset;
|
||||||
|
int sun_dyn_MemberName::_flags_offset;
|
||||||
|
int sun_dyn_MemberName::_vmtarget_offset;
|
||||||
|
int sun_dyn_MemberName::_vmindex_offset;
|
||||||
|
|
||||||
|
int sun_dyn_DirectMethodHandle::_vmindex_offset;
|
||||||
|
|
||||||
|
int sun_dyn_BoundMethodHandle::_argument_offset;
|
||||||
|
int sun_dyn_BoundMethodHandle::_vmargslot_offset;
|
||||||
|
|
||||||
|
int sun_dyn_AdapterMethodHandle::_conversion_offset;
|
||||||
|
|
||||||
|
void java_dyn_MethodHandle::compute_offsets() {
|
||||||
|
klassOop k = SystemDictionary::MethodHandle_klass();
|
||||||
|
if (k != NULL && EnableMethodHandles) {
|
||||||
|
compute_offset(_type_offset, k, vmSymbols::type_name(), vmSymbols::java_dyn_MethodType_signature(), true);
|
||||||
|
compute_offset(_vmtarget_offset, k, vmSymbols::vmtarget_name(), vmSymbols::object_signature(), true);
|
||||||
|
compute_offset(_vmentry_offset, k, vmSymbols::vmentry_name(), vmSymbols::machine_word_signature(), true);
|
||||||
|
|
||||||
|
// Note: MH.vmslots (if it is present) is a hoisted copy of MH.type.form.vmslots.
|
||||||
|
// It is optional pending experiments to keep or toss.
|
||||||
|
compute_optional_offset(_vmslots_offset, k, vmSymbols::vmslots_name(), vmSymbols::int_signature(), true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void sun_dyn_MemberName::compute_offsets() {
|
||||||
|
klassOop k = SystemDictionary::MemberName_klass();
|
||||||
|
if (k != NULL && EnableMethodHandles) {
|
||||||
|
compute_offset(_clazz_offset, k, vmSymbols::clazz_name(), vmSymbols::class_signature());
|
||||||
|
compute_offset(_name_offset, k, vmSymbols::name_name(), vmSymbols::string_signature());
|
||||||
|
compute_offset(_type_offset, k, vmSymbols::type_name(), vmSymbols::object_signature());
|
||||||
|
compute_offset(_flags_offset, k, vmSymbols::flags_name(), vmSymbols::int_signature());
|
||||||
|
compute_offset(_vmtarget_offset, k, vmSymbols::vmtarget_name(), vmSymbols::object_signature());
|
||||||
|
compute_offset(_vmindex_offset, k, vmSymbols::vmindex_name(), vmSymbols::int_signature());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void sun_dyn_DirectMethodHandle::compute_offsets() {
|
||||||
|
klassOop k = SystemDictionary::DirectMethodHandle_klass();
|
||||||
|
if (k != NULL && EnableMethodHandles) {
|
||||||
|
compute_offset(_vmindex_offset, k, vmSymbols::vmindex_name(), vmSymbols::int_signature(), true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void sun_dyn_BoundMethodHandle::compute_offsets() {
|
||||||
|
klassOop k = SystemDictionary::BoundMethodHandle_klass();
|
||||||
|
if (k != NULL && EnableMethodHandles) {
|
||||||
|
compute_offset(_vmargslot_offset, k, vmSymbols::vmargslot_name(), vmSymbols::int_signature(), true);
|
||||||
|
compute_offset(_argument_offset, k, vmSymbols::argument_name(), vmSymbols::object_signature(), true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void sun_dyn_AdapterMethodHandle::compute_offsets() {
|
||||||
|
klassOop k = SystemDictionary::AdapterMethodHandle_klass();
|
||||||
|
if (k != NULL && EnableMethodHandles) {
|
||||||
|
compute_offset(_conversion_offset, k, vmSymbols::conversion_name(), vmSymbols::int_signature(), true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
oop java_dyn_MethodHandle::type(oop mh) {
|
||||||
|
return mh->obj_field(_type_offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
void java_dyn_MethodHandle::set_type(oop mh, oop mtype) {
|
||||||
|
mh->obj_field_put(_type_offset, mtype);
|
||||||
|
}
|
||||||
|
|
||||||
|
int java_dyn_MethodHandle::vmslots(oop mh) {
|
||||||
|
int vmslots_offset = _vmslots_offset;
|
||||||
|
if (vmslots_offset != 0) {
|
||||||
|
#ifdef ASSERT
|
||||||
|
int x = mh->int_field(vmslots_offset);
|
||||||
|
int y = compute_vmslots(mh);
|
||||||
|
assert(x == y, "correct hoisted value");
|
||||||
|
#endif
|
||||||
|
return mh->int_field(vmslots_offset);
|
||||||
|
} else {
|
||||||
|
return compute_vmslots(mh);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if MH.vmslots exists, hoist into it the value of type.form.vmslots
|
||||||
|
void java_dyn_MethodHandle::init_vmslots(oop mh) {
|
||||||
|
int vmslots_offset = _vmslots_offset;
|
||||||
|
if (vmslots_offset != 0) {
|
||||||
|
mh->int_field_put(vmslots_offset, compute_vmslots(mh));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// fetch type.form.vmslots, which is the number of JVM stack slots
|
||||||
|
// required to carry the arguments of this MH
|
||||||
|
int java_dyn_MethodHandle::compute_vmslots(oop mh) {
|
||||||
|
oop mtype = type(mh);
|
||||||
|
if (mtype == NULL) return 0; // Java code would get NPE
|
||||||
|
oop form = java_dyn_MethodType::form(mtype);
|
||||||
|
if (form == NULL) return 0; // Java code would get NPE
|
||||||
|
return java_dyn_MethodTypeForm::vmslots(form);
|
||||||
|
}
|
||||||
|
|
||||||
|
// fetch the low-level entry point for this mh
|
||||||
|
MethodHandleEntry* java_dyn_MethodHandle::vmentry(oop mh) {
|
||||||
|
return (MethodHandleEntry*) mh->address_field(_vmentry_offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
void java_dyn_MethodHandle::set_vmentry(oop mh, MethodHandleEntry* me) {
|
||||||
|
assert(_vmentry_offset != 0, "must be present");
|
||||||
|
|
||||||
|
// This is always the final step that initializes a valid method handle:
|
||||||
|
mh->release_address_field_put(_vmentry_offset, (address) me);
|
||||||
|
|
||||||
|
// There should be enough memory barriers on exit from native methods
|
||||||
|
// to ensure that the MH is fully initialized to all threads before
|
||||||
|
// Java code can publish it in global data structures.
|
||||||
|
// But just in case, we use release_address_field_put.
|
||||||
|
}
|
||||||
|
|
||||||
|
/// MemberName accessors
|
||||||
|
|
||||||
|
oop sun_dyn_MemberName::clazz(oop mname) {
|
||||||
|
assert(is_instance(mname), "wrong type");
|
||||||
|
return mname->obj_field(_clazz_offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
void sun_dyn_MemberName::set_clazz(oop mname, oop clazz) {
|
||||||
|
assert(is_instance(mname), "wrong type");
|
||||||
|
mname->obj_field_put(_clazz_offset, clazz);
|
||||||
|
}
|
||||||
|
|
||||||
|
oop sun_dyn_MemberName::name(oop mname) {
|
||||||
|
assert(is_instance(mname), "wrong type");
|
||||||
|
return mname->obj_field(_name_offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
void sun_dyn_MemberName::set_name(oop mname, oop name) {
|
||||||
|
assert(is_instance(mname), "wrong type");
|
||||||
|
mname->obj_field_put(_name_offset, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
oop sun_dyn_MemberName::type(oop mname) {
|
||||||
|
assert(is_instance(mname), "wrong type");
|
||||||
|
return mname->obj_field(_type_offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
void sun_dyn_MemberName::set_type(oop mname, oop type) {
|
||||||
|
assert(is_instance(mname), "wrong type");
|
||||||
|
mname->obj_field_put(_type_offset, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
int sun_dyn_MemberName::flags(oop mname) {
|
||||||
|
assert(is_instance(mname), "wrong type");
|
||||||
|
return mname->int_field(_flags_offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
void sun_dyn_MemberName::set_flags(oop mname, int flags) {
|
||||||
|
assert(is_instance(mname), "wrong type");
|
||||||
|
mname->int_field_put(_flags_offset, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
oop sun_dyn_MemberName::vmtarget(oop mname) {
|
||||||
|
assert(is_instance(mname), "wrong type");
|
||||||
|
return mname->obj_field(_vmtarget_offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
void sun_dyn_MemberName::set_vmtarget(oop mname, oop ref) {
|
||||||
|
assert(is_instance(mname), "wrong type");
|
||||||
|
mname->obj_field_put(_vmtarget_offset, ref);
|
||||||
|
}
|
||||||
|
|
||||||
|
int sun_dyn_MemberName::vmindex(oop mname) {
|
||||||
|
assert(is_instance(mname), "wrong type");
|
||||||
|
return mname->int_field(_vmindex_offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
void sun_dyn_MemberName::set_vmindex(oop mname, int index) {
|
||||||
|
assert(is_instance(mname), "wrong type");
|
||||||
|
mname->int_field_put(_vmindex_offset, index);
|
||||||
|
}
|
||||||
|
|
||||||
|
oop java_dyn_MethodHandle::vmtarget(oop mh) {
|
||||||
|
assert(is_instance(mh), "MH only");
|
||||||
|
return mh->obj_field(_vmtarget_offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
void java_dyn_MethodHandle::set_vmtarget(oop mh, oop ref) {
|
||||||
|
assert(is_instance(mh), "MH only");
|
||||||
|
mh->obj_field_put(_vmtarget_offset, ref);
|
||||||
|
}
|
||||||
|
|
||||||
|
int sun_dyn_DirectMethodHandle::vmindex(oop mh) {
|
||||||
|
assert(is_instance(mh), "DMH only");
|
||||||
|
return mh->int_field(_vmindex_offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
void sun_dyn_DirectMethodHandle::set_vmindex(oop mh, int index) {
|
||||||
|
assert(is_instance(mh), "DMH only");
|
||||||
|
mh->int_field_put(_vmindex_offset, index);
|
||||||
|
}
|
||||||
|
|
||||||
|
int sun_dyn_BoundMethodHandle::vmargslot(oop mh) {
|
||||||
|
assert(is_instance(mh), "BMH only");
|
||||||
|
return mh->int_field(_vmargslot_offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
oop sun_dyn_BoundMethodHandle::argument(oop mh) {
|
||||||
|
assert(is_instance(mh), "BMH only");
|
||||||
|
return mh->obj_field(_argument_offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
int sun_dyn_AdapterMethodHandle::conversion(oop mh) {
|
||||||
|
assert(is_instance(mh), "AMH only");
|
||||||
|
return mh->int_field(_conversion_offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
void sun_dyn_AdapterMethodHandle::set_conversion(oop mh, int conv) {
|
||||||
|
assert(is_instance(mh), "AMH only");
|
||||||
|
mh->int_field_put(_conversion_offset, conv);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Support for java_dyn_MethodType
|
||||||
|
|
||||||
|
int java_dyn_MethodType::_rtype_offset;
|
||||||
|
int java_dyn_MethodType::_ptypes_offset;
|
||||||
|
int java_dyn_MethodType::_form_offset;
|
||||||
|
|
||||||
|
void java_dyn_MethodType::compute_offsets() {
|
||||||
|
klassOop k = SystemDictionary::MethodType_klass();
|
||||||
|
if (k != NULL) {
|
||||||
|
compute_offset(_rtype_offset, k, vmSymbols::rtype_name(), vmSymbols::class_signature());
|
||||||
|
compute_offset(_ptypes_offset, k, vmSymbols::ptypes_name(), vmSymbols::class_array_signature());
|
||||||
|
compute_offset(_form_offset, k, vmSymbols::form_name(), vmSymbols::java_dyn_MethodTypeForm_signature());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void java_dyn_MethodType::print_signature(oop mt, outputStream* st) {
|
||||||
|
st->print("(");
|
||||||
|
objArrayOop pts = ptypes(mt);
|
||||||
|
for (int i = 0, limit = pts->length(); i < limit; i++) {
|
||||||
|
java_lang_Class::print_signature(pts->obj_at(i), st);
|
||||||
|
}
|
||||||
|
st->print(")");
|
||||||
|
java_lang_Class::print_signature(rtype(mt), st);
|
||||||
|
}
|
||||||
|
|
||||||
|
symbolOop java_dyn_MethodType::as_signature(oop mt, bool intern_if_not_found, TRAPS) {
|
||||||
|
ResourceMark rm;
|
||||||
|
stringStream buffer(128);
|
||||||
|
print_signature(mt, &buffer);
|
||||||
|
const char* sigstr = buffer.base();
|
||||||
|
int siglen = (int) buffer.size();
|
||||||
|
if (!intern_if_not_found)
|
||||||
|
return SymbolTable::probe(sigstr, siglen);
|
||||||
|
else
|
||||||
|
return oopFactory::new_symbol(sigstr, siglen, THREAD);
|
||||||
|
}
|
||||||
|
|
||||||
|
oop java_dyn_MethodType::rtype(oop mt) {
|
||||||
|
assert(is_instance(mt), "must be a MethodType");
|
||||||
|
return mt->obj_field(_rtype_offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
objArrayOop java_dyn_MethodType::ptypes(oop mt) {
|
||||||
|
assert(is_instance(mt), "must be a MethodType");
|
||||||
|
return (objArrayOop) mt->obj_field(_ptypes_offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
oop java_dyn_MethodType::form(oop mt) {
|
||||||
|
assert(is_instance(mt), "must be a MethodType");
|
||||||
|
return mt->obj_field(_form_offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
oop java_dyn_MethodType::ptype(oop mt, int idx) {
|
||||||
|
return ptypes(mt)->obj_at(idx);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Support for java_dyn_MethodTypeForm
|
||||||
|
|
||||||
|
int java_dyn_MethodTypeForm::_vmslots_offset;
|
||||||
|
int java_dyn_MethodTypeForm::_erasedType_offset;
|
||||||
|
|
||||||
|
void java_dyn_MethodTypeForm::compute_offsets() {
|
||||||
|
klassOop k = SystemDictionary::MethodTypeForm_klass();
|
||||||
|
if (k != NULL) {
|
||||||
|
compute_optional_offset(_vmslots_offset, k, vmSymbols::vmslots_name(), vmSymbols::int_signature(), true);
|
||||||
|
compute_optional_offset(_erasedType_offset, k, vmSymbols::erasedType_name(), vmSymbols::java_dyn_MethodType_signature(), true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int java_dyn_MethodTypeForm::vmslots(oop mtform) {
|
||||||
|
assert(mtform->klass() == SystemDictionary::MethodTypeForm_klass(), "MTForm only");
|
||||||
|
return mtform->int_field(_vmslots_offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
oop java_dyn_MethodTypeForm::erasedType(oop mtform) {
|
||||||
|
assert(mtform->klass() == SystemDictionary::MethodTypeForm_klass(), "MTForm only");
|
||||||
|
return mtform->obj_field(_erasedType_offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Support for java_security_AccessControlContext
|
// Support for java_security_AccessControlContext
|
||||||
|
|
||||||
int java_security_AccessControlContext::_context_offset = 0;
|
int java_security_AccessControlContext::_context_offset = 0;
|
||||||
int java_security_AccessControlContext::_privilegedContext_offset = 0;
|
int java_security_AccessControlContext::_privilegedContext_offset = 0;
|
||||||
int java_security_AccessControlContext::_isPrivileged_offset = 0;
|
int java_security_AccessControlContext::_isPrivileged_offset = 0;
|
||||||
|
|
||||||
|
|
||||||
void java_security_AccessControlContext::compute_offsets() {
|
void java_security_AccessControlContext::compute_offsets() {
|
||||||
assert(_isPrivileged_offset == 0, "offsets should be initialized only once");
|
assert(_isPrivileged_offset == 0, "offsets should be initialized only once");
|
||||||
fieldDescriptor fd;
|
fieldDescriptor fd;
|
||||||
@ -2442,6 +2766,15 @@ void JavaClasses::compute_offsets() {
|
|||||||
java_lang_System::compute_offsets();
|
java_lang_System::compute_offsets();
|
||||||
java_lang_Thread::compute_offsets();
|
java_lang_Thread::compute_offsets();
|
||||||
java_lang_ThreadGroup::compute_offsets();
|
java_lang_ThreadGroup::compute_offsets();
|
||||||
|
if (EnableMethodHandles) {
|
||||||
|
java_dyn_MethodHandle::compute_offsets();
|
||||||
|
sun_dyn_MemberName::compute_offsets();
|
||||||
|
sun_dyn_DirectMethodHandle::compute_offsets();
|
||||||
|
sun_dyn_BoundMethodHandle::compute_offsets();
|
||||||
|
sun_dyn_AdapterMethodHandle::compute_offsets();
|
||||||
|
java_dyn_MethodType::compute_offsets();
|
||||||
|
java_dyn_MethodTypeForm::compute_offsets();
|
||||||
|
}
|
||||||
java_security_AccessControlContext::compute_offsets();
|
java_security_AccessControlContext::compute_offsets();
|
||||||
// Initialize reflection classes. The layouts of these classes
|
// Initialize reflection classes. The layouts of these classes
|
||||||
// changed with the new reflection implementation in JDK 1.4, and
|
// changed with the new reflection implementation in JDK 1.4, and
|
||||||
@ -2459,6 +2792,9 @@ void JavaClasses::compute_offsets() {
|
|||||||
sun_reflect_UnsafeStaticFieldAccessorImpl::compute_offsets();
|
sun_reflect_UnsafeStaticFieldAccessorImpl::compute_offsets();
|
||||||
}
|
}
|
||||||
sun_misc_AtomicLongCSImpl::compute_offsets();
|
sun_misc_AtomicLongCSImpl::compute_offsets();
|
||||||
|
|
||||||
|
// generated interpreter code wants to know about the offsets we just computed:
|
||||||
|
AbstractAssembler::update_delayed_values();
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef PRODUCT
|
#ifndef PRODUCT
|
||||||
|
@ -151,6 +151,12 @@ class java_lang_Class : AllStatic {
|
|||||||
// Conversion
|
// Conversion
|
||||||
static klassOop as_klassOop(oop java_class);
|
static klassOop as_klassOop(oop java_class);
|
||||||
static BasicType as_BasicType(oop java_class, klassOop* reference_klass = NULL);
|
static BasicType as_BasicType(oop java_class, klassOop* reference_klass = NULL);
|
||||||
|
static BasicType as_BasicType(oop java_class, KlassHandle* reference_klass) {
|
||||||
|
klassOop refk_oop = NULL;
|
||||||
|
BasicType result = as_BasicType(java_class, &refk_oop);
|
||||||
|
(*reference_klass) = KlassHandle(refk_oop);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
static symbolOop as_signature(oop java_class, bool intern_if_not_found, TRAPS);
|
static symbolOop as_signature(oop java_class, bool intern_if_not_found, TRAPS);
|
||||||
static void print_signature(oop java_class, outputStream *st);
|
static void print_signature(oop java_class, outputStream *st);
|
||||||
// Testing
|
// Testing
|
||||||
@ -778,6 +784,284 @@ class java_lang_ref_SoftReference: public java_lang_ref_Reference {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// Interface to java.dyn.MethodHandle objects
|
||||||
|
|
||||||
|
class MethodHandleEntry;
|
||||||
|
|
||||||
|
class java_dyn_MethodHandle: AllStatic {
|
||||||
|
friend class JavaClasses;
|
||||||
|
|
||||||
|
private:
|
||||||
|
static int _vmentry_offset; // assembly code trampoline for MH
|
||||||
|
static int _vmtarget_offset; // class-specific target reference
|
||||||
|
static int _type_offset; // the MethodType of this MH
|
||||||
|
static int _vmslots_offset; // OPTIONAL hoisted type.form.vmslots
|
||||||
|
|
||||||
|
static void compute_offsets();
|
||||||
|
|
||||||
|
public:
|
||||||
|
// Accessors
|
||||||
|
static oop type(oop mh);
|
||||||
|
static void set_type(oop mh, oop mtype);
|
||||||
|
|
||||||
|
static oop vmtarget(oop mh);
|
||||||
|
static void set_vmtarget(oop mh, oop target);
|
||||||
|
|
||||||
|
static MethodHandleEntry* vmentry(oop mh);
|
||||||
|
static void set_vmentry(oop mh, MethodHandleEntry* data);
|
||||||
|
|
||||||
|
static int vmslots(oop mh);
|
||||||
|
static void init_vmslots(oop mh);
|
||||||
|
static int compute_vmslots(oop mh);
|
||||||
|
|
||||||
|
// Testers
|
||||||
|
static bool is_subclass(klassOop klass) {
|
||||||
|
return Klass::cast(klass)->is_subclass_of(SystemDictionary::MethodHandle_klass());
|
||||||
|
}
|
||||||
|
static bool is_instance(oop obj) {
|
||||||
|
return obj != NULL && is_subclass(obj->klass());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Accessors for code generation:
|
||||||
|
static int type_offset_in_bytes() { return _type_offset; }
|
||||||
|
static int vmtarget_offset_in_bytes() { return _vmtarget_offset; }
|
||||||
|
static int vmentry_offset_in_bytes() { return _vmentry_offset; }
|
||||||
|
static int vmslots_offset_in_bytes() { return _vmslots_offset; }
|
||||||
|
};
|
||||||
|
|
||||||
|
class sun_dyn_DirectMethodHandle: public java_dyn_MethodHandle {
|
||||||
|
friend class JavaClasses;
|
||||||
|
|
||||||
|
private:
|
||||||
|
// _vmtarget_offset; // method or class or interface
|
||||||
|
static int _vmindex_offset; // negative or vtable idx or itable idx
|
||||||
|
static void compute_offsets();
|
||||||
|
|
||||||
|
public:
|
||||||
|
// Accessors
|
||||||
|
static int vmindex(oop mh);
|
||||||
|
static void set_vmindex(oop mh, int index);
|
||||||
|
|
||||||
|
// Testers
|
||||||
|
static bool is_subclass(klassOop klass) {
|
||||||
|
return Klass::cast(klass)->is_subclass_of(SystemDictionary::DirectMethodHandle_klass());
|
||||||
|
}
|
||||||
|
static bool is_instance(oop obj) {
|
||||||
|
return obj != NULL && is_subclass(obj->klass());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Accessors for code generation:
|
||||||
|
static int vmindex_offset_in_bytes() { return _vmindex_offset; }
|
||||||
|
};
|
||||||
|
|
||||||
|
class sun_dyn_BoundMethodHandle: public java_dyn_MethodHandle {
|
||||||
|
friend class JavaClasses;
|
||||||
|
|
||||||
|
private:
|
||||||
|
static int _argument_offset; // argument value bound into this MH
|
||||||
|
static int _vmargslot_offset; // relevant argument slot (<= vmslots)
|
||||||
|
static void compute_offsets();
|
||||||
|
|
||||||
|
public:
|
||||||
|
static oop argument(oop mh);
|
||||||
|
static void set_argument(oop mh, oop ref);
|
||||||
|
|
||||||
|
static jint vmargslot(oop mh);
|
||||||
|
static void set_vmargslot(oop mh, jint slot);
|
||||||
|
|
||||||
|
// Testers
|
||||||
|
static bool is_subclass(klassOop klass) {
|
||||||
|
return Klass::cast(klass)->is_subclass_of(SystemDictionary::BoundMethodHandle_klass());
|
||||||
|
}
|
||||||
|
static bool is_instance(oop obj) {
|
||||||
|
return obj != NULL && is_subclass(obj->klass());
|
||||||
|
}
|
||||||
|
|
||||||
|
static int argument_offset_in_bytes() { return _argument_offset; }
|
||||||
|
static int vmargslot_offset_in_bytes() { return _vmargslot_offset; }
|
||||||
|
};
|
||||||
|
|
||||||
|
class sun_dyn_AdapterMethodHandle: public sun_dyn_BoundMethodHandle {
|
||||||
|
friend class JavaClasses;
|
||||||
|
|
||||||
|
private:
|
||||||
|
static int _conversion_offset; // type of conversion to apply
|
||||||
|
static void compute_offsets();
|
||||||
|
|
||||||
|
public:
|
||||||
|
static int conversion(oop mh);
|
||||||
|
static void set_conversion(oop mh, int conv);
|
||||||
|
|
||||||
|
// Testers
|
||||||
|
static bool is_subclass(klassOop klass) {
|
||||||
|
return Klass::cast(klass)->is_subclass_of(SystemDictionary::AdapterMethodHandle_klass());
|
||||||
|
}
|
||||||
|
static bool is_instance(oop obj) {
|
||||||
|
return obj != NULL && is_subclass(obj->klass());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Relevant integer codes (keep these in synch. with MethodHandleNatives.Constants):
|
||||||
|
enum {
|
||||||
|
OP_RETYPE_ONLY = 0x0, // no argument changes; straight retype
|
||||||
|
OP_CHECK_CAST = 0x1, // ref-to-ref conversion; requires a Class argument
|
||||||
|
OP_PRIM_TO_PRIM = 0x2, // converts from one primitive to another
|
||||||
|
OP_REF_TO_PRIM = 0x3, // unboxes a wrapper to produce a primitive
|
||||||
|
OP_PRIM_TO_REF = 0x4, // boxes a primitive into a wrapper (NYI)
|
||||||
|
OP_SWAP_ARGS = 0x5, // swap arguments (vminfo is 2nd arg)
|
||||||
|
OP_ROT_ARGS = 0x6, // rotate arguments (vminfo is displaced arg)
|
||||||
|
OP_DUP_ARGS = 0x7, // duplicates one or more arguments (at TOS)
|
||||||
|
OP_DROP_ARGS = 0x8, // remove one or more argument slots
|
||||||
|
OP_COLLECT_ARGS = 0x9, // combine one or more arguments into a varargs (NYI)
|
||||||
|
OP_SPREAD_ARGS = 0xA, // expand in place a varargs array (of known size)
|
||||||
|
OP_FLYBY = 0xB, // operate first on reified argument list (NYI)
|
||||||
|
OP_RICOCHET = 0xC, // run an adapter chain on the return value (NYI)
|
||||||
|
CONV_OP_LIMIT = 0xD, // limit of CONV_OP enumeration
|
||||||
|
|
||||||
|
CONV_OP_MASK = 0xF00, // this nybble contains the conversion op field
|
||||||
|
CONV_VMINFO_MASK = 0x0FF, // LSB is reserved for JVM use
|
||||||
|
CONV_VMINFO_SHIFT = 0, // position of bits in CONV_VMINFO_MASK
|
||||||
|
CONV_OP_SHIFT = 8, // position of bits in CONV_OP_MASK
|
||||||
|
CONV_DEST_TYPE_SHIFT = 12, // byte 2 has the adapter BasicType (if needed)
|
||||||
|
CONV_SRC_TYPE_SHIFT = 16, // byte 2 has the source BasicType (if needed)
|
||||||
|
CONV_STACK_MOVE_SHIFT = 20, // high 12 bits give signed SP change
|
||||||
|
CONV_STACK_MOVE_MASK = (1 << (32 - CONV_STACK_MOVE_SHIFT)) - 1
|
||||||
|
};
|
||||||
|
|
||||||
|
static int conversion_offset_in_bytes() { return _conversion_offset; }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// Interface to sun.dyn.MemberName objects
|
||||||
|
// (These are a private interface for Java code to query the class hierarchy.)
|
||||||
|
|
||||||
|
class sun_dyn_MemberName: AllStatic {
|
||||||
|
friend class JavaClasses;
|
||||||
|
|
||||||
|
private:
|
||||||
|
// From java.dyn.MemberName:
|
||||||
|
// private Class<?> clazz; // class in which the method is defined
|
||||||
|
// private String name; // may be null if not yet materialized
|
||||||
|
// private Object type; // may be null if not yet materialized
|
||||||
|
// private int flags; // modifier bits; see reflect.Modifier
|
||||||
|
// private Object vmtarget; // VM-specific target value
|
||||||
|
// private int vmindex; // method index within class or interface
|
||||||
|
static int _clazz_offset;
|
||||||
|
static int _name_offset;
|
||||||
|
static int _type_offset;
|
||||||
|
static int _flags_offset;
|
||||||
|
static int _vmtarget_offset;
|
||||||
|
static int _vmindex_offset;
|
||||||
|
|
||||||
|
static void compute_offsets();
|
||||||
|
|
||||||
|
public:
|
||||||
|
// Accessors
|
||||||
|
static oop clazz(oop mname);
|
||||||
|
static void set_clazz(oop mname, oop clazz);
|
||||||
|
|
||||||
|
static oop type(oop mname);
|
||||||
|
static void set_type(oop mname, oop type);
|
||||||
|
|
||||||
|
static oop name(oop mname);
|
||||||
|
static void set_name(oop mname, oop name);
|
||||||
|
|
||||||
|
static int flags(oop mname);
|
||||||
|
static void set_flags(oop mname, int flags);
|
||||||
|
|
||||||
|
static int modifiers(oop mname) { return (u2) flags(mname); }
|
||||||
|
static void set_modifiers(oop mname, int mods)
|
||||||
|
{ set_flags(mname, (flags(mname) &~ (u2)-1) | (u2)mods); }
|
||||||
|
|
||||||
|
static oop vmtarget(oop mname);
|
||||||
|
static void set_vmtarget(oop mname, oop target);
|
||||||
|
|
||||||
|
static int vmindex(oop mname);
|
||||||
|
static void set_vmindex(oop mname, int index);
|
||||||
|
|
||||||
|
// Testers
|
||||||
|
static bool is_subclass(klassOop klass) {
|
||||||
|
return Klass::cast(klass)->is_subclass_of(SystemDictionary::MemberName_klass());
|
||||||
|
}
|
||||||
|
static bool is_instance(oop obj) {
|
||||||
|
return obj != NULL && is_subclass(obj->klass());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Relevant integer codes (keep these in synch. with MethodHandleNatives.Constants):
|
||||||
|
enum {
|
||||||
|
MN_IS_METHOD = 0x00010000, // method (not constructor)
|
||||||
|
MN_IS_CONSTRUCTOR = 0x00020000, // constructor
|
||||||
|
MN_IS_FIELD = 0x00040000, // field
|
||||||
|
MN_IS_TYPE = 0x00080000, // nested type
|
||||||
|
MN_SEARCH_SUPERCLASSES = 0x00100000, // for MHN.getMembers
|
||||||
|
MN_SEARCH_INTERFACES = 0x00200000, // for MHN.getMembers
|
||||||
|
VM_INDEX_UNINITIALIZED = -99
|
||||||
|
};
|
||||||
|
|
||||||
|
// Accessors for code generation:
|
||||||
|
static int clazz_offset_in_bytes() { return _clazz_offset; }
|
||||||
|
static int type_offset_in_bytes() { return _type_offset; }
|
||||||
|
static int name_offset_in_bytes() { return _name_offset; }
|
||||||
|
static int flags_offset_in_bytes() { return _flags_offset; }
|
||||||
|
static int vmtarget_offset_in_bytes() { return _vmtarget_offset; }
|
||||||
|
static int vmindex_offset_in_bytes() { return _vmindex_offset; }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// Interface to java.dyn.MethodType objects
|
||||||
|
|
||||||
|
class java_dyn_MethodType: AllStatic {
|
||||||
|
friend class JavaClasses;
|
||||||
|
|
||||||
|
private:
|
||||||
|
static int _rtype_offset;
|
||||||
|
static int _ptypes_offset;
|
||||||
|
static int _form_offset;
|
||||||
|
|
||||||
|
static void compute_offsets();
|
||||||
|
|
||||||
|
public:
|
||||||
|
// Accessors
|
||||||
|
static oop rtype(oop mt);
|
||||||
|
static objArrayOop ptypes(oop mt);
|
||||||
|
static oop form(oop mt);
|
||||||
|
|
||||||
|
static oop ptype(oop mt, int index);
|
||||||
|
|
||||||
|
static symbolOop as_signature(oop mt, bool intern_if_not_found, TRAPS);
|
||||||
|
static void print_signature(oop mt, outputStream* st);
|
||||||
|
|
||||||
|
static bool is_instance(oop obj) {
|
||||||
|
return obj != NULL && obj->klass() == SystemDictionary::MethodType_klass();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Accessors for code generation:
|
||||||
|
static int rtype_offset_in_bytes() { return _rtype_offset; }
|
||||||
|
static int ptypes_offset_in_bytes() { return _ptypes_offset; }
|
||||||
|
static int form_offset_in_bytes() { return _form_offset; }
|
||||||
|
};
|
||||||
|
|
||||||
|
class java_dyn_MethodTypeForm: AllStatic {
|
||||||
|
friend class JavaClasses;
|
||||||
|
|
||||||
|
private:
|
||||||
|
static int _vmslots_offset; // number of argument slots needed
|
||||||
|
static int _erasedType_offset; // erasedType = canonical MethodType
|
||||||
|
|
||||||
|
static void compute_offsets();
|
||||||
|
|
||||||
|
public:
|
||||||
|
// Accessors
|
||||||
|
static int vmslots(oop mtform);
|
||||||
|
static oop erasedType(oop mtform);
|
||||||
|
|
||||||
|
// Accessors for code generation:
|
||||||
|
static int vmslots_offset_in_bytes() { return _vmslots_offset; }
|
||||||
|
static int erasedType_offset_in_bytes() { return _erasedType_offset; }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Interface to java.security.AccessControlContext objects
|
// Interface to java.security.AccessControlContext objects
|
||||||
|
|
||||||
class java_security_AccessControlContext: AllStatic {
|
class java_security_AccessControlContext: AllStatic {
|
||||||
|
@ -31,6 +31,7 @@ PlaceholderTable* SystemDictionary::_placeholders = NULL;
|
|||||||
Dictionary* SystemDictionary::_shared_dictionary = NULL;
|
Dictionary* SystemDictionary::_shared_dictionary = NULL;
|
||||||
LoaderConstraintTable* SystemDictionary::_loader_constraints = NULL;
|
LoaderConstraintTable* SystemDictionary::_loader_constraints = NULL;
|
||||||
ResolutionErrorTable* SystemDictionary::_resolution_errors = NULL;
|
ResolutionErrorTable* SystemDictionary::_resolution_errors = NULL;
|
||||||
|
SymbolPropertyTable* SystemDictionary::_invoke_method_table = NULL;
|
||||||
|
|
||||||
|
|
||||||
int SystemDictionary::_number_of_modifications = 0;
|
int SystemDictionary::_number_of_modifications = 0;
|
||||||
@ -966,6 +967,8 @@ klassOop SystemDictionary::parse_stream(symbolHandle class_name,
|
|||||||
instanceKlassHandle k = ClassFileParser(st).parseClassFile(class_name,
|
instanceKlassHandle k = ClassFileParser(st).parseClassFile(class_name,
|
||||||
class_loader,
|
class_loader,
|
||||||
protection_domain,
|
protection_domain,
|
||||||
|
host_klass,
|
||||||
|
cp_patches,
|
||||||
parsed_name,
|
parsed_name,
|
||||||
THREAD);
|
THREAD);
|
||||||
|
|
||||||
@ -1691,6 +1694,10 @@ void SystemDictionary::always_strong_classes_do(OopClosure* blk) {
|
|||||||
// represent classes we're actively loading.
|
// represent classes we're actively loading.
|
||||||
placeholders_do(blk);
|
placeholders_do(blk);
|
||||||
|
|
||||||
|
// Visit extra methods
|
||||||
|
if (invoke_method_table() != NULL)
|
||||||
|
invoke_method_table()->oops_do(blk);
|
||||||
|
|
||||||
// Loader constraints. We must keep the symbolOop used in the name alive.
|
// Loader constraints. We must keep the symbolOop used in the name alive.
|
||||||
constraints()->always_strong_classes_do(blk);
|
constraints()->always_strong_classes_do(blk);
|
||||||
|
|
||||||
@ -1726,6 +1733,10 @@ void SystemDictionary::oops_do(OopClosure* f) {
|
|||||||
// Adjust dictionary
|
// Adjust dictionary
|
||||||
dictionary()->oops_do(f);
|
dictionary()->oops_do(f);
|
||||||
|
|
||||||
|
// Visit extra methods
|
||||||
|
if (invoke_method_table() != NULL)
|
||||||
|
invoke_method_table()->oops_do(f);
|
||||||
|
|
||||||
// Partially loaded classes
|
// Partially loaded classes
|
||||||
placeholders()->oops_do(f);
|
placeholders()->oops_do(f);
|
||||||
|
|
||||||
@ -1798,6 +1809,8 @@ void SystemDictionary::placeholders_do(void f(symbolOop, oop)) {
|
|||||||
|
|
||||||
void SystemDictionary::methods_do(void f(methodOop)) {
|
void SystemDictionary::methods_do(void f(methodOop)) {
|
||||||
dictionary()->methods_do(f);
|
dictionary()->methods_do(f);
|
||||||
|
if (invoke_method_table() != NULL)
|
||||||
|
invoke_method_table()->methods_do(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
@ -1830,6 +1843,7 @@ void SystemDictionary::initialize(TRAPS) {
|
|||||||
_number_of_modifications = 0;
|
_number_of_modifications = 0;
|
||||||
_loader_constraints = new LoaderConstraintTable(_loader_constraint_size);
|
_loader_constraints = new LoaderConstraintTable(_loader_constraint_size);
|
||||||
_resolution_errors = new ResolutionErrorTable(_resolution_error_size);
|
_resolution_errors = new ResolutionErrorTable(_resolution_error_size);
|
||||||
|
// _invoke_method_table is allocated lazily in find_method_handle_invoke()
|
||||||
|
|
||||||
// Allocate private object used as system class loader lock
|
// Allocate private object used as system class loader lock
|
||||||
_system_loader_lock_obj = oopFactory::new_system_objArray(0, CHECK);
|
_system_loader_lock_obj = oopFactory::new_system_objArray(0, CHECK);
|
||||||
@ -1891,6 +1905,9 @@ void SystemDictionary::initialize_wk_klasses_until(WKID limit_id, WKID &start_id
|
|||||||
wk_klass_name_limits[0] = s;
|
wk_klass_name_limits[0] = s;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// move the starting value forward to the limit:
|
||||||
|
start_id = limit_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1924,6 +1941,17 @@ void SystemDictionary::initialize_preloaded_classes(TRAPS) {
|
|||||||
instanceKlass::cast(WK_KLASS(final_reference_klass))->set_reference_type(REF_FINAL);
|
instanceKlass::cast(WK_KLASS(final_reference_klass))->set_reference_type(REF_FINAL);
|
||||||
instanceKlass::cast(WK_KLASS(phantom_reference_klass))->set_reference_type(REF_PHANTOM);
|
instanceKlass::cast(WK_KLASS(phantom_reference_klass))->set_reference_type(REF_PHANTOM);
|
||||||
|
|
||||||
|
WKID meth_group_start = WK_KLASS_ENUM_NAME(MethodHandle_klass);
|
||||||
|
WKID meth_group_end = WK_KLASS_ENUM_NAME(WrongMethodTypeException_klass);
|
||||||
|
initialize_wk_klasses_until(meth_group_start, scan, CHECK);
|
||||||
|
if (EnableMethodHandles) {
|
||||||
|
initialize_wk_klasses_through(meth_group_start, scan, CHECK);
|
||||||
|
}
|
||||||
|
if (_well_known_klasses[meth_group_start] == NULL) {
|
||||||
|
// Skip the rest of the method handle classes, if MethodHandle is not loaded.
|
||||||
|
scan = WKID(meth_group_end+1);
|
||||||
|
}
|
||||||
|
|
||||||
initialize_wk_klasses_until(WKID_LIMIT, scan, CHECK);
|
initialize_wk_klasses_until(WKID_LIMIT, scan, CHECK);
|
||||||
|
|
||||||
_box_klasses[T_BOOLEAN] = WK_KLASS(boolean_klass);
|
_box_klasses[T_BOOLEAN] = WK_KLASS(boolean_klass);
|
||||||
@ -2254,6 +2282,91 @@ char* SystemDictionary::check_signature_loaders(symbolHandle signature,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
methodOop SystemDictionary::find_method_handle_invoke(symbolHandle signature,
|
||||||
|
Handle class_loader,
|
||||||
|
Handle protection_domain,
|
||||||
|
TRAPS) {
|
||||||
|
if (!EnableMethodHandles) return NULL;
|
||||||
|
assert(class_loader.is_null() && protection_domain.is_null(),
|
||||||
|
"cannot load specialized versions of MethodHandle.invoke");
|
||||||
|
if (invoke_method_table() == NULL) {
|
||||||
|
// create this side table lazily
|
||||||
|
_invoke_method_table = new SymbolPropertyTable(_invoke_method_size);
|
||||||
|
}
|
||||||
|
unsigned int hash = invoke_method_table()->compute_hash(signature);
|
||||||
|
int index = invoke_method_table()->hash_to_index(hash);
|
||||||
|
SymbolPropertyEntry* spe = invoke_method_table()->find_entry(index, hash, signature);
|
||||||
|
if (spe == NULL || spe->property_oop() == NULL) {
|
||||||
|
// Must create lots of stuff here, but outside of the SystemDictionary lock.
|
||||||
|
Handle mt = compute_method_handle_type(signature(),
|
||||||
|
class_loader, protection_domain,
|
||||||
|
CHECK_NULL);
|
||||||
|
KlassHandle mh_klass = SystemDictionaryHandles::MethodHandle_klass();
|
||||||
|
methodHandle m = methodOopDesc::make_invoke_method(mh_klass, signature,
|
||||||
|
mt, CHECK_NULL);
|
||||||
|
// Now grab the lock. We might have to throw away the new method,
|
||||||
|
// if a racing thread has managed to install one at the same time.
|
||||||
|
{
|
||||||
|
MutexLocker ml(SystemDictionary_lock, Thread::current());
|
||||||
|
spe = invoke_method_table()->find_entry(index, hash, signature);
|
||||||
|
if (spe == NULL)
|
||||||
|
spe = invoke_method_table()->add_entry(index, hash, signature);
|
||||||
|
if (spe->property_oop() == NULL)
|
||||||
|
spe->set_property_oop(m());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
methodOop m = (methodOop) spe->property_oop();
|
||||||
|
assert(m->is_method(), "");
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ask Java code to find or construct a java.dyn.MethodType for the given
|
||||||
|
// signature, as interpreted relative to the given class loader.
|
||||||
|
// Because of class loader constraints, all method handle usage must be
|
||||||
|
// consistent with this loader.
|
||||||
|
Handle SystemDictionary::compute_method_handle_type(symbolHandle signature,
|
||||||
|
Handle class_loader,
|
||||||
|
Handle protection_domain,
|
||||||
|
TRAPS) {
|
||||||
|
Handle empty;
|
||||||
|
int npts = ArgumentCount(signature()).size();
|
||||||
|
objArrayHandle pts = oopFactory::new_objArray(SystemDictionary::class_klass(), npts, CHECK_(empty));
|
||||||
|
int arg = 0;
|
||||||
|
Handle rt; // the return type from the signature
|
||||||
|
for (SignatureStream ss(signature()); !ss.is_done(); ss.next()) {
|
||||||
|
oop mirror;
|
||||||
|
if (!ss.is_object()) {
|
||||||
|
mirror = Universe::java_mirror(ss.type());
|
||||||
|
} else {
|
||||||
|
symbolOop name_oop = ss.as_symbol(CHECK_(empty));
|
||||||
|
symbolHandle name(THREAD, name_oop);
|
||||||
|
klassOop klass = resolve_or_fail(name,
|
||||||
|
class_loader, protection_domain,
|
||||||
|
true, CHECK_(empty));
|
||||||
|
mirror = Klass::cast(klass)->java_mirror();
|
||||||
|
}
|
||||||
|
if (ss.at_return_type())
|
||||||
|
rt = Handle(THREAD, mirror);
|
||||||
|
else
|
||||||
|
pts->obj_at_put(arg++, mirror);
|
||||||
|
}
|
||||||
|
assert(arg == npts, "");
|
||||||
|
|
||||||
|
// call MethodType java.dyn.MethodType::makeImpl(Class rt, Class[] pts, false, true)
|
||||||
|
bool varargs = false, trusted = true;
|
||||||
|
JavaCallArguments args(Handle(THREAD, rt()));
|
||||||
|
args.push_oop(pts());
|
||||||
|
args.push_int(false);
|
||||||
|
args.push_int(trusted);
|
||||||
|
JavaValue result(T_OBJECT);
|
||||||
|
JavaCalls::call_static(&result,
|
||||||
|
SystemDictionary::MethodType_klass(),
|
||||||
|
vmSymbols::makeImpl_name(), vmSymbols::makeImpl_signature(),
|
||||||
|
&args, CHECK_(empty));
|
||||||
|
return Handle(THREAD, (oop) result.get_jobject());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Since the identity hash code for symbols changes when the symbols are
|
// Since the identity hash code for symbols changes when the symbols are
|
||||||
// moved from the regular perm gen (hash in the mark word) to the shared
|
// moved from the regular perm gen (hash in the mark word) to the shared
|
||||||
// spaces (hash is the address), the classes loaded into the dictionary
|
// spaces (hash is the address), the classes loaded into the dictionary
|
||||||
|
@ -63,6 +63,7 @@ class PlaceholderTable;
|
|||||||
class LoaderConstraintTable;
|
class LoaderConstraintTable;
|
||||||
class HashtableBucket;
|
class HashtableBucket;
|
||||||
class ResolutionErrorTable;
|
class ResolutionErrorTable;
|
||||||
|
class SymbolPropertyTable;
|
||||||
|
|
||||||
// Certain classes are preloaded, such as java.lang.Object and java.lang.String.
|
// Certain classes are preloaded, such as java.lang.Object and java.lang.String.
|
||||||
// They are all "well-known", in the sense that no class loader is allowed
|
// They are all "well-known", in the sense that no class loader is allowed
|
||||||
@ -131,6 +132,16 @@ class ResolutionErrorTable;
|
|||||||
template(reflect_constant_pool_klass, sun_reflect_ConstantPool, Opt_Only_JDK15) \
|
template(reflect_constant_pool_klass, sun_reflect_ConstantPool, Opt_Only_JDK15) \
|
||||||
template(reflect_unsafe_static_field_accessor_impl_klass, sun_reflect_UnsafeStaticFieldAccessorImpl, Opt_Only_JDK15) \
|
template(reflect_unsafe_static_field_accessor_impl_klass, sun_reflect_UnsafeStaticFieldAccessorImpl, Opt_Only_JDK15) \
|
||||||
\
|
\
|
||||||
|
/* support for dynamic typing; it's OK if these are NULL in earlier JDKs */ \
|
||||||
|
template(MethodHandle_klass, java_dyn_MethodHandle, Opt) \
|
||||||
|
template(MemberName_klass, sun_dyn_MemberName, Opt) \
|
||||||
|
template(MethodHandleImpl_klass, sun_dyn_MethodHandleImpl, Opt) \
|
||||||
|
template(AdapterMethodHandle_klass, sun_dyn_AdapterMethodHandle, Opt) \
|
||||||
|
template(BoundMethodHandle_klass, sun_dyn_BoundMethodHandle, Opt) \
|
||||||
|
template(DirectMethodHandle_klass, sun_dyn_DirectMethodHandle, Opt) \
|
||||||
|
template(MethodType_klass, java_dyn_MethodType, Opt) \
|
||||||
|
template(MethodTypeForm_klass, java_dyn_MethodTypeForm, Opt) \
|
||||||
|
template(WrongMethodTypeException_klass, java_dyn_WrongMethodTypeException, Opt) \
|
||||||
template(vector_klass, java_util_Vector, Pre) \
|
template(vector_klass, java_util_Vector, Pre) \
|
||||||
template(hashtable_klass, java_util_Hashtable, Pre) \
|
template(hashtable_klass, java_util_Hashtable, Pre) \
|
||||||
template(stringBuffer_klass, java_lang_StringBuffer, Pre) \
|
template(stringBuffer_klass, java_lang_StringBuffer, Pre) \
|
||||||
@ -444,6 +455,17 @@ public:
|
|||||||
static char* check_signature_loaders(symbolHandle signature, Handle loader1,
|
static char* check_signature_loaders(symbolHandle signature, Handle loader1,
|
||||||
Handle loader2, bool is_method, TRAPS);
|
Handle loader2, bool is_method, TRAPS);
|
||||||
|
|
||||||
|
// JSR 292
|
||||||
|
// find the java.dyn.MethodHandles::invoke method for a given signature
|
||||||
|
static methodOop find_method_handle_invoke(symbolHandle signature,
|
||||||
|
Handle class_loader,
|
||||||
|
Handle protection_domain,
|
||||||
|
TRAPS);
|
||||||
|
// ask Java to compute the java.dyn.MethodType object for a given signature
|
||||||
|
static Handle compute_method_handle_type(symbolHandle signature,
|
||||||
|
Handle class_loader,
|
||||||
|
Handle protection_domain,
|
||||||
|
TRAPS);
|
||||||
// Utility for printing loader "name" as part of tracing constraints
|
// Utility for printing loader "name" as part of tracing constraints
|
||||||
static const char* loader_name(oop loader) {
|
static const char* loader_name(oop loader) {
|
||||||
return ((loader) == NULL ? "<bootloader>" :
|
return ((loader) == NULL ? "<bootloader>" :
|
||||||
@ -460,6 +482,7 @@ public:
|
|||||||
enum Constants {
|
enum Constants {
|
||||||
_loader_constraint_size = 107, // number of entries in constraint table
|
_loader_constraint_size = 107, // number of entries in constraint table
|
||||||
_resolution_error_size = 107, // number of entries in resolution error table
|
_resolution_error_size = 107, // number of entries in resolution error table
|
||||||
|
_invoke_method_size = 139, // number of entries in invoke method table
|
||||||
_nof_buckets = 1009 // number of buckets in hash table
|
_nof_buckets = 1009 // number of buckets in hash table
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -489,6 +512,9 @@ public:
|
|||||||
// Resolution errors
|
// Resolution errors
|
||||||
static ResolutionErrorTable* _resolution_errors;
|
static ResolutionErrorTable* _resolution_errors;
|
||||||
|
|
||||||
|
// Invoke methods (JSR 292)
|
||||||
|
static SymbolPropertyTable* _invoke_method_table;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// for VM_CounterDecay iteration support
|
// for VM_CounterDecay iteration support
|
||||||
friend class CounterDecay;
|
friend class CounterDecay;
|
||||||
@ -506,6 +532,7 @@ private:
|
|||||||
static PlaceholderTable* placeholders() { return _placeholders; }
|
static PlaceholderTable* placeholders() { return _placeholders; }
|
||||||
static LoaderConstraintTable* constraints() { return _loader_constraints; }
|
static LoaderConstraintTable* constraints() { return _loader_constraints; }
|
||||||
static ResolutionErrorTable* resolution_errors() { return _resolution_errors; }
|
static ResolutionErrorTable* resolution_errors() { return _resolution_errors; }
|
||||||
|
static SymbolPropertyTable* invoke_method_table() { return _invoke_method_table; }
|
||||||
|
|
||||||
// Basic loading operations
|
// Basic loading operations
|
||||||
static klassOop resolve_instance_class_or_null(symbolHandle class_name, Handle class_loader, Handle protection_domain, TRAPS);
|
static klassOop resolve_instance_class_or_null(symbolHandle class_name, Handle class_loader, Handle protection_domain, TRAPS);
|
||||||
|
@ -216,7 +216,26 @@
|
|||||||
template(sun_reflect_UnsafeStaticFieldAccessorImpl, "sun/reflect/UnsafeStaticFieldAccessorImpl")\
|
template(sun_reflect_UnsafeStaticFieldAccessorImpl, "sun/reflect/UnsafeStaticFieldAccessorImpl")\
|
||||||
template(base_name, "base") \
|
template(base_name, "base") \
|
||||||
\
|
\
|
||||||
/* common method names */ \
|
/* Support for JSR 292 & invokedynamic (JDK 1.7 and above) */ \
|
||||||
|
template(java_dyn_MethodHandle, "java/dyn/MethodHandle") \
|
||||||
|
template(java_dyn_MethodType, "java/dyn/MethodType") \
|
||||||
|
template(java_dyn_WrongMethodTypeException, "java/dyn/WrongMethodTypeException") \
|
||||||
|
template(java_dyn_MethodType_signature, "Ljava/dyn/MethodType;") \
|
||||||
|
template(java_dyn_MethodHandle_signature, "Ljava/dyn/MethodHandle;") \
|
||||||
|
/* internal classes known only to the JVM: */ \
|
||||||
|
template(java_dyn_MethodTypeForm, "java/dyn/MethodTypeForm") \
|
||||||
|
template(java_dyn_MethodTypeForm_signature, "Ljava/dyn/MethodTypeForm;") \
|
||||||
|
template(sun_dyn_MemberName, "sun/dyn/MemberName") \
|
||||||
|
template(sun_dyn_MethodHandleImpl, "sun/dyn/MethodHandleImpl") \
|
||||||
|
template(sun_dyn_AdapterMethodHandle, "sun/dyn/AdapterMethodHandle") \
|
||||||
|
template(sun_dyn_BoundMethodHandle, "sun/dyn/BoundMethodHandle") \
|
||||||
|
template(sun_dyn_DirectMethodHandle, "sun/dyn/DirectMethodHandle") \
|
||||||
|
template(makeImpl_name, "makeImpl") /*MethodType::makeImpl*/ \
|
||||||
|
template(makeImpl_signature, "(Ljava/lang/Class;[Ljava/lang/Class;ZZ)Ljava/dyn/MethodType;") \
|
||||||
|
NOT_LP64( do_alias(machine_word_signature, int_signature) ) \
|
||||||
|
LP64_ONLY( do_alias(machine_word_signature, long_signature) ) \
|
||||||
|
\
|
||||||
|
/* common method and field names */ \
|
||||||
template(object_initializer_name, "<init>") \
|
template(object_initializer_name, "<init>") \
|
||||||
template(class_initializer_name, "<clinit>") \
|
template(class_initializer_name, "<clinit>") \
|
||||||
template(println_name, "println") \
|
template(println_name, "println") \
|
||||||
@ -289,6 +308,21 @@
|
|||||||
template(bitCount_name, "bitCount") \
|
template(bitCount_name, "bitCount") \
|
||||||
template(profile_name, "profile") \
|
template(profile_name, "profile") \
|
||||||
template(equals_name, "equals") \
|
template(equals_name, "equals") \
|
||||||
|
template(toString_name, "toString") \
|
||||||
|
template(values_name, "values") \
|
||||||
|
template(receiver_name, "receiver") \
|
||||||
|
template(vmtarget_name, "vmtarget") \
|
||||||
|
template(vmentry_name, "vmentry") \
|
||||||
|
template(vmslots_name, "vmslots") \
|
||||||
|
template(vmindex_name, "vmindex") \
|
||||||
|
template(vmargslot_name, "vmargslot") \
|
||||||
|
template(flags_name, "flags") \
|
||||||
|
template(argument_name, "argument") \
|
||||||
|
template(conversion_name, "conversion") \
|
||||||
|
template(rtype_name, "rtype") \
|
||||||
|
template(ptypes_name, "ptypes") \
|
||||||
|
template(form_name, "form") \
|
||||||
|
template(erasedType_name, "erasedType") \
|
||||||
\
|
\
|
||||||
/* non-intrinsic name/signature pairs: */ \
|
/* non-intrinsic name/signature pairs: */ \
|
||||||
template(register_method_name, "register") \
|
template(register_method_name, "register") \
|
||||||
@ -353,6 +387,7 @@
|
|||||||
template(void_classloader_signature, "()Ljava/lang/ClassLoader;") \
|
template(void_classloader_signature, "()Ljava/lang/ClassLoader;") \
|
||||||
template(void_object_signature, "()Ljava/lang/Object;") \
|
template(void_object_signature, "()Ljava/lang/Object;") \
|
||||||
template(void_class_signature, "()Ljava/lang/Class;") \
|
template(void_class_signature, "()Ljava/lang/Class;") \
|
||||||
|
template(void_string_signature, "()Ljava/lang/String;") \
|
||||||
template(object_array_object_object_signature, "(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;")\
|
template(object_array_object_object_signature, "(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;")\
|
||||||
template(exception_void_signature, "(Ljava/lang/Exception;)V") \
|
template(exception_void_signature, "(Ljava/lang/Exception;)V") \
|
||||||
template(protectiondomain_signature, "[Ljava/security/ProtectionDomain;") \
|
template(protectiondomain_signature, "[Ljava/security/ProtectionDomain;") \
|
||||||
|
@ -107,13 +107,11 @@ address VtableStubs::create_stub(bool is_vtable_stub, int vtable_index, methodOo
|
|||||||
s = create_itable_stub(vtable_index);
|
s = create_itable_stub(vtable_index);
|
||||||
}
|
}
|
||||||
enter(is_vtable_stub, vtable_index, s);
|
enter(is_vtable_stub, vtable_index, s);
|
||||||
#ifndef PRODUCT
|
|
||||||
if (PrintAdapterHandlers) {
|
if (PrintAdapterHandlers) {
|
||||||
tty->print_cr("Decoding VtableStub %s[%d]@%d",
|
tty->print_cr("Decoding VtableStub %s[%d]@%d",
|
||||||
is_vtable_stub? "vtbl": "itbl", vtable_index, VtableStub::receiver_location());
|
is_vtable_stub? "vtbl": "itbl", vtable_index, VtableStub::receiver_location());
|
||||||
Disassembler::decode(s->code_begin(), s->code_end());
|
Disassembler::decode(s->code_begin(), s->code_end());
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
return s->entry_point();
|
return s->entry_point();
|
||||||
}
|
}
|
||||||
|
@ -254,6 +254,7 @@ assembler_<arch>.cpp cardTableModRefBS.hpp
|
|||||||
assembler_<arch>.cpp collectedHeap.inline.hpp
|
assembler_<arch>.cpp collectedHeap.inline.hpp
|
||||||
assembler_<arch>.cpp interfaceSupport.hpp
|
assembler_<arch>.cpp interfaceSupport.hpp
|
||||||
assembler_<arch>.cpp interpreter.hpp
|
assembler_<arch>.cpp interpreter.hpp
|
||||||
|
assembler_<arch>.cpp methodHandles.hpp
|
||||||
assembler_<arch>.cpp objectMonitor.hpp
|
assembler_<arch>.cpp objectMonitor.hpp
|
||||||
assembler_<arch>.cpp os.hpp
|
assembler_<arch>.cpp os.hpp
|
||||||
assembler_<arch>.cpp resourceArea.hpp
|
assembler_<arch>.cpp resourceArea.hpp
|
||||||
@ -1274,6 +1275,7 @@ cpCacheKlass.cpp bytecodes.hpp
|
|||||||
cpCacheKlass.cpp collectedHeap.hpp
|
cpCacheKlass.cpp collectedHeap.hpp
|
||||||
cpCacheKlass.cpp constantPoolOop.hpp
|
cpCacheKlass.cpp constantPoolOop.hpp
|
||||||
cpCacheKlass.cpp cpCacheKlass.hpp
|
cpCacheKlass.cpp cpCacheKlass.hpp
|
||||||
|
cpCacheKlass.cpp genOopClosures.inline.hpp
|
||||||
cpCacheKlass.cpp handles.inline.hpp
|
cpCacheKlass.cpp handles.inline.hpp
|
||||||
cpCacheKlass.cpp javaClasses.hpp
|
cpCacheKlass.cpp javaClasses.hpp
|
||||||
cpCacheKlass.cpp markSweep.inline.hpp
|
cpCacheKlass.cpp markSweep.inline.hpp
|
||||||
@ -2202,6 +2204,7 @@ interpreter_<arch_model>.cpp interpreterGenerator.hpp
|
|||||||
interpreter_<arch_model>.cpp jvmtiExport.hpp
|
interpreter_<arch_model>.cpp jvmtiExport.hpp
|
||||||
interpreter_<arch_model>.cpp jvmtiThreadState.hpp
|
interpreter_<arch_model>.cpp jvmtiThreadState.hpp
|
||||||
interpreter_<arch_model>.cpp methodDataOop.hpp
|
interpreter_<arch_model>.cpp methodDataOop.hpp
|
||||||
|
interpreter_<arch_model>.cpp methodHandles.hpp
|
||||||
interpreter_<arch_model>.cpp methodOop.hpp
|
interpreter_<arch_model>.cpp methodOop.hpp
|
||||||
interpreter_<arch_model>.cpp oop.inline.hpp
|
interpreter_<arch_model>.cpp oop.inline.hpp
|
||||||
interpreter_<arch_model>.cpp sharedRuntime.hpp
|
interpreter_<arch_model>.cpp sharedRuntime.hpp
|
||||||
@ -2596,6 +2599,7 @@ linkResolver.cpp handles.inline.hpp
|
|||||||
linkResolver.cpp instanceKlass.hpp
|
linkResolver.cpp instanceKlass.hpp
|
||||||
linkResolver.cpp interpreterRuntime.hpp
|
linkResolver.cpp interpreterRuntime.hpp
|
||||||
linkResolver.cpp linkResolver.hpp
|
linkResolver.cpp linkResolver.hpp
|
||||||
|
linkResolver.cpp methodHandles.hpp
|
||||||
linkResolver.cpp nativeLookup.hpp
|
linkResolver.cpp nativeLookup.hpp
|
||||||
linkResolver.cpp objArrayOop.hpp
|
linkResolver.cpp objArrayOop.hpp
|
||||||
linkResolver.cpp reflection.hpp
|
linkResolver.cpp reflection.hpp
|
||||||
@ -2812,6 +2816,25 @@ methodDataOop.hpp oop.hpp
|
|||||||
methodDataOop.hpp orderAccess.hpp
|
methodDataOop.hpp orderAccess.hpp
|
||||||
methodDataOop.hpp universe.hpp
|
methodDataOop.hpp universe.hpp
|
||||||
|
|
||||||
|
methodHandles.hpp frame.inline.hpp
|
||||||
|
methodHandles.hpp globals.hpp
|
||||||
|
methodHandles.hpp interfaceSupport.hpp
|
||||||
|
methodHandles.hpp javaClasses.hpp
|
||||||
|
methodHandles.hpp vmSymbols.hpp
|
||||||
|
|
||||||
|
methodHandles.cpp allocation.inline.hpp
|
||||||
|
methodHandles.cpp interpreter.hpp
|
||||||
|
methodHandles.cpp javaCalls.hpp
|
||||||
|
methodHandles.cpp methodHandles.hpp
|
||||||
|
methodHandles.cpp oopFactory.hpp
|
||||||
|
methodHandles.cpp reflection.hpp
|
||||||
|
methodHandles.cpp signature.hpp
|
||||||
|
methodHandles.cpp symbolTable.hpp
|
||||||
|
|
||||||
|
methodHandles_<arch>.cpp allocation.inline.hpp
|
||||||
|
methodHandles_<arch>.cpp interpreter.hpp
|
||||||
|
methodHandles_<arch>.cpp methodHandles.hpp
|
||||||
|
|
||||||
methodKlass.cpp collectedHeap.inline.hpp
|
methodKlass.cpp collectedHeap.inline.hpp
|
||||||
methodKlass.cpp constMethodKlass.hpp
|
methodKlass.cpp constMethodKlass.hpp
|
||||||
methodKlass.cpp gcLocker.hpp
|
methodKlass.cpp gcLocker.hpp
|
||||||
@ -3061,6 +3084,7 @@ oop.inline.hpp arrayKlass.hpp
|
|||||||
oop.inline.hpp arrayOop.hpp
|
oop.inline.hpp arrayOop.hpp
|
||||||
oop.inline.hpp atomic.hpp
|
oop.inline.hpp atomic.hpp
|
||||||
oop.inline.hpp barrierSet.inline.hpp
|
oop.inline.hpp barrierSet.inline.hpp
|
||||||
|
oop.inline.hpp bytes_<arch>.hpp
|
||||||
oop.inline.hpp cardTableModRefBS.hpp
|
oop.inline.hpp cardTableModRefBS.hpp
|
||||||
oop.inline.hpp collectedHeap.inline.hpp
|
oop.inline.hpp collectedHeap.inline.hpp
|
||||||
oop.inline.hpp compactingPermGenGen.hpp
|
oop.inline.hpp compactingPermGenGen.hpp
|
||||||
@ -3674,6 +3698,7 @@ sharedRuntime.cpp interpreterRuntime.hpp
|
|||||||
sharedRuntime.cpp interpreter.hpp
|
sharedRuntime.cpp interpreter.hpp
|
||||||
sharedRuntime.cpp javaCalls.hpp
|
sharedRuntime.cpp javaCalls.hpp
|
||||||
sharedRuntime.cpp jvmtiExport.hpp
|
sharedRuntime.cpp jvmtiExport.hpp
|
||||||
|
sharedRuntime.cpp methodHandles.hpp
|
||||||
sharedRuntime.cpp jvmtiRedefineClassesTrace.hpp
|
sharedRuntime.cpp jvmtiRedefineClassesTrace.hpp
|
||||||
sharedRuntime.cpp nativeInst_<arch>.hpp
|
sharedRuntime.cpp nativeInst_<arch>.hpp
|
||||||
sharedRuntime.cpp nativeLookup.hpp
|
sharedRuntime.cpp nativeLookup.hpp
|
||||||
@ -3862,6 +3887,7 @@ stubGenerator_<arch_model>.cpp frame.inline.hpp
|
|||||||
stubGenerator_<arch_model>.cpp handles.inline.hpp
|
stubGenerator_<arch_model>.cpp handles.inline.hpp
|
||||||
stubGenerator_<arch_model>.cpp instanceOop.hpp
|
stubGenerator_<arch_model>.cpp instanceOop.hpp
|
||||||
stubGenerator_<arch_model>.cpp interpreter.hpp
|
stubGenerator_<arch_model>.cpp interpreter.hpp
|
||||||
|
stubGenerator_<arch_model>.cpp methodHandles.hpp
|
||||||
stubGenerator_<arch_model>.cpp methodOop.hpp
|
stubGenerator_<arch_model>.cpp methodOop.hpp
|
||||||
stubGenerator_<arch_model>.cpp nativeInst_<arch>.hpp
|
stubGenerator_<arch_model>.cpp nativeInst_<arch>.hpp
|
||||||
stubGenerator_<arch_model>.cpp objArrayKlass.hpp
|
stubGenerator_<arch_model>.cpp objArrayKlass.hpp
|
||||||
|
@ -36,6 +36,12 @@ constantPoolKlass.cpp psPromotionManager.inline.hpp
|
|||||||
constantPoolKlass.cpp psScavenge.inline.hpp
|
constantPoolKlass.cpp psScavenge.inline.hpp
|
||||||
constantPoolKlass.cpp parOopClosures.inline.hpp
|
constantPoolKlass.cpp parOopClosures.inline.hpp
|
||||||
|
|
||||||
|
constantPoolKlass.cpp cardTableRS.hpp
|
||||||
|
constantPoolKlass.cpp oop.pcgc.inline.hpp
|
||||||
|
constantPoolKlass.cpp psPromotionManager.inline.hpp
|
||||||
|
constantPoolKlass.cpp psScavenge.inline.hpp
|
||||||
|
constantPoolKlass.cpp parOopClosures.inline.hpp
|
||||||
|
|
||||||
genCollectedHeap.cpp concurrentMarkSweepThread.hpp
|
genCollectedHeap.cpp concurrentMarkSweepThread.hpp
|
||||||
genCollectedHeap.cpp vmCMSOperations.hpp
|
genCollectedHeap.cpp vmCMSOperations.hpp
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved.
|
* Copyright 1997-2009 Sun Microsystems, Inc. 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
|
||||||
@ -61,6 +61,7 @@ class AbstractInterpreter: AllStatic {
|
|||||||
empty, // empty method (code: _return)
|
empty, // empty method (code: _return)
|
||||||
accessor, // accessor method (code: _aload_0, _getfield, _(a|i)return)
|
accessor, // accessor method (code: _aload_0, _getfield, _(a|i)return)
|
||||||
abstract, // abstract method (throws an AbstractMethodException)
|
abstract, // abstract method (throws an AbstractMethodException)
|
||||||
|
method_handle, // java.dyn.MethodHandles::invoke
|
||||||
java_lang_math_sin, // implementation of java.lang.Math.sin (x)
|
java_lang_math_sin, // implementation of java.lang.Math.sin (x)
|
||||||
java_lang_math_cos, // implementation of java.lang.Math.cos (x)
|
java_lang_math_cos, // implementation of java.lang.Math.cos (x)
|
||||||
java_lang_math_tan, // implementation of java.lang.Math.tan (x)
|
java_lang_math_tan, // implementation of java.lang.Math.tan (x)
|
||||||
@ -91,8 +92,6 @@ class AbstractInterpreter: AllStatic {
|
|||||||
|
|
||||||
static address _rethrow_exception_entry; // rethrows an activation in previous frame
|
static address _rethrow_exception_entry; // rethrows an activation in previous frame
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
friend class AbstractInterpreterGenerator;
|
friend class AbstractInterpreterGenerator;
|
||||||
friend class InterpreterGenerator;
|
friend class InterpreterGenerator;
|
||||||
friend class InterpreterMacroAssembler;
|
friend class InterpreterMacroAssembler;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved.
|
* Copyright 1997-2009 Sun Microsystems, Inc. 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,7 @@ void CppInterpreterGenerator::generate_all() {
|
|||||||
method_entry(empty);
|
method_entry(empty);
|
||||||
method_entry(accessor);
|
method_entry(accessor);
|
||||||
method_entry(abstract);
|
method_entry(abstract);
|
||||||
|
method_entry(method_handle);
|
||||||
method_entry(java_lang_math_sin );
|
method_entry(java_lang_math_sin );
|
||||||
method_entry(java_lang_math_cos );
|
method_entry(java_lang_math_cos );
|
||||||
method_entry(java_lang_math_tan );
|
method_entry(java_lang_math_tan );
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved.
|
* Copyright 1997-2009 Sun Microsystems, Inc. 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
|
||||||
@ -168,10 +168,14 @@ AbstractInterpreter::MethodKind AbstractInterpreter::method_kind(methodHandle m)
|
|||||||
// Abstract method?
|
// Abstract method?
|
||||||
if (m->is_abstract()) return abstract;
|
if (m->is_abstract()) return abstract;
|
||||||
|
|
||||||
|
// Invoker for method handles?
|
||||||
|
if (m->is_method_handle_invoke()) return method_handle;
|
||||||
|
|
||||||
// Native method?
|
// Native method?
|
||||||
// Note: This test must come _before_ the test for intrinsic
|
// Note: This test must come _before_ the test for intrinsic
|
||||||
// methods. See also comments below.
|
// methods. See also comments below.
|
||||||
if (m->is_native()) {
|
if (m->is_native()) {
|
||||||
|
assert(!m->is_method_handle_invoke(), "overlapping bits here, watch out");
|
||||||
return m->is_synchronized() ? native_synchronized : native;
|
return m->is_synchronized() ? native_synchronized : native;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -249,6 +253,7 @@ void AbstractInterpreter::print_method_kind(MethodKind kind) {
|
|||||||
case empty : tty->print("empty" ); break;
|
case empty : tty->print("empty" ); break;
|
||||||
case accessor : tty->print("accessor" ); break;
|
case accessor : tty->print("accessor" ); break;
|
||||||
case abstract : tty->print("abstract" ); break;
|
case abstract : tty->print("abstract" ); break;
|
||||||
|
case method_handle : tty->print("method_handle" ); break;
|
||||||
case java_lang_math_sin : tty->print("java_lang_math_sin" ); break;
|
case java_lang_math_sin : tty->print("java_lang_math_sin" ); break;
|
||||||
case java_lang_math_cos : tty->print("java_lang_math_cos" ); break;
|
case java_lang_math_cos : tty->print("java_lang_math_cos" ); break;
|
||||||
case java_lang_math_tan : tty->print("java_lang_math_tan" ); break;
|
case java_lang_math_tan : tty->print("java_lang_math_tan" ); break;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved.
|
* Copyright 1997-2009 Sun Microsystems, Inc. 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
|
||||||
@ -293,6 +293,24 @@ IRT_ENTRY(void, InterpreterRuntime::throw_ClassCastException(
|
|||||||
THROW_MSG(vmSymbols::java_lang_ClassCastException(), message);
|
THROW_MSG(vmSymbols::java_lang_ClassCastException(), message);
|
||||||
IRT_END
|
IRT_END
|
||||||
|
|
||||||
|
// required can be either a MethodType, or a Class (for a single argument)
|
||||||
|
// actual (if not null) can be either a MethodHandle, or an arbitrary value (for a single argument)
|
||||||
|
IRT_ENTRY(void, InterpreterRuntime::throw_WrongMethodTypeException(JavaThread* thread,
|
||||||
|
oopDesc* required,
|
||||||
|
oopDesc* actual)) {
|
||||||
|
ResourceMark rm(thread);
|
||||||
|
char* message = SharedRuntime::generate_wrong_method_type_message(thread, required, actual);
|
||||||
|
|
||||||
|
if (ProfileTraps) {
|
||||||
|
note_trap(thread, Deoptimization::Reason_constraint, CHECK);
|
||||||
|
}
|
||||||
|
|
||||||
|
// create exception
|
||||||
|
THROW_MSG(vmSymbols::java_dyn_WrongMethodTypeException(), message);
|
||||||
|
}
|
||||||
|
IRT_END
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// exception_handler_for_exception(...) returns the continuation address,
|
// exception_handler_for_exception(...) returns the continuation address,
|
||||||
// the exception oop (via TLS) and sets the bci/bcp for the continuation.
|
// the exception oop (via TLS) and sets the bci/bcp for the continuation.
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved.
|
* Copyright 1997-2009 Sun Microsystems, Inc. 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
|
||||||
@ -66,6 +66,7 @@ class InterpreterRuntime: AllStatic {
|
|||||||
static void throw_StackOverflowError(JavaThread* thread);
|
static void throw_StackOverflowError(JavaThread* thread);
|
||||||
static void throw_ArrayIndexOutOfBoundsException(JavaThread* thread, char* name, jint index);
|
static void throw_ArrayIndexOutOfBoundsException(JavaThread* thread, char* name, jint index);
|
||||||
static void throw_ClassCastException(JavaThread* thread, oopDesc* obj);
|
static void throw_ClassCastException(JavaThread* thread, oopDesc* obj);
|
||||||
|
static void throw_WrongMethodTypeException(JavaThread* thread, oopDesc* mtype = NULL, oopDesc* mhandle = NULL);
|
||||||
static void create_exception(JavaThread* thread, char* name, char* message);
|
static void create_exception(JavaThread* thread, char* name, char* message);
|
||||||
static void create_klass_exception(JavaThread* thread, char* name, oopDesc* obj);
|
static void create_klass_exception(JavaThread* thread, char* name, oopDesc* obj);
|
||||||
static address exception_handler_for_exception(JavaThread* thread, oopDesc* exception);
|
static address exception_handler_for_exception(JavaThread* thread, oopDesc* exception);
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved.
|
* Copyright 1997-2009 Sun Microsystems, Inc. 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
|
||||||
@ -151,6 +151,20 @@ void LinkResolver::lookup_method_in_interfaces(methodHandle& result, KlassHandle
|
|||||||
result = methodHandle(THREAD, ik->lookup_method_in_all_interfaces(name(), signature()));
|
result = methodHandle(THREAD, ik->lookup_method_in_all_interfaces(name(), signature()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LinkResolver::lookup_implicit_method(methodHandle& result, KlassHandle klass, symbolHandle name, symbolHandle signature, TRAPS) {
|
||||||
|
if (EnableMethodHandles && MethodHandles::enabled() &&
|
||||||
|
name == vmSymbolHandles::invoke_name() && klass() == SystemDictionary::MethodHandle_klass()) {
|
||||||
|
methodOop result_oop = SystemDictionary::find_method_handle_invoke(signature,
|
||||||
|
Handle(),
|
||||||
|
Handle(),
|
||||||
|
CHECK);
|
||||||
|
if (result_oop != NULL) {
|
||||||
|
assert(result_oop->is_method_handle_invoke() && result_oop->signature() == signature(), "consistent");
|
||||||
|
result = methodHandle(THREAD, result_oop);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void LinkResolver::check_method_accessability(KlassHandle ref_klass,
|
void LinkResolver::check_method_accessability(KlassHandle ref_klass,
|
||||||
KlassHandle resolved_klass,
|
KlassHandle resolved_klass,
|
||||||
KlassHandle sel_klass,
|
KlassHandle sel_klass,
|
||||||
@ -239,6 +253,11 @@ void LinkResolver::resolve_method(methodHandle& resolved_method, KlassHandle res
|
|||||||
// 3. lookup method in all the interfaces implemented by the resolved klass
|
// 3. lookup method in all the interfaces implemented by the resolved klass
|
||||||
lookup_method_in_interfaces(resolved_method, resolved_klass, method_name, method_signature, CHECK);
|
lookup_method_in_interfaces(resolved_method, resolved_klass, method_name, method_signature, CHECK);
|
||||||
|
|
||||||
|
if (resolved_method.is_null()) {
|
||||||
|
// JSR 292: see if this is an implicitly generated method MethodHandle.invoke(*...)
|
||||||
|
lookup_implicit_method(resolved_method, resolved_klass, method_name, method_signature, CHECK);
|
||||||
|
}
|
||||||
|
|
||||||
if (resolved_method.is_null()) {
|
if (resolved_method.is_null()) {
|
||||||
// 4. method lookup failed
|
// 4. method lookup failed
|
||||||
ResourceMark rm(THREAD);
|
ResourceMark rm(THREAD);
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 1997-2005 Sun Microsystems, Inc. All Rights Reserved.
|
* Copyright 1997-2009 Sun Microsystems, Inc. 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
|
||||||
@ -103,6 +103,7 @@ class LinkResolver: AllStatic {
|
|||||||
static void lookup_method_in_klasses (methodHandle& result, KlassHandle klass, symbolHandle name, symbolHandle signature, TRAPS);
|
static void lookup_method_in_klasses (methodHandle& result, KlassHandle klass, symbolHandle name, symbolHandle signature, TRAPS);
|
||||||
static void lookup_instance_method_in_klasses (methodHandle& result, KlassHandle klass, symbolHandle name, symbolHandle signature, TRAPS);
|
static void lookup_instance_method_in_klasses (methodHandle& result, KlassHandle klass, symbolHandle name, symbolHandle signature, TRAPS);
|
||||||
static void lookup_method_in_interfaces (methodHandle& result, KlassHandle klass, symbolHandle name, symbolHandle signature, TRAPS);
|
static void lookup_method_in_interfaces (methodHandle& result, KlassHandle klass, symbolHandle name, symbolHandle signature, TRAPS);
|
||||||
|
static void lookup_implicit_method (methodHandle& result, KlassHandle klass, symbolHandle name, symbolHandle signature, TRAPS);
|
||||||
|
|
||||||
static int vtable_index_of_miranda_method(KlassHandle klass, symbolHandle name, symbolHandle signature, TRAPS);
|
static int vtable_index_of_miranda_method(KlassHandle klass, symbolHandle name, symbolHandle signature, TRAPS);
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved.
|
* Copyright 1997-2009 Sun Microsystems, Inc. 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
|
||||||
@ -168,6 +168,7 @@ address TemplateInterpreter::_throw_ArrayIndexOutOfBoundsException_entry = NU
|
|||||||
address TemplateInterpreter::_throw_ArrayStoreException_entry = NULL;
|
address TemplateInterpreter::_throw_ArrayStoreException_entry = NULL;
|
||||||
address TemplateInterpreter::_throw_ArithmeticException_entry = NULL;
|
address TemplateInterpreter::_throw_ArithmeticException_entry = NULL;
|
||||||
address TemplateInterpreter::_throw_ClassCastException_entry = NULL;
|
address TemplateInterpreter::_throw_ClassCastException_entry = NULL;
|
||||||
|
address TemplateInterpreter::_throw_WrongMethodType_entry = NULL;
|
||||||
address TemplateInterpreter::_throw_NullPointerException_entry = NULL;
|
address TemplateInterpreter::_throw_NullPointerException_entry = NULL;
|
||||||
address TemplateInterpreter::_throw_StackOverflowError_entry = NULL;
|
address TemplateInterpreter::_throw_StackOverflowError_entry = NULL;
|
||||||
address TemplateInterpreter::_throw_exception_entry = NULL;
|
address TemplateInterpreter::_throw_exception_entry = NULL;
|
||||||
@ -341,6 +342,7 @@ void TemplateInterpreterGenerator::generate_all() {
|
|||||||
Interpreter::_throw_ArrayStoreException_entry = generate_klass_exception_handler("java/lang/ArrayStoreException" );
|
Interpreter::_throw_ArrayStoreException_entry = generate_klass_exception_handler("java/lang/ArrayStoreException" );
|
||||||
Interpreter::_throw_ArithmeticException_entry = generate_exception_handler("java/lang/ArithmeticException" , "/ by zero");
|
Interpreter::_throw_ArithmeticException_entry = generate_exception_handler("java/lang/ArithmeticException" , "/ by zero");
|
||||||
Interpreter::_throw_ClassCastException_entry = generate_ClassCastException_handler();
|
Interpreter::_throw_ClassCastException_entry = generate_ClassCastException_handler();
|
||||||
|
Interpreter::_throw_WrongMethodType_entry = generate_WrongMethodType_handler();
|
||||||
Interpreter::_throw_NullPointerException_entry = generate_exception_handler("java/lang/NullPointerException" , NULL );
|
Interpreter::_throw_NullPointerException_entry = generate_exception_handler("java/lang/NullPointerException" , NULL );
|
||||||
Interpreter::_throw_StackOverflowError_entry = generate_StackOverflowError_handler();
|
Interpreter::_throw_StackOverflowError_entry = generate_StackOverflowError_handler();
|
||||||
}
|
}
|
||||||
@ -358,6 +360,7 @@ void TemplateInterpreterGenerator::generate_all() {
|
|||||||
method_entry(empty)
|
method_entry(empty)
|
||||||
method_entry(accessor)
|
method_entry(accessor)
|
||||||
method_entry(abstract)
|
method_entry(abstract)
|
||||||
|
method_entry(method_handle)
|
||||||
method_entry(java_lang_math_sin )
|
method_entry(java_lang_math_sin )
|
||||||
method_entry(java_lang_math_cos )
|
method_entry(java_lang_math_cos )
|
||||||
method_entry(java_lang_math_tan )
|
method_entry(java_lang_math_tan )
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved.
|
* Copyright 1997-2009 Sun Microsystems, Inc. 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
|
||||||
@ -77,6 +77,7 @@ class TemplateInterpreter: public AbstractInterpreter {
|
|||||||
friend class VMStructs;
|
friend class VMStructs;
|
||||||
friend class InterpreterMacroAssembler;
|
friend class InterpreterMacroAssembler;
|
||||||
friend class TemplateInterpreterGenerator;
|
friend class TemplateInterpreterGenerator;
|
||||||
|
friend class InterpreterGenerator;
|
||||||
friend class TemplateTable;
|
friend class TemplateTable;
|
||||||
// friend class Interpreter;
|
// friend class Interpreter;
|
||||||
public:
|
public:
|
||||||
@ -93,6 +94,7 @@ class TemplateInterpreter: public AbstractInterpreter {
|
|||||||
static address _throw_ArrayStoreException_entry;
|
static address _throw_ArrayStoreException_entry;
|
||||||
static address _throw_ArithmeticException_entry;
|
static address _throw_ArithmeticException_entry;
|
||||||
static address _throw_ClassCastException_entry;
|
static address _throw_ClassCastException_entry;
|
||||||
|
static address _throw_WrongMethodType_entry;
|
||||||
static address _throw_NullPointerException_entry;
|
static address _throw_NullPointerException_entry;
|
||||||
static address _throw_exception_entry;
|
static address _throw_exception_entry;
|
||||||
|
|
||||||
@ -137,6 +139,7 @@ class TemplateInterpreter: public AbstractInterpreter {
|
|||||||
static address remove_activation_entry() { return _remove_activation_entry; }
|
static address remove_activation_entry() { return _remove_activation_entry; }
|
||||||
static address throw_exception_entry() { return _throw_exception_entry; }
|
static address throw_exception_entry() { return _throw_exception_entry; }
|
||||||
static address throw_ArithmeticException_entry() { return _throw_ArithmeticException_entry; }
|
static address throw_ArithmeticException_entry() { return _throw_ArithmeticException_entry; }
|
||||||
|
static address throw_WrongMethodType_entry() { return _throw_WrongMethodType_entry; }
|
||||||
static address throw_NullPointerException_entry() { return _throw_NullPointerException_entry; }
|
static address throw_NullPointerException_entry() { return _throw_NullPointerException_entry; }
|
||||||
static address throw_StackOverflowError_entry() { return _throw_StackOverflowError_entry; }
|
static address throw_StackOverflowError_entry() { return _throw_StackOverflowError_entry; }
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved.
|
* Copyright 1997-2009 Sun Microsystems, Inc. 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
|
||||||
@ -48,6 +48,7 @@ class TemplateInterpreterGenerator: public AbstractInterpreterGenerator {
|
|||||||
}
|
}
|
||||||
address generate_exception_handler_common(const char* name, const char* message, bool pass_oop);
|
address generate_exception_handler_common(const char* name, const char* message, bool pass_oop);
|
||||||
address generate_ClassCastException_handler();
|
address generate_ClassCastException_handler();
|
||||||
|
address generate_WrongMethodType_handler();
|
||||||
address generate_ArrayIndexOutOfBounds_handler(const char* name);
|
address generate_ArrayIndexOutOfBounds_handler(const char* name);
|
||||||
address generate_continuation_for(TosState state);
|
address generate_continuation_for(TosState state);
|
||||||
address generate_return_entry_for(TosState state, int step);
|
address generate_return_entry_for(TosState state, int step);
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved.
|
* Copyright 2003-2009 Sun Microsystems, Inc. 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
|
||||||
@ -928,6 +928,10 @@ public:
|
|||||||
// shared classes at runtime, where constraints were previously created.
|
// shared classes at runtime, where constraints were previously created.
|
||||||
guarantee(SystemDictionary::constraints()->number_of_entries() == 0,
|
guarantee(SystemDictionary::constraints()->number_of_entries() == 0,
|
||||||
"loader constraints are not saved");
|
"loader constraints are not saved");
|
||||||
|
// Revisit and implement this if we prelink method handle call sites:
|
||||||
|
guarantee(SystemDictionary::invoke_method_table() == NULL ||
|
||||||
|
SystemDictionary::invoke_method_table()->number_of_entries() == 0,
|
||||||
|
"invoke method table is not saved");
|
||||||
GenCollectedHeap* gch = GenCollectedHeap::heap();
|
GenCollectedHeap* gch = GenCollectedHeap::heap();
|
||||||
|
|
||||||
// At this point, many classes have been loaded.
|
// At this point, many classes have been loaded.
|
||||||
|
@ -298,7 +298,11 @@ void methodKlass::oop_print_on(oop obj, outputStream* st) {
|
|||||||
m->code()->print_value_on(st);
|
m->code()->print_value_on(st);
|
||||||
st->cr();
|
st->cr();
|
||||||
}
|
}
|
||||||
if (m->is_native()) {
|
if (m->is_method_handle_invoke()) {
|
||||||
|
st->print_cr(" - invoke method type: " INTPTR_FORMAT, (address) m->method_handle_type());
|
||||||
|
// m is classified as native, but it does not have an interesting
|
||||||
|
// native_function or signature handler
|
||||||
|
} else if (m->is_native()) {
|
||||||
st->print_cr(" - native function: " INTPTR_FORMAT, m->native_function());
|
st->print_cr(" - native function: " INTPTR_FORMAT, m->native_function());
|
||||||
st->print_cr(" - signature handler: " INTPTR_FORMAT, m->signature_handler());
|
st->print_cr(" - signature handler: " INTPTR_FORMAT, m->signature_handler());
|
||||||
}
|
}
|
||||||
|
@ -304,6 +304,12 @@ void methodOopDesc::cleanup_inline_caches() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int methodOopDesc::extra_stack_words() {
|
||||||
|
// not an inline function, to avoid a header dependency on Interpreter
|
||||||
|
return extra_stack_entries() * Interpreter::stackElementSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void methodOopDesc::compute_size_of_parameters(Thread *thread) {
|
void methodOopDesc::compute_size_of_parameters(Thread *thread) {
|
||||||
symbolHandle h_signature(thread, signature());
|
symbolHandle h_signature(thread, signature());
|
||||||
ArgumentSizeComputer asc(h_signature);
|
ArgumentSizeComputer asc(h_signature);
|
||||||
@ -564,6 +570,11 @@ void methodOopDesc::set_signature_handler(address handler) {
|
|||||||
|
|
||||||
|
|
||||||
bool methodOopDesc::is_not_compilable(int comp_level) const {
|
bool methodOopDesc::is_not_compilable(int comp_level) const {
|
||||||
|
if (is_method_handle_invoke()) {
|
||||||
|
// compilers must recognize this method specially, or not at all
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
methodDataOop mdo = method_data();
|
methodDataOop mdo = method_data();
|
||||||
if (mdo != NULL
|
if (mdo != NULL
|
||||||
&& (uint)mdo->decompile_count() > (uint)PerMethodRecompilationCutoff) {
|
&& (uint)mdo->decompile_count() > (uint)PerMethodRecompilationCutoff) {
|
||||||
@ -651,7 +662,7 @@ void methodOopDesc::link_method(methodHandle h_method, TRAPS) {
|
|||||||
assert(entry != NULL, "interpreter entry must be non-null");
|
assert(entry != NULL, "interpreter entry must be non-null");
|
||||||
// Sets both _i2i_entry and _from_interpreted_entry
|
// Sets both _i2i_entry and _from_interpreted_entry
|
||||||
set_interpreter_entry(entry);
|
set_interpreter_entry(entry);
|
||||||
if (is_native()) {
|
if (is_native() && !is_method_handle_invoke()) {
|
||||||
set_native_function(
|
set_native_function(
|
||||||
SharedRuntime::native_method_throw_unsatisfied_link_error_entry(),
|
SharedRuntime::native_method_throw_unsatisfied_link_error_entry(),
|
||||||
!native_bind_event_is_interesting);
|
!native_bind_event_is_interesting);
|
||||||
@ -783,6 +794,100 @@ bool methodOopDesc::should_not_be_cached() const {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Constant pool structure for invoke methods:
|
||||||
|
enum {
|
||||||
|
_imcp_invoke_name = 1, // utf8: 'invoke'
|
||||||
|
_imcp_invoke_signature, // utf8: (variable symbolOop)
|
||||||
|
_imcp_method_type_value, // string: (variable java/dyn/MethodType, sic)
|
||||||
|
_imcp_limit
|
||||||
|
};
|
||||||
|
|
||||||
|
oop methodOopDesc::method_handle_type() const {
|
||||||
|
if (!is_method_handle_invoke()) { assert(false, "caller resp."); return NULL; }
|
||||||
|
oop mt = constants()->resolved_string_at(_imcp_method_type_value);
|
||||||
|
assert(mt->klass() == SystemDictionary::MethodType_klass(), "");
|
||||||
|
return mt;
|
||||||
|
}
|
||||||
|
|
||||||
|
jint* methodOopDesc::method_type_offsets_chain() {
|
||||||
|
static jint pchase[] = { -1, -1, -1 };
|
||||||
|
if (pchase[0] == -1) {
|
||||||
|
jint step0 = in_bytes(constants_offset());
|
||||||
|
jint step1 = (constantPoolOopDesc::header_size() + _imcp_method_type_value) * HeapWordSize;
|
||||||
|
// do this in reverse to avoid races:
|
||||||
|
OrderAccess::release_store(&pchase[1], step1);
|
||||||
|
OrderAccess::release_store(&pchase[0], step0);
|
||||||
|
}
|
||||||
|
return pchase;
|
||||||
|
}
|
||||||
|
|
||||||
|
methodHandle methodOopDesc::make_invoke_method(KlassHandle holder,
|
||||||
|
symbolHandle signature,
|
||||||
|
Handle method_type, TRAPS) {
|
||||||
|
methodHandle empty;
|
||||||
|
|
||||||
|
assert(holder() == SystemDictionary::MethodHandle_klass(),
|
||||||
|
"must be a JSR 292 magic type");
|
||||||
|
|
||||||
|
if (TraceMethodHandles) {
|
||||||
|
tty->print("Creating invoke method for ");
|
||||||
|
signature->print_value();
|
||||||
|
tty->cr();
|
||||||
|
}
|
||||||
|
|
||||||
|
constantPoolHandle cp;
|
||||||
|
{
|
||||||
|
constantPoolOop cp_oop = oopFactory::new_constantPool(_imcp_limit, IsSafeConc, CHECK_(empty));
|
||||||
|
cp = constantPoolHandle(THREAD, cp_oop);
|
||||||
|
}
|
||||||
|
cp->symbol_at_put(_imcp_invoke_name, vmSymbols::invoke_name());
|
||||||
|
cp->symbol_at_put(_imcp_invoke_signature, signature());
|
||||||
|
cp->string_at_put(_imcp_method_type_value, vmSymbols::void_signature());
|
||||||
|
cp->set_pool_holder(holder());
|
||||||
|
|
||||||
|
// set up the fancy stuff:
|
||||||
|
cp->pseudo_string_at_put(_imcp_method_type_value, method_type());
|
||||||
|
methodHandle m;
|
||||||
|
{
|
||||||
|
int flags_bits = (JVM_MH_INVOKE_BITS | JVM_ACC_PUBLIC | JVM_ACC_FINAL);
|
||||||
|
methodOop m_oop = oopFactory::new_method(0, accessFlags_from(flags_bits),
|
||||||
|
0, 0, 0, IsSafeConc, CHECK_(empty));
|
||||||
|
m = methodHandle(THREAD, m_oop);
|
||||||
|
}
|
||||||
|
m->set_constants(cp());
|
||||||
|
m->set_name_index(_imcp_invoke_name);
|
||||||
|
m->set_signature_index(_imcp_invoke_signature);
|
||||||
|
assert(m->name() == vmSymbols::invoke_name(), "");
|
||||||
|
assert(m->signature() == signature(), "");
|
||||||
|
#ifdef CC_INTERP
|
||||||
|
ResultTypeFinder rtf(signature());
|
||||||
|
m->set_result_index(rtf.type());
|
||||||
|
#endif
|
||||||
|
m->compute_size_of_parameters(THREAD);
|
||||||
|
m->set_exception_table(Universe::the_empty_int_array());
|
||||||
|
|
||||||
|
// Finally, set up its entry points.
|
||||||
|
assert(m->method_handle_type() == method_type(), "");
|
||||||
|
assert(m->can_be_statically_bound(), "");
|
||||||
|
m->set_vtable_index(methodOopDesc::nonvirtual_vtable_index);
|
||||||
|
m->link_method(m, CHECK_(empty));
|
||||||
|
|
||||||
|
#ifdef ASSERT
|
||||||
|
// Make sure the pointer chase works.
|
||||||
|
address p = (address) m();
|
||||||
|
for (jint* pchase = method_type_offsets_chain(); (*pchase) != -1; pchase++) {
|
||||||
|
p = *(address*)(p + (*pchase));
|
||||||
|
}
|
||||||
|
assert((oop)p == method_type(), "pointer chase is correct");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (TraceMethodHandles)
|
||||||
|
m->print_on(tty);
|
||||||
|
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
methodHandle methodOopDesc:: clone_with_new_data(methodHandle m, u_char* new_code, int new_code_length,
|
methodHandle methodOopDesc:: clone_with_new_data(methodHandle m, u_char* new_code, int new_code_length,
|
||||||
u_char* new_compressed_linenumber_table, int new_compressed_linenumber_size, TRAPS) {
|
u_char* new_compressed_linenumber_table, int new_compressed_linenumber_size, TRAPS) {
|
||||||
|
@ -320,6 +320,7 @@ class methodOopDesc : public oopDesc {
|
|||||||
enum VtableIndexFlag {
|
enum VtableIndexFlag {
|
||||||
// Valid vtable indexes are non-negative (>= 0).
|
// Valid vtable indexes are non-negative (>= 0).
|
||||||
// These few negative values are used as sentinels.
|
// These few negative values are used as sentinels.
|
||||||
|
highest_unused_vtable_index_value = -5,
|
||||||
invalid_vtable_index = -4, // distinct from any valid vtable index
|
invalid_vtable_index = -4, // distinct from any valid vtable index
|
||||||
garbage_vtable_index = -3, // not yet linked; no vtable layout yet
|
garbage_vtable_index = -3, // not yet linked; no vtable layout yet
|
||||||
nonvirtual_vtable_index = -2 // there is no need for vtable dispatch
|
nonvirtual_vtable_index = -2 // there is no need for vtable dispatch
|
||||||
@ -523,6 +524,18 @@ class methodOopDesc : public oopDesc {
|
|||||||
// Reflection support
|
// Reflection support
|
||||||
bool is_overridden_in(klassOop k) const;
|
bool is_overridden_in(klassOop k) const;
|
||||||
|
|
||||||
|
// JSR 292 support
|
||||||
|
bool is_method_handle_invoke() const { return access_flags().is_method_handle_invoke(); }
|
||||||
|
static methodHandle make_invoke_method(KlassHandle holder,
|
||||||
|
symbolHandle signature,
|
||||||
|
Handle method_type,
|
||||||
|
TRAPS);
|
||||||
|
// these operate only on invoke methods:
|
||||||
|
oop method_handle_type() const;
|
||||||
|
static jint* method_type_offsets_chain(); // series of pointer-offsets, terminated by -1
|
||||||
|
// presize interpreter frames for extra interpreter stack entries, if needed
|
||||||
|
static int extra_stack_entries() { return EnableMethodHandles ? (int)MethodHandlePushLimit : 0; }
|
||||||
|
static int extra_stack_words(); // = extra_stack_entries() * Interpreter::stackElementSize()
|
||||||
// RedefineClasses() support:
|
// RedefineClasses() support:
|
||||||
bool is_old() const { return access_flags().is_old(); }
|
bool is_old() const { return access_flags().is_old(); }
|
||||||
void set_is_old() { _access_flags.set_is_old(); }
|
void set_is_old() { _access_flags.set_is_old(); }
|
||||||
|
@ -263,6 +263,9 @@ class oopDesc {
|
|||||||
jdouble double_field_acquire(int offset) const;
|
jdouble double_field_acquire(int offset) const;
|
||||||
void release_double_field_put(int offset, jdouble contents);
|
void release_double_field_put(int offset, jdouble contents);
|
||||||
|
|
||||||
|
address address_field_acquire(int offset) const;
|
||||||
|
void release_address_field_put(int offset, address contents);
|
||||||
|
|
||||||
// printing functions for VM debugging
|
// printing functions for VM debugging
|
||||||
void print_on(outputStream* st) const; // First level print
|
void print_on(outputStream* st) const; // First level print
|
||||||
void print_value_on(outputStream* st) const; // Second level print.
|
void print_value_on(outputStream* st) const; // Second level print.
|
||||||
|
@ -349,6 +349,9 @@ inline void oopDesc::release_float_field_put(int offset, jfloat contents) { Or
|
|||||||
inline jdouble oopDesc::double_field_acquire(int offset) const { return OrderAccess::load_acquire(double_field_addr(offset)); }
|
inline jdouble oopDesc::double_field_acquire(int offset) const { return OrderAccess::load_acquire(double_field_addr(offset)); }
|
||||||
inline void oopDesc::release_double_field_put(int offset, jdouble contents) { OrderAccess::release_store(double_field_addr(offset), contents); }
|
inline void oopDesc::release_double_field_put(int offset, jdouble contents) { OrderAccess::release_store(double_field_addr(offset), contents); }
|
||||||
|
|
||||||
|
inline address oopDesc::address_field_acquire(int offset) const { return (address) OrderAccess::load_ptr_acquire(address_field_addr(offset)); }
|
||||||
|
inline void oopDesc::release_address_field_put(int offset, address contents) { OrderAccess::release_store_ptr(address_field_addr(offset), contents); }
|
||||||
|
|
||||||
inline int oopDesc::size_given_klass(Klass* klass) {
|
inline int oopDesc::size_given_klass(Klass* klass) {
|
||||||
int lh = klass->layout_helper();
|
int lh = klass->layout_helper();
|
||||||
int s = lh >> LogHeapWordSize; // deliver size scaled by wordSize
|
int s = lh >> LogHeapWordSize; // deliver size scaled by wordSize
|
||||||
|
@ -1043,6 +1043,51 @@ AllocateNode::AllocateNode(Compile* C, const TypeFunc *atype,
|
|||||||
//=============================================================================
|
//=============================================================================
|
||||||
uint AllocateArrayNode::size_of() const { return sizeof(*this); }
|
uint AllocateArrayNode::size_of() const { return sizeof(*this); }
|
||||||
|
|
||||||
|
Node* AllocateArrayNode::Ideal(PhaseGVN *phase, bool can_reshape) {
|
||||||
|
if (remove_dead_region(phase, can_reshape)) return this;
|
||||||
|
|
||||||
|
const Type* type = phase->type(Ideal_length());
|
||||||
|
if (type->isa_int() && type->is_int()->_hi < 0) {
|
||||||
|
if (can_reshape) {
|
||||||
|
PhaseIterGVN *igvn = phase->is_IterGVN();
|
||||||
|
// Unreachable fall through path (negative array length),
|
||||||
|
// the allocation can only throw so disconnect it.
|
||||||
|
Node* proj = proj_out(TypeFunc::Control);
|
||||||
|
Node* catchproj = NULL;
|
||||||
|
if (proj != NULL) {
|
||||||
|
for (DUIterator_Fast imax, i = proj->fast_outs(imax); i < imax; i++) {
|
||||||
|
Node *cn = proj->fast_out(i);
|
||||||
|
if (cn->is_Catch()) {
|
||||||
|
catchproj = cn->as_Multi()->proj_out(CatchProjNode::fall_through_index);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (catchproj != NULL && catchproj->outcnt() > 0 &&
|
||||||
|
(catchproj->outcnt() > 1 ||
|
||||||
|
catchproj->unique_out()->Opcode() != Op_Halt)) {
|
||||||
|
assert(catchproj->is_CatchProj(), "must be a CatchProjNode");
|
||||||
|
Node* nproj = catchproj->clone();
|
||||||
|
igvn->register_new_node_with_optimizer(nproj);
|
||||||
|
|
||||||
|
Node *frame = new (phase->C, 1) ParmNode( phase->C->start(), TypeFunc::FramePtr );
|
||||||
|
frame = phase->transform(frame);
|
||||||
|
// Halt & Catch Fire
|
||||||
|
Node *halt = new (phase->C, TypeFunc::Parms) HaltNode( nproj, frame );
|
||||||
|
phase->C->root()->add_req(halt);
|
||||||
|
phase->transform(halt);
|
||||||
|
|
||||||
|
igvn->replace_node(catchproj, phase->C->top());
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Can't correct it during regular GVN so register for IGVN
|
||||||
|
phase->C->record_for_igvn(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
// Retrieve the length from the AllocateArrayNode. Narrow the type with a
|
// Retrieve the length from the AllocateArrayNode. Narrow the type with a
|
||||||
// CastII, if appropriate. If we are not allowed to create new nodes, and
|
// CastII, if appropriate. If we are not allowed to create new nodes, and
|
||||||
// a CastII is appropriate, return NULL.
|
// a CastII is appropriate, return NULL.
|
||||||
|
@ -762,6 +762,7 @@ public:
|
|||||||
}
|
}
|
||||||
virtual int Opcode() const;
|
virtual int Opcode() const;
|
||||||
virtual uint size_of() const; // Size is bigger
|
virtual uint size_of() const; // Size is bigger
|
||||||
|
virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
|
||||||
|
|
||||||
// Dig the length operand out of a array allocation site.
|
// Dig the length operand out of a array allocation site.
|
||||||
Node* Ideal_length() {
|
Node* Ideal_length() {
|
||||||
|
@ -806,8 +806,7 @@ void PhaseMacroExpand::process_users_of_allocation(AllocateNode *alloc) {
|
|||||||
}
|
}
|
||||||
} else if (use->is_AddP()) {
|
} else if (use->is_AddP()) {
|
||||||
// raw memory addresses used only by the initialization
|
// raw memory addresses used only by the initialization
|
||||||
_igvn.hash_delete(use);
|
_igvn.replace_node(use, C->top());
|
||||||
_igvn.subsume_node(use, C->top());
|
|
||||||
} else {
|
} else {
|
||||||
assert(false, "only Initialize or AddP expected");
|
assert(false, "only Initialize or AddP expected");
|
||||||
}
|
}
|
||||||
@ -1291,8 +1290,7 @@ void PhaseMacroExpand::expand_allocate_common(
|
|||||||
if (_fallthroughcatchproj != NULL) {
|
if (_fallthroughcatchproj != NULL) {
|
||||||
ctrl = _fallthroughcatchproj->clone();
|
ctrl = _fallthroughcatchproj->clone();
|
||||||
transform_later(ctrl);
|
transform_later(ctrl);
|
||||||
_igvn.hash_delete(_fallthroughcatchproj);
|
_igvn.replace_node(_fallthroughcatchproj, result_region);
|
||||||
_igvn.subsume_node(_fallthroughcatchproj, result_region);
|
|
||||||
} else {
|
} else {
|
||||||
ctrl = top();
|
ctrl = top();
|
||||||
}
|
}
|
||||||
@ -1303,8 +1301,7 @@ void PhaseMacroExpand::expand_allocate_common(
|
|||||||
} else {
|
} else {
|
||||||
slow_result = _resproj->clone();
|
slow_result = _resproj->clone();
|
||||||
transform_later(slow_result);
|
transform_later(slow_result);
|
||||||
_igvn.hash_delete(_resproj);
|
_igvn.replace_node(_resproj, result_phi_rawoop);
|
||||||
_igvn.subsume_node(_resproj, result_phi_rawoop);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Plug slow-path into result merge point
|
// Plug slow-path into result merge point
|
||||||
@ -1613,18 +1610,15 @@ bool PhaseMacroExpand::eliminate_locking_node(AbstractLockNode *alock) {
|
|||||||
assert(membar != NULL && membar->Opcode() == Op_MemBarAcquire, "");
|
assert(membar != NULL && membar->Opcode() == Op_MemBarAcquire, "");
|
||||||
Node* ctrlproj = membar->proj_out(TypeFunc::Control);
|
Node* ctrlproj = membar->proj_out(TypeFunc::Control);
|
||||||
Node* memproj = membar->proj_out(TypeFunc::Memory);
|
Node* memproj = membar->proj_out(TypeFunc::Memory);
|
||||||
_igvn.hash_delete(ctrlproj);
|
_igvn.replace_node(ctrlproj, fallthroughproj);
|
||||||
_igvn.subsume_node(ctrlproj, fallthroughproj);
|
_igvn.replace_node(memproj, memproj_fallthrough);
|
||||||
_igvn.hash_delete(memproj);
|
|
||||||
_igvn.subsume_node(memproj, memproj_fallthrough);
|
|
||||||
|
|
||||||
// Delete FastLock node also if this Lock node is unique user
|
// Delete FastLock node also if this Lock node is unique user
|
||||||
// (a loop peeling may clone a Lock node).
|
// (a loop peeling may clone a Lock node).
|
||||||
Node* flock = alock->as_Lock()->fastlock_node();
|
Node* flock = alock->as_Lock()->fastlock_node();
|
||||||
if (flock->outcnt() == 1) {
|
if (flock->outcnt() == 1) {
|
||||||
assert(flock->unique_out() == alock, "sanity");
|
assert(flock->unique_out() == alock, "sanity");
|
||||||
_igvn.hash_delete(flock);
|
_igvn.replace_node(flock, top());
|
||||||
_igvn.subsume_node(flock, top());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1634,20 +1628,16 @@ bool PhaseMacroExpand::eliminate_locking_node(AbstractLockNode *alock) {
|
|||||||
MemBarNode* membar = ctrl->in(0)->as_MemBar();
|
MemBarNode* membar = ctrl->in(0)->as_MemBar();
|
||||||
assert(membar->Opcode() == Op_MemBarRelease &&
|
assert(membar->Opcode() == Op_MemBarRelease &&
|
||||||
mem->is_Proj() && membar == mem->in(0), "");
|
mem->is_Proj() && membar == mem->in(0), "");
|
||||||
_igvn.hash_delete(fallthroughproj);
|
_igvn.replace_node(fallthroughproj, ctrl);
|
||||||
_igvn.subsume_node(fallthroughproj, ctrl);
|
_igvn.replace_node(memproj_fallthrough, mem);
|
||||||
_igvn.hash_delete(memproj_fallthrough);
|
|
||||||
_igvn.subsume_node(memproj_fallthrough, mem);
|
|
||||||
fallthroughproj = ctrl;
|
fallthroughproj = ctrl;
|
||||||
memproj_fallthrough = mem;
|
memproj_fallthrough = mem;
|
||||||
ctrl = membar->in(TypeFunc::Control);
|
ctrl = membar->in(TypeFunc::Control);
|
||||||
mem = membar->in(TypeFunc::Memory);
|
mem = membar->in(TypeFunc::Memory);
|
||||||
}
|
}
|
||||||
|
|
||||||
_igvn.hash_delete(fallthroughproj);
|
_igvn.replace_node(fallthroughproj, ctrl);
|
||||||
_igvn.subsume_node(fallthroughproj, ctrl);
|
_igvn.replace_node(memproj_fallthrough, mem);
|
||||||
_igvn.hash_delete(memproj_fallthrough);
|
|
||||||
_igvn.subsume_node(memproj_fallthrough, mem);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1879,13 +1869,12 @@ void PhaseMacroExpand::expand_lock_node(LockNode *lock) {
|
|||||||
region->init_req(1, slow_ctrl);
|
region->init_req(1, slow_ctrl);
|
||||||
// region inputs are now complete
|
// region inputs are now complete
|
||||||
transform_later(region);
|
transform_later(region);
|
||||||
_igvn.subsume_node(_fallthroughproj, region);
|
_igvn.replace_node(_fallthroughproj, region);
|
||||||
|
|
||||||
Node *memproj = transform_later( new(C, 1) ProjNode(call, TypeFunc::Memory) );
|
Node *memproj = transform_later( new(C, 1) ProjNode(call, TypeFunc::Memory) );
|
||||||
mem_phi->init_req(1, memproj );
|
mem_phi->init_req(1, memproj );
|
||||||
transform_later(mem_phi);
|
transform_later(mem_phi);
|
||||||
_igvn.hash_delete(_memproj_fallthrough);
|
_igvn.replace_node(_memproj_fallthrough, mem_phi);
|
||||||
_igvn.subsume_node(_memproj_fallthrough, mem_phi);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------expand_unlock_node----------------------
|
//------------------------------expand_unlock_node----------------------
|
||||||
@ -1943,14 +1932,13 @@ void PhaseMacroExpand::expand_unlock_node(UnlockNode *unlock) {
|
|||||||
region->init_req(1, slow_ctrl);
|
region->init_req(1, slow_ctrl);
|
||||||
// region inputs are now complete
|
// region inputs are now complete
|
||||||
transform_later(region);
|
transform_later(region);
|
||||||
_igvn.subsume_node(_fallthroughproj, region);
|
_igvn.replace_node(_fallthroughproj, region);
|
||||||
|
|
||||||
Node *memproj = transform_later( new(C, 1) ProjNode(call, TypeFunc::Memory) );
|
Node *memproj = transform_later( new(C, 1) ProjNode(call, TypeFunc::Memory) );
|
||||||
mem_phi->init_req(1, memproj );
|
mem_phi->init_req(1, memproj );
|
||||||
mem_phi->init_req(2, mem);
|
mem_phi->init_req(2, mem);
|
||||||
transform_later(mem_phi);
|
transform_later(mem_phi);
|
||||||
_igvn.hash_delete(_memproj_fallthrough);
|
_igvn.replace_node(_memproj_fallthrough, mem_phi);
|
||||||
_igvn.subsume_node(_memproj_fallthrough, mem_phi);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------expand_macro_nodes----------------------
|
//------------------------------expand_macro_nodes----------------------
|
||||||
@ -1969,9 +1957,7 @@ bool PhaseMacroExpand::expand_macro_nodes() {
|
|||||||
if (n->is_AbstractLock()) {
|
if (n->is_AbstractLock()) {
|
||||||
success = eliminate_locking_node(n->as_AbstractLock());
|
success = eliminate_locking_node(n->as_AbstractLock());
|
||||||
} else if (n->Opcode() == Op_Opaque1 || n->Opcode() == Op_Opaque2) {
|
} else if (n->Opcode() == Op_Opaque1 || n->Opcode() == Op_Opaque2) {
|
||||||
_igvn.add_users_to_worklist(n);
|
_igvn.replace_node(n, n->in(1));
|
||||||
_igvn.hash_delete(n);
|
|
||||||
_igvn.subsume_node(n, n->in(1));
|
|
||||||
success = true;
|
success = true;
|
||||||
}
|
}
|
||||||
assert(success == (C->macro_count() < old_macro_count), "elimination reduces macro count");
|
assert(success == (C->macro_count() < old_macro_count), "elimination reduces macro count");
|
||||||
|
@ -218,6 +218,26 @@ Node *MemNode::Ideal_common(PhaseGVN *phase, bool can_reshape) {
|
|||||||
// Don't bother trying to transform a dead node
|
// Don't bother trying to transform a dead node
|
||||||
if( ctl && ctl->is_top() ) return NodeSentinel;
|
if( ctl && ctl->is_top() ) return NodeSentinel;
|
||||||
|
|
||||||
|
PhaseIterGVN *igvn = phase->is_IterGVN();
|
||||||
|
// Wait if control on the worklist.
|
||||||
|
if (ctl && can_reshape && igvn != NULL) {
|
||||||
|
Node* bol = NULL;
|
||||||
|
Node* cmp = NULL;
|
||||||
|
if (ctl->in(0)->is_If()) {
|
||||||
|
assert(ctl->is_IfTrue() || ctl->is_IfFalse(), "sanity");
|
||||||
|
bol = ctl->in(0)->in(1);
|
||||||
|
if (bol->is_Bool())
|
||||||
|
cmp = ctl->in(0)->in(1)->in(1);
|
||||||
|
}
|
||||||
|
if (igvn->_worklist.member(ctl) ||
|
||||||
|
(bol != NULL && igvn->_worklist.member(bol)) ||
|
||||||
|
(cmp != NULL && igvn->_worklist.member(cmp)) ) {
|
||||||
|
// This control path may be dead.
|
||||||
|
// Delay this memory node transformation until the control is processed.
|
||||||
|
phase->is_IterGVN()->_worklist.push(this);
|
||||||
|
return NodeSentinel; // caller will return NULL
|
||||||
|
}
|
||||||
|
}
|
||||||
// Ignore if memory is dead, or self-loop
|
// Ignore if memory is dead, or self-loop
|
||||||
Node *mem = in(MemNode::Memory);
|
Node *mem = in(MemNode::Memory);
|
||||||
if( phase->type( mem ) == Type::TOP ) return NodeSentinel; // caller will return NULL
|
if( phase->type( mem ) == Type::TOP ) return NodeSentinel; // caller will return NULL
|
||||||
@ -227,14 +247,22 @@ Node *MemNode::Ideal_common(PhaseGVN *phase, bool can_reshape) {
|
|||||||
const Type *t_adr = phase->type( address );
|
const Type *t_adr = phase->type( address );
|
||||||
if( t_adr == Type::TOP ) return NodeSentinel; // caller will return NULL
|
if( t_adr == Type::TOP ) return NodeSentinel; // caller will return NULL
|
||||||
|
|
||||||
PhaseIterGVN *igvn = phase->is_IterGVN();
|
if( can_reshape && igvn != NULL &&
|
||||||
if( can_reshape && igvn != NULL && igvn->_worklist.member(address) ) {
|
(igvn->_worklist.member(address) || phase->type(address) != adr_type()) ) {
|
||||||
// The address's base and type may change when the address is processed.
|
// The address's base and type may change when the address is processed.
|
||||||
// Delay this mem node transformation until the address is processed.
|
// Delay this mem node transformation until the address is processed.
|
||||||
phase->is_IterGVN()->_worklist.push(this);
|
phase->is_IterGVN()->_worklist.push(this);
|
||||||
return NodeSentinel; // caller will return NULL
|
return NodeSentinel; // caller will return NULL
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef ASSERT
|
||||||
|
Node* base = NULL;
|
||||||
|
if (address->is_AddP())
|
||||||
|
base = address->in(AddPNode::Base);
|
||||||
|
assert(base == NULL || t_adr->isa_rawptr() ||
|
||||||
|
!phase->type(base)->higher_equal(TypePtr::NULL_PTR), "NULL+offs not RAW address?");
|
||||||
|
#endif
|
||||||
|
|
||||||
// Avoid independent memory operations
|
// Avoid independent memory operations
|
||||||
Node* old_mem = mem;
|
Node* old_mem = mem;
|
||||||
|
|
||||||
@ -1307,22 +1335,20 @@ Node *LoadNode::Ideal(PhaseGVN *phase, bool can_reshape) {
|
|||||||
set_req(MemNode::Control,ctrl);
|
set_req(MemNode::Control,ctrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for useless control edge in some common special cases
|
|
||||||
if (in(MemNode::Control) != NULL) {
|
|
||||||
intptr_t ignore = 0;
|
intptr_t ignore = 0;
|
||||||
Node* base = AddPNode::Ideal_base_and_offset(address, phase, ignore);
|
Node* base = AddPNode::Ideal_base_and_offset(address, phase, ignore);
|
||||||
if (base != NULL
|
if (base != NULL
|
||||||
|
&& phase->C->get_alias_index(phase->type(address)->is_ptr()) != Compile::AliasIdxRaw) {
|
||||||
|
// Check for useless control edge in some common special cases
|
||||||
|
if (in(MemNode::Control) != NULL
|
||||||
&& phase->type(base)->higher_equal(TypePtr::NOTNULL)
|
&& phase->type(base)->higher_equal(TypePtr::NOTNULL)
|
||||||
&& phase->C->get_alias_index(phase->type(address)->is_ptr()) != Compile::AliasIdxRaw
|
|
||||||
&& all_controls_dominate(base, phase->C->start())) {
|
&& all_controls_dominate(base, phase->C->start())) {
|
||||||
// A method-invariant, non-null address (constant or 'this' argument).
|
// A method-invariant, non-null address (constant or 'this' argument).
|
||||||
set_req(MemNode::Control, NULL);
|
set_req(MemNode::Control, NULL);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (EliminateAutoBox && can_reshape && in(Address)->is_AddP()) {
|
if (EliminateAutoBox && can_reshape) {
|
||||||
Node* base = in(Address)->in(AddPNode::Base);
|
assert(!phase->type(base)->higher_equal(TypePtr::NULL_PTR), "the autobox pointer should be non-null");
|
||||||
if (base != NULL) {
|
|
||||||
Compile::AliasType* atp = phase->C->alias_type(adr_type());
|
Compile::AliasType* atp = phase->C->alias_type(adr_type());
|
||||||
if (is_autobox_object(atp)) {
|
if (is_autobox_object(atp)) {
|
||||||
Node* result = eliminate_autobox(phase);
|
Node* result = eliminate_autobox(phase);
|
||||||
@ -1455,10 +1481,11 @@ const Type *LoadNode::Value( PhaseTransform *phase ) const {
|
|||||||
jt = _type;
|
jt = _type;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (EliminateAutoBox) {
|
if (EliminateAutoBox && adr->is_AddP()) {
|
||||||
// The pointers in the autobox arrays are always non-null
|
// The pointers in the autobox arrays are always non-null
|
||||||
Node* base = in(Address)->in(AddPNode::Base);
|
Node* base = adr->in(AddPNode::Base);
|
||||||
if (base != NULL) {
|
if (base != NULL &&
|
||||||
|
!phase->type(base)->higher_equal(TypePtr::NULL_PTR)) {
|
||||||
Compile::AliasType* atp = phase->C->alias_type(base->adr_type());
|
Compile::AliasType* atp = phase->C->alias_type(base->adr_type());
|
||||||
if (is_autobox_cache(atp)) {
|
if (is_autobox_cache(atp)) {
|
||||||
return jt->join(TypePtr::NOTNULL)->is_ptr();
|
return jt->join(TypePtr::NOTNULL)->is_ptr();
|
||||||
|
@ -2256,7 +2256,8 @@ void Scheduling::DoScheduling() {
|
|||||||
// bother scheduling them.
|
// bother scheduling them.
|
||||||
Node *last = bb->_nodes[_bb_end];
|
Node *last = bb->_nodes[_bb_end];
|
||||||
if( last->is_Catch() ||
|
if( last->is_Catch() ||
|
||||||
(last->is_Mach() && last->as_Mach()->ideal_Opcode() == Op_Halt) ) {
|
// Exclude unreachable path case when Halt node is in a separate block.
|
||||||
|
(_bb_end > 1 && last->is_Mach() && last->as_Mach()->ideal_Opcode() == Op_Halt) ) {
|
||||||
// There must be a prior call. Skip it.
|
// There must be a prior call. Skip it.
|
||||||
while( !bb->_nodes[--_bb_end]->is_Call() ) {
|
while( !bb->_nodes[--_bb_end]->is_Call() ) {
|
||||||
assert( bb->_nodes[_bb_end]->is_Proj(), "skipping projections after expected call" );
|
assert( bb->_nodes[_bb_end]->is_Proj(), "skipping projections after expected call" );
|
||||||
|
2347
hotspot/src/share/vm/prims/methodHandles.cpp
Normal file
2347
hotspot/src/share/vm/prims/methodHandles.cpp
Normal file
File diff suppressed because it is too large
Load Diff
435
hotspot/src/share/vm/prims/methodHandles.hpp
Normal file
435
hotspot/src/share/vm/prims/methodHandles.hpp
Normal file
@ -0,0 +1,435 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
||||||
|
* CA 95054 USA or visit www.sun.com if you need additional information or
|
||||||
|
* have any questions.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
class MacroAssembler;
|
||||||
|
class Label;
|
||||||
|
class MethodHandleEntry;
|
||||||
|
|
||||||
|
class MethodHandles: AllStatic {
|
||||||
|
// JVM support for MethodHandle, MethodType, and related types
|
||||||
|
// in java.dyn and java.dyn.hotspot.
|
||||||
|
// See also javaClasses for layouts java_dyn_Method{Handle,Type,Type::Form}.
|
||||||
|
public:
|
||||||
|
enum EntryKind {
|
||||||
|
_check_mtype, // how a caller calls a MH
|
||||||
|
_wrong_method_type, // what happens when there is a type mismatch
|
||||||
|
_invokestatic_mh, // how a MH emulates invokestatic
|
||||||
|
_invokespecial_mh, // ditto for the other invokes...
|
||||||
|
_invokevirtual_mh,
|
||||||
|
_invokeinterface_mh,
|
||||||
|
_bound_ref_mh, // reference argument is bound
|
||||||
|
_bound_int_mh, // int argument is bound (via an Integer or Float)
|
||||||
|
_bound_long_mh, // long argument is bound (via a Long or Double)
|
||||||
|
_bound_ref_direct_mh, // same as above, with direct linkage to methodOop
|
||||||
|
_bound_int_direct_mh,
|
||||||
|
_bound_long_direct_mh,
|
||||||
|
|
||||||
|
_adapter_mh_first, // adapter sequence goes here...
|
||||||
|
_adapter_retype_only = _adapter_mh_first + sun_dyn_AdapterMethodHandle::OP_RETYPE_ONLY,
|
||||||
|
_adapter_check_cast = _adapter_mh_first + sun_dyn_AdapterMethodHandle::OP_CHECK_CAST,
|
||||||
|
_adapter_prim_to_prim = _adapter_mh_first + sun_dyn_AdapterMethodHandle::OP_PRIM_TO_PRIM,
|
||||||
|
_adapter_ref_to_prim = _adapter_mh_first + sun_dyn_AdapterMethodHandle::OP_REF_TO_PRIM,
|
||||||
|
_adapter_prim_to_ref = _adapter_mh_first + sun_dyn_AdapterMethodHandle::OP_PRIM_TO_REF,
|
||||||
|
_adapter_swap_args = _adapter_mh_first + sun_dyn_AdapterMethodHandle::OP_SWAP_ARGS,
|
||||||
|
_adapter_rot_args = _adapter_mh_first + sun_dyn_AdapterMethodHandle::OP_ROT_ARGS,
|
||||||
|
_adapter_dup_args = _adapter_mh_first + sun_dyn_AdapterMethodHandle::OP_DUP_ARGS,
|
||||||
|
_adapter_drop_args = _adapter_mh_first + sun_dyn_AdapterMethodHandle::OP_DROP_ARGS,
|
||||||
|
_adapter_collect_args = _adapter_mh_first + sun_dyn_AdapterMethodHandle::OP_COLLECT_ARGS,
|
||||||
|
_adapter_spread_args = _adapter_mh_first + sun_dyn_AdapterMethodHandle::OP_SPREAD_ARGS,
|
||||||
|
_adapter_flyby = _adapter_mh_first + sun_dyn_AdapterMethodHandle::OP_FLYBY,
|
||||||
|
_adapter_ricochet = _adapter_mh_first + sun_dyn_AdapterMethodHandle::OP_RICOCHET,
|
||||||
|
_adapter_mh_last = _adapter_mh_first + sun_dyn_AdapterMethodHandle::CONV_OP_LIMIT - 1,
|
||||||
|
|
||||||
|
// Optimized adapter types
|
||||||
|
|
||||||
|
// argument list reordering
|
||||||
|
_adapter_opt_swap_1,
|
||||||
|
_adapter_opt_swap_2,
|
||||||
|
_adapter_opt_rot_1_up,
|
||||||
|
_adapter_opt_rot_1_down,
|
||||||
|
_adapter_opt_rot_2_up,
|
||||||
|
_adapter_opt_rot_2_down,
|
||||||
|
// primitive single to single:
|
||||||
|
_adapter_opt_i2i, // i2c, i2z, i2b, i2s
|
||||||
|
// primitive double to single:
|
||||||
|
_adapter_opt_l2i,
|
||||||
|
_adapter_opt_d2f,
|
||||||
|
// primitive single to double:
|
||||||
|
_adapter_opt_i2l,
|
||||||
|
_adapter_opt_f2d,
|
||||||
|
// conversion between floating point and integer type is handled by Java
|
||||||
|
|
||||||
|
// reference to primitive:
|
||||||
|
_adapter_opt_unboxi,
|
||||||
|
_adapter_opt_unboxl,
|
||||||
|
|
||||||
|
// spreading (array length cases 0, 1, >=2)
|
||||||
|
_adapter_opt_spread_0,
|
||||||
|
_adapter_opt_spread_1,
|
||||||
|
_adapter_opt_spread_more,
|
||||||
|
|
||||||
|
_EK_LIMIT,
|
||||||
|
_EK_FIRST = 0
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
static bool enabled() { return _enabled; }
|
||||||
|
static void set_enabled(bool z);
|
||||||
|
|
||||||
|
private:
|
||||||
|
enum { // import sun_dyn_AdapterMethodHandle::CONV_OP_*
|
||||||
|
CONV_OP_LIMIT = sun_dyn_AdapterMethodHandle::CONV_OP_LIMIT,
|
||||||
|
CONV_OP_MASK = sun_dyn_AdapterMethodHandle::CONV_OP_MASK,
|
||||||
|
CONV_VMINFO_MASK = sun_dyn_AdapterMethodHandle::CONV_VMINFO_MASK,
|
||||||
|
CONV_VMINFO_SHIFT = sun_dyn_AdapterMethodHandle::CONV_VMINFO_SHIFT,
|
||||||
|
CONV_OP_SHIFT = sun_dyn_AdapterMethodHandle::CONV_OP_SHIFT,
|
||||||
|
CONV_DEST_TYPE_SHIFT = sun_dyn_AdapterMethodHandle::CONV_DEST_TYPE_SHIFT,
|
||||||
|
CONV_SRC_TYPE_SHIFT = sun_dyn_AdapterMethodHandle::CONV_SRC_TYPE_SHIFT,
|
||||||
|
CONV_STACK_MOVE_SHIFT = sun_dyn_AdapterMethodHandle::CONV_STACK_MOVE_SHIFT,
|
||||||
|
CONV_STACK_MOVE_MASK = sun_dyn_AdapterMethodHandle::CONV_STACK_MOVE_MASK
|
||||||
|
};
|
||||||
|
|
||||||
|
static bool _enabled;
|
||||||
|
static MethodHandleEntry* _entries[_EK_LIMIT];
|
||||||
|
static const char* _entry_names[_EK_LIMIT+1];
|
||||||
|
static bool ek_valid(EntryKind ek) { return (uint)ek < (uint)_EK_LIMIT; }
|
||||||
|
static bool conv_op_valid(int op) { return (uint)op < (uint)CONV_OP_LIMIT; }
|
||||||
|
|
||||||
|
public:
|
||||||
|
static bool have_entry(EntryKind ek) { return ek_valid(ek) && _entries[ek] != NULL; }
|
||||||
|
static MethodHandleEntry* entry(EntryKind ek) { assert(ek_valid(ek), "initialized");
|
||||||
|
return _entries[ek]; }
|
||||||
|
static const char* entry_name(EntryKind ek) { assert(ek_valid(ek), "oob");
|
||||||
|
return _entry_names[ek]; }
|
||||||
|
static EntryKind adapter_entry_kind(int op) { assert(conv_op_valid(op), "oob");
|
||||||
|
return EntryKind(_adapter_mh_first + op); }
|
||||||
|
|
||||||
|
static void init_entry(EntryKind ek, MethodHandleEntry* me) {
|
||||||
|
assert(ek_valid(ek), "oob");
|
||||||
|
assert(_entries[ek] == NULL, "no double initialization");
|
||||||
|
_entries[ek] = me;
|
||||||
|
}
|
||||||
|
|
||||||
|
static jint adapter_conversion(int conv_op, BasicType src, BasicType dest,
|
||||||
|
int stack_move = 0, int vminfo = 0) {
|
||||||
|
assert(conv_op_valid(conv_op), "oob");
|
||||||
|
jint conv = ((conv_op << CONV_OP_SHIFT)
|
||||||
|
| (src << CONV_SRC_TYPE_SHIFT)
|
||||||
|
| (dest << CONV_DEST_TYPE_SHIFT)
|
||||||
|
| (stack_move << CONV_STACK_MOVE_SHIFT)
|
||||||
|
| (vminfo << CONV_VMINFO_SHIFT)
|
||||||
|
);
|
||||||
|
assert(adapter_conversion_op(conv) == conv_op, "decode conv_op");
|
||||||
|
assert(adapter_conversion_src_type(conv) == src, "decode src");
|
||||||
|
assert(adapter_conversion_dest_type(conv) == dest, "decode dest");
|
||||||
|
assert(adapter_conversion_stack_move(conv) == stack_move, "decode stack_move");
|
||||||
|
assert(adapter_conversion_vminfo(conv) == vminfo, "decode vminfo");
|
||||||
|
return conv;
|
||||||
|
}
|
||||||
|
static int adapter_conversion_op(jint conv) {
|
||||||
|
return ((conv >> CONV_OP_SHIFT) & 0xF);
|
||||||
|
}
|
||||||
|
static BasicType adapter_conversion_src_type(jint conv) {
|
||||||
|
return (BasicType)((conv >> CONV_SRC_TYPE_SHIFT) & 0xF);
|
||||||
|
}
|
||||||
|
static BasicType adapter_conversion_dest_type(jint conv) {
|
||||||
|
return (BasicType)((conv >> CONV_DEST_TYPE_SHIFT) & 0xF);
|
||||||
|
}
|
||||||
|
static int adapter_conversion_stack_move(jint conv) {
|
||||||
|
return (conv >> CONV_STACK_MOVE_SHIFT);
|
||||||
|
}
|
||||||
|
static int adapter_conversion_vminfo(jint conv) {
|
||||||
|
return (conv >> CONV_VMINFO_SHIFT) & CONV_VMINFO_MASK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Offset in words that the interpreter stack pointer moves when an argument is pushed.
|
||||||
|
// The stack_move value must always be a multiple of this.
|
||||||
|
static int stack_move_unit() {
|
||||||
|
return frame::interpreter_frame_expression_stack_direction() * Interpreter::stackElementWords();
|
||||||
|
}
|
||||||
|
|
||||||
|
enum { CONV_VMINFO_SIGN_FLAG = 0x80 };
|
||||||
|
static int adapter_subword_vminfo(BasicType dest) {
|
||||||
|
if (dest == T_BOOLEAN) return (BitsPerInt - 1);
|
||||||
|
if (dest == T_CHAR) return (BitsPerInt - 16);
|
||||||
|
if (dest == T_BYTE) return (BitsPerInt - 8) | CONV_VMINFO_SIGN_FLAG;
|
||||||
|
if (dest == T_SHORT) return (BitsPerInt - 16) | CONV_VMINFO_SIGN_FLAG;
|
||||||
|
return 0; // case T_INT
|
||||||
|
}
|
||||||
|
// Here is the transformation the i2i adapter must perform:
|
||||||
|
static int truncate_subword_from_vminfo(jint value, int vminfo) {
|
||||||
|
jint tem = value << vminfo;
|
||||||
|
if ((vminfo & CONV_VMINFO_SIGN_FLAG) != 0) {
|
||||||
|
return (jint)tem >> vminfo;
|
||||||
|
} else {
|
||||||
|
return (juint)tem >> vminfo;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline address from_compiled_entry(EntryKind ek);
|
||||||
|
static inline address from_interpreted_entry(EntryKind ek);
|
||||||
|
|
||||||
|
// helpers for decode_method.
|
||||||
|
static methodOop decode_methodOop(methodOop m, int& decode_flags_result);
|
||||||
|
static methodOop decode_vmtarget(oop vmtarget, int vmindex, oop mtype, klassOop& receiver_limit_result, int& decode_flags_result);
|
||||||
|
static methodOop decode_MemberName(oop mname, klassOop& receiver_limit_result, int& decode_flags_result);
|
||||||
|
static methodOop decode_MethodHandle(oop mh, klassOop& receiver_limit_result, int& decode_flags_result);
|
||||||
|
static methodOop decode_DirectMethodHandle(oop mh, klassOop& receiver_limit_result, int& decode_flags_result);
|
||||||
|
static methodOop decode_BoundMethodHandle(oop mh, klassOop& receiver_limit_result, int& decode_flags_result);
|
||||||
|
static methodOop decode_AdapterMethodHandle(oop mh, klassOop& receiver_limit_result, int& decode_flags_result);
|
||||||
|
|
||||||
|
// Find out how many stack slots an mh pushes or pops.
|
||||||
|
// The result is *not* reported as a multiple of stack_move_unit();
|
||||||
|
// It is a signed net number of pushes (a difference in vmslots).
|
||||||
|
// To compare with a stack_move value, first multiply by stack_move_unit().
|
||||||
|
static int decode_MethodHandle_stack_pushes(oop mh);
|
||||||
|
|
||||||
|
public:
|
||||||
|
// working with member names
|
||||||
|
static void resolve_MemberName(Handle mname, TRAPS); // compute vmtarget/vmindex from name/type
|
||||||
|
static void expand_MemberName(Handle mname, int suppress, TRAPS); // expand defc/name/type if missing
|
||||||
|
static void init_MemberName(oop mname_oop, oop target); // compute vmtarget/vmindex from target
|
||||||
|
static void init_MemberName(oop mname_oop, methodOop m, bool do_dispatch);
|
||||||
|
static void init_MemberName(oop mname_oop, klassOop field_holder, AccessFlags mods, int offset);
|
||||||
|
static int find_MemberNames(klassOop k, symbolOop name, symbolOop sig,
|
||||||
|
int mflags, klassOop caller,
|
||||||
|
int skip, objArrayOop results);
|
||||||
|
// bit values for suppress argument to expand_MemberName:
|
||||||
|
enum { _suppress_defc = 1, _suppress_name = 2, _suppress_type = 4 };
|
||||||
|
|
||||||
|
// called from InterpreterGenerator and StubGenerator
|
||||||
|
static address generate_method_handle_interpreter_entry(MacroAssembler* _masm);
|
||||||
|
static void generate_method_handle_stub(MacroAssembler* _masm, EntryKind ek);
|
||||||
|
|
||||||
|
// argument list parsing
|
||||||
|
static int argument_slot(oop method_type, int arg);
|
||||||
|
static int argument_slot_count(oop method_type) { return argument_slot(method_type, -1); }
|
||||||
|
static int argument_slot_to_argnum(oop method_type, int argslot);
|
||||||
|
|
||||||
|
// Runtime support
|
||||||
|
enum { // bit-encoded flags from decode_method or decode_vmref
|
||||||
|
_dmf_has_receiver = 0x01, // target method has leading reference argument
|
||||||
|
_dmf_does_dispatch = 0x02, // method handle performs virtual or interface dispatch
|
||||||
|
_dmf_from_interface = 0x04, // peforms interface dispatch
|
||||||
|
_DMF_DIRECT_MASK = (_dmf_from_interface*2 - _dmf_has_receiver),
|
||||||
|
_dmf_binds_method = 0x08,
|
||||||
|
_dmf_binds_argument = 0x10,
|
||||||
|
_DMF_BOUND_MASK = (_dmf_binds_argument*2 - _dmf_binds_method),
|
||||||
|
_dmf_adapter_lsb = 0x20,
|
||||||
|
_DMF_ADAPTER_MASK = (_dmf_adapter_lsb << CONV_OP_LIMIT) - _dmf_adapter_lsb
|
||||||
|
};
|
||||||
|
static methodOop decode_method(oop x, klassOop& receiver_limit_result, int& decode_flags_result);
|
||||||
|
enum {
|
||||||
|
// format of query to getConstant:
|
||||||
|
GC_JVM_PUSH_LIMIT = 0,
|
||||||
|
GC_JVM_STACK_MOVE_LIMIT = 1,
|
||||||
|
|
||||||
|
// format of result from getTarget / encode_target:
|
||||||
|
ETF_HANDLE_OR_METHOD_NAME = 0, // all available data (immediate MH or method)
|
||||||
|
ETF_DIRECT_HANDLE = 1, // ultimate method handle (will be a DMH, may be self)
|
||||||
|
ETF_METHOD_NAME = 2, // ultimate method as MemberName
|
||||||
|
ETF_REFLECT_METHOD = 3 // ultimate method as java.lang.reflect object (sans refClass)
|
||||||
|
};
|
||||||
|
static int get_named_constant(int which, Handle name_box, TRAPS);
|
||||||
|
static oop encode_target(Handle mh, int format, TRAPS); // report vmtarget (to Java code)
|
||||||
|
static bool class_cast_needed(klassOop src, klassOop dst);
|
||||||
|
|
||||||
|
private:
|
||||||
|
// These checkers operate on a pair of whole MethodTypes:
|
||||||
|
static const char* check_method_type_change(oop src_mtype, int src_beg, int src_end,
|
||||||
|
int insert_argnum, oop insert_type,
|
||||||
|
int change_argnum, oop change_type,
|
||||||
|
int delete_argnum,
|
||||||
|
oop dst_mtype, int dst_beg, int dst_end);
|
||||||
|
static const char* check_method_type_insertion(oop src_mtype,
|
||||||
|
int insert_argnum, oop insert_type,
|
||||||
|
oop dst_mtype) {
|
||||||
|
oop no_ref = NULL;
|
||||||
|
return check_method_type_change(src_mtype, 0, -1,
|
||||||
|
insert_argnum, insert_type,
|
||||||
|
-1, no_ref, -1, dst_mtype, 0, -1);
|
||||||
|
}
|
||||||
|
static const char* check_method_type_conversion(oop src_mtype,
|
||||||
|
int change_argnum, oop change_type,
|
||||||
|
oop dst_mtype) {
|
||||||
|
oop no_ref = NULL;
|
||||||
|
return check_method_type_change(src_mtype, 0, -1, -1, no_ref,
|
||||||
|
change_argnum, change_type,
|
||||||
|
-1, dst_mtype, 0, -1);
|
||||||
|
}
|
||||||
|
static const char* check_method_type_passthrough(oop src_mtype, oop dst_mtype) {
|
||||||
|
oop no_ref = NULL;
|
||||||
|
return check_method_type_change(src_mtype, 0, -1,
|
||||||
|
-1, no_ref, -1, no_ref, -1,
|
||||||
|
dst_mtype, 0, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// These checkers operate on pairs of argument or return types:
|
||||||
|
static const char* check_argument_type_change(BasicType src_type, klassOop src_klass,
|
||||||
|
BasicType dst_type, klassOop dst_klass,
|
||||||
|
int argnum);
|
||||||
|
|
||||||
|
static const char* check_argument_type_change(oop src_type, oop dst_type,
|
||||||
|
int argnum) {
|
||||||
|
klassOop src_klass = NULL, dst_klass = NULL;
|
||||||
|
BasicType src_bt = java_lang_Class::as_BasicType(src_type, &src_klass);
|
||||||
|
BasicType dst_bt = java_lang_Class::as_BasicType(dst_type, &dst_klass);
|
||||||
|
return check_argument_type_change(src_bt, src_klass,
|
||||||
|
dst_bt, dst_klass, argnum);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char* check_return_type_change(oop src_type, oop dst_type) {
|
||||||
|
return check_argument_type_change(src_type, dst_type, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char* check_return_type_change(BasicType src_type, klassOop src_klass,
|
||||||
|
BasicType dst_type, klassOop dst_klass) {
|
||||||
|
return check_argument_type_change(src_type, src_klass, dst_type, dst_klass, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char* check_method_receiver(methodOop m, klassOop passed_recv_type);
|
||||||
|
|
||||||
|
// These verifiers can block, and will throw an error if the checking fails:
|
||||||
|
static void verify_vmslots(Handle mh, TRAPS);
|
||||||
|
static void verify_vmargslot(Handle mh, int argnum, int argslot, TRAPS);
|
||||||
|
|
||||||
|
static void verify_method_type(methodHandle m, Handle mtype,
|
||||||
|
bool has_bound_oop,
|
||||||
|
KlassHandle bound_oop_type,
|
||||||
|
TRAPS);
|
||||||
|
|
||||||
|
static void verify_method_signature(methodHandle m, Handle mtype,
|
||||||
|
int first_ptype_pos,
|
||||||
|
KlassHandle insert_ptype, TRAPS);
|
||||||
|
|
||||||
|
static void verify_DirectMethodHandle(Handle mh, methodHandle m, TRAPS);
|
||||||
|
static void verify_BoundMethodHandle(Handle mh, Handle target, int argnum,
|
||||||
|
bool direct_to_method, TRAPS);
|
||||||
|
static void verify_BoundMethodHandle_with_receiver(Handle mh, methodHandle m, TRAPS);
|
||||||
|
static void verify_AdapterMethodHandle(Handle mh, int argnum, TRAPS);
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
// Fill in the fields of a DirectMethodHandle mh. (MH.type must be pre-filled.)
|
||||||
|
static void init_DirectMethodHandle(Handle mh, methodHandle method, bool do_dispatch, TRAPS);
|
||||||
|
|
||||||
|
// Fill in the fields of a BoundMethodHandle mh. (MH.type, BMH.argument must be pre-filled.)
|
||||||
|
static void init_BoundMethodHandle(Handle mh, Handle target, int argnum, TRAPS);
|
||||||
|
static void init_BoundMethodHandle_with_receiver(Handle mh,
|
||||||
|
methodHandle original_m,
|
||||||
|
KlassHandle receiver_limit,
|
||||||
|
int decode_flags,
|
||||||
|
TRAPS);
|
||||||
|
|
||||||
|
// Fill in the fields of an AdapterMethodHandle mh. (MH.type must be pre-filled.)
|
||||||
|
static void init_AdapterMethodHandle(Handle mh, Handle target, int argnum, TRAPS);
|
||||||
|
|
||||||
|
#ifdef ASSERT
|
||||||
|
static bool spot_check_entry_names();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
private:
|
||||||
|
static methodHandle dispatch_decoded_method(methodHandle m,
|
||||||
|
KlassHandle receiver_limit,
|
||||||
|
int decode_flags,
|
||||||
|
KlassHandle receiver_klass,
|
||||||
|
TRAPS);
|
||||||
|
|
||||||
|
static bool same_basic_type_for_arguments(BasicType src, BasicType dst,
|
||||||
|
bool for_return = false);
|
||||||
|
static bool same_basic_type_for_returns(BasicType src, BasicType dst) {
|
||||||
|
return same_basic_type_for_arguments(src, dst, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
enum { // arg_mask values
|
||||||
|
_INSERT_NO_MASK = -1,
|
||||||
|
_INSERT_REF_MASK = 0,
|
||||||
|
_INSERT_INT_MASK = 1,
|
||||||
|
_INSERT_LONG_MASK = 3
|
||||||
|
};
|
||||||
|
static void insert_arg_slots(MacroAssembler* _masm,
|
||||||
|
RegisterOrConstant arg_slots,
|
||||||
|
int arg_mask,
|
||||||
|
Register rax_argslot,
|
||||||
|
Register rbx_temp, Register rdx_temp);
|
||||||
|
|
||||||
|
static void remove_arg_slots(MacroAssembler* _masm,
|
||||||
|
RegisterOrConstant arg_slots,
|
||||||
|
Register rax_argslot,
|
||||||
|
Register rbx_temp, Register rdx_temp);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// Access methods for the "entry" field of a java.dyn.MethodHandle.
|
||||||
|
// The field is primarily a jump target for compiled calls.
|
||||||
|
// However, we squirrel away some nice pointers for other uses,
|
||||||
|
// just before the jump target.
|
||||||
|
// Aspects of a method handle entry:
|
||||||
|
// - from_compiled_entry - stub used when compiled code calls the MH
|
||||||
|
// - from_interpreted_entry - stub used when the interpreter calls the MH
|
||||||
|
// - type_checking_entry - stub for runtime casting between MHForm siblings (NYI)
|
||||||
|
class MethodHandleEntry {
|
||||||
|
public:
|
||||||
|
class Data {
|
||||||
|
friend class MethodHandleEntry;
|
||||||
|
size_t _total_size; // size including Data and code stub
|
||||||
|
MethodHandleEntry* _type_checking_entry;
|
||||||
|
address _from_interpreted_entry;
|
||||||
|
MethodHandleEntry* method_entry() { return (MethodHandleEntry*)(this + 1); }
|
||||||
|
};
|
||||||
|
|
||||||
|
Data* data() { return (Data*)this - 1; }
|
||||||
|
|
||||||
|
address start_address() { return (address) data(); }
|
||||||
|
address end_address() { return start_address() + data()->_total_size; }
|
||||||
|
|
||||||
|
address from_compiled_entry() { return (address) this; }
|
||||||
|
|
||||||
|
address from_interpreted_entry() { return data()->_from_interpreted_entry; }
|
||||||
|
void set_from_interpreted_entry(address e) { data()->_from_interpreted_entry = e; }
|
||||||
|
|
||||||
|
MethodHandleEntry* type_checking_entry() { return data()->_type_checking_entry; }
|
||||||
|
void set_type_checking_entry(MethodHandleEntry* e) { data()->_type_checking_entry = e; }
|
||||||
|
|
||||||
|
void set_end_address(address end_addr) {
|
||||||
|
size_t total_size = end_addr - start_address();
|
||||||
|
assert(total_size > 0 && total_size < 0x1000, "reasonable end address");
|
||||||
|
data()->_total_size = total_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compiler support:
|
||||||
|
static int from_interpreted_entry_offset_in_bytes() {
|
||||||
|
return (int)( offset_of(Data, _from_interpreted_entry) - sizeof(Data) );
|
||||||
|
}
|
||||||
|
static int type_checking_entry_offset_in_bytes() {
|
||||||
|
return (int)( offset_of(Data, _from_interpreted_entry) - sizeof(Data) );
|
||||||
|
}
|
||||||
|
|
||||||
|
static address start_compiled_entry(MacroAssembler* _masm,
|
||||||
|
address interpreted_entry = NULL);
|
||||||
|
static MethodHandleEntry* finish_compiled_entry(MacroAssembler* masm, address start_addr);
|
||||||
|
};
|
||||||
|
|
||||||
|
address MethodHandles::from_compiled_entry(EntryKind ek) { return entry(ek)->from_compiled_entry(); }
|
||||||
|
address MethodHandles::from_interpreted_entry(EntryKind ek) { return entry(ek)->from_interpreted_entry(); }
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved.
|
* Copyright 1997-2009 Sun Microsystems, Inc. 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
|
||||||
@ -78,6 +78,7 @@ char* NativeLookup::long_jni_name(methodHandle method) {
|
|||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
void JNICALL JVM_RegisterUnsafeMethods(JNIEnv *env, jclass unsafecls);
|
void JNICALL JVM_RegisterUnsafeMethods(JNIEnv *env, jclass unsafecls);
|
||||||
|
void JNICALL JVM_RegisterMethodHandleMethods(JNIEnv *env, jclass unsafecls);
|
||||||
void JNICALL JVM_RegisterPerfMethods(JNIEnv *env, jclass perfclass);
|
void JNICALL JVM_RegisterPerfMethods(JNIEnv *env, jclass perfclass);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -97,6 +98,9 @@ static address lookup_special_native(char* jni_name) {
|
|||||||
if (strstr(jni_name, "Java_sun_misc_Unsafe_registerNatives") != NULL) {
|
if (strstr(jni_name, "Java_sun_misc_Unsafe_registerNatives") != NULL) {
|
||||||
return CAST_FROM_FN_PTR(address, JVM_RegisterUnsafeMethods);
|
return CAST_FROM_FN_PTR(address, JVM_RegisterUnsafeMethods);
|
||||||
}
|
}
|
||||||
|
if (strstr(jni_name, "Java_sun_dyn_MethodHandleNatives_registerNatives") != NULL) {
|
||||||
|
return CAST_FROM_FN_PTR(address, JVM_RegisterMethodHandleMethods);
|
||||||
|
}
|
||||||
if (strstr(jni_name, "Java_sun_misc_Perf_registerNatives") != NULL) {
|
if (strstr(jni_name, "Java_sun_misc_Perf_registerNatives") != NULL) {
|
||||||
return CAST_FROM_FN_PTR(address, JVM_RegisterPerfMethods);
|
return CAST_FROM_FN_PTR(address, JVM_RegisterPerfMethods);
|
||||||
}
|
}
|
||||||
|
@ -2627,6 +2627,13 @@ jint Arguments::parse(const JavaVMInitArgs* args) {
|
|||||||
}
|
}
|
||||||
#endif // PRODUCT
|
#endif // PRODUCT
|
||||||
|
|
||||||
|
if (EnableMethodHandles && !AnonymousClasses) {
|
||||||
|
if (!FLAG_IS_DEFAULT(AnonymousClasses)) {
|
||||||
|
warning("forcing AnonymousClasses true to enable EnableMethodHandles");
|
||||||
|
}
|
||||||
|
AnonymousClasses = true;
|
||||||
|
}
|
||||||
|
|
||||||
if (PrintGCDetails) {
|
if (PrintGCDetails) {
|
||||||
// Turn on -verbose:gc options as well
|
// Turn on -verbose:gc options as well
|
||||||
PrintGC = true;
|
PrintGC = true;
|
||||||
|
@ -3301,6 +3301,21 @@ class CommandLineFlags {
|
|||||||
product(bool, AnonymousClasses, false, \
|
product(bool, AnonymousClasses, false, \
|
||||||
"support sun.misc.Unsafe.defineAnonymousClass") \
|
"support sun.misc.Unsafe.defineAnonymousClass") \
|
||||||
\
|
\
|
||||||
|
product(bool, EnableMethodHandles, false, \
|
||||||
|
"support method handles (true by default under JSR 292)") \
|
||||||
|
\
|
||||||
|
diagnostic(intx, MethodHandlePushLimit, 3, \
|
||||||
|
"number of additional stack slots a method handle may push") \
|
||||||
|
\
|
||||||
|
develop(bool, TraceMethodHandles, false, \
|
||||||
|
"trace internal method handle operations") \
|
||||||
|
\
|
||||||
|
diagnostic(bool, VerifyMethodHandles, trueInDebug, \
|
||||||
|
"perform extra checks when constructing method handles") \
|
||||||
|
\
|
||||||
|
diagnostic(bool, OptimizeMethodHandles, true, \
|
||||||
|
"when constructing method handles, try to improve them") \
|
||||||
|
\
|
||||||
product(bool, TaggedStackInterpreter, false, \
|
product(bool, TaggedStackInterpreter, false, \
|
||||||
"Insert tags in interpreter execution stack for oopmap generaion")\
|
"Insert tags in interpreter execution stack for oopmap generaion")\
|
||||||
\
|
\
|
||||||
|
@ -37,11 +37,6 @@ JavaCallWrapper::JavaCallWrapper(methodHandle callee_method, Handle receiver, Ja
|
|||||||
guarantee(!thread->is_Compiler_thread(), "cannot make java calls from the compiler");
|
guarantee(!thread->is_Compiler_thread(), "cannot make java calls from the compiler");
|
||||||
_result = result;
|
_result = result;
|
||||||
|
|
||||||
// Make sure that that the value of the higest_lock is at least the same as the current stackpointer,
|
|
||||||
// since, the Java code is highly likely to use locks.
|
|
||||||
// Use '(address)this' to guarantee that highest_lock address is conservative and inside our thread
|
|
||||||
thread->update_highest_lock((address)this);
|
|
||||||
|
|
||||||
// Allocate handle block for Java code. This must be done before we change thread_state to _thread_in_Java_or_stub,
|
// Allocate handle block for Java code. This must be done before we change thread_state to _thread_in_Java_or_stub,
|
||||||
// since it can potentially block.
|
// since it can potentially block.
|
||||||
JNIHandleBlock* new_handles = JNIHandleBlock::allocate_block(thread);
|
JNIHandleBlock* new_handles = JNIHandleBlock::allocate_block(thread);
|
||||||
|
@ -1471,9 +1471,73 @@ char* SharedRuntime::generate_class_cast_message(
|
|||||||
return generate_class_cast_message(objName, targetKlass->external_name());
|
return generate_class_cast_message(objName, targetKlass->external_name());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char* SharedRuntime::generate_wrong_method_type_message(JavaThread* thread,
|
||||||
|
oopDesc* required,
|
||||||
|
oopDesc* actual) {
|
||||||
|
assert(EnableMethodHandles, "");
|
||||||
|
oop singleKlass = wrong_method_type_is_for_single_argument(thread, required);
|
||||||
|
if (singleKlass != NULL) {
|
||||||
|
const char* objName = "argument or return value";
|
||||||
|
if (actual != NULL) {
|
||||||
|
// be flexible about the junk passed in:
|
||||||
|
klassOop ak = (actual->is_klass()
|
||||||
|
? (klassOop)actual
|
||||||
|
: actual->klass());
|
||||||
|
objName = Klass::cast(ak)->external_name();
|
||||||
|
}
|
||||||
|
Klass* targetKlass = Klass::cast(required->is_klass()
|
||||||
|
? (klassOop)required
|
||||||
|
: java_lang_Class::as_klassOop(required));
|
||||||
|
return generate_class_cast_message(objName, targetKlass->external_name());
|
||||||
|
} else {
|
||||||
|
// %%% need to get the MethodType string, without messing around too much
|
||||||
|
// Get a signature from the invoke instruction
|
||||||
|
const char* mhName = "method handle";
|
||||||
|
const char* targetType = "the required signature";
|
||||||
|
vframeStream vfst(thread, true);
|
||||||
|
if (!vfst.at_end()) {
|
||||||
|
Bytecode_invoke* call = Bytecode_invoke_at(vfst.method(), vfst.bci());
|
||||||
|
methodHandle target;
|
||||||
|
{
|
||||||
|
EXCEPTION_MARK;
|
||||||
|
target = call->static_target(THREAD);
|
||||||
|
if (HAS_PENDING_EXCEPTION) { CLEAR_PENDING_EXCEPTION; }
|
||||||
|
}
|
||||||
|
if (target.not_null()
|
||||||
|
&& target->is_method_handle_invoke()
|
||||||
|
&& required == target->method_handle_type()) {
|
||||||
|
targetType = target->signature()->as_C_string();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
klassOop kignore; int fignore;
|
||||||
|
methodOop actual_method = MethodHandles::decode_method(actual,
|
||||||
|
kignore, fignore);
|
||||||
|
if (actual_method != NULL) {
|
||||||
|
if (actual_method->name() == vmSymbols::invoke_name())
|
||||||
|
mhName = "$";
|
||||||
|
else
|
||||||
|
mhName = actual_method->signature()->as_C_string();
|
||||||
|
if (mhName[0] == '$')
|
||||||
|
mhName = actual_method->signature()->as_C_string();
|
||||||
|
}
|
||||||
|
return generate_class_cast_message(mhName, targetType,
|
||||||
|
" cannot be called as ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
oop SharedRuntime::wrong_method_type_is_for_single_argument(JavaThread* thr,
|
||||||
|
oopDesc* required) {
|
||||||
|
if (required == NULL) return NULL;
|
||||||
|
if (required->klass() == SystemDictionary::class_klass())
|
||||||
|
return required;
|
||||||
|
if (required->is_klass())
|
||||||
|
return Klass::cast(klassOop(required))->java_mirror();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
char* SharedRuntime::generate_class_cast_message(
|
char* SharedRuntime::generate_class_cast_message(
|
||||||
const char* objName, const char* targetKlassName) {
|
const char* objName, const char* targetKlassName, const char* desc) {
|
||||||
const char* desc = " cannot be cast to ";
|
|
||||||
size_t msglen = strlen(objName) + strlen(desc) + strlen(targetKlassName) + 1;
|
size_t msglen = strlen(objName) + strlen(desc) + strlen(targetKlassName) + 1;
|
||||||
|
|
||||||
char* message = NEW_RESOURCE_ARRAY(char, msglen);
|
char* message = NEW_RESOURCE_ARRAY(char, msglen);
|
||||||
|
@ -211,11 +211,33 @@ class SharedRuntime: AllStatic {
|
|||||||
*/
|
*/
|
||||||
static char* generate_class_cast_message(JavaThread* thr, const char* name);
|
static char* generate_class_cast_message(JavaThread* thr, const char* name);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fill in the message for a WrongMethodTypeException
|
||||||
|
*
|
||||||
|
* @param thr the current thread
|
||||||
|
* @param mtype (optional) expected method type (or argument class)
|
||||||
|
* @param mhandle (optional) actual method handle (or argument)
|
||||||
|
* @return the dynamically allocated exception message
|
||||||
|
*
|
||||||
|
* BCP for the frame on top of the stack must refer to an
|
||||||
|
* 'invokevirtual' op for a method handle, or an 'invokedyamic' op.
|
||||||
|
* The caller (or one of its callers) must use a ResourceMark
|
||||||
|
* in order to correctly free the result.
|
||||||
|
*/
|
||||||
|
static char* generate_wrong_method_type_message(JavaThread* thr,
|
||||||
|
oopDesc* mtype = NULL,
|
||||||
|
oopDesc* mhandle = NULL);
|
||||||
|
|
||||||
|
/** Return non-null if the mtype is a klass or Class, not a MethodType. */
|
||||||
|
static oop wrong_method_type_is_for_single_argument(JavaThread* thr,
|
||||||
|
oopDesc* mtype);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fill in the "X cannot be cast to a Y" message for ClassCastException
|
* Fill in the "X cannot be cast to a Y" message for ClassCastException
|
||||||
*
|
*
|
||||||
* @param name the name of the class of the object attempted to be cast
|
* @param name the name of the class of the object attempted to be cast
|
||||||
* @param klass the name of the target klass attempt
|
* @param klass the name of the target klass attempt
|
||||||
|
* @param gripe the specific kind of problem being reported
|
||||||
* @return the dynamically allocated exception message (must be freed
|
* @return the dynamically allocated exception message (must be freed
|
||||||
* by the caller using a resource mark)
|
* by the caller using a resource mark)
|
||||||
*
|
*
|
||||||
@ -224,7 +246,8 @@ class SharedRuntime: AllStatic {
|
|||||||
* The caller (or one of it's callers) must use a ResourceMark
|
* The caller (or one of it's callers) must use a ResourceMark
|
||||||
* in order to correctly free the result.
|
* in order to correctly free the result.
|
||||||
*/
|
*/
|
||||||
static char* generate_class_cast_message(const char* name, const char* klass);
|
static char* generate_class_cast_message(const char* name, const char* klass,
|
||||||
|
const char* gripe = " cannot be cast to ");
|
||||||
|
|
||||||
// Resolves a call site- may patch in the destination of the call into the
|
// Resolves a call site- may patch in the destination of the call into the
|
||||||
// compiled code.
|
// compiled code.
|
||||||
|
@ -1120,7 +1120,7 @@ ObjectMonitor * ATTR ObjectSynchronizer::inflate (Thread * Self, oop object) {
|
|||||||
// m->OwnerIsThread = 1. Note that a thread can inflate an object
|
// m->OwnerIsThread = 1. Note that a thread can inflate an object
|
||||||
// that it has stack-locked -- as might happen in wait() -- directly
|
// that it has stack-locked -- as might happen in wait() -- directly
|
||||||
// with CAS. That is, we can avoid the xchg-NULL .... ST idiom.
|
// with CAS. That is, we can avoid the xchg-NULL .... ST idiom.
|
||||||
m->set_owner (mark->locker());
|
m->set_owner(mark->locker());
|
||||||
m->set_object(object);
|
m->set_object(object);
|
||||||
// TODO-FIXME: assert BasicLock->dhw != 0.
|
// TODO-FIXME: assert BasicLock->dhw != 0.
|
||||||
|
|
||||||
@ -1216,7 +1216,6 @@ void ObjectSynchronizer::fast_enter(Handle obj, BasicLock* lock, bool attempt_re
|
|||||||
assert(!obj->mark()->has_bias_pattern(), "biases should be revoked by now");
|
assert(!obj->mark()->has_bias_pattern(), "biases should be revoked by now");
|
||||||
}
|
}
|
||||||
|
|
||||||
THREAD->update_highest_lock((address)lock);
|
|
||||||
slow_enter (obj, lock, THREAD) ;
|
slow_enter (obj, lock, THREAD) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -128,7 +128,6 @@ Thread::Thread() {
|
|||||||
debug_only(_allow_allocation_count = 0;)
|
debug_only(_allow_allocation_count = 0;)
|
||||||
NOT_PRODUCT(_allow_safepoint_count = 0;)
|
NOT_PRODUCT(_allow_safepoint_count = 0;)
|
||||||
CHECK_UNHANDLED_OOPS_ONLY(_gc_locked_out_count = 0;)
|
CHECK_UNHANDLED_OOPS_ONLY(_gc_locked_out_count = 0;)
|
||||||
_highest_lock = NULL;
|
|
||||||
_jvmti_env_iteration_count = 0;
|
_jvmti_env_iteration_count = 0;
|
||||||
_vm_operation_started_count = 0;
|
_vm_operation_started_count = 0;
|
||||||
_vm_operation_completed_count = 0;
|
_vm_operation_completed_count = 0;
|
||||||
@ -790,19 +789,6 @@ void Thread::check_for_valid_safepoint_state(bool potential_vm_operation) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool Thread::lock_is_in_stack(address adr) const {
|
|
||||||
assert(Thread::current() == this, "lock_is_in_stack can only be called from current thread");
|
|
||||||
// High limit: highest_lock is set during thread execution
|
|
||||||
// Low limit: address of the local variable dummy, rounded to 4K boundary.
|
|
||||||
// (The rounding helps finding threads in unsafe mode, even if the particular stack
|
|
||||||
// frame has been popped already. Correct as long as stacks are at least 4K long and aligned.)
|
|
||||||
address end = os::current_stack_pointer();
|
|
||||||
if (_highest_lock >= adr && adr >= end) return true;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool Thread::is_in_stack(address adr) const {
|
bool Thread::is_in_stack(address adr) const {
|
||||||
assert(Thread::current() == this, "is_in_stack can only be called from current thread");
|
assert(Thread::current() == this, "is_in_stack can only be called from current thread");
|
||||||
address end = os::current_stack_pointer();
|
address end = os::current_stack_pointer();
|
||||||
@ -818,8 +804,7 @@ bool Thread::is_in_stack(address adr) const {
|
|||||||
// should be revisited, and they should be removed if possible.
|
// should be revisited, and they should be removed if possible.
|
||||||
|
|
||||||
bool Thread::is_lock_owned(address adr) const {
|
bool Thread::is_lock_owned(address adr) const {
|
||||||
if (lock_is_in_stack(adr) ) return true;
|
return (_stack_base >= adr && adr >= (_stack_base - _stack_size));
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Thread::set_as_starting_thread() {
|
bool Thread::set_as_starting_thread() {
|
||||||
@ -1664,7 +1649,7 @@ JavaThread* JavaThread::active() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool JavaThread::is_lock_owned(address adr) const {
|
bool JavaThread::is_lock_owned(address adr) const {
|
||||||
if (lock_is_in_stack(adr)) return true;
|
if (Thread::is_lock_owned(adr)) return true;
|
||||||
|
|
||||||
for (MonitorChunk* chunk = monitor_chunks(); chunk != NULL; chunk = chunk->next()) {
|
for (MonitorChunk* chunk = monitor_chunks(); chunk != NULL; chunk = chunk->next()) {
|
||||||
if (chunk->contains(adr)) return true;
|
if (chunk->contains(adr)) return true;
|
||||||
@ -2443,7 +2428,7 @@ void JavaThread::print_on(outputStream *st) const {
|
|||||||
if (thread_oop != NULL && java_lang_Thread::is_daemon(thread_oop)) st->print("daemon ");
|
if (thread_oop != NULL && java_lang_Thread::is_daemon(thread_oop)) st->print("daemon ");
|
||||||
Thread::print_on(st);
|
Thread::print_on(st);
|
||||||
// print guess for valid stack memory region (assume 4K pages); helps lock debugging
|
// print guess for valid stack memory region (assume 4K pages); helps lock debugging
|
||||||
st->print_cr("[" INTPTR_FORMAT ".." INTPTR_FORMAT "]", (intptr_t)last_Java_sp() & ~right_n_bits(12), highest_lock());
|
st->print_cr("[" INTPTR_FORMAT "]", (intptr_t)last_Java_sp() & ~right_n_bits(12));
|
||||||
if (thread_oop != NULL && JDK_Version::is_gte_jdk15x_version()) {
|
if (thread_oop != NULL && JDK_Version::is_gte_jdk15x_version()) {
|
||||||
st->print_cr(" java.lang.Thread.State: %s", java_lang_Thread::thread_status_name(thread_oop));
|
st->print_cr(" java.lang.Thread.State: %s", java_lang_Thread::thread_status_name(thread_oop));
|
||||||
}
|
}
|
||||||
@ -3733,25 +3718,13 @@ JavaThread *Threads::owning_thread_from_monitor_owner(address owner, bool doLock
|
|||||||
// heavyweight monitors, then the owner is the stack address of the
|
// heavyweight monitors, then the owner is the stack address of the
|
||||||
// Lock Word in the owning Java thread's stack.
|
// Lock Word in the owning Java thread's stack.
|
||||||
//
|
//
|
||||||
// We can't use Thread::is_lock_owned() or Thread::lock_is_in_stack() because
|
|
||||||
// those routines rely on the "current" stack pointer. That would be our
|
|
||||||
// stack pointer which is not relevant to the question. Instead we use the
|
|
||||||
// highest lock ever entered by the thread and find the thread that is
|
|
||||||
// higher than and closest to our target stack address.
|
|
||||||
//
|
|
||||||
address least_diff = 0;
|
|
||||||
bool least_diff_initialized = false;
|
|
||||||
JavaThread* the_owner = NULL;
|
JavaThread* the_owner = NULL;
|
||||||
{
|
{
|
||||||
MutexLockerEx ml(doLock ? Threads_lock : NULL);
|
MutexLockerEx ml(doLock ? Threads_lock : NULL);
|
||||||
ALL_JAVA_THREADS(q) {
|
ALL_JAVA_THREADS(q) {
|
||||||
address addr = q->highest_lock();
|
if (q->is_lock_owned(owner)) {
|
||||||
if (addr == NULL || addr < owner) continue; // thread has entered no monitors or is too low
|
|
||||||
address diff = (address)(addr - owner);
|
|
||||||
if (!least_diff_initialized || diff < least_diff) {
|
|
||||||
least_diff_initialized = true;
|
|
||||||
least_diff = diff;
|
|
||||||
the_owner = q;
|
the_owner = q;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -200,14 +200,6 @@ class Thread: public ThreadShadow {
|
|||||||
friend class ThreadLocalStorage;
|
friend class ThreadLocalStorage;
|
||||||
friend class GC_locker;
|
friend class GC_locker;
|
||||||
|
|
||||||
// In order for all threads to be able to use fast locking, we need to know the highest stack
|
|
||||||
// address of where a lock is on the stack (stacks normally grow towards lower addresses). This
|
|
||||||
// variable is initially set to NULL, indicating no locks are used by the thread. During the thread's
|
|
||||||
// execution, it will be set whenever locking can happen, i.e., when we call out to Java code or use
|
|
||||||
// an ObjectLocker. The value is never decreased, hence, it will over the lifetime of a thread
|
|
||||||
// approximate the real stackbase.
|
|
||||||
address _highest_lock; // Highest stack address where a JavaLock exist
|
|
||||||
|
|
||||||
ThreadLocalAllocBuffer _tlab; // Thread-local eden
|
ThreadLocalAllocBuffer _tlab; // Thread-local eden
|
||||||
|
|
||||||
int _vm_operation_started_count; // VM_Operation support
|
int _vm_operation_started_count; // VM_Operation support
|
||||||
@ -400,18 +392,14 @@ public:
|
|||||||
// Sweeper support
|
// Sweeper support
|
||||||
void nmethods_do();
|
void nmethods_do();
|
||||||
|
|
||||||
// Fast-locking support
|
|
||||||
address highest_lock() const { return _highest_lock; }
|
|
||||||
void update_highest_lock(address base) { if (base > _highest_lock) _highest_lock = base; }
|
|
||||||
|
|
||||||
// Tells if adr belong to this thread. This is used
|
// Tells if adr belong to this thread. This is used
|
||||||
// for checking if a lock is owned by the running thread.
|
// for checking if a lock is owned by the running thread.
|
||||||
// Warning: the method can only be used on the running thread
|
|
||||||
// Fast lock support uses these methods
|
// Used by fast lock support
|
||||||
virtual bool lock_is_in_stack(address adr) const;
|
|
||||||
virtual bool is_lock_owned(address adr) const;
|
virtual bool is_lock_owned(address adr) const;
|
||||||
|
|
||||||
// Check if address is in the stack of the thread (not just for locks).
|
// Check if address is in the stack of the thread (not just for locks).
|
||||||
|
// Warning: the method can only be used on the running thread
|
||||||
bool is_in_stack(address adr) const;
|
bool is_in_stack(address adr) const;
|
||||||
|
|
||||||
// Sets this thread as starting thread. Returns failure if thread
|
// Sets this thread as starting thread. Returns failure if thread
|
||||||
|
@ -656,7 +656,6 @@ static inline uint64_t cast_uint64_t(size_t x)
|
|||||||
\
|
\
|
||||||
volatile_nonstatic_field(Thread, _suspend_flags, uint32_t) \
|
volatile_nonstatic_field(Thread, _suspend_flags, uint32_t) \
|
||||||
nonstatic_field(Thread, _active_handles, JNIHandleBlock*) \
|
nonstatic_field(Thread, _active_handles, JNIHandleBlock*) \
|
||||||
nonstatic_field(Thread, _highest_lock, address) \
|
|
||||||
nonstatic_field(Thread, _tlab, ThreadLocalAllocBuffer) \
|
nonstatic_field(Thread, _tlab, ThreadLocalAllocBuffer) \
|
||||||
nonstatic_field(Thread, _current_pending_monitor, ObjectMonitor*) \
|
nonstatic_field(Thread, _current_pending_monitor, ObjectMonitor*) \
|
||||||
nonstatic_field(Thread, _current_pending_monitor_is_from_java, bool) \
|
nonstatic_field(Thread, _current_pending_monitor_is_from_java, bool) \
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved.
|
* Copyright 1997-2009 Sun Microsystems, Inc. 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
|
||||||
@ -47,6 +47,8 @@ enum {
|
|||||||
JVM_ACC_IS_OLD = 0x00010000, // RedefineClasses() has replaced this method
|
JVM_ACC_IS_OLD = 0x00010000, // RedefineClasses() has replaced this method
|
||||||
JVM_ACC_IS_OBSOLETE = 0x00020000, // RedefineClasses() has made method obsolete
|
JVM_ACC_IS_OBSOLETE = 0x00020000, // RedefineClasses() has made method obsolete
|
||||||
JVM_ACC_IS_PREFIXED_NATIVE = 0x00040000, // JVMTI has prefixed this native method
|
JVM_ACC_IS_PREFIXED_NATIVE = 0x00040000, // JVMTI has prefixed this native method
|
||||||
|
JVM_MH_INVOKE_BITS // = 0x10001100 // MethodHandle.invoke quasi-native
|
||||||
|
= (JVM_ACC_NATIVE | JVM_ACC_SYNTHETIC | JVM_ACC_MONITOR_MATCH),
|
||||||
|
|
||||||
// klassOop flags
|
// klassOop flags
|
||||||
JVM_ACC_HAS_MIRANDA_METHODS = 0x10000000, // True if this class has miranda methods in it's vtable
|
JVM_ACC_HAS_MIRANDA_METHODS = 0x10000000, // True if this class has miranda methods in it's vtable
|
||||||
@ -72,6 +74,7 @@ enum {
|
|||||||
|
|
||||||
// flags accepted by set_field_flags()
|
// flags accepted by set_field_flags()
|
||||||
JVM_ACC_FIELD_FLAGS = 0x00008000 | JVM_ACC_WRITTEN_FLAGS
|
JVM_ACC_FIELD_FLAGS = 0x00008000 | JVM_ACC_WRITTEN_FLAGS
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -114,6 +117,15 @@ class AccessFlags VALUE_OBJ_CLASS_SPEC {
|
|||||||
bool is_obsolete () const { return (_flags & JVM_ACC_IS_OBSOLETE ) != 0; }
|
bool is_obsolete () const { return (_flags & JVM_ACC_IS_OBSOLETE ) != 0; }
|
||||||
bool is_prefixed_native () const { return (_flags & JVM_ACC_IS_PREFIXED_NATIVE ) != 0; }
|
bool is_prefixed_native () const { return (_flags & JVM_ACC_IS_PREFIXED_NATIVE ) != 0; }
|
||||||
|
|
||||||
|
// JSR 292: A method of the form MethodHandle.invoke(A...)R method is
|
||||||
|
// neither bytecoded nor a JNI native, but rather a fast call through
|
||||||
|
// a lightweight method handle object. Because it is not bytecoded,
|
||||||
|
// it has the native bit set, but the monitor-match bit is also set
|
||||||
|
// to distinguish it from a JNI native (which never has the match bit set).
|
||||||
|
// The synthetic bit is also present, because such a method is never
|
||||||
|
// explicitly defined in Java code.
|
||||||
|
bool is_method_handle_invoke () const { return (_flags & JVM_MH_INVOKE_BITS) == JVM_MH_INVOKE_BITS; }
|
||||||
|
|
||||||
// klassOop flags
|
// klassOop flags
|
||||||
bool has_miranda_methods () const { return (_flags & JVM_ACC_HAS_MIRANDA_METHODS ) != 0; }
|
bool has_miranda_methods () const { return (_flags & JVM_ACC_HAS_MIRANDA_METHODS ) != 0; }
|
||||||
bool has_vanilla_constructor () const { return (_flags & JVM_ACC_HAS_VANILLA_CONSTRUCTOR) != 0; }
|
bool has_vanilla_constructor () const { return (_flags & JVM_ACC_HAS_VANILLA_CONSTRUCTOR) != 0; }
|
||||||
@ -199,6 +211,14 @@ class AccessFlags VALUE_OBJ_CLASS_SPEC {
|
|||||||
jshort as_short() { return (jshort)_flags; }
|
jshort as_short() { return (jshort)_flags; }
|
||||||
jint as_int() { return _flags; }
|
jint as_int() { return _flags; }
|
||||||
|
|
||||||
|
inline friend AccessFlags accessFlags_from(jint flags);
|
||||||
|
|
||||||
// Printing/debugging
|
// Printing/debugging
|
||||||
void print_on(outputStream* st) const PRODUCT_RETURN;
|
void print_on(outputStream* st) const PRODUCT_RETURN;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
inline AccessFlags accessFlags_from(jint flags) {
|
||||||
|
AccessFlags af;
|
||||||
|
af._flags = flags;
|
||||||
|
return af;
|
||||||
|
}
|
||||||
|
@ -237,6 +237,9 @@ class Exceptions {
|
|||||||
#define THROW_ARG_0(name, signature, arg) THROW_ARG_(name, signature, arg, 0)
|
#define THROW_ARG_0(name, signature, arg) THROW_ARG_(name, signature, arg, 0)
|
||||||
#define THROW_MSG_CAUSE_0(name, message, cause) THROW_MSG_CAUSE_(name, message, cause, 0)
|
#define THROW_MSG_CAUSE_0(name, message, cause) THROW_MSG_CAUSE_(name, message, cause, 0)
|
||||||
|
|
||||||
|
#define THROW_NULL(name) THROW_(name, NULL)
|
||||||
|
#define THROW_MSG_NULL(name, message) THROW_MSG_(name, message, NULL)
|
||||||
|
|
||||||
// The CATCH macro checks that no exception has been thrown by a function; it is used at
|
// The CATCH macro checks that no exception has been thrown by a function; it is used at
|
||||||
// call sites about which is statically known that the callee cannot throw an exception
|
// call sites about which is statically known that the callee cannot throw an exception
|
||||||
// even though it is declared with TRAPS.
|
// even though it is declared with TRAPS.
|
||||||
|
@ -408,6 +408,15 @@ inline bool is_java_primitive(BasicType t) {
|
|||||||
return T_BOOLEAN <= t && t <= T_LONG;
|
return T_BOOLEAN <= t && t <= T_LONG;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline bool is_subword_type(BasicType t) {
|
||||||
|
// these guys are processed exactly like T_INT in calling sequences:
|
||||||
|
return (t == T_BOOLEAN || t == T_CHAR || t == T_BYTE || t == T_SHORT);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool is_signed_subword_type(BasicType t) {
|
||||||
|
return (t == T_BYTE || t == T_SHORT);
|
||||||
|
}
|
||||||
|
|
||||||
// Convert a char from a classfile signature to a BasicType
|
// Convert a char from a classfile signature to a BasicType
|
||||||
inline BasicType char2type(char c) {
|
inline BasicType char2type(char c) {
|
||||||
switch( c ) {
|
switch( c ) {
|
||||||
|
44
hotspot/test/compiler/6539464/Test.java
Normal file
44
hotspot/test/compiler/6539464/Test.java
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
||||||
|
* CA 95054 USA or visit www.sun.com if you need additional information or
|
||||||
|
* have any questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @test
|
||||||
|
* @bug 6539464
|
||||||
|
* @summary Math.log() produces inconsistent results between successive runs.
|
||||||
|
*
|
||||||
|
* @run main/othervm -Xcomp -XX:CompileOnly=Test.main Test
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class Test {
|
||||||
|
static double log_value = 17197;
|
||||||
|
static double log_result = Math.log(log_value);
|
||||||
|
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
for (int i = 0; i < 1000000; i++) {
|
||||||
|
double log_result2 = Math.log(log_value);
|
||||||
|
if (log_result2 != log_result) {
|
||||||
|
throw new InternalError("Math.log produces inconsistent results: " + log_result2 + " != " + log_result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -26,7 +26,7 @@
|
|||||||
* @bug 6636138
|
* @bug 6636138
|
||||||
* @summary SuperWord::co_locate_pack(Node_List* p) generates memory graph that leads to memory order violation.
|
* @summary SuperWord::co_locate_pack(Node_List* p) generates memory graph that leads to memory order violation.
|
||||||
*
|
*
|
||||||
* @run main/othervm -server -Xbatch -XX:CompileOnly=Test1.init -XX:+UseSuperword Test1
|
* @run main/othervm -server -Xbatch -XX:CompileOnly=Test1.init Test1
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class Test1 {
|
class Test1 {
|
||||||
|
@ -26,7 +26,7 @@
|
|||||||
* @bug 6636138
|
* @bug 6636138
|
||||||
* @summary SuperWord::co_locate_pack(Node_List* p) generates memory graph that leads to memory order violation.
|
* @summary SuperWord::co_locate_pack(Node_List* p) generates memory graph that leads to memory order violation.
|
||||||
*
|
*
|
||||||
* @run main/othervm -server -Xbatch -XX:CompileOnly=Test2.shift -XX:+UseSuperword Test2
|
* @run main/othervm -server -Xbatch -XX:CompileOnly=Test2.shift Test2
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class Test2 {
|
class Test2 {
|
||||||
|
849
hotspot/test/compiler/6711117/Test.java
Normal file
849
hotspot/test/compiler/6711117/Test.java
Normal file
@ -0,0 +1,849 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
||||||
|
* CA 95054 USA or visit www.sun.com if you need additional information or
|
||||||
|
* have any questions.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @test
|
||||||
|
* @bug 6711117
|
||||||
|
* @summary Assertion in 64bit server vm (flat != TypePtr::BOTTOM,"cannot alias-analyze an untyped ptr")
|
||||||
|
* @run main/othervm -Xcomp -XX:+IgnoreUnrecognizedVMOptions -XX:+AggressiveOpts -XX:+UseCompressedOops Test
|
||||||
|
*/
|
||||||
|
|
||||||
|
final class Test_Class_0 {
|
||||||
|
final static char var_1 = 'E';
|
||||||
|
short var_2 = 16213;
|
||||||
|
final static String var_3 = "jiiibmmsk";
|
||||||
|
|
||||||
|
|
||||||
|
public Test_Class_0()
|
||||||
|
{
|
||||||
|
var_2 ^= 'M';
|
||||||
|
final String var_18 = var_3;
|
||||||
|
var_2--;
|
||||||
|
var_2 |= (byte)('D' / (byte)var_2) - ((byte)1.6680514E38F << + ((byte)'O') & 7320241275829036032L);
|
||||||
|
func_2(((!false & false | false ? true : false) ? true : true | !true) ? var_2 : 834513107);
|
||||||
|
var_2 >>>= var_1;
|
||||||
|
"smiosoebk".codePointCount(true ^ (false ^ ! !false) ? (byte)- ((byte)430513598) : + ((byte)'_'), ~ (true ? (byte)']' : (byte)-2.8272547997066827E307));
|
||||||
|
var_2 -= true ? var_1 : var_1;
|
||||||
|
var_2 ^= var_1;
|
||||||
|
var_2 &= (var_2 |= ~ ((byte)(var_2 *= var_2)));
|
||||||
|
long var_19 = 0L;
|
||||||
|
short var_20 = var_2 += 'P';
|
||||||
|
while (var_19 < 1)
|
||||||
|
{
|
||||||
|
var_2 ^= true ? (byte)- +1.2219539475209E308 : (byte)1.2748408476894178E308;
|
||||||
|
var_19++;
|
||||||
|
var_2 = (byte)((1489358000 == (var_20 | 7816908224315289600L) ? var_1 : var_1) ^ var_19);
|
||||||
|
var_20--;
|
||||||
|
}
|
||||||
|
var_20 -= 'f';
|
||||||
|
var_20 <<= (((new Test_Class_0[(byte)var_20])[(byte)var_2]).var_2 *= false ? 'g' : 'x');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static float func_0()
|
||||||
|
{
|
||||||
|
((new Test_Class_0[(byte)7.774490796987995E307])[(byte)'v']).var_2 <<= false ^ !false ? (short)'v' : "".codePointCount(594464985, 579036736);
|
||||||
|
((new Test_Class_0[(byte)(((new Test_Class_0[(byte)1361657519])[(byte)2.3703713E38F]).var_2-- - (short)3.5589388134844986E307)])[((true ? !true : false) ^ (!false ? true : !true) ? !false : false) ? (byte)7.047289E37F : (byte)- ((byte)2.6620062118475144E307)]).var_2 *= 3273943364390983680L;
|
||||||
|
--((new Test_Class_0[false ? (byte)(short)1.4965069E36F : (byte)286322022])[(byte)- ((byte)2.742619E38F)]).var_2;
|
||||||
|
long var_4;
|
||||||
|
{
|
||||||
|
double var_5;
|
||||||
|
}
|
||||||
|
var_4 = (byte)1.3509231E38F;
|
||||||
|
((new Test_Class_0[(byte)'_'])[('g' | 1427123046096105472L) < var_1 >> (byte)(int)(byte)7697616672011068416L ? (byte)var_1 : (byte)1251856579]).var_2--;
|
||||||
|
switch (--((new Test_Class_0[(byte)5.0656327E37F])[(byte)'e']).var_2 != ++((new Test_Class_0[(byte)(int)1.3728667270920175E308])[(byte)+ + -1.6338179407381788E308]).var_2 | !var_3.equalsIgnoreCase("iiwwwln") ? (false ? (byte)1.8291216E38F : (byte)4.778575546584698E307) : (byte)1048254181)
|
||||||
|
{
|
||||||
|
case 99:
|
||||||
|
|
||||||
|
}
|
||||||
|
{
|
||||||
|
byte var_6 = 13;
|
||||||
|
}
|
||||||
|
var_4 = --((new Test_Class_0[!var_3.endsWith("qaoioore") ^ false ? (byte)2.827362738392923E307 : (byte)~4890175967151316992L])[(byte)(short)var_1]).var_2;
|
||||||
|
++((new Test_Class_0[(byte)(1.0075552E38F + (short)2083553541)])[(byte)(short)(byte)(short)1.6872205E38F]).var_2;
|
||||||
|
return ((new Test_Class_0[(byte)var_1])[(byte)+ +5760973323384750080L]).var_2 - (false ? (byte)'i' : (var_4 = (short)1.2458781351126844E308) + 2.131006E38F);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static long func_1(String arg_0, Object arg_1, final long arg_2)
|
||||||
|
{
|
||||||
|
arg_0 = false ? arg_0 : "fgbrpgsq";
|
||||||
|
((new Test_Class_0[(byte)- ((byte)']')])[false ? (byte)757239006 : (byte)1866002020]).var_2 ^= (short)(true ? (byte)(((new Test_Class_0[(byte)1416194866])[(byte)1.2309887362692395E308]).var_2 >>= (int)~ ~ ~arg_2) : (byte)5804970709284726784L);
|
||||||
|
final long var_7 = (long)(- + ((long)+ - + - -2.5396583E38F) - - +1.8770165E38F % 2472404173160781824L < --((new Test_Class_0[(byte)5.569360482341752E307])[(byte)(double)(byte)8131142397821553664L]).var_2 ^ true ? (false ? (byte)- -1.163275451591927E308 : (byte)var_1) : (false ? (byte)1843746036 : (byte)1.0209668642291047E308));
|
||||||
|
arg_0 = (arg_0 = arg_0.substring(699480935));
|
||||||
|
switch (((new Test_Class_0[(byte)(5415649243316856832L >> 861936806)])[true | true & !false ? (byte)(short)- -7.785169683394908E307 : (byte)+ ((byte)arg_2)]).var_2++)
|
||||||
|
{
|
||||||
|
case 42:
|
||||||
|
|
||||||
|
case 102:
|
||||||
|
|
||||||
|
}
|
||||||
|
arg_1 = (true || false ? false : true) ? (arg_0 = (arg_0 = "jbfaru")) : arg_0;
|
||||||
|
arg_1 = new byte[(byte)2.669957E38F];
|
||||||
|
boolean var_8 = ! ((false ? (short)1.4259420861834744E308 : (short)7.352115508157158E307) != 1.7635658130722812E308);
|
||||||
|
arg_1 = new Object[(byte)- ((byte)(short)1.8950693E38F)];
|
||||||
|
arg_0 = arg_0;
|
||||||
|
return (byte)1.4762239057269886E308 & 4923938844759802880L;
|
||||||
|
}
|
||||||
|
|
||||||
|
double[][] func_2(final int arg_0)
|
||||||
|
{
|
||||||
|
var_2 >>>= (var_2 >>= var_2++);
|
||||||
|
float var_9 = 0F;
|
||||||
|
var_2 %= var_2;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
++var_2;
|
||||||
|
var_9++;
|
||||||
|
var_2++;
|
||||||
|
} while (true && (var_9 < 1 && false));
|
||||||
|
double var_10 = 0;
|
||||||
|
final int var_11 = 11903395;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
--var_2;
|
||||||
|
var_10++;
|
||||||
|
++var_2;
|
||||||
|
} while ((false & true || false) && (var_10 < 2 && ~ ((byte)'[') == (byte)(1.1943192E38F % ('c' << var_1) % (byte)((var_2 |= var_2) + 591679039 / ~5932100696448264192L))));
|
||||||
|
String var_12 = "jkwnk";
|
||||||
|
var_12 = var_3;
|
||||||
|
var_12 = (var_12 = (var_12 = var_3));
|
||||||
|
var_12 = "qrhdwx";
|
||||||
|
var_12 = var_12;
|
||||||
|
short var_13 = (true && true) ^ true | ! (!true || 1646418779 <= (byte)var_1) ? var_2 : var_2;
|
||||||
|
return new double[(byte)var_1][true || false ^ !true ^ true ? (byte)arg_0 : (byte)var_10];
|
||||||
|
}
|
||||||
|
|
||||||
|
private final int func_3()
|
||||||
|
{
|
||||||
|
long var_14 = 's' * (~ ~6656240461354863616L * 3151744928387344384L) << ~ (((var_2 >>>= 6600935261424147456L) % 1798503219359364096L | - ~3832249967647077376L / - ((byte)~1529201870915276800L)) / var_2);
|
||||||
|
{
|
||||||
|
var_14 |= !false | (byte)1078230528 >= (byte)1.3972878565417081E308 | (true | !true & !true & !false) ? var_1 : '_';
|
||||||
|
}
|
||||||
|
long var_15 = 7589204885152164864L;
|
||||||
|
var_2 ^= (var_1 < (byte)'r' ? 475314139 : 'Z') <= 1943074698 ? 'h' : var_1;
|
||||||
|
return 'V' * (false ? (byte)5.498204E37F : (byte)1.0137001669765466E308);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static boolean func_4(boolean arg_0, byte arg_1, boolean arg_2)
|
||||||
|
{
|
||||||
|
arg_1++;
|
||||||
|
arg_1 &= (((((new Test_Class_0[arg_1][arg_1][arg_1])[arg_1])[arg_1])[arg_1]).var_2 |= arg_2 ? (short)~3038084056596854784L : (short)+ (arg_1 = arg_1));
|
||||||
|
arg_0 |= true;
|
||||||
|
arg_1 %= (arg_1 |= ((new Test_Class_0[arg_1])[arg_1]).var_2--);
|
||||||
|
if (false)
|
||||||
|
{
|
||||||
|
arg_0 |= arg_2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
++(((new Test_Class_0[arg_1][arg_1][arg_1])[arg_1 += var_1])[(!arg_2 | (arg_0 &= false)) ^ (arg_0 | arg_0) ? arg_1 : (arg_1 <<= 3192041751921364992L)][arg_1 /= arg_1]).var_2;
|
||||||
|
}
|
||||||
|
arg_1 &= +(new byte[arg_1])[arg_1];
|
||||||
|
arg_1 <<= 3632133838014908416L;
|
||||||
|
byte[] var_16 = (new byte[arg_1][arg_1--])[arg_1];
|
||||||
|
long var_17;
|
||||||
|
arg_1 ^= ~ arg_1--;
|
||||||
|
arg_0 ^= (arg_2 ^= 1186877294 >= ((new Test_Class_0[arg_1][arg_1])[arg_1][arg_1]).var_2) & arg_2;
|
||||||
|
return var_3.startsWith(var_3);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
String result = "[\n";
|
||||||
|
result += "Test_Class_0.var_2 = "; result += Test.Printer.print(var_2);
|
||||||
|
result += "\n";
|
||||||
|
result += "Test_Class_0.var_1 = "; result += Test.Printer.print(var_1);
|
||||||
|
result += "\n";
|
||||||
|
result += "Test_Class_0.var_3 = "; result += Test.Printer.print(var_3);
|
||||||
|
result += "";
|
||||||
|
result += "\n]";
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class Test_Class_1 {
|
||||||
|
static int var_21 = 670918363;
|
||||||
|
final float var_22 = 8.650798E37F;
|
||||||
|
static int var_23 = 1774228457;
|
||||||
|
final int var_24 = 1282736974;
|
||||||
|
final byte var_25 = !false & false | true ? (byte)7.677121016144275E307 : (byte)'r';
|
||||||
|
static long var_26 = 2939310115459338240L;
|
||||||
|
final long var_27 = var_25 - 7555453173456381952L;
|
||||||
|
double var_28;
|
||||||
|
static String var_29;
|
||||||
|
|
||||||
|
|
||||||
|
public Test_Class_1()
|
||||||
|
{
|
||||||
|
var_29 = Test_Class_0.var_3;
|
||||||
|
((false ? false || ! !true : ! (! !true & !true)) ? new Test_Class_0() : new Test_Class_0()).var_2++;
|
||||||
|
var_23 -= 2.963694E38F;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
String result = "[\n";
|
||||||
|
result += "Test_Class_1.var_21 = "; result += Test.Printer.print(var_21);
|
||||||
|
result += "\n";
|
||||||
|
result += "Test_Class_1.var_23 = "; result += Test.Printer.print(var_23);
|
||||||
|
result += "\n";
|
||||||
|
result += "Test_Class_1.var_24 = "; result += Test.Printer.print(var_24);
|
||||||
|
result += "\n";
|
||||||
|
result += "Test_Class_1.var_26 = "; result += Test.Printer.print(var_26);
|
||||||
|
result += "\n";
|
||||||
|
result += "Test_Class_1.var_27 = "; result += Test.Printer.print(var_27);
|
||||||
|
result += "\n";
|
||||||
|
result += "Test_Class_1.var_28 = "; result += Test.Printer.print(var_28);
|
||||||
|
result += "\n";
|
||||||
|
result += "Test_Class_1.var_22 = "; result += Test.Printer.print(var_22);
|
||||||
|
result += "\n";
|
||||||
|
result += "Test_Class_1.var_25 = "; result += Test.Printer.print(var_25);
|
||||||
|
result += "\n";
|
||||||
|
result += "Test_Class_1.var_29 = "; result += Test.Printer.print(var_29);
|
||||||
|
result += "";
|
||||||
|
result += "\n]";
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class Test_Class_2 {
|
||||||
|
double var_30;
|
||||||
|
static byte var_31;
|
||||||
|
static char var_32;
|
||||||
|
float var_33;
|
||||||
|
double var_34 = !false & (true ? true : ! !true && false) ? 'q' - 4789231433793305600L - (var_33 = -1.0677024E38F) : 2.65473560313378E307;
|
||||||
|
final double var_35 = ~Test_Class_1.var_26 == 5.145660681364723E307 | false ? 1.4134775E38F : 1.77223030708671E308;
|
||||||
|
final int var_36 = Test_Class_1.var_23 |= Test_Class_1.var_21++;
|
||||||
|
|
||||||
|
|
||||||
|
public Test_Class_2()
|
||||||
|
{
|
||||||
|
Test_Class_0.var_3.replace(Test_Class_0.var_1, 'Q');
|
||||||
|
var_32 = (var_32 = (var_32 = '_'));
|
||||||
|
Test_Class_1.var_26 |= Test_Class_0.var_1;
|
||||||
|
Test_Class_1.var_29 = (Test_Class_1.var_29 = Test_Class_0.var_3);
|
||||||
|
var_32 = Test_Class_0.var_1;
|
||||||
|
var_33 = ((new Test_Class_0[(byte)851412948463452160L])[var_31 = new Test_Class_1().var_25]).var_2;
|
||||||
|
var_33 = ! (((!false | false) & (false || !true) ? false : ! !false) | false) ? new Test_Class_1().var_25 : (var_31 = new Test_Class_1().var_25);
|
||||||
|
float var_38 = 0F;
|
||||||
|
var_34 /= 5336005797857974272L;
|
||||||
|
for ("ccnyq".endsWith((new String[(byte)Test_Class_1.var_26])[var_31 = (var_31 = (var_31 = (byte)4.7927775E37F))]); var_38 < 2; var_32 = '^' <= Test_Class_0.var_1 ^ true ? (var_32 = Test_Class_0.var_1) : (var_32 = 'V'))
|
||||||
|
{
|
||||||
|
var_32 = true ? 'a' : (var_32 = Test_Class_0.var_1);
|
||||||
|
var_38++;
|
||||||
|
var_33 = new Test_Class_1().var_24;
|
||||||
|
var_32 = ! (true || true ? !false : (short)3.2844383E37F < 2.1400662E38F) ? (char)1.2691096999143248E308 : (! !false ^ true ? 's' : 'q');
|
||||||
|
}
|
||||||
|
var_32 = 'B';
|
||||||
|
{
|
||||||
|
var_32 = Test_Class_0.var_1;
|
||||||
|
}
|
||||||
|
var_32 = Test_Class_0.var_1;
|
||||||
|
Test_Class_1.var_29 = "ov";
|
||||||
|
Test_Class_1.var_29 = "smtolghw";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
protected final static String func_0(final long[][] arg_0, byte arg_1, char arg_2)
|
||||||
|
{
|
||||||
|
arg_1 <<= (((new Test_Class_2[arg_1])[arg_1]).var_34 > new Test_Class_0().var_2 | true ? new Test_Class_0() : (new Test_Class_0[arg_1][arg_1])[new Test_Class_1().var_25][new Test_Class_1().var_25]).var_2;
|
||||||
|
Test_Class_1.var_26 >>>= (!true | !true | (new boolean[arg_1])[arg_1] || true ? (new Test_Class_1[arg_1])[arg_1] : new Test_Class_1()).var_27;
|
||||||
|
float var_37 = 0F;
|
||||||
|
arg_2 >>= ((new Test_Class_1[arg_1][arg_1])[arg_1][arg_1]).var_25;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
((new Test_Class_2[arg_1 /= 2055714081])[arg_1]).var_34 = 'l';
|
||||||
|
var_37++;
|
||||||
|
Test_Class_1.var_29 = Test_Class_0.var_3;
|
||||||
|
} while ((false ? false : false) && var_37 < 7);
|
||||||
|
Test_Class_1.var_29 = Test_Class_0.var_3 + "";
|
||||||
|
((new Test_Class_2[new Test_Class_1().var_25][new Test_Class_1().var_25])[new Test_Class_1().var_25][arg_1 |= new Test_Class_0().var_2]).var_34 += Test_Class_0.var_1;
|
||||||
|
return "esb";
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
String result = "[\n";
|
||||||
|
result += "Test_Class_2.var_32 = "; result += Test.Printer.print(var_32);
|
||||||
|
result += "\n";
|
||||||
|
result += "Test_Class_2.var_36 = "; result += Test.Printer.print(var_36);
|
||||||
|
result += "\n";
|
||||||
|
result += "Test_Class_2.var_30 = "; result += Test.Printer.print(var_30);
|
||||||
|
result += "\n";
|
||||||
|
result += "Test_Class_2.var_34 = "; result += Test.Printer.print(var_34);
|
||||||
|
result += "\n";
|
||||||
|
result += "Test_Class_2.var_35 = "; result += Test.Printer.print(var_35);
|
||||||
|
result += "\n";
|
||||||
|
result += "Test_Class_2.var_33 = "; result += Test.Printer.print(var_33);
|
||||||
|
result += "\n";
|
||||||
|
result += "Test_Class_2.var_31 = "; result += Test.Printer.print(var_31);
|
||||||
|
result += "";
|
||||||
|
result += "\n]";
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
final class Test_Class_3 extends Test_Class_2 {
|
||||||
|
byte var_39 = 23;
|
||||||
|
static boolean var_40 = false;
|
||||||
|
|
||||||
|
|
||||||
|
public Test_Class_3()
|
||||||
|
{
|
||||||
|
if (true)
|
||||||
|
{
|
||||||
|
Test_Class_1.var_21 |= new Test_Class_1().var_27;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
final float var_46 = 7.9266674E37F;
|
||||||
|
++Test_Class_1.var_26;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
Test_Class_1.var_23++;
|
||||||
|
}
|
||||||
|
var_30 = ((new Test_Class_1[var_39][var_39])[var_39][var_39]).var_25;
|
||||||
|
if (var_40 &= (var_40 |= (var_40 |= var_40)))
|
||||||
|
{
|
||||||
|
Test_Class_0.var_3.indexOf(Test_Class_1.var_29 = "xfgyblg", 'X' >>> ((Test_Class_1)(new Object[var_39])[((new Test_Class_1[var_39])[var_39]).var_25]).var_27);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var_40 &= var_40 && var_40;
|
||||||
|
}
|
||||||
|
((Test_Class_2)(((new boolean[var_39])[var_39++] ? (var_40 &= var_40) : (var_40 &= false)) ? (new Test_Class_2[var_39][var_39])[var_39][var_39] : (new Object[var_39][var_39])[var_39][var_39])).var_33 = (var_40 ? new Test_Class_1() : new Test_Class_1()).var_25;
|
||||||
|
switch (var_39)
|
||||||
|
{
|
||||||
|
case 24:
|
||||||
|
|
||||||
|
}
|
||||||
|
var_39 += (((var_40 ^= true) ? new Test_Class_0() : new Test_Class_0()).var_2 ^= var_40 & (var_40 | false) ? var_39-- : var_36);
|
||||||
|
new Test_Class_0().var_2 %= (new Test_Class_0().var_2 += (var_39 ^= Test_Class_1.var_26));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private static String func_0()
|
||||||
|
{
|
||||||
|
--Test_Class_1.var_26;
|
||||||
|
{
|
||||||
|
Test_Class_1.var_29 = var_40 ? Test_Class_0.var_3 : "rahqjhqf";
|
||||||
|
}
|
||||||
|
if (var_40 ^= var_40)
|
||||||
|
{
|
||||||
|
Test_Class_1.var_26 >>= (Test_Class_2.var_32 = Test_Class_0.var_1) / new Test_Class_0().var_2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
++Test_Class_1.var_21;
|
||||||
|
}
|
||||||
|
++Test_Class_1.var_26;
|
||||||
|
int var_41 = 0;
|
||||||
|
++Test_Class_1.var_26;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
var_40 = (var_40 = true);
|
||||||
|
var_41++;
|
||||||
|
Test_Class_0 var_42 = new Test_Class_0();
|
||||||
|
} while (var_41 < 1);
|
||||||
|
Test_Class_1.var_29 = "f";
|
||||||
|
Test_Class_1 var_43;
|
||||||
|
var_43 = (var_43 = new Test_Class_1());
|
||||||
|
Test_Class_2.var_32 = 'V';
|
||||||
|
long var_44 = 0L;
|
||||||
|
Test_Class_1.var_23--;
|
||||||
|
while (var_40 && (var_44 < 1 && var_40))
|
||||||
|
{
|
||||||
|
Test_Class_1.var_29 = "bsgewkmk";
|
||||||
|
var_44++;
|
||||||
|
Test_Class_1.var_29 = "ktegattny";
|
||||||
|
var_40 &= var_40 ^ (var_40 |= (short)4.4487427E37F < 'n') & true;
|
||||||
|
}
|
||||||
|
Test_Class_1.var_23 %= (((var_40 |= true & (var_40 &= var_40)) ^ true ? new Test_Class_0() : new Test_Class_0()).var_2 -= 1.6638270827800162E308);
|
||||||
|
float var_45;
|
||||||
|
var_32 = (Test_Class_2.var_32 = Test_Class_0.var_1);
|
||||||
|
return false ? "fluk" : "wt";
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
String result = "[\n";
|
||||||
|
result += "Test_Class_3.var_32 = "; result += Test.Printer.print(var_32);
|
||||||
|
result += "\n";
|
||||||
|
result += "Test_Class_3.var_36 = "; result += Test.Printer.print(var_36);
|
||||||
|
result += "\n";
|
||||||
|
result += "Test_Class_3.var_30 = "; result += Test.Printer.print(var_30);
|
||||||
|
result += "\n";
|
||||||
|
result += "Test_Class_3.var_34 = "; result += Test.Printer.print(var_34);
|
||||||
|
result += "\n";
|
||||||
|
result += "Test_Class_3.var_35 = "; result += Test.Printer.print(var_35);
|
||||||
|
result += "\n";
|
||||||
|
result += "Test_Class_3.var_33 = "; result += Test.Printer.print(var_33);
|
||||||
|
result += "\n";
|
||||||
|
result += "Test_Class_3.var_31 = "; result += Test.Printer.print(var_31);
|
||||||
|
result += "\n";
|
||||||
|
result += "Test_Class_3.var_39 = "; result += Test.Printer.print(var_39);
|
||||||
|
result += "\n";
|
||||||
|
result += "Test_Class_3.var_40 = "; result += Test.Printer.print(var_40);
|
||||||
|
result += "";
|
||||||
|
result += "\n]";
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class Test_Class_4 {
|
||||||
|
final float var_47 = 1.9043434E38F;
|
||||||
|
final byte var_48 = 32;
|
||||||
|
final float var_49 = 2.8176504E38F;
|
||||||
|
final char var_50 = 'r';
|
||||||
|
final String var_51 = "uwgmnjpg";
|
||||||
|
static int var_52;
|
||||||
|
short[] var_53;
|
||||||
|
Test_Class_1 var_54;
|
||||||
|
|
||||||
|
|
||||||
|
public Test_Class_4()
|
||||||
|
{
|
||||||
|
final float var_55 = (3.1554042E38F == var_50 ^ (Test_Class_3.var_40 |= true) ? (Test_Class_3.var_40 ^= Test_Class_3.var_40) ^ true : Test_Class_3.var_40) ? new Test_Class_0().var_2 : 2.965321E38F;
|
||||||
|
new Test_Class_0().var_2 = (new Test_Class_0().var_2 >>= +new Test_Class_1().var_25);
|
||||||
|
((Test_Class_1.var_29 = (Test_Class_1.var_29 = (Test_Class_1.var_29 = "l"))) + "").equalsIgnoreCase(Test_Class_1.var_29 = "garnio");
|
||||||
|
double var_56 = 0;
|
||||||
|
Test_Class_1.var_29 = var_51;
|
||||||
|
while (var_56 < 1)
|
||||||
|
{
|
||||||
|
((Test_Class_3)(Test_Class_2)(new Object[var_48])[var_48]).var_33 = ++Test_Class_1.var_26;
|
||||||
|
var_56++;
|
||||||
|
Test_Class_1.var_29 = (Test_Class_1.var_29 = "fvyjrih");
|
||||||
|
float[] var_57;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
((new Test_Class_2[var_48])[((new Test_Class_3[var_48][var_48])[var_48][var_48]).var_39]).var_34 *= 2.2119221943262553E307;
|
||||||
|
Test_Class_2.var_32 = true ? 'q' : 't';
|
||||||
|
((new Test_Class_3[--((Test_Class_3)new Test_Class_2()).var_39])[var_48]).var_33 = new Test_Class_0().var_2;
|
||||||
|
int var_58 = 'i' >> (var_48 << Test_Class_0.var_1);
|
||||||
|
}
|
||||||
|
Test_Class_3.var_40 &= true && var_51.equalsIgnoreCase(var_51) || new Test_Class_0().var_2 < --((new Test_Class_3[var_48])[var_48]).var_39;
|
||||||
|
((Test_Class_3)(Test_Class_2)(new Object[var_48][var_48])[var_48][var_48]).var_34 += Test_Class_1.var_26--;
|
||||||
|
var_54 = new Test_Class_1();
|
||||||
|
Test_Class_3.var_40 |= (long)(!true ^ var_47 > ((Test_Class_2)(new Object[var_48])[var_48]).var_34 ? (Test_Class_2.var_31 = (Test_Class_3.var_31 = (Test_Class_3.var_31 = var_48))) : (var_54 = new Test_Class_1()).var_25) <= var_48;
|
||||||
|
(Test_Class_3.var_40 ? (true ? new Test_Class_0() : new Test_Class_0()) : new Test_Class_0()).var_2 &= var_48;
|
||||||
|
(Test_Class_3.var_40 ? (Test_Class_3)new Test_Class_2() : (new Test_Class_3[var_48][var_48])[var_48][var_48]).var_34 += Test_Class_1.var_21;
|
||||||
|
Test_Class_3 var_59;
|
||||||
|
Test_Class_2.var_32 = 'H';
|
||||||
|
--Test_Class_1.var_26;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
String result = "[\n";
|
||||||
|
result += "Test_Class_4.var_50 = "; result += Test.Printer.print(var_50);
|
||||||
|
result += "\n";
|
||||||
|
result += "Test_Class_4.var_52 = "; result += Test.Printer.print(var_52);
|
||||||
|
result += "\n";
|
||||||
|
result += "Test_Class_4.var_53 = "; result += Test.Printer.print(var_53);
|
||||||
|
result += "\n";
|
||||||
|
result += "Test_Class_4.var_47 = "; result += Test.Printer.print(var_47);
|
||||||
|
result += "\n";
|
||||||
|
result += "Test_Class_4.var_49 = "; result += Test.Printer.print(var_49);
|
||||||
|
result += "\n";
|
||||||
|
result += "Test_Class_4.var_48 = "; result += Test.Printer.print(var_48);
|
||||||
|
result += "\n";
|
||||||
|
result += "Test_Class_4.var_51 = "; result += Test.Printer.print(var_51);
|
||||||
|
result += "\n";
|
||||||
|
result += "Test_Class_4.var_54 = "; result += Test.Printer.print(var_54);
|
||||||
|
result += "";
|
||||||
|
result += "\n]";
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class Test_Class_5 extends Test_Class_4 {
|
||||||
|
char var_60 = '_';
|
||||||
|
final byte var_61 = 101;
|
||||||
|
|
||||||
|
|
||||||
|
public Test_Class_5()
|
||||||
|
{
|
||||||
|
Test_Class_0.var_3.indexOf(Test_Class_1.var_21, (Test_Class_3.var_40 |= Test_Class_3.var_40) ? new Test_Class_1().var_24 : 'i');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
final char func_0(Test_Class_1 arg_0, final Test_Class_1 arg_1)
|
||||||
|
{
|
||||||
|
long var_62 = 0L;
|
||||||
|
"aoal".toLowerCase();
|
||||||
|
for (byte var_63 = arg_0.var_25; var_62 < 1 && "ji".startsWith("dikrs".endsWith("va") ? (Test_Class_1.var_29 = "mvp") : Test_Class_0.var_3, Test_Class_1.var_23); ((Test_Class_2)(new Object[arg_0.var_25])[var_63]).var_34 -= new Test_Class_2().var_36)
|
||||||
|
{
|
||||||
|
((Test_Class_3.var_40 ? false : Test_Class_3.var_40) ? (Test_Class_0)(new Object[arg_1.var_25][arg_1.var_25])[arg_1.var_25][var_63] : (Test_Class_0)(new Object[var_48][var_48])[var_63][var_63]).var_2 += true ^ Test_Class_3.var_40 ^ (((new Test_Class_3[var_63][var_63])[var_63][var_61]).var_35 != 2.1423512E38F | ! !false) ? var_49 + ~var_48 : 3.1549515E38F;
|
||||||
|
var_62++;
|
||||||
|
(!false & ((Test_Class_3.var_40 |= (Test_Class_3.var_40 ^= true)) & true) ? (Test_Class_2)(new Object[var_63])[var_63] : (new Test_Class_2[var_63][var_61])[var_63][arg_0.var_25]).var_33 = (var_60 *= (var_60 *= ((new Test_Class_3[var_48][var_61])[var_61][var_63]).var_35));
|
||||||
|
float var_64;
|
||||||
|
}
|
||||||
|
Test_Class_1.var_29 = "xyenjknu";
|
||||||
|
Test_Class_3.var_40 ^= (Test_Class_3.var_40 = !false & true) ? Test_Class_3.var_40 : Test_Class_3.var_40;
|
||||||
|
((new Test_Class_2[var_48][arg_1.var_25])[arg_0.var_25][var_48]).var_33 = var_61;
|
||||||
|
Test_Class_1.var_21 |= --(((new Test_Class_3[Test_Class_3.var_31 = arg_0.var_25][var_61])[var_61])[(((new Test_Class_3[var_48][var_61])[var_48])[((Test_Class_3)(new Test_Class_2[var_48][arg_0.var_25])[var_61][var_48]).var_39]).var_39 >>>= var_60]).var_39;
|
||||||
|
var_51.compareToIgnoreCase("hgcaybk");
|
||||||
|
Test_Class_0 var_65 = (Test_Class_1.var_29 = "t").codePointBefore(1602805584) >= (float)((new Test_Class_3[var_48][var_61])[var_48][Test_Class_2.var_31 = arg_1.var_25]).var_39 - 7.256386549028811E307 ? new Test_Class_0() : ((new Test_Class_0[arg_0.var_25][var_48][var_48])[arg_0.var_25])[arg_0.var_25][Test_Class_2.var_31 = arg_1.var_25];
|
||||||
|
return 'U';
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static Test_Class_1 func_1(final short arg_0, long arg_1)
|
||||||
|
{
|
||||||
|
--new Test_Class_0().var_2;
|
||||||
|
"xb".length();
|
||||||
|
if ((Test_Class_3.var_40 ^= (Test_Class_2.var_32 = Test_Class_0.var_1) == 1.2609472E38F) ? (Test_Class_3.var_40 = (Test_Class_3.var_40 = Test_Class_3.var_40)) : true)
|
||||||
|
{
|
||||||
|
--Test_Class_1.var_26;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
"ybbe".substring(209378562, var_52 = (Test_Class_1.var_21 |= (Test_Class_2.var_31 = (byte)'a')));
|
||||||
|
}
|
||||||
|
Test_Class_3.var_40 &= (Test_Class_3.var_40 &= true) && (Test_Class_1.var_29 = (Test_Class_1.var_29 = Test_Class_0.var_3)).endsWith(Test_Class_0.var_3);
|
||||||
|
(false ? new Test_Class_0() : new Test_Class_0()).var_2 >>= new Test_Class_1().var_25;
|
||||||
|
return 9.430116214455637E307 <= (true ? (Test_Class_3)new Test_Class_2() : (Test_Class_3)new Test_Class_2()).var_34 ? new Test_Class_1() : new Test_Class_1();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
String result = "[\n";
|
||||||
|
result += "Test_Class_5.var_50 = "; result += Test.Printer.print(var_50);
|
||||||
|
result += "\n";
|
||||||
|
result += "Test_Class_5.var_60 = "; result += Test.Printer.print(var_60);
|
||||||
|
result += "\n";
|
||||||
|
result += "Test_Class_5.var_52 = "; result += Test.Printer.print(var_52);
|
||||||
|
result += "\n";
|
||||||
|
result += "Test_Class_5.var_53 = "; result += Test.Printer.print(var_53);
|
||||||
|
result += "\n";
|
||||||
|
result += "Test_Class_5.var_47 = "; result += Test.Printer.print(var_47);
|
||||||
|
result += "\n";
|
||||||
|
result += "Test_Class_5.var_49 = "; result += Test.Printer.print(var_49);
|
||||||
|
result += "\n";
|
||||||
|
result += "Test_Class_5.var_48 = "; result += Test.Printer.print(var_48);
|
||||||
|
result += "\n";
|
||||||
|
result += "Test_Class_5.var_61 = "; result += Test.Printer.print(var_61);
|
||||||
|
result += "\n";
|
||||||
|
result += "Test_Class_5.var_51 = "; result += Test.Printer.print(var_51);
|
||||||
|
result += "\n";
|
||||||
|
result += "Test_Class_5.var_54 = "; result += Test.Printer.print(var_54);
|
||||||
|
result += "";
|
||||||
|
result += "\n]";
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Test {
|
||||||
|
Test_Class_4 var_66;
|
||||||
|
Test_Class_3 var_67;
|
||||||
|
Test_Class_5 var_68;
|
||||||
|
Test_Class_2[] var_69;
|
||||||
|
long var_70 = ++Test_Class_1.var_26 & Test_Class_1.var_21++;
|
||||||
|
final static double var_71 = 3.566207721984698E307;
|
||||||
|
static boolean var_72;
|
||||||
|
final static String var_73 = "nmxx";
|
||||||
|
|
||||||
|
|
||||||
|
private final char func_0(Test_Class_3 arg_0, final boolean[] arg_1)
|
||||||
|
{
|
||||||
|
((Test_Class_5)(arg_1[arg_0.var_39++] ? new Test_Class_2[(var_67 = arg_0).var_39] : (new Object[arg_0.var_39])[arg_0.var_39])).var_54 = new Test_Class_1();
|
||||||
|
new Test_Class_0();
|
||||||
|
(((new Test[arg_0.var_39][arg_0.var_39][arg_0.var_39])[++arg_0.var_39])[arg_0.var_39][arg_0.var_39]).var_66 = (var_68 = (new Test_Class_5[arg_0.var_39][arg_0.var_39])[arg_0.var_39][arg_0.var_39]);
|
||||||
|
((new Test[arg_0.var_39])[(arg_0 = (var_67 = (arg_0 = arg_0))).var_39]).var_70 = ((new long[arg_0.var_39][arg_0.var_39])[arg_0.var_39])[arg_0.var_39 = ((var_67 = (arg_0 = arg_0)).var_39 -= new Test_Class_0().var_2)] << ']';
|
||||||
|
arg_0 = (new Test_Class_0().var_2 *= ((new Test_Class_2[arg_0.var_39])[arg_0.var_39]).var_34) >= arg_0.var_39 ? (var_67 = arg_0) : (arg_0 = arg_0);
|
||||||
|
Test_Class_1.var_26--;
|
||||||
|
Test_Class_4 var_74 = var_66 = (Test_Class_5)(new Test_Class_4[arg_0.var_39])[arg_0.var_39];
|
||||||
|
Test_Class_3.var_40 ^= ! (Test_Class_3.var_40 &= (Test_Class_3.var_40 ^= Test_Class_3.var_40) | (Test_Class_3.var_40 &= Test_Class_3.var_40));
|
||||||
|
var_72 = (arg_1[(var_67 = arg_0).var_39] | !Test_Class_3.var_40 & !Test_Class_3.var_40 ? (Test_Class_1.var_29 = var_73).endsWith((var_66 = var_74).var_51) && (Test_Class_3.var_40 ^= Test_Class_3.var_40) : (Test_Class_3.var_40 ^= Test_Class_3.var_40)) ^ !Test_Class_3.var_40;
|
||||||
|
Test_Class_3.var_40 &= (Test_Class_3.var_40 &= (Test_Class_3.var_40 = Test_Class_3.var_40) & Test_Class_3.var_40 ^ Test_Class_3.var_40);
|
||||||
|
arg_0.var_39 -= --var_70;
|
||||||
|
int var_75;
|
||||||
|
double var_76;
|
||||||
|
{
|
||||||
|
boolean var_77;
|
||||||
|
var_70 ^= new Test_Class_0().var_2++;
|
||||||
|
}
|
||||||
|
Test_Class_1.var_26 /= Test_Class_0.var_3.lastIndexOf(~new Test_Class_1().var_25, Test_Class_1.var_21);
|
||||||
|
Test_Class_1.var_26 |= Test_Class_1.var_21;
|
||||||
|
(((new Test_Class_3[arg_0.var_39][arg_0.var_39][var_74.var_48])[arg_0.var_39])[arg_0.var_39][arg_0.var_39]).var_34 %= (var_67 = arg_0).var_39;
|
||||||
|
Test_Class_1.var_21 &= arg_0.var_39;
|
||||||
|
var_68 = (var_68 = (Test_Class_5)var_74);
|
||||||
|
var_72 = false;
|
||||||
|
return new Test_Class_5().var_60 ^= 'v';
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Test_Class_2 func_1(byte[][] arg_0, final int arg_1, Test_Class_1 arg_2, final Test_Class_1 arg_3)
|
||||||
|
{
|
||||||
|
((new Test[arg_3.var_25])[((Test_Class_3)new Test_Class_2()).var_39 *= --Test_Class_1.var_26]).var_67 = (((new Test[arg_2.var_25])[(((new Test[arg_2.var_25][arg_2.var_25])[arg_3.var_25][arg_3.var_25]).var_67 = (new Test_Class_3[arg_2.var_25][arg_2.var_25])[arg_2.var_25][arg_3.var_25]).var_39 %= Test_Class_1.var_26]).var_67 = (((new Test[arg_3.var_25][arg_2.var_25])[arg_3.var_25][arg_2.var_25]).var_67 = (((new Test[arg_3.var_25])[arg_2.var_25]).var_67 = (Test_Class_3)new Test_Class_2())));
|
||||||
|
{
|
||||||
|
--Test_Class_1.var_26;
|
||||||
|
}
|
||||||
|
if (!Test_Class_3.var_40)
|
||||||
|
{
|
||||||
|
"jfqj".replaceAll("ac", Test_Class_0.var_3);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
arg_2 = (((new Test_Class_5[arg_3.var_25][arg_2.var_25])[((new Test_Class_3[arg_2.var_25])[arg_3.var_25]).var_39][((Test_Class_3)(new Test_Class_2[arg_2.var_25])[arg_3.var_25]).var_39]).var_54 = arg_3);
|
||||||
|
new Test_Class_1();
|
||||||
|
}
|
||||||
|
if (true)
|
||||||
|
{
|
||||||
|
Test_Class_0.func_0();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Test_Class_1.var_23 /= Test_Class_1.var_26;
|
||||||
|
}
|
||||||
|
Test_Class_1.var_26--;
|
||||||
|
Test_Class_1.var_23 ^= Test_Class_0.var_1;
|
||||||
|
return new Test_Class_2();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String execute()
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
Test t = new Test();
|
||||||
|
try { t.test(); }
|
||||||
|
catch(Throwable e) { }
|
||||||
|
try { return t.toString(); }
|
||||||
|
catch (Throwable e) { return "Error during result conversion to String"; }
|
||||||
|
} catch (Throwable e) { return "Error during test execution"; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
Test t = new Test();
|
||||||
|
try { t.test(); }
|
||||||
|
catch(Throwable e) { }
|
||||||
|
try { System.out.println(t); }
|
||||||
|
catch(Throwable e) { }
|
||||||
|
} catch (Throwable e) { }
|
||||||
|
}
|
||||||
|
|
||||||
|
private void test()
|
||||||
|
{
|
||||||
|
double var_78 = 0;
|
||||||
|
--Test_Class_1.var_26;
|
||||||
|
long var_79;
|
||||||
|
for (var_70 /= 8.089457748637276E307; var_78 < 162 && !true & (true ? Test_Class_3.var_40 : (Test_Class_3.var_40 ^= Test_Class_3.var_40)); Test_Class_1.var_26 -= 1.2513521E38F)
|
||||||
|
{
|
||||||
|
short var_80 = 10682;
|
||||||
|
Test_Class_1.var_21--;
|
||||||
|
var_78++;
|
||||||
|
var_72 = (Test_Class_3.var_40 |= (Test_Class_3.var_40 ^= false));
|
||||||
|
++Test_Class_1.var_26;
|
||||||
|
}
|
||||||
|
Test_Class_2 var_81;
|
||||||
|
new Test_Class_4();
|
||||||
|
int var_82 = 0;
|
||||||
|
++Test_Class_1.var_23;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
--Test_Class_1.var_26;
|
||||||
|
var_82++;
|
||||||
|
++Test_Class_1.var_21;
|
||||||
|
} while ((Test_Class_3.var_40 ^= false & false) && var_82 < 256);
|
||||||
|
Test_Class_1.var_23 |= (var_68 = (var_68 = (Test_Class_5)(var_66 = new Test_Class_4()))).var_48 + (Test_Class_1.var_26 >>> new Test_Class_0().var_2);
|
||||||
|
(true ? new Test_Class_5() : (var_68 = (var_68 = new Test_Class_5()))).var_60 *= Test_Class_0.var_1;
|
||||||
|
}
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
String result = "[\n";
|
||||||
|
result += "Test.var_69 = "; result += Printer.print(var_69);
|
||||||
|
result += "\n";
|
||||||
|
result += "Test.var_70 = "; result += Printer.print(var_70);
|
||||||
|
result += "\n";
|
||||||
|
result += "Test.var_71 = "; result += Printer.print(var_71);
|
||||||
|
result += "\n";
|
||||||
|
result += "Test.var_73 = "; result += Printer.print(var_73);
|
||||||
|
result += "\n";
|
||||||
|
result += "Test.var_68 = "; result += Printer.print(var_68);
|
||||||
|
result += "\n";
|
||||||
|
result += "Test.var_66 = "; result += Printer.print(var_66);
|
||||||
|
result += "\n";
|
||||||
|
result += "Test.var_72 = "; result += Printer.print(var_72);
|
||||||
|
result += "\n";
|
||||||
|
result += "Test.var_67 = "; result += Printer.print(var_67);
|
||||||
|
result += "";
|
||||||
|
result += "\n]";
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
static class Printer
|
||||||
|
{
|
||||||
|
public static String print(boolean arg) { return String.valueOf(arg); }
|
||||||
|
public static String print(byte arg) { return String.valueOf(arg); }
|
||||||
|
public static String print(short arg) { return String.valueOf(arg); }
|
||||||
|
public static String print(char arg) { return String.valueOf((int)arg); }
|
||||||
|
public static String print(int arg) { return String.valueOf(arg); }
|
||||||
|
public static String print(long arg) { return String.valueOf(arg); }
|
||||||
|
public static String print(float arg) { return String.valueOf(arg); }
|
||||||
|
public static String print(double arg) { return String.valueOf(arg); }
|
||||||
|
|
||||||
|
|
||||||
|
public static String print(Object arg)
|
||||||
|
{
|
||||||
|
return print_r(new java.util.Stack(), arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String print_r(java.util.Stack visitedObjects, Object arg)
|
||||||
|
{
|
||||||
|
String result = "";
|
||||||
|
if (arg == null)
|
||||||
|
result += "null";
|
||||||
|
else
|
||||||
|
if (arg.getClass().isArray())
|
||||||
|
{
|
||||||
|
for (int i = 0; i < visitedObjects.size(); i++)
|
||||||
|
if (visitedObjects.elementAt(i) == arg) return "<recursive>";
|
||||||
|
|
||||||
|
visitedObjects.push(arg);
|
||||||
|
|
||||||
|
final String delimiter = ", ";
|
||||||
|
result += "[";
|
||||||
|
|
||||||
|
if (arg instanceof Object[])
|
||||||
|
{
|
||||||
|
Object[] array = (Object[]) arg;
|
||||||
|
for (int i = 0; i < array.length; i++)
|
||||||
|
{
|
||||||
|
result += print_r(visitedObjects, array[i]);
|
||||||
|
if (i < array.length - 1) result += delimiter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (arg instanceof boolean[])
|
||||||
|
{
|
||||||
|
boolean[] array = (boolean[]) arg;
|
||||||
|
for (int i = 0; i < array.length; i++)
|
||||||
|
{
|
||||||
|
result += print(array[i]);
|
||||||
|
if (i < array.length - 1) result += delimiter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (arg instanceof byte[])
|
||||||
|
{
|
||||||
|
byte[] array = (byte[]) arg;
|
||||||
|
for (int i = 0; i < array.length; i++)
|
||||||
|
{
|
||||||
|
result += print(array[i]);
|
||||||
|
if (i < array.length - 1) result += delimiter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (arg instanceof short[])
|
||||||
|
{
|
||||||
|
short[] array = (short[]) arg;
|
||||||
|
for (int i = 0; i < array.length; i++)
|
||||||
|
{
|
||||||
|
result += print(array[i]);
|
||||||
|
if (i < array.length - 1) result += delimiter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (arg instanceof char[])
|
||||||
|
{
|
||||||
|
char[] array = (char[]) arg;
|
||||||
|
for (int i = 0; i < array.length; i++)
|
||||||
|
{
|
||||||
|
result += print(array[i]);
|
||||||
|
if (i < array.length - 1) result += delimiter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (arg instanceof int[])
|
||||||
|
{
|
||||||
|
int[] array = (int[]) arg;
|
||||||
|
for (int i = 0; i < array.length; i++)
|
||||||
|
{
|
||||||
|
result += print(array[i]);
|
||||||
|
if (i < array.length - 1) result += delimiter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (arg instanceof long[])
|
||||||
|
{
|
||||||
|
long[] array = (long[]) arg;
|
||||||
|
for (int i = 0; i < array.length; i++)
|
||||||
|
{
|
||||||
|
result += print(array[i]);
|
||||||
|
if (i < array.length - 1) result += delimiter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (arg instanceof float[])
|
||||||
|
{
|
||||||
|
float[] array = (float[]) arg;
|
||||||
|
for (int i = 0; i < array.length; i++)
|
||||||
|
{
|
||||||
|
result += print(array[i]);
|
||||||
|
if (i < array.length - 1) result += delimiter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (arg instanceof double[])
|
||||||
|
{
|
||||||
|
double[] array = (double[]) arg;
|
||||||
|
for (int i = 0; i < array.length; i++)
|
||||||
|
{
|
||||||
|
result += print(array[i]);
|
||||||
|
if (i < array.length - 1) result += delimiter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result += "]";
|
||||||
|
visitedObjects.pop();
|
||||||
|
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
result += arg.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
96
hotspot/test/compiler/6823453/Test.java
Normal file
96
hotspot/test/compiler/6823453/Test.java
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
||||||
|
* CA 95054 USA or visit www.sun.com if you need additional information or
|
||||||
|
* have any questions.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @test
|
||||||
|
* @bug 6823453
|
||||||
|
* @summary DeoptimizeALot causes fastdebug server jvm to fail with assert(false,"unscheduable graph")
|
||||||
|
* @run main/othervm -Xcomp -XX:CompileOnly=Test -XX:+DeoptimizeALot Test
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class Test {
|
||||||
|
|
||||||
|
static long vara_1 = 1L;
|
||||||
|
|
||||||
|
static void testa() {
|
||||||
|
short var_2 = (byte) 1.0E10;
|
||||||
|
|
||||||
|
for ( Object temp = new byte[(byte)1.0E10]; true ;
|
||||||
|
var_2 = "1".equals("0") ? ((byte) vara_1) : 1 ) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void testb() {
|
||||||
|
long var_1 = -1L;
|
||||||
|
|
||||||
|
short var_2 = (byte) 1.0E10;
|
||||||
|
|
||||||
|
for ( Object temp = new byte[(byte)1.0E10]; true ;
|
||||||
|
var_2 = "1".equals("0") ? ((byte) var_1) : 1 ) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void testc() {
|
||||||
|
long var_1 = -1L;
|
||||||
|
if (vara_1 > 0) var_1 = 1L;
|
||||||
|
|
||||||
|
int var_2 = (byte)var_1 - 128;
|
||||||
|
|
||||||
|
for ( Object temp = new byte[var_2]; true ;
|
||||||
|
var_2 = "1".equals("0") ? 2 : 1 ) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void testd() {
|
||||||
|
long var_1 = 0L;
|
||||||
|
|
||||||
|
int var_2 = (byte)var_1 + 1;
|
||||||
|
for (int i=0; i<2 ; i++) var_2 = var_2 - 1;
|
||||||
|
|
||||||
|
for ( Object temp = new byte[var_2]; true ;
|
||||||
|
var_2 = "1".equals("0") ? 2 : 1 ) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
int nex = 0;
|
||||||
|
|
||||||
|
try {
|
||||||
|
testa();
|
||||||
|
}
|
||||||
|
catch (java.lang.NegativeArraySizeException ex) { nex++; }
|
||||||
|
try {
|
||||||
|
testb();
|
||||||
|
}
|
||||||
|
catch (java.lang.NegativeArraySizeException ex) { nex++; }
|
||||||
|
try {
|
||||||
|
testc();
|
||||||
|
}
|
||||||
|
catch (java.lang.NegativeArraySizeException ex) { nex++; }
|
||||||
|
try {
|
||||||
|
testd();
|
||||||
|
}
|
||||||
|
catch (java.lang.NegativeArraySizeException ex) { nex++; }
|
||||||
|
|
||||||
|
if (nex != 4)
|
||||||
|
System.exit(97);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
x
Reference in New Issue
Block a user