Tue, 14 Apr 2009 12:25:54 -0700
Merge
src/share/vm/runtime/arguments.cpp | file | annotate | diff | comparison | revisions | |
src/share/vm/runtime/globals.hpp | file | annotate | diff | comparison | revisions |
1.1 --- a/agent/src/share/classes/sun/jvm/hotspot/runtime/ClassConstants.java Thu Apr 09 13:59:45 2009 -0700 1.2 +++ b/agent/src/share/classes/sun/jvm/hotspot/runtime/ClassConstants.java Tue Apr 14 12:25:54 2009 -0700 1.3 @@ -142,34 +142,35 @@ 1.4 // from jvm.h 1.5 1.6 public static final long JVM_RECOGNIZED_CLASS_MODIFIERS = (JVM_ACC_PUBLIC | 1.7 - JVM_ACC_FINAL | 1.8 - JVM_ACC_SUPER | 1.9 - JVM_ACC_INTERFACE | 1.10 - JVM_ACC_ABSTRACT | 1.11 - JVM_ACC_ANNOTATION | 1.12 - JVM_ACC_SYNTHETIC); 1.13 + JVM_ACC_FINAL | 1.14 + JVM_ACC_SUPER | 1.15 + JVM_ACC_INTERFACE | 1.16 + JVM_ACC_ABSTRACT | 1.17 + JVM_ACC_ANNOTATION | 1.18 + JVM_ACC_ENUM | 1.19 + JVM_ACC_SYNTHETIC); 1.20 1.21 1.22 public static final long JVM_RECOGNIZED_FIELD_MODIFIERS = (JVM_ACC_PUBLIC | 1.23 - JVM_ACC_PRIVATE | 1.24 - JVM_ACC_PROTECTED | 1.25 - JVM_ACC_STATIC | 1.26 - JVM_ACC_FINAL | 1.27 - JVM_ACC_VOLATILE | 1.28 - JVM_ACC_TRANSIENT | 1.29 - JVM_ACC_ENUM | 1.30 - JVM_ACC_SYNTHETIC); 1.31 + JVM_ACC_PRIVATE | 1.32 + JVM_ACC_PROTECTED | 1.33 + JVM_ACC_STATIC | 1.34 + JVM_ACC_FINAL | 1.35 + JVM_ACC_VOLATILE | 1.36 + JVM_ACC_TRANSIENT | 1.37 + JVM_ACC_ENUM | 1.38 + JVM_ACC_SYNTHETIC); 1.39 1.40 public static final long JVM_RECOGNIZED_METHOD_MODIFIERS = (JVM_ACC_PUBLIC | 1.41 - JVM_ACC_PRIVATE | 1.42 - JVM_ACC_PROTECTED | 1.43 - JVM_ACC_STATIC | 1.44 - JVM_ACC_FINAL | 1.45 - JVM_ACC_SYNCHRONIZED | 1.46 - JVM_ACC_BRIDGE | 1.47 - JVM_ACC_VARARGS | 1.48 - JVM_ACC_NATIVE | 1.49 - JVM_ACC_ABSTRACT | 1.50 - JVM_ACC_STRICT | 1.51 - JVM_ACC_SYNTHETIC); 1.52 + JVM_ACC_PRIVATE | 1.53 + JVM_ACC_PROTECTED | 1.54 + JVM_ACC_STATIC | 1.55 + JVM_ACC_FINAL | 1.56 + JVM_ACC_SYNCHRONIZED | 1.57 + JVM_ACC_BRIDGE | 1.58 + JVM_ACC_VARARGS | 1.59 + JVM_ACC_NATIVE | 1.60 + JVM_ACC_ABSTRACT | 1.61 + JVM_ACC_STRICT | 1.62 + JVM_ACC_SYNTHETIC); 1.63 }
2.1 --- a/agent/src/share/classes/sun/jvm/hotspot/tools/jcore/ByteCodeRewriter.java Thu Apr 09 13:59:45 2009 -0700 2.2 +++ b/agent/src/share/classes/sun/jvm/hotspot/tools/jcore/ByteCodeRewriter.java Tue Apr 14 12:25:54 2009 -0700 2.3 @@ -89,29 +89,6 @@ 2.4 // update the code buffer hotspot specific bytecode with the jvm bytecode 2.5 code[bci] = (byte) (0xFF & bytecode); 2.6 2.7 - // RewriteFrequentPairs 2.8 - if(hotspotcode == Bytecodes._fast_iaccess_0 || 2.9 - hotspotcode == Bytecodes._fast_aaccess_0 || 2.10 - hotspotcode == Bytecodes._fast_faccess_0) { 2.11 - // rewrite next bytecode as _getfield 2.12 - bci++; 2.13 - code[bci] = (byte) (0xFF & Bytecodes._getfield); 2.14 - bytecode = Bytecodes._getfield; 2.15 - hotspotcode = Bytecodes._getfield; 2.16 - } else if (hotspotcode == Bytecodes._fast_iload2) { 2.17 - // rewrite next bytecode as _iload 2.18 - bci++; 2.19 - code[bci] = (byte) (0xFF & Bytecodes._iload); 2.20 - bytecode = Bytecodes._iload; 2.21 - hotspotcode = Bytecodes._iload; 2.22 - } else if (hotspotcode == Bytecodes._fast_icaload) { 2.23 - // rewrite next bytecode as _caload 2.24 - bci++; 2.25 - code[bci] = (byte) (0xFF & Bytecodes._caload); 2.26 - bytecode = Bytecodes._caload; 2.27 - bytecode = Bytecodes._caload; 2.28 - } 2.29 - 2.30 short cpoolIndex = 0; 2.31 switch (bytecode) { 2.32 // bytecodes with ConstantPoolCache index
3.1 --- a/agent/src/share/classes/sun/jvm/hotspot/tools/jcore/ClassDump.java Thu Apr 09 13:59:45 2009 -0700 3.2 +++ b/agent/src/share/classes/sun/jvm/hotspot/tools/jcore/ClassDump.java Tue Apr 14 12:25:54 2009 -0700 3.3 @@ -59,8 +59,14 @@ 3.4 SystemDictionary dict = VM.getVM().getSystemDictionary(); 3.5 dict.classesDo(new SystemDictionary.ClassVisitor() { 3.6 public void visit(Klass k) { 3.7 - if (k instanceof InstanceKlass) 3.8 - dumpKlass((InstanceKlass) k); 3.9 + if (k instanceof InstanceKlass) { 3.10 + try { 3.11 + dumpKlass((InstanceKlass) k); 3.12 + } catch (Exception e) { 3.13 + System.out.println(k.getName().asString()); 3.14 + e.printStackTrace(); 3.15 + } 3.16 + } 3.17 } 3.18 }); 3.19 }
4.1 --- a/agent/src/share/classes/sun/jvm/hotspot/tools/jcore/ClassWriter.java Thu Apr 09 13:59:45 2009 -0700 4.2 +++ b/agent/src/share/classes/sun/jvm/hotspot/tools/jcore/ClassWriter.java Tue Apr 14 12:25:54 2009 -0700 4.3 @@ -40,7 +40,6 @@ 4.4 protected InstanceKlass klass; 4.5 protected DataOutputStream dos; 4.6 protected ConstantPool cpool; 4.7 - protected boolean is15Format; 4.8 4.9 // Map between class name to index of type CONSTANT_Class 4.10 protected Map classToIndex = new HashMap(); 4.11 @@ -73,7 +72,6 @@ 4.12 klass = kls; 4.13 dos = new DataOutputStream(os); 4.14 cpool = klass.getConstants(); 4.15 - is15Format = is15ClassFile(); 4.16 } 4.17 4.18 public void write() throws IOException { 4.19 @@ -82,7 +80,7 @@ 4.20 // write magic 4.21 dos.writeInt(0xCAFEBABE); 4.22 4.23 - writeVersion(is15Format); 4.24 + writeVersion(); 4.25 writeConstantPool(); 4.26 writeClassAccessFlags(); 4.27 writeThisClass(); 4.28 @@ -96,43 +94,14 @@ 4.29 dos.flush(); 4.30 } 4.31 4.32 - protected boolean is15ClassFile() { 4.33 - // if klass has generic signature, then it is 1.5 class file. 4.34 - if (klass.getGenericSignature() != null) { 4.35 - return true; 4.36 - } 4.37 - 4.38 - // if atleast one method has generic signature 4.39 - // , then we have 1.5 class file. 4.40 - ObjArray methods = klass.getMethods(); 4.41 - final int numMethods = (int) methods.getLength(); 4.42 - for (int m = 0; m < numMethods; m++) { 4.43 - Method curMethod = (Method) methods.getObjAt(m); 4.44 - if (curMethod.getGenericSignature() != null) { 4.45 - return true; 4.46 - } 4.47 - } 4.48 - 4.49 - // if atleast one field has non-zero generic signature index, then we have 4.50 - // 1.5 class file 4.51 - TypeArray fields = klass.getFields(); 4.52 - final int numFields = (int) fields.getLength(); 4.53 - for (int f = 0; f < numFields; f += InstanceKlass.NEXT_OFFSET) { 4.54 - short genSigIndex = fields.getShortAt(f + InstanceKlass.GENERIC_SIGNATURE_INDEX_OFFSET); 4.55 - if (genSigIndex != (short)0) return true; 4.56 - } 4.57 - 4.58 - return false; 4.59 + protected void writeVersion() throws IOException { 4.60 + dos.writeShort((short)klass.minorVersion()); 4.61 + dos.writeShort((short)klass.majorVersion()); 4.62 } 4.63 4.64 - protected void writeVersion(boolean is15Format) throws IOException { 4.65 - if (is15Format) { 4.66 - dos.writeShort(MINOR_VERSION); 4.67 - dos.writeShort(MAJOR_VERSION); 4.68 - } else { 4.69 - dos.writeShort(MINOR_VERSION_OLD); 4.70 - dos.writeShort(MAJOR_VERSION_OLD); 4.71 - } 4.72 + protected void writeIndex(int index) throws IOException { 4.73 + if (index == 0) throw new InternalError(); 4.74 + dos.writeShort(index); 4.75 } 4.76 4.77 protected void writeConstantPool() throws IOException { 4.78 @@ -392,8 +361,8 @@ 4.79 if (DEBUG) debugMessage("\tfield name = " + nameIndex + ", signature = " + signatureIndex); 4.80 4.81 short fieldAttributeCount = 0; 4.82 - boolean isSyn = isSynthetic(accessFlags); 4.83 - if (isSyn) 4.84 + boolean hasSyn = hasSyntheticAttribute(accessFlags); 4.85 + if (hasSyn) 4.86 fieldAttributeCount++; 4.87 4.88 short initvalIndex = fields.getShortAt(index + InstanceKlass.INITVAL_INDEX_OFFSET); 4.89 @@ -407,18 +376,18 @@ 4.90 dos.writeShort(fieldAttributeCount); 4.91 4.92 // write synthetic, if applicable 4.93 - if (isSyn) 4.94 + if (hasSyn) 4.95 writeSynthetic(); 4.96 4.97 if (initvalIndex != 0) { 4.98 - dos.writeShort(_constantValueIndex); 4.99 + writeIndex(_constantValueIndex); 4.100 dos.writeInt(2); 4.101 dos.writeShort(initvalIndex); 4.102 if (DEBUG) debugMessage("\tfield init value = " + initvalIndex); 4.103 } 4.104 4.105 if (genSigIndex != 0) { 4.106 - dos.writeShort(_signatureIndex); 4.107 + writeIndex(_signatureIndex); 4.108 dos.writeInt(2); 4.109 dos.writeShort(genSigIndex); 4.110 if (DEBUG) debugMessage("\tfield generic signature index " + genSigIndex); 4.111 @@ -430,8 +399,13 @@ 4.112 return (accessFlags & (short) JVM_ACC_SYNTHETIC) != 0; 4.113 } 4.114 4.115 + protected boolean hasSyntheticAttribute(short accessFlags) { 4.116 + // Check if flags have the attribute and if the constant pool contains an entry for it. 4.117 + return isSynthetic(accessFlags) && _syntheticIndex != 0; 4.118 + } 4.119 + 4.120 protected void writeSynthetic() throws IOException { 4.121 - dos.writeShort(_syntheticIndex); 4.122 + writeIndex(_syntheticIndex); 4.123 dos.writeInt(0); 4.124 } 4.125 4.126 @@ -459,8 +433,8 @@ 4.127 4.128 short methodAttributeCount = 0; 4.129 4.130 - final boolean isSyn = isSynthetic((short)accessFlags); 4.131 - if (isSyn) 4.132 + final boolean hasSyn = hasSyntheticAttribute((short)accessFlags); 4.133 + if (hasSyn) 4.134 methodAttributeCount++; 4.135 4.136 final boolean hasCheckedExceptions = m.hasCheckedExceptions(); 4.137 @@ -478,27 +452,11 @@ 4.138 dos.writeShort(methodAttributeCount); 4.139 if (DEBUG) debugMessage("\tmethod attribute count = " + methodAttributeCount); 4.140 4.141 - if (isSyn) { 4.142 + if (hasSyn) { 4.143 if (DEBUG) debugMessage("\tmethod is synthetic"); 4.144 writeSynthetic(); 4.145 } 4.146 4.147 - if (hasCheckedExceptions) { 4.148 - CheckedExceptionElement[] exceptions = m.getCheckedExceptions(); 4.149 - dos.writeShort(_exceptionsIndex); 4.150 - 4.151 - int attrSize = 2 /* number_of_exceptions */ + 4.152 - exceptions.length * 2 /* exception_index */; 4.153 - dos.writeInt(attrSize); 4.154 - dos.writeShort(exceptions.length); 4.155 - if (DEBUG) debugMessage("\tmethod has " + exceptions.length 4.156 - + " checked exception(s)"); 4.157 - for (int e = 0; e < exceptions.length; e++) { 4.158 - short cpIndex = (short) exceptions[e].getClassCPIndex(); 4.159 - dos.writeShort(cpIndex); 4.160 - } 4.161 - } 4.162 - 4.163 if (isCodeAvailable) { 4.164 byte[] code = m.getByteCode(); 4.165 short codeAttrCount = 0; 4.166 @@ -574,7 +532,7 @@ 4.167 4.168 // start writing Code 4.169 4.170 - dos.writeShort(_codeIndex); 4.171 + writeIndex(_codeIndex); 4.172 4.173 dos.writeInt(codeSize); 4.174 if (DEBUG) debugMessage("\tcode attribute length = " + codeSize); 4.175 @@ -608,7 +566,7 @@ 4.176 4.177 // write LineNumberTable, if available. 4.178 if (hasLineNumberTable) { 4.179 - dos.writeShort(_lineNumberTableIndex); 4.180 + writeIndex(_lineNumberTableIndex); 4.181 dos.writeInt(lineNumberAttrLen); 4.182 dos.writeShort((short) lineNumberTable.length); 4.183 for (int l = 0; l < lineNumberTable.length; l++) { 4.184 @@ -619,7 +577,7 @@ 4.185 4.186 // write LocalVariableTable, if available. 4.187 if (hasLocalVariableTable) { 4.188 - dos.writeShort((short) _localVariableTableIndex); 4.189 + writeIndex((short) _localVariableTableIndex); 4.190 dos.writeInt(localVarAttrLen); 4.191 dos.writeShort((short) localVariableTable.length); 4.192 for (int l = 0; l < localVariableTable.length; l++) { 4.193 @@ -632,6 +590,22 @@ 4.194 } 4.195 } 4.196 4.197 + if (hasCheckedExceptions) { 4.198 + CheckedExceptionElement[] exceptions = m.getCheckedExceptions(); 4.199 + writeIndex(_exceptionsIndex); 4.200 + 4.201 + int attrSize = 2 /* number_of_exceptions */ + 4.202 + exceptions.length * 2 /* exception_index */; 4.203 + dos.writeInt(attrSize); 4.204 + dos.writeShort(exceptions.length); 4.205 + if (DEBUG) debugMessage("\tmethod has " + exceptions.length 4.206 + + " checked exception(s)"); 4.207 + for (int e = 0; e < exceptions.length; e++) { 4.208 + short cpIndex = (short) exceptions[e].getClassCPIndex(); 4.209 + dos.writeShort(cpIndex); 4.210 + } 4.211 + } 4.212 + 4.213 if (isGeneric) { 4.214 writeGenericSignature(m.getGenericSignature().asString()); 4.215 } 4.216 @@ -643,7 +617,7 @@ 4.217 } 4.218 4.219 protected void writeGenericSignature(String signature) throws IOException { 4.220 - dos.writeShort(_signatureIndex); 4.221 + writeIndex(_signatureIndex); 4.222 if (DEBUG) debugMessage("signature attribute = " + _signatureIndex); 4.223 dos.writeInt(2); 4.224 Short index = (Short) utf8ToIndex.get(signature); 4.225 @@ -653,12 +627,12 @@ 4.226 4.227 protected void writeClassAttributes() throws IOException { 4.228 final long flags = klass.getAccessFlags(); 4.229 - final boolean isSyn = isSynthetic((short) flags); 4.230 + final boolean hasSyn = hasSyntheticAttribute((short) flags); 4.231 4.232 // check for source file 4.233 short classAttributeCount = 0; 4.234 4.235 - if (isSyn) 4.236 + if (hasSyn) 4.237 classAttributeCount++; 4.238 4.239 Symbol sourceFileName = klass.getSourceFileName(); 4.240 @@ -677,12 +651,12 @@ 4.241 dos.writeShort(classAttributeCount); 4.242 if (DEBUG) debugMessage("class attribute count = " + classAttributeCount); 4.243 4.244 - if (isSyn) 4.245 + if (hasSyn) 4.246 writeSynthetic(); 4.247 4.248 // write SourceFile, if any 4.249 if (sourceFileName != null) { 4.250 - dos.writeShort(_sourceFileIndex); 4.251 + writeIndex(_sourceFileIndex); 4.252 if (DEBUG) debugMessage("source file attribute = " + _sourceFileIndex); 4.253 dos.writeInt(2); 4.254 Short index = (Short) utf8ToIndex.get(sourceFileName.asString()); 4.255 @@ -697,7 +671,7 @@ 4.256 4.257 // write inner classes, if any 4.258 if (numInnerClasses != 0) { 4.259 - dos.writeShort(_innerClassesIndex); 4.260 + writeIndex(_innerClassesIndex); 4.261 final int innerAttrLen = 2 /* number_of_inner_classes */ + 4.262 numInnerClasses * ( 4.263 2 /* inner_class_info_index */ +
5.1 --- a/src/cpu/sparc/vm/assembler_sparc.cpp Thu Apr 09 13:59:45 2009 -0700 5.2 +++ b/src/cpu/sparc/vm/assembler_sparc.cpp Tue Apr 14 12:25:54 2009 -0700 5.3 @@ -3029,6 +3029,58 @@ 5.4 5.5 5.6 5.7 +void MacroAssembler::check_method_handle_type(Register mtype_reg, Register mh_reg, 5.8 + Register temp_reg, 5.9 + Label& wrong_method_type) { 5.10 + assert_different_registers(mtype_reg, mh_reg, temp_reg); 5.11 + // compare method type against that of the receiver 5.12 + RegisterOrConstant mhtype_offset = delayed_value(java_dyn_MethodHandle::type_offset_in_bytes, temp_reg); 5.13 + ld_ptr(mh_reg, mhtype_offset, temp_reg); 5.14 + cmp(temp_reg, mtype_reg); 5.15 + br(Assembler::notEqual, false, Assembler::pn, wrong_method_type); 5.16 + delayed()->nop(); 5.17 +} 5.18 + 5.19 + 5.20 +void MacroAssembler::jump_to_method_handle_entry(Register mh_reg, Register temp_reg) { 5.21 + assert(mh_reg == G3_method_handle, "caller must put MH object in G3"); 5.22 + assert_different_registers(mh_reg, temp_reg); 5.23 + 5.24 + // pick out the interpreted side of the handler 5.25 + ld_ptr(mh_reg, delayed_value(java_dyn_MethodHandle::vmentry_offset_in_bytes, temp_reg), temp_reg); 5.26 + 5.27 + // off we go... 5.28 + ld_ptr(temp_reg, MethodHandleEntry::from_interpreted_entry_offset_in_bytes(), temp_reg); 5.29 + jmp(temp_reg, 0); 5.30 + 5.31 + // for the various stubs which take control at this point, 5.32 + // see MethodHandles::generate_method_handle_stub 5.33 + 5.34 + // (Can any caller use this delay slot? If so, add an option for supression.) 5.35 + delayed()->nop(); 5.36 +} 5.37 + 5.38 +RegisterOrConstant MacroAssembler::argument_offset(RegisterOrConstant arg_slot, 5.39 + int extra_slot_offset) { 5.40 + // cf. TemplateTable::prepare_invoke(), if (load_receiver). 5.41 + int stackElementSize = Interpreter::stackElementWords() * wordSize; 5.42 + int offset = Interpreter::expr_offset_in_bytes(extra_slot_offset+0); 5.43 + int offset1 = Interpreter::expr_offset_in_bytes(extra_slot_offset+1); 5.44 + assert(offset1 - offset == stackElementSize, "correct arithmetic"); 5.45 + if (arg_slot.is_constant()) { 5.46 + offset += arg_slot.as_constant() * stackElementSize; 5.47 + return offset; 5.48 + } else { 5.49 + Register temp = arg_slot.as_register(); 5.50 + sll_ptr(temp, exact_log2(stackElementSize), temp); 5.51 + if (offset != 0) 5.52 + add(temp, offset, temp); 5.53 + return temp; 5.54 + } 5.55 +} 5.56 + 5.57 + 5.58 + 5.59 void MacroAssembler::biased_locking_enter(Register obj_reg, Register mark_reg, 5.60 Register temp_reg, 5.61 Label& done, Label* slow_case,
6.1 --- a/src/cpu/sparc/vm/assembler_sparc.hpp Thu Apr 09 13:59:45 2009 -0700 6.2 +++ b/src/cpu/sparc/vm/assembler_sparc.hpp Tue Apr 14 12:25:54 2009 -0700 6.3 @@ -84,6 +84,10 @@ 6.4 6.5 REGISTER_DECLARATION(Register, Gtemp , G5); 6.6 6.7 +// JSR 292 fixed register usages: 6.8 +REGISTER_DECLARATION(Register, G5_method_type , G5); 6.9 +REGISTER_DECLARATION(Register, G3_method_handle , G3); 6.10 + 6.11 // The compiler requires that G5_megamorphic_method is G5_inline_cache_klass, 6.12 // because a single patchable "set" instruction (NativeMovConstReg, 6.13 // or NativeMovConstPatching for compiler1) instruction 6.14 @@ -91,9 +95,13 @@ 6.15 // call site is an inline cache or is megamorphic. See the function 6.16 // CompiledIC::set_to_megamorphic. 6.17 // 6.18 -// On the other hand, G5_inline_cache_klass must differ from G5_method, 6.19 -// because both registers are needed for an inline cache that calls 6.20 -// an interpreted method. 6.21 +// If a inline cache targets an interpreted method, then the 6.22 +// G5 register will be used twice during the call. First, 6.23 +// the call site will be patched to load a compiledICHolder 6.24 +// into G5. (This is an ordered pair of ic_klass, method.) 6.25 +// The c2i adapter will first check the ic_klass, then load 6.26 +// G5_method with the method part of the pair just before 6.27 +// jumping into the interpreter. 6.28 // 6.29 // Note that G5_method is only the method-self for the interpreter, 6.30 // and is logically unrelated to G5_megamorphic_method. 6.31 @@ -1931,6 +1939,7 @@ 6.32 inline void store_ptr_contents( Register s, Address& a, int offset = 0 ); 6.33 inline void jumpl_to( Address& a, Register d, int offset = 0 ); 6.34 inline void jump_to( Address& a, int offset = 0 ); 6.35 + inline void jump_indirect_to( Address& a, Register temp, int ld_offset = 0, int jmp_offset = 0 ); 6.36 6.37 // ring buffer traceable jumps 6.38 6.39 @@ -2366,6 +2375,16 @@ 6.40 Register temp2_reg, 6.41 Label& L_success); 6.42 6.43 + // method handles (JSR 292) 6.44 + void check_method_handle_type(Register mtype_reg, Register mh_reg, 6.45 + Register temp_reg, 6.46 + Label& wrong_method_type); 6.47 + void jump_to_method_handle_entry(Register mh_reg, Register temp_reg); 6.48 + // offset relative to Gargs of argument at tos[arg_slot]. 6.49 + // (arg_slot == 0 means the last argument, not the first). 6.50 + RegisterOrConstant argument_offset(RegisterOrConstant arg_slot, 6.51 + int extra_slot_offset = 0); 6.52 + 6.53 6.54 // Stack overflow checking 6.55
7.1 --- a/src/cpu/sparc/vm/assembler_sparc.inline.hpp Thu Apr 09 13:59:45 2009 -0700 7.2 +++ b/src/cpu/sparc/vm/assembler_sparc.inline.hpp Tue Apr 14 12:25:54 2009 -0700 7.3 @@ -671,6 +671,15 @@ 7.4 } 7.5 7.6 7.7 +inline void MacroAssembler::jump_indirect_to( Address& a, Register temp, 7.8 + int ld_offset, int jmp_offset ) { 7.9 + assert_not_delayed(); 7.10 + //sethi(a); // sethi is caller responsibility for this one 7.11 + ld_ptr(a, temp, ld_offset); 7.12 + jmp(temp, jmp_offset); 7.13 +} 7.14 + 7.15 + 7.16 inline void MacroAssembler::set_oop( jobject obj, Register d ) { 7.17 set_oop(allocate_oop_address(obj, d)); 7.18 }
8.1 --- a/src/cpu/sparc/vm/cppInterpreter_sparc.cpp Thu Apr 09 13:59:45 2009 -0700 8.2 +++ b/src/cpu/sparc/vm/cppInterpreter_sparc.cpp Tue Apr 14 12:25:54 2009 -0700 8.3 @@ -1,5 +1,5 @@ 8.4 /* 8.5 - * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved. 8.6 + * Copyright 2007-2009 Sun Microsystems, Inc. All Rights Reserved. 8.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 8.8 * 8.9 * This code is free software; you can redistribute it and/or modify it 8.10 @@ -1017,6 +1017,7 @@ 8.11 const int slop_factor = 2*wordSize; 8.12 8.13 const int fixed_size = ((sizeof(BytecodeInterpreter) + slop_factor) >> LogBytesPerWord) + // what is the slop factor? 8.14 + //6815692//methodOopDesc::extra_stack_words() + // extra push slots for MH adapters 8.15 frame::memory_parameter_word_sp_offset + // register save area + param window 8.16 (native ? frame::interpreter_frame_extra_outgoing_argument_words : 0); // JNI, class 8.17 8.18 @@ -1163,6 +1164,9 @@ 8.19 __ st_ptr(O2, XXX_STATE(_stack)); // PREPUSH 8.20 8.21 __ lduh(max_stack, O3); // Full size expression stack 8.22 + guarantee(!EnableMethodHandles, "no support yet for java.dyn.MethodHandle"); //6815692 8.23 + //6815692//if (EnableMethodHandles) 8.24 + //6815692// __ inc(O3, methodOopDesc::extra_stack_entries()); 8.25 __ sll(O3, LogBytesPerWord, O3); 8.26 __ sub(O2, O3, O3); 8.27 // __ sub(O3, wordSize, O3); // so prepush doesn't look out of bounds 8.28 @@ -2017,7 +2021,9 @@ 8.29 8.30 const int fixed_size = sizeof(BytecodeInterpreter)/wordSize + // interpreter state object 8.31 frame::memory_parameter_word_sp_offset; // register save area + param window 8.32 + const int extra_stack = 0; //6815692//methodOopDesc::extra_stack_entries(); 8.33 return (round_to(max_stack + 8.34 + extra_stack + 8.35 slop_factor + 8.36 fixed_size + 8.37 monitor_size + 8.38 @@ -2104,7 +2110,8 @@ 8.39 // Need +1 here because stack_base points to the word just above the first expr stack entry 8.40 // and stack_limit is supposed to point to the word just below the last expr stack entry. 8.41 // See generate_compute_interpreter_state. 8.42 - to_fill->_stack_limit = stack_base - (method->max_stack() + 1); 8.43 + int extra_stack = 0; //6815692//methodOopDesc::extra_stack_entries(); 8.44 + to_fill->_stack_limit = stack_base - (method->max_stack() + 1 + extra_stack); 8.45 to_fill->_monitor_base = (BasicObjectLock*) monitor_base; 8.46 8.47 // sparc specific
9.1 --- a/src/cpu/sparc/vm/interpreterGenerator_sparc.hpp Thu Apr 09 13:59:45 2009 -0700 9.2 +++ b/src/cpu/sparc/vm/interpreterGenerator_sparc.hpp Tue Apr 14 12:25:54 2009 -0700 9.3 @@ -1,5 +1,5 @@ 9.4 /* 9.5 - * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved. 9.6 + * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved. 9.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 9.8 * 9.9 * This code is free software; you can redistribute it and/or modify it 9.10 @@ -29,6 +29,7 @@ 9.11 address generate_normal_entry(bool synchronized); 9.12 address generate_native_entry(bool synchronized); 9.13 address generate_abstract_entry(void); 9.14 + address generate_method_handle_entry(void); 9.15 address generate_math_entry(AbstractInterpreter::MethodKind kind); 9.16 address generate_empty_entry(void); 9.17 address generate_accessor_entry(void);
10.1 --- a/src/cpu/sparc/vm/interpreter_sparc.cpp Thu Apr 09 13:59:45 2009 -0700 10.2 +++ b/src/cpu/sparc/vm/interpreter_sparc.cpp Tue Apr 14 12:25:54 2009 -0700 10.3 @@ -1,5 +1,5 @@ 10.4 /* 10.5 - * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved. 10.6 + * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved. 10.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 10.8 * 10.9 * This code is free software; you can redistribute it and/or modify it 10.10 @@ -235,6 +235,19 @@ 10.11 } 10.12 10.13 10.14 + 10.15 +// Method handle invoker 10.16 +// Dispatch a method of the form java.dyn.MethodHandles::invoke(...) 10.17 +address InterpreterGenerator::generate_method_handle_entry(void) { 10.18 + if (!EnableMethodHandles) { 10.19 + return generate_abstract_entry(); 10.20 + } 10.21 + return generate_abstract_entry(); //6815692// 10.22 +} 10.23 + 10.24 + 10.25 + 10.26 + 10.27 //---------------------------------------------------------------------------------------------------- 10.28 // Entry points & stack frame layout 10.29 // 10.30 @@ -364,6 +377,7 @@ 10.31 case Interpreter::empty : entry_point = ((InterpreterGenerator*)this)->generate_empty_entry(); break; 10.32 case Interpreter::accessor : entry_point = ((InterpreterGenerator*)this)->generate_accessor_entry(); break; 10.33 case Interpreter::abstract : entry_point = ((InterpreterGenerator*)this)->generate_abstract_entry(); break; 10.34 + case Interpreter::method_handle : entry_point = ((InterpreterGenerator*)this)->generate_method_handle_entry(); break; 10.35 case Interpreter::java_lang_math_sin : break; 10.36 case Interpreter::java_lang_math_cos : break; 10.37 case Interpreter::java_lang_math_tan : break;
11.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 11.2 +++ b/src/cpu/sparc/vm/methodHandles_sparc.cpp Tue Apr 14 12:25:54 2009 -0700 11.3 @@ -0,0 +1,70 @@ 11.4 +/* 11.5 + * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved. 11.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 11.7 + * 11.8 + * This code is free software; you can redistribute it and/or modify it 11.9 + * under the terms of the GNU General Public License version 2 only, as 11.10 + * published by the Free Software Foundation. 11.11 + * 11.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 11.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 11.15 + * version 2 for more details (a copy is included in the LICENSE file that 11.16 + * accompanied this code). 11.17 + * 11.18 + * You should have received a copy of the GNU General Public License version 11.19 + * 2 along with this work; if not, write to the Free Software Foundation, 11.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 11.21 + * 11.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 11.23 + * CA 95054 USA or visit www.sun.com if you need additional information or 11.24 + * have any questions. 11.25 + * 11.26 + */ 11.27 + 11.28 +#include "incls/_precompiled.incl" 11.29 +#include "incls/_methodHandles_sparc.cpp.incl" 11.30 + 11.31 +#define __ _masm-> 11.32 + 11.33 +address MethodHandleEntry::start_compiled_entry(MacroAssembler* _masm, 11.34 + address interpreted_entry) { 11.35 + __ align(wordSize); 11.36 + address target = __ pc() + sizeof(Data); 11.37 + while (__ pc() < target) { 11.38 + __ nop(); 11.39 + __ align(wordSize); 11.40 + } 11.41 + 11.42 + MethodHandleEntry* me = (MethodHandleEntry*) __ pc(); 11.43 + me->set_end_address(__ pc()); // set a temporary end_address 11.44 + me->set_from_interpreted_entry(interpreted_entry); 11.45 + me->set_type_checking_entry(NULL); 11.46 + 11.47 + return (address) me; 11.48 +} 11.49 + 11.50 +MethodHandleEntry* MethodHandleEntry::finish_compiled_entry(MacroAssembler* _masm, 11.51 + address start_addr) { 11.52 + MethodHandleEntry* me = (MethodHandleEntry*) start_addr; 11.53 + assert(me->end_address() == start_addr, "valid ME"); 11.54 + 11.55 + // Fill in the real end_address: 11.56 + __ align(wordSize); 11.57 + me->set_end_address(__ pc()); 11.58 + 11.59 + return me; 11.60 +} 11.61 + 11.62 + 11.63 +// Code generation 11.64 +address MethodHandles::generate_method_handle_interpreter_entry(MacroAssembler* _masm) { 11.65 + ShouldNotReachHere(); //NYI, 6815692 11.66 + return NULL; 11.67 +} 11.68 + 11.69 +// Generate an "entry" field for a method handle. 11.70 +// This determines how the method handle will respond to calls. 11.71 +void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHandles::EntryKind ek) { 11.72 + ShouldNotReachHere(); //NYI, 6815692 11.73 +}
12.1 --- a/src/cpu/sparc/vm/register_definitions_sparc.cpp Thu Apr 09 13:59:45 2009 -0700 12.2 +++ b/src/cpu/sparc/vm/register_definitions_sparc.cpp Tue Apr 14 12:25:54 2009 -0700 12.3 @@ -1,5 +1,5 @@ 12.4 /* 12.5 - * Copyright 2002-2008 Sun Microsystems, Inc. All Rights Reserved. 12.6 + * Copyright 2002-2009 Sun Microsystems, Inc. All Rights Reserved. 12.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 12.8 * 12.9 * This code is free software; you can redistribute it and/or modify it 12.10 @@ -142,6 +142,8 @@ 12.11 REGISTER_DEFINITION(Register, G3_scratch); 12.12 REGISTER_DEFINITION(Register, G4_scratch); 12.13 REGISTER_DEFINITION(Register, Gtemp); 12.14 +REGISTER_DEFINITION(Register, G5_method_type); 12.15 +REGISTER_DEFINITION(Register, G3_method_handle); 12.16 REGISTER_DEFINITION(Register, Lentry_args); 12.17 12.18 #ifdef CC_INTERP
13.1 --- a/src/cpu/sparc/vm/sharedRuntime_sparc.cpp Thu Apr 09 13:59:45 2009 -0700 13.2 +++ b/src/cpu/sparc/vm/sharedRuntime_sparc.cpp Tue Apr 14 12:25:54 2009 -0700 13.3 @@ -1,5 +1,5 @@ 13.4 /* 13.5 - * Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved. 13.6 + * Copyright 2003-2009 Sun Microsystems, Inc. All Rights Reserved. 13.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 13.8 * 13.9 * This code is free software; you can redistribute it and/or modify it 13.10 @@ -937,12 +937,12 @@ 13.11 // Inputs: 13.12 // G2_thread - TLS 13.13 // G5_method - Method oop 13.14 - // O0 - Flag telling us to restore SP from O5 13.15 - // O4_args - Pointer to interpreter's args 13.16 - // O5 - Caller's saved SP, to be restored if needed 13.17 + // G4 (Gargs) - Pointer to interpreter's args 13.18 + // O0..O4 - free for scratch 13.19 + // O5_savedSP - Caller's saved SP, to be restored if needed 13.20 // O6 - Current SP! 13.21 // O7 - Valid return address 13.22 - // L0-L7, I0-I7 - Caller's temps (no frame pushed yet) 13.23 + // L0-L7, I0-I7 - Caller's temps (no frame pushed yet) 13.24 13.25 // Outputs: 13.26 // G2_thread - TLS 13.27 @@ -954,7 +954,7 @@ 13.28 // F0-F7 - more outgoing args 13.29 13.30 13.31 - // O4 is about to get loaded up with compiled callee's args 13.32 + // Gargs is the incoming argument base, and also an outgoing argument. 13.33 __ sub(Gargs, BytesPerWord, Gargs); 13.34 13.35 #ifdef ASSERT
14.1 --- a/src/cpu/sparc/vm/templateInterpreter_sparc.cpp Thu Apr 09 13:59:45 2009 -0700 14.2 +++ b/src/cpu/sparc/vm/templateInterpreter_sparc.cpp Tue Apr 14 12:25:54 2009 -0700 14.3 @@ -1,5 +1,5 @@ 14.4 /* 14.5 - * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved. 14.6 + * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved. 14.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 14.8 * 14.9 * This code is free software; you can redistribute it and/or modify it 14.10 @@ -108,6 +108,24 @@ 14.11 } 14.12 14.13 14.14 +// Arguments are: required type in G5_method_type, and 14.15 +// failing object (or NULL) in G3_method_handle. 14.16 +address TemplateInterpreterGenerator::generate_WrongMethodType_handler() { 14.17 + address entry = __ pc(); 14.18 + // expression stack must be empty before entering the VM if an exception 14.19 + // happened 14.20 + __ empty_expression_stack(); 14.21 + // load exception object 14.22 + __ call_VM(Oexception, 14.23 + CAST_FROM_FN_PTR(address, 14.24 + InterpreterRuntime::throw_WrongMethodTypeException), 14.25 + G5_method_type, // required 14.26 + G3_method_handle); // actual 14.27 + __ should_not_reach_here(); 14.28 + return entry; 14.29 +} 14.30 + 14.31 + 14.32 address TemplateInterpreterGenerator::generate_ArrayIndexOutOfBounds_handler(const char* name) { 14.33 address entry = __ pc(); 14.34 // expression stack must be empty before entering the VM if an exception happened 14.35 @@ -448,6 +466,7 @@ 14.36 14.37 const int extra_space = 14.38 rounded_vm_local_words + // frame local scratch space 14.39 + //6815692//methodOopDesc::extra_stack_words() + // extra push slots for MH adapters 14.40 frame::memory_parameter_word_sp_offset + // register save area 14.41 (native_call ? frame::interpreter_frame_extra_outgoing_argument_words : 0); 14.42 14.43 @@ -1447,6 +1466,7 @@ 14.44 round_to(callee_extra_locals * Interpreter::stackElementWords(), WordsPerLong); 14.45 const int max_stack_words = max_stack * Interpreter::stackElementWords(); 14.46 return (round_to((max_stack_words 14.47 + //6815692//+ methodOopDesc::extra_stack_words() 14.48 + rounded_vm_local_words 14.49 + frame::memory_parameter_word_sp_offset), WordsPerLong) 14.50 // already rounded
15.1 --- a/src/cpu/sparc/vm/vtableStubs_sparc.cpp Thu Apr 09 13:59:45 2009 -0700 15.2 +++ b/src/cpu/sparc/vm/vtableStubs_sparc.cpp Tue Apr 14 12:25:54 2009 -0700 15.3 @@ -114,6 +114,9 @@ 15.4 (int)(s->code_end() - __ pc())); 15.5 } 15.6 guarantee(__ pc() <= s->code_end(), "overflowed buffer"); 15.7 + // shut the door on sizing bugs 15.8 + int slop = 2*BytesPerInstWord; // 32-bit offset is this much larger than a 13-bit one 15.9 + assert(vtable_index > 10 || __ pc() + slop <= s->code_end(), "room for sethi;add"); 15.10 15.11 s->set_exception_points(npe_addr, ame_addr); 15.12 return s; 15.13 @@ -208,6 +211,9 @@ 15.14 (int)(s->code_end() - __ pc())); 15.15 } 15.16 guarantee(__ pc() <= s->code_end(), "overflowed buffer"); 15.17 + // shut the door on sizing bugs 15.18 + int slop = 2*BytesPerInstWord; // 32-bit offset is this much larger than a 13-bit one 15.19 + assert(itable_index > 10 || __ pc() + slop <= s->code_end(), "room for sethi;add"); 15.20 15.21 s->set_exception_points(npe_addr, ame_addr); 15.22 return s; 15.23 @@ -233,6 +239,50 @@ 15.24 return (basic + slop); 15.25 } 15.26 } 15.27 + 15.28 + // In order to tune these parameters, run the JVM with VM options 15.29 + // +PrintMiscellaneous and +WizardMode to see information about 15.30 + // actual itable stubs. Look for lines like this: 15.31 + // itable #1 at 0x5551212[116] left over: 8 15.32 + // Reduce the constants so that the "left over" number is 8 15.33 + // Do not aim at a left-over number of zero, because a very 15.34 + // large vtable or itable offset (> 4K) will require an extra 15.35 + // sethi/or pair of instructions. 15.36 + // 15.37 + // The JVM98 app. _202_jess has a megamorphic interface call. 15.38 + // The itable code looks like this: 15.39 + // Decoding VtableStub itbl[1]@16 15.40 + // ld [ %o0 + 4 ], %g3 15.41 + // save %sp, -64, %sp 15.42 + // ld [ %g3 + 0xe8 ], %l2 15.43 + // sll %l2, 2, %l2 15.44 + // add %l2, 0x134, %l2 15.45 + // and %l2, -8, %l2 ! NOT_LP64 only 15.46 + // add %g3, %l2, %l2 15.47 + // add %g3, 4, %g3 15.48 + // ld [ %l2 ], %l5 15.49 + // brz,pn %l5, throw_icce 15.50 + // cmp %l5, %g5 15.51 + // be %icc, success 15.52 + // add %l2, 8, %l2 15.53 + // loop: 15.54 + // ld [ %l2 ], %l5 15.55 + // brz,pn %l5, throw_icce 15.56 + // cmp %l5, %g5 15.57 + // bne,pn %icc, loop 15.58 + // add %l2, 8, %l2 15.59 + // success: 15.60 + // ld [ %l2 + -4 ], %l2 15.61 + // ld [ %g3 + %l2 ], %l5 15.62 + // restore %l5, 0, %g5 15.63 + // ld [ %g5 + 0x44 ], %g3 15.64 + // jmp %g3 15.65 + // nop 15.66 + // throw_icce: 15.67 + // sethi %hi(throw_ICCE_entry), %g3 15.68 + // ! 5 more instructions here, LP64_ONLY 15.69 + // jmp %g3 + %lo(throw_ICCE_entry) 15.70 + // restore 15.71 } 15.72 15.73
16.1 --- a/src/cpu/x86/vm/assembler_x86.cpp Thu Apr 09 13:59:45 2009 -0700 16.2 +++ b/src/cpu/x86/vm/assembler_x86.cpp Tue Apr 14 12:25:54 2009 -0700 16.3 @@ -7609,6 +7609,83 @@ 16.4 } 16.5 16.6 16.7 +// registers on entry: 16.8 +// - rax ('check' register): required MethodType 16.9 +// - rcx: method handle 16.10 +// - rdx, rsi, or ?: killable temp 16.11 +void MacroAssembler::check_method_handle_type(Register mtype_reg, Register mh_reg, 16.12 + Register temp_reg, 16.13 + Label& wrong_method_type) { 16.14 + if (UseCompressedOops) unimplemented(); // field accesses must decode 16.15 + // compare method type against that of the receiver 16.16 + cmpptr(mtype_reg, Address(mh_reg, delayed_value(java_dyn_MethodHandle::type_offset_in_bytes, temp_reg))); 16.17 + jcc(Assembler::notEqual, wrong_method_type); 16.18 +} 16.19 + 16.20 + 16.21 +// A method handle has a "vmslots" field which gives the size of its 16.22 +// argument list in JVM stack slots. This field is either located directly 16.23 +// in every method handle, or else is indirectly accessed through the 16.24 +// method handle's MethodType. This macro hides the distinction. 16.25 +void MacroAssembler::load_method_handle_vmslots(Register vmslots_reg, Register mh_reg, 16.26 + Register temp_reg) { 16.27 + if (UseCompressedOops) unimplemented(); // field accesses must decode 16.28 + // load mh.type.form.vmslots 16.29 + if (java_dyn_MethodHandle::vmslots_offset_in_bytes() != 0) { 16.30 + // hoist vmslots into every mh to avoid dependent load chain 16.31 + movl(vmslots_reg, Address(mh_reg, delayed_value(java_dyn_MethodHandle::vmslots_offset_in_bytes, temp_reg))); 16.32 + } else { 16.33 + Register temp2_reg = vmslots_reg; 16.34 + movptr(temp2_reg, Address(mh_reg, delayed_value(java_dyn_MethodHandle::type_offset_in_bytes, temp_reg))); 16.35 + movptr(temp2_reg, Address(temp2_reg, delayed_value(java_dyn_MethodType::form_offset_in_bytes, temp_reg))); 16.36 + movl(vmslots_reg, Address(temp2_reg, delayed_value(java_dyn_MethodTypeForm::vmslots_offset_in_bytes, temp_reg))); 16.37 + } 16.38 +} 16.39 + 16.40 + 16.41 +// registers on entry: 16.42 +// - rcx: method handle 16.43 +// - rdx: killable temp (interpreted only) 16.44 +// - rax: killable temp (compiled only) 16.45 +void MacroAssembler::jump_to_method_handle_entry(Register mh_reg, Register temp_reg) { 16.46 + assert(mh_reg == rcx, "caller must put MH object in rcx"); 16.47 + assert_different_registers(mh_reg, temp_reg); 16.48 + 16.49 + if (UseCompressedOops) unimplemented(); // field accesses must decode 16.50 + 16.51 + // pick out the interpreted side of the handler 16.52 + movptr(temp_reg, Address(mh_reg, delayed_value(java_dyn_MethodHandle::vmentry_offset_in_bytes, temp_reg))); 16.53 + 16.54 + // off we go... 16.55 + jmp(Address(temp_reg, MethodHandleEntry::from_interpreted_entry_offset_in_bytes())); 16.56 + 16.57 + // for the various stubs which take control at this point, 16.58 + // see MethodHandles::generate_method_handle_stub 16.59 +} 16.60 + 16.61 + 16.62 +Address MacroAssembler::argument_address(RegisterOrConstant arg_slot, 16.63 + int extra_slot_offset) { 16.64 + // cf. TemplateTable::prepare_invoke(), if (load_receiver). 16.65 + int stackElementSize = Interpreter::stackElementSize(); 16.66 + int offset = Interpreter::expr_offset_in_bytes(extra_slot_offset+0); 16.67 +#ifdef ASSERT 16.68 + int offset1 = Interpreter::expr_offset_in_bytes(extra_slot_offset+1); 16.69 + assert(offset1 - offset == stackElementSize, "correct arithmetic"); 16.70 +#endif 16.71 + Register scale_reg = noreg; 16.72 + Address::ScaleFactor scale_factor = Address::no_scale; 16.73 + if (arg_slot.is_constant()) { 16.74 + offset += arg_slot.as_constant() * stackElementSize; 16.75 + } else { 16.76 + scale_reg = arg_slot.as_register(); 16.77 + scale_factor = Address::times(stackElementSize); 16.78 + } 16.79 + offset += wordSize; // return PC is on stack 16.80 + return Address(rsp, scale_reg, scale_factor, offset); 16.81 +} 16.82 + 16.83 + 16.84 void MacroAssembler::verify_oop_addr(Address addr, const char* s) { 16.85 if (!VerifyOops) return; 16.86
17.1 --- a/src/cpu/x86/vm/assembler_x86.hpp Thu Apr 09 13:59:45 2009 -0700 17.2 +++ b/src/cpu/x86/vm/assembler_x86.hpp Tue Apr 14 12:25:54 2009 -0700 17.3 @@ -1857,6 +1857,16 @@ 17.4 Register temp_reg, 17.5 Label& L_success); 17.6 17.7 + // method handles (JSR 292) 17.8 + void check_method_handle_type(Register mtype_reg, Register mh_reg, 17.9 + Register temp_reg, 17.10 + Label& wrong_method_type); 17.11 + void load_method_handle_vmslots(Register vmslots_reg, Register mh_reg, 17.12 + Register temp_reg); 17.13 + void jump_to_method_handle_entry(Register mh_reg, Register temp_reg); 17.14 + Address argument_address(RegisterOrConstant arg_slot, int extra_slot_offset = 0); 17.15 + 17.16 + 17.17 //---- 17.18 void set_word_if_not_zero(Register reg); // sets reg to 1 if not zero, otherwise 0 17.19
18.1 --- a/src/cpu/x86/vm/cppInterpreter_x86.cpp Thu Apr 09 13:59:45 2009 -0700 18.2 +++ b/src/cpu/x86/vm/cppInterpreter_x86.cpp Tue Apr 14 12:25:54 2009 -0700 18.3 @@ -513,10 +513,11 @@ 18.4 // compute full expression stack limit 18.5 18.6 const Address size_of_stack (rbx, methodOopDesc::max_stack_offset()); 18.7 + const int extra_stack = 0; //6815692//methodOopDesc::extra_stack_words(); 18.8 __ load_unsigned_short(rdx, size_of_stack); // get size of expression stack in words 18.9 __ negptr(rdx); // so we can subtract in next step 18.10 // Allocate expression stack 18.11 - __ lea(rsp, Address(rsp, rdx, Address::times_ptr)); 18.12 + __ lea(rsp, Address(rsp, rdx, Address::times_ptr, -extra_stack)); 18.13 __ movptr(STATE(_stack_limit), rsp); 18.14 } 18.15 18.16 @@ -659,8 +660,9 @@ 18.17 // Always give one monitor to allow us to start interp if sync method. 18.18 // Any additional monitors need a check when moving the expression stack 18.19 const int one_monitor = frame::interpreter_frame_monitor_size() * wordSize; 18.20 + const int extra_stack = 0; //6815692//methodOopDesc::extra_stack_entries(); 18.21 __ load_unsigned_short(rax, size_of_stack); // get size of expression stack in words 18.22 - __ lea(rax, Address(noreg, rax, Interpreter::stackElementScale(), one_monitor)); 18.23 + __ lea(rax, Address(noreg, rax, Interpreter::stackElementScale(), extra_stack + one_monitor)); 18.24 __ lea(rax, Address(rax, rdx, Interpreter::stackElementScale(), overhead_size)); 18.25 18.26 #ifdef ASSERT 18.27 @@ -2185,6 +2187,7 @@ 18.28 case Interpreter::empty : entry_point = ((InterpreterGenerator*)this)->generate_empty_entry(); break; 18.29 case Interpreter::accessor : entry_point = ((InterpreterGenerator*)this)->generate_accessor_entry(); break; 18.30 case Interpreter::abstract : entry_point = ((InterpreterGenerator*)this)->generate_abstract_entry(); break; 18.31 + case Interpreter::method_handle : entry_point = ((InterpreterGenerator*)this)->generate_method_handle_entry(); break; 18.32 18.33 case Interpreter::java_lang_math_sin : // fall thru 18.34 case Interpreter::java_lang_math_cos : // fall thru 18.35 @@ -2224,7 +2227,8 @@ 18.36 const int overhead_size = sizeof(BytecodeInterpreter)/wordSize + 18.37 ( frame::sender_sp_offset - frame::link_offset) + 2; 18.38 18.39 - const int method_stack = (method->max_locals() + method->max_stack()) * 18.40 + const int extra_stack = 0; //6815692//methodOopDesc::extra_stack_entries(); 18.41 + const int method_stack = (method->max_locals() + method->max_stack() + extra_stack) * 18.42 Interpreter::stackElementWords(); 18.43 return overhead_size + method_stack + stub_code; 18.44 } 18.45 @@ -2289,7 +2293,8 @@ 18.46 // Need +1 here because stack_base points to the word just above the first expr stack entry 18.47 // and stack_limit is supposed to point to the word just below the last expr stack entry. 18.48 // See generate_compute_interpreter_state. 18.49 - to_fill->_stack_limit = stack_base - (method->max_stack() + 1); 18.50 + int extra_stack = 0; //6815692//methodOopDesc::extra_stack_entries(); 18.51 + to_fill->_stack_limit = stack_base - (method->max_stack() + extra_stack + 1); 18.52 to_fill->_monitor_base = (BasicObjectLock*) monitor_base; 18.53 18.54 to_fill->_self_link = to_fill; 18.55 @@ -2335,7 +2340,8 @@ 18.56 monitor_size); 18.57 18.58 // Now with full size expression stack 18.59 - int full_frame_size = short_frame_size + method->max_stack() * BytesPerWord; 18.60 + int extra_stack = 0; //6815692//methodOopDesc::extra_stack_entries(); 18.61 + int full_frame_size = short_frame_size + (method->max_stack() + extra_stack) * BytesPerWord; 18.62 18.63 // and now with only live portion of the expression stack 18.64 short_frame_size = short_frame_size + tempcount * BytesPerWord;
19.1 --- a/src/cpu/x86/vm/interp_masm_x86_32.cpp Thu Apr 09 13:59:45 2009 -0700 19.2 +++ b/src/cpu/x86/vm/interp_masm_x86_32.cpp Tue Apr 14 12:25:54 2009 -0700 19.3 @@ -555,13 +555,18 @@ 19.4 } 19.5 19.6 19.7 -// Jump to from_interpreted entry of a call unless single stepping is possible 19.8 -// in this thread in which case we must call the i2i entry 19.9 -void InterpreterMacroAssembler::jump_from_interpreted(Register method, Register temp) { 19.10 +void InterpreterMacroAssembler::prepare_to_jump_from_interpreted() { 19.11 // set sender sp 19.12 lea(rsi, Address(rsp, wordSize)); 19.13 // record last_sp 19.14 movptr(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), rsi); 19.15 +} 19.16 + 19.17 + 19.18 +// Jump to from_interpreted entry of a call unless single stepping is possible 19.19 +// in this thread in which case we must call the i2i entry 19.20 +void InterpreterMacroAssembler::jump_from_interpreted(Register method, Register temp) { 19.21 + prepare_to_jump_from_interpreted(); 19.22 19.23 if (JvmtiExport::can_post_interpreter_events()) { 19.24 Label run_compiled_code;
20.1 --- a/src/cpu/x86/vm/interp_masm_x86_32.hpp Thu Apr 09 13:59:45 2009 -0700 20.2 +++ b/src/cpu/x86/vm/interp_masm_x86_32.hpp Tue Apr 14 12:25:54 2009 -0700 20.3 @@ -161,6 +161,7 @@ 20.4 20.5 20.6 // jump to an invoked target 20.7 + void prepare_to_jump_from_interpreted(); 20.8 void jump_from_interpreted(Register method, Register temp); 20.9 20.10 // Returning from interpreted functions
21.1 --- a/src/cpu/x86/vm/interp_masm_x86_64.cpp Thu Apr 09 13:59:45 2009 -0700 21.2 +++ b/src/cpu/x86/vm/interp_masm_x86_64.cpp Tue Apr 14 12:25:54 2009 -0700 21.3 @@ -551,13 +551,18 @@ 21.4 MacroAssembler::call_VM_leaf_base(entry_point, 3); 21.5 } 21.6 21.7 -// Jump to from_interpreted entry of a call unless single stepping is possible 21.8 -// in this thread in which case we must call the i2i entry 21.9 -void InterpreterMacroAssembler::jump_from_interpreted(Register method, Register temp) { 21.10 +void InterpreterMacroAssembler::prepare_to_jump_from_interpreted() { 21.11 // set sender sp 21.12 lea(r13, Address(rsp, wordSize)); 21.13 // record last_sp 21.14 movptr(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), r13); 21.15 +} 21.16 + 21.17 + 21.18 +// Jump to from_interpreted entry of a call unless single stepping is possible 21.19 +// in this thread in which case we must call the i2i entry 21.20 +void InterpreterMacroAssembler::jump_from_interpreted(Register method, Register temp) { 21.21 + prepare_to_jump_from_interpreted(); 21.22 21.23 if (JvmtiExport::can_post_interpreter_events()) { 21.24 Label run_compiled_code;
22.1 --- a/src/cpu/x86/vm/interp_masm_x86_64.hpp Thu Apr 09 13:59:45 2009 -0700 22.2 +++ b/src/cpu/x86/vm/interp_masm_x86_64.hpp Tue Apr 14 12:25:54 2009 -0700 22.3 @@ -1,5 +1,5 @@ 22.4 /* 22.5 - * Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved. 22.6 + * Copyright 2003-2009 Sun Microsystems, Inc. All Rights Reserved. 22.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 22.8 * 22.9 * This code is free software; you can redistribute it and/or modify it 22.10 @@ -176,6 +176,7 @@ 22.11 void dispatch_via (TosState state, address* table); 22.12 22.13 // jump to an invoked target 22.14 + void prepare_to_jump_from_interpreted(); 22.15 void jump_from_interpreted(Register method, Register temp); 22.16 22.17
23.1 --- a/src/cpu/x86/vm/interpreterGenerator_x86.hpp Thu Apr 09 13:59:45 2009 -0700 23.2 +++ b/src/cpu/x86/vm/interpreterGenerator_x86.hpp Tue Apr 14 12:25:54 2009 -0700 23.3 @@ -1,5 +1,5 @@ 23.4 /* 23.5 - * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved. 23.6 + * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved. 23.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 23.8 * 23.9 * This code is free software; you can redistribute it and/or modify it 23.10 @@ -32,6 +32,7 @@ 23.11 address generate_normal_entry(bool synchronized); 23.12 address generate_native_entry(bool synchronized); 23.13 address generate_abstract_entry(void); 23.14 + address generate_method_handle_entry(void); 23.15 address generate_math_entry(AbstractInterpreter::MethodKind kind); 23.16 address generate_empty_entry(void); 23.17 address generate_accessor_entry(void);
24.1 --- a/src/cpu/x86/vm/interpreter_x86_32.cpp Thu Apr 09 13:59:45 2009 -0700 24.2 +++ b/src/cpu/x86/vm/interpreter_x86_32.cpp Tue Apr 14 12:25:54 2009 -0700 24.3 @@ -1,5 +1,5 @@ 24.4 /* 24.5 - * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved. 24.6 + * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved. 24.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 24.8 * 24.9 * This code is free software; you can redistribute it and/or modify it 24.10 @@ -201,11 +201,12 @@ 24.11 address entry_point = __ pc(); 24.12 24.13 // abstract method entry 24.14 - // remove return address. Not really needed, since exception handling throws away expression stack 24.15 - __ pop(rbx); 24.16 24.17 - // adjust stack to what a normal return would do 24.18 - __ mov(rsp, rsi); 24.19 + // pop return address, reset last_sp to NULL 24.20 + __ empty_expression_stack(); 24.21 + __ restore_bcp(); // rsi must be correct for exception handler (was destroyed) 24.22 + __ restore_locals(); // make sure locals pointer is correct as well (was destroyed) 24.23 + 24.24 // throw exception 24.25 __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_AbstractMethodError)); 24.26 // the call_VM checks for exception, so we should never return here. 24.27 @@ -214,6 +215,20 @@ 24.28 return entry_point; 24.29 } 24.30 24.31 + 24.32 +// Method handle invoker 24.33 +// Dispatch a method of the form java.dyn.MethodHandles::invoke(...) 24.34 +address InterpreterGenerator::generate_method_handle_entry(void) { 24.35 + if (!EnableMethodHandles) { 24.36 + return generate_abstract_entry(); 24.37 + } 24.38 + 24.39 + address entry_point = MethodHandles::generate_method_handle_interpreter_entry(_masm); 24.40 + 24.41 + return entry_point; 24.42 +} 24.43 + 24.44 + 24.45 // This method tells the deoptimizer how big an interpreted frame must be: 24.46 int AbstractInterpreter::size_activation(methodOop method, 24.47 int tempcount,
25.1 --- a/src/cpu/x86/vm/interpreter_x86_64.cpp Thu Apr 09 13:59:45 2009 -0700 25.2 +++ b/src/cpu/x86/vm/interpreter_x86_64.cpp Tue Apr 14 12:25:54 2009 -0700 25.3 @@ -1,5 +1,5 @@ 25.4 /* 25.5 - * Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved. 25.6 + * Copyright 2003-2009 Sun Microsystems, Inc. All Rights Reserved. 25.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 25.8 * 25.9 * This code is free software; you can redistribute it and/or modify it 25.10 @@ -294,6 +294,16 @@ 25.11 } 25.12 25.13 25.14 +// Method handle invoker 25.15 +// Dispatch a method of the form java.dyn.MethodHandles::invoke(...) 25.16 +address InterpreterGenerator::generate_method_handle_entry(void) { 25.17 + if (!EnableMethodHandles) { 25.18 + return generate_abstract_entry(); 25.19 + } 25.20 + return generate_abstract_entry(); //6815692// 25.21 +} 25.22 + 25.23 + 25.24 // Empty method, generate a very fast return. 25.25 25.26 address InterpreterGenerator::generate_empty_entry(void) {
26.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 26.2 +++ b/src/cpu/x86/vm/methodHandles_x86.cpp Tue Apr 14 12:25:54 2009 -0700 26.3 @@ -0,0 +1,1133 @@ 26.4 +/* 26.5 + * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved. 26.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 26.7 + * 26.8 + * This code is free software; you can redistribute it and/or modify it 26.9 + * under the terms of the GNU General Public License version 2 only, as 26.10 + * published by the Free Software Foundation. 26.11 + * 26.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 26.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 26.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 26.15 + * version 2 for more details (a copy is included in the LICENSE file that 26.16 + * accompanied this code). 26.17 + * 26.18 + * You should have received a copy of the GNU General Public License version 26.19 + * 2 along with this work; if not, write to the Free Software Foundation, 26.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 26.21 + * 26.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 26.23 + * CA 95054 USA or visit www.sun.com if you need additional information or 26.24 + * have any questions. 26.25 + * 26.26 + */ 26.27 + 26.28 +#include "incls/_precompiled.incl" 26.29 +#include "incls/_methodHandles_x86.cpp.incl" 26.30 + 26.31 +#define __ _masm-> 26.32 + 26.33 +address MethodHandleEntry::start_compiled_entry(MacroAssembler* _masm, 26.34 + address interpreted_entry) { 26.35 + // Just before the actual machine code entry point, allocate space 26.36 + // for a MethodHandleEntry::Data record, so that we can manage everything 26.37 + // from one base pointer. 26.38 + __ align(wordSize); 26.39 + address target = __ pc() + sizeof(Data); 26.40 + while (__ pc() < target) { 26.41 + __ nop(); 26.42 + __ align(wordSize); 26.43 + } 26.44 + 26.45 + MethodHandleEntry* me = (MethodHandleEntry*) __ pc(); 26.46 + me->set_end_address(__ pc()); // set a temporary end_address 26.47 + me->set_from_interpreted_entry(interpreted_entry); 26.48 + me->set_type_checking_entry(NULL); 26.49 + 26.50 + return (address) me; 26.51 +} 26.52 + 26.53 +MethodHandleEntry* MethodHandleEntry::finish_compiled_entry(MacroAssembler* _masm, 26.54 + address start_addr) { 26.55 + MethodHandleEntry* me = (MethodHandleEntry*) start_addr; 26.56 + assert(me->end_address() == start_addr, "valid ME"); 26.57 + 26.58 + // Fill in the real end_address: 26.59 + __ align(wordSize); 26.60 + me->set_end_address(__ pc()); 26.61 + 26.62 + return me; 26.63 +} 26.64 + 26.65 +#ifdef ASSERT 26.66 +static void verify_argslot(MacroAssembler* _masm, Register rax_argslot, 26.67 + const char* error_message) { 26.68 + // Verify that argslot lies within (rsp, rbp]. 26.69 + Label L_ok, L_bad; 26.70 + __ cmpptr(rax_argslot, rbp); 26.71 + __ jcc(Assembler::above, L_bad); 26.72 + __ cmpptr(rsp, rax_argslot); 26.73 + __ jcc(Assembler::below, L_ok); 26.74 + __ bind(L_bad); 26.75 + __ stop(error_message); 26.76 + __ bind(L_ok); 26.77 +} 26.78 +#endif 26.79 + 26.80 + 26.81 +// Code generation 26.82 +address MethodHandles::generate_method_handle_interpreter_entry(MacroAssembler* _masm) { 26.83 + // rbx: methodOop 26.84 + // rcx: receiver method handle (must load from sp[MethodTypeForm.vmslots]) 26.85 + // rsi/r13: sender SP (must preserve; see prepare_to_jump_from_interpreted) 26.86 + // rdx: garbage temp, blown away 26.87 + 26.88 + Register rbx_method = rbx; 26.89 + Register rcx_recv = rcx; 26.90 + Register rax_mtype = rax; 26.91 + Register rdx_temp = rdx; 26.92 + 26.93 + // emit WrongMethodType path first, to enable jccb back-branch from main path 26.94 + Label wrong_method_type; 26.95 + __ bind(wrong_method_type); 26.96 + __ push(rax_mtype); // required mtype 26.97 + __ push(rcx_recv); // bad mh (1st stacked argument) 26.98 + __ jump(ExternalAddress(Interpreter::throw_WrongMethodType_entry())); 26.99 + 26.100 + // here's where control starts out: 26.101 + __ align(CodeEntryAlignment); 26.102 + address entry_point = __ pc(); 26.103 + 26.104 + // fetch the MethodType from the method handle into rax (the 'check' register) 26.105 + { 26.106 + Register tem = rbx_method; 26.107 + for (jint* pchase = methodOopDesc::method_type_offsets_chain(); (*pchase) != -1; pchase++) { 26.108 + __ movptr(rax_mtype, Address(tem, *pchase)); 26.109 + tem = rax_mtype; // in case there is another indirection 26.110 + } 26.111 + } 26.112 + Register rbx_temp = rbx_method; // done with incoming methodOop 26.113 + 26.114 + // given the MethodType, find out where the MH argument is buried 26.115 + __ movptr(rdx_temp, Address(rax_mtype, 26.116 + __ delayed_value(java_dyn_MethodType::form_offset_in_bytes, rbx_temp))); 26.117 + __ movl(rdx_temp, Address(rdx_temp, 26.118 + __ delayed_value(java_dyn_MethodTypeForm::vmslots_offset_in_bytes, rbx_temp))); 26.119 + __ movptr(rcx_recv, __ argument_address(rdx_temp)); 26.120 + 26.121 + __ check_method_handle_type(rax_mtype, rcx_recv, rdx_temp, wrong_method_type); 26.122 + __ jump_to_method_handle_entry(rcx_recv, rdx_temp); 26.123 + 26.124 + return entry_point; 26.125 +} 26.126 + 26.127 +// Helper to insert argument slots into the stack. 26.128 +// arg_slots must be a multiple of stack_move_unit() and <= 0 26.129 +void MethodHandles::insert_arg_slots(MacroAssembler* _masm, 26.130 + RegisterOrConstant arg_slots, 26.131 + int arg_mask, 26.132 + Register rax_argslot, 26.133 + Register rbx_temp, Register rdx_temp) { 26.134 + assert_different_registers(rax_argslot, rbx_temp, rdx_temp, 26.135 + (!arg_slots.is_register() ? rsp : arg_slots.as_register())); 26.136 + 26.137 +#ifdef ASSERT 26.138 + verify_argslot(_masm, rax_argslot, "insertion point must fall within current frame"); 26.139 + if (arg_slots.is_register()) { 26.140 + Label L_ok, L_bad; 26.141 + __ cmpptr(arg_slots.as_register(), (int32_t) NULL_WORD); 26.142 + __ jcc(Assembler::greater, L_bad); 26.143 + __ testl(arg_slots.as_register(), -stack_move_unit() - 1); 26.144 + __ jcc(Assembler::zero, L_ok); 26.145 + __ bind(L_bad); 26.146 + __ stop("assert arg_slots <= 0 and clear low bits"); 26.147 + __ bind(L_ok); 26.148 + } else { 26.149 + assert(arg_slots.as_constant() <= 0, ""); 26.150 + assert(arg_slots.as_constant() % -stack_move_unit() == 0, ""); 26.151 + } 26.152 +#endif //ASSERT 26.153 + 26.154 +#ifdef _LP64 26.155 + if (arg_slots.is_register()) { 26.156 + // clean high bits of stack motion register (was loaded as an int) 26.157 + __ movslq(arg_slots.as_register(), arg_slots.as_register()); 26.158 + } 26.159 +#endif 26.160 + 26.161 + // Make space on the stack for the inserted argument(s). 26.162 + // Then pull down everything shallower than rax_argslot. 26.163 + // The stacked return address gets pulled down with everything else. 26.164 + // That is, copy [rsp, argslot) downward by -size words. In pseudo-code: 26.165 + // rsp -= size; 26.166 + // for (rdx = rsp + size; rdx < argslot; rdx++) 26.167 + // rdx[-size] = rdx[0] 26.168 + // argslot -= size; 26.169 + __ mov(rdx_temp, rsp); // source pointer for copy 26.170 + __ lea(rsp, Address(rsp, arg_slots, Address::times_ptr)); 26.171 + { 26.172 + Label loop; 26.173 + __ bind(loop); 26.174 + // pull one word down each time through the loop 26.175 + __ movptr(rbx_temp, Address(rdx_temp, 0)); 26.176 + __ movptr(Address(rdx_temp, arg_slots, Address::times_ptr), rbx_temp); 26.177 + __ addptr(rdx_temp, wordSize); 26.178 + __ cmpptr(rdx_temp, rax_argslot); 26.179 + __ jcc(Assembler::less, loop); 26.180 + } 26.181 + 26.182 + // Now move the argslot down, to point to the opened-up space. 26.183 + __ lea(rax_argslot, Address(rax_argslot, arg_slots, Address::times_ptr)); 26.184 + 26.185 + if (TaggedStackInterpreter && arg_mask != _INSERT_NO_MASK) { 26.186 + // The caller has specified a bitmask of tags to put into the opened space. 26.187 + // This only works when the arg_slots value is an assembly-time constant. 26.188 + int constant_arg_slots = arg_slots.as_constant() / stack_move_unit(); 26.189 + int tag_offset = Interpreter::tag_offset_in_bytes() - Interpreter::value_offset_in_bytes(); 26.190 + for (int slot = 0; slot < constant_arg_slots; slot++) { 26.191 + BasicType slot_type = ((arg_mask & (1 << slot)) == 0 ? T_OBJECT : T_INT); 26.192 + int slot_offset = Interpreter::stackElementSize() * slot; 26.193 + Address tag_addr(rax_argslot, slot_offset + tag_offset); 26.194 + __ movptr(tag_addr, frame::tag_for_basic_type(slot_type)); 26.195 + } 26.196 + // Note that the new argument slots are tagged properly but contain 26.197 + // garbage at this point. The value portions must be initialized 26.198 + // by the caller. (Especially references!) 26.199 + } 26.200 +} 26.201 + 26.202 +// Helper to remove argument slots from the stack. 26.203 +// arg_slots must be a multiple of stack_move_unit() and >= 0 26.204 +void MethodHandles::remove_arg_slots(MacroAssembler* _masm, 26.205 + RegisterOrConstant arg_slots, 26.206 + Register rax_argslot, 26.207 + Register rbx_temp, Register rdx_temp) { 26.208 + assert_different_registers(rax_argslot, rbx_temp, rdx_temp, 26.209 + (!arg_slots.is_register() ? rsp : arg_slots.as_register())); 26.210 + 26.211 +#ifdef ASSERT 26.212 + { 26.213 + // Verify that [argslot..argslot+size) lies within (rsp, rbp). 26.214 + Label L_ok, L_bad; 26.215 + __ lea(rbx_temp, Address(rax_argslot, arg_slots, Address::times_ptr)); 26.216 + __ cmpptr(rbx_temp, rbp); 26.217 + __ jcc(Assembler::above, L_bad); 26.218 + __ cmpptr(rsp, rax_argslot); 26.219 + __ jcc(Assembler::below, L_ok); 26.220 + __ bind(L_bad); 26.221 + __ stop("deleted argument(s) must fall within current frame"); 26.222 + __ bind(L_ok); 26.223 + } 26.224 + if (arg_slots.is_register()) { 26.225 + Label L_ok, L_bad; 26.226 + __ cmpptr(arg_slots.as_register(), (int32_t) NULL_WORD); 26.227 + __ jcc(Assembler::less, L_bad); 26.228 + __ testl(arg_slots.as_register(), -stack_move_unit() - 1); 26.229 + __ jcc(Assembler::zero, L_ok); 26.230 + __ bind(L_bad); 26.231 + __ stop("assert arg_slots >= 0 and clear low bits"); 26.232 + __ bind(L_ok); 26.233 + } else { 26.234 + assert(arg_slots.as_constant() >= 0, ""); 26.235 + assert(arg_slots.as_constant() % -stack_move_unit() == 0, ""); 26.236 + } 26.237 +#endif //ASSERT 26.238 + 26.239 +#ifdef _LP64 26.240 + if (false) { // not needed, since register is positive 26.241 + // clean high bits of stack motion register (was loaded as an int) 26.242 + if (arg_slots.is_register()) 26.243 + __ movslq(arg_slots.as_register(), arg_slots.as_register()); 26.244 + } 26.245 +#endif 26.246 + 26.247 + // Pull up everything shallower than rax_argslot. 26.248 + // Then remove the excess space on the stack. 26.249 + // The stacked return address gets pulled up with everything else. 26.250 + // That is, copy [rsp, argslot) upward by size words. In pseudo-code: 26.251 + // for (rdx = argslot-1; rdx >= rsp; --rdx) 26.252 + // rdx[size] = rdx[0] 26.253 + // argslot += size; 26.254 + // rsp += size; 26.255 + __ lea(rdx_temp, Address(rax_argslot, -wordSize)); // source pointer for copy 26.256 + { 26.257 + Label loop; 26.258 + __ bind(loop); 26.259 + // pull one word up each time through the loop 26.260 + __ movptr(rbx_temp, Address(rdx_temp, 0)); 26.261 + __ movptr(Address(rdx_temp, arg_slots, Address::times_ptr), rbx_temp); 26.262 + __ addptr(rdx_temp, -wordSize); 26.263 + __ cmpptr(rdx_temp, rsp); 26.264 + __ jcc(Assembler::greaterEqual, loop); 26.265 + } 26.266 + 26.267 + // Now move the argslot up, to point to the just-copied block. 26.268 + __ lea(rsp, Address(rsp, arg_slots, Address::times_ptr)); 26.269 + // And adjust the argslot address to point at the deletion point. 26.270 + __ lea(rax_argslot, Address(rax_argslot, arg_slots, Address::times_ptr)); 26.271 +} 26.272 + 26.273 +#ifndef PRODUCT 26.274 +void trace_method_handle_stub(const char* adaptername, 26.275 + oop mh, 26.276 + intptr_t* entry_sp, 26.277 + intptr_t* saved_sp) { 26.278 + // called as a leaf from native code: do not block the JVM! 26.279 + printf("MH %s "PTR_FORMAT" "PTR_FORMAT" "INTX_FORMAT"\n", adaptername, mh, entry_sp, entry_sp - saved_sp); 26.280 +} 26.281 +#endif //PRODUCT 26.282 + 26.283 +// Generate an "entry" field for a method handle. 26.284 +// This determines how the method handle will respond to calls. 26.285 +void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHandles::EntryKind ek) { 26.286 + // Here is the register state during an interpreted call, 26.287 + // as set up by generate_method_handle_interpreter_entry(): 26.288 + // - rbx: garbage temp (was MethodHandle.invoke methodOop, unused) 26.289 + // - rcx: receiver method handle 26.290 + // - rax: method handle type (only used by the check_mtype entry point) 26.291 + // - rsi/r13: sender SP (must preserve; see prepare_to_jump_from_interpreted) 26.292 + // - rdx: garbage temp, can blow away 26.293 + 26.294 + Register rcx_recv = rcx; 26.295 + Register rax_argslot = rax; 26.296 + Register rbx_temp = rbx; 26.297 + Register rdx_temp = rdx; 26.298 + 26.299 + guarantee(java_dyn_MethodHandle::vmentry_offset_in_bytes() != 0, "must have offsets"); 26.300 + 26.301 + // some handy addresses 26.302 + Address rbx_method_fie( rbx, methodOopDesc::from_interpreted_offset() ); 26.303 + 26.304 + Address rcx_mh_vmtarget( rcx_recv, java_dyn_MethodHandle::vmtarget_offset_in_bytes() ); 26.305 + Address rcx_dmh_vmindex( rcx_recv, sun_dyn_DirectMethodHandle::vmindex_offset_in_bytes() ); 26.306 + 26.307 + Address rcx_bmh_vmargslot( rcx_recv, sun_dyn_BoundMethodHandle::vmargslot_offset_in_bytes() ); 26.308 + Address rcx_bmh_argument( rcx_recv, sun_dyn_BoundMethodHandle::argument_offset_in_bytes() ); 26.309 + 26.310 + Address rcx_amh_vmargslot( rcx_recv, sun_dyn_AdapterMethodHandle::vmargslot_offset_in_bytes() ); 26.311 + Address rcx_amh_argument( rcx_recv, sun_dyn_AdapterMethodHandle::argument_offset_in_bytes() ); 26.312 + Address rcx_amh_conversion( rcx_recv, sun_dyn_AdapterMethodHandle::conversion_offset_in_bytes() ); 26.313 + Address vmarg; // __ argument_address(vmargslot) 26.314 + 26.315 + int tag_offset = -1; 26.316 + if (TaggedStackInterpreter) { 26.317 + tag_offset = Interpreter::tag_offset_in_bytes() - Interpreter::value_offset_in_bytes(); 26.318 + assert(tag_offset = wordSize, "stack grows as expected"); 26.319 + } 26.320 + 26.321 + if (have_entry(ek)) { 26.322 + __ nop(); // empty stubs make SG sick 26.323 + return; 26.324 + } 26.325 + 26.326 + address interp_entry = __ pc(); 26.327 + if (UseCompressedOops) __ unimplemented("UseCompressedOops"); 26.328 + 26.329 +#ifndef PRODUCT 26.330 + if (TraceMethodHandles) { 26.331 + __ push(rax); __ push(rbx); __ push(rcx); __ push(rdx); __ push(rsi); __ push(rdi); 26.332 + __ lea(rax, Address(rsp, wordSize*6)); // entry_sp 26.333 + // arguments: 26.334 + __ push(rsi); // saved_sp 26.335 + __ push(rax); // entry_sp 26.336 + __ push(rcx); // mh 26.337 + __ push(rcx); 26.338 + __ movptr(Address(rsp, 0), (intptr_t)entry_name(ek)); 26.339 + __ call_VM_leaf(CAST_FROM_FN_PTR(address, trace_method_handle_stub), 4); 26.340 + __ pop(rdi); __ pop(rsi); __ pop(rdx); __ pop(rcx); __ pop(rbx); __ pop(rax); 26.341 + } 26.342 +#endif //PRODUCT 26.343 + 26.344 + switch ((int) ek) { 26.345 + case _check_mtype: 26.346 + { 26.347 + // this stub is special, because it requires a live mtype argument 26.348 + Register rax_mtype = rax; 26.349 + 26.350 + // emit WrongMethodType path first, to enable jccb back-branch 26.351 + Label wrong_method_type; 26.352 + __ bind(wrong_method_type); 26.353 + __ movptr(rdx_temp, ExternalAddress((address) &_entries[_wrong_method_type])); 26.354 + __ jmp(Address(rdx_temp, MethodHandleEntry::from_interpreted_entry_offset_in_bytes())); 26.355 + __ hlt(); 26.356 + 26.357 + interp_entry = __ pc(); 26.358 + __ check_method_handle_type(rax_mtype, rcx_recv, rdx_temp, wrong_method_type); 26.359 + // now rax_mtype is dead; subsequent stubs will use it as a temp 26.360 + 26.361 + __ jump_to_method_handle_entry(rcx_recv, rdx_temp); 26.362 + } 26.363 + break; 26.364 + 26.365 + case _wrong_method_type: 26.366 + { 26.367 + // this stub is special, because it requires a live mtype argument 26.368 + Register rax_mtype = rax; 26.369 + 26.370 + interp_entry = __ pc(); 26.371 + __ push(rax_mtype); // required mtype 26.372 + __ push(rcx_recv); // random mh (1st stacked argument) 26.373 + __ jump(ExternalAddress(Interpreter::throw_WrongMethodType_entry())); 26.374 + } 26.375 + break; 26.376 + 26.377 + case _invokestatic_mh: 26.378 + case _invokespecial_mh: 26.379 + { 26.380 + Register rbx_method = rbx_temp; 26.381 + __ movptr(rbx_method, rcx_mh_vmtarget); // target is a methodOop 26.382 + __ verify_oop(rbx_method); 26.383 + // same as TemplateTable::invokestatic or invokespecial, 26.384 + // minus the CP setup and profiling: 26.385 + if (ek == _invokespecial_mh) { 26.386 + // Must load & check the first argument before entering the target method. 26.387 + __ load_method_handle_vmslots(rax_argslot, rcx_recv, rdx_temp); 26.388 + __ movptr(rcx_recv, __ argument_address(rax_argslot, -1)); 26.389 + __ null_check(rcx_recv); 26.390 + __ verify_oop(rcx_recv); 26.391 + } 26.392 + __ jmp(rbx_method_fie); 26.393 + } 26.394 + break; 26.395 + 26.396 + case _invokevirtual_mh: 26.397 + { 26.398 + // same as TemplateTable::invokevirtual, 26.399 + // minus the CP setup and profiling: 26.400 + 26.401 + // pick out the vtable index and receiver offset from the MH, 26.402 + // and then we can discard it: 26.403 + __ load_method_handle_vmslots(rax_argslot, rcx_recv, rdx_temp); 26.404 + Register rbx_index = rbx_temp; 26.405 + __ movl(rbx_index, rcx_dmh_vmindex); 26.406 + // Note: The verifier allows us to ignore rcx_mh_vmtarget. 26.407 + __ movptr(rcx_recv, __ argument_address(rax_argslot, -1)); 26.408 + __ null_check(rcx_recv, oopDesc::klass_offset_in_bytes()); 26.409 + 26.410 + // get receiver klass 26.411 + Register rax_klass = rax_argslot; 26.412 + __ load_klass(rax_klass, rcx_recv); 26.413 + __ verify_oop(rax_klass); 26.414 + 26.415 + // get target methodOop & entry point 26.416 + const int base = instanceKlass::vtable_start_offset() * wordSize; 26.417 + assert(vtableEntry::size() * wordSize == wordSize, "adjust the scaling in the code below"); 26.418 + Address vtable_entry_addr(rax_klass, 26.419 + rbx_index, Address::times_ptr, 26.420 + base + vtableEntry::method_offset_in_bytes()); 26.421 + Register rbx_method = rbx_temp; 26.422 + __ movl(rbx_method, vtable_entry_addr); 26.423 + 26.424 + __ verify_oop(rbx_method); 26.425 + __ jmp(rbx_method_fie); 26.426 + } 26.427 + break; 26.428 + 26.429 + case _invokeinterface_mh: 26.430 + { 26.431 + // same as TemplateTable::invokeinterface, 26.432 + // minus the CP setup and profiling: 26.433 + 26.434 + // pick out the interface and itable index from the MH. 26.435 + __ load_method_handle_vmslots(rax_argslot, rcx_recv, rdx_temp); 26.436 + Register rdx_intf = rdx_temp; 26.437 + Register rbx_index = rbx_temp; 26.438 + __ movptr(rdx_intf, rcx_mh_vmtarget); 26.439 + __ movl(rbx_index, rcx_dmh_vmindex); 26.440 + __ movptr(rcx_recv, __ argument_address(rax_argslot, -1)); 26.441 + __ null_check(rcx_recv, oopDesc::klass_offset_in_bytes()); 26.442 + 26.443 + // get receiver klass 26.444 + Register rax_klass = rax_argslot; 26.445 + __ load_klass(rax_klass, rcx_recv); 26.446 + __ verify_oop(rax_klass); 26.447 + 26.448 + Register rcx_temp = rcx_recv; 26.449 + Register rbx_method = rbx_index; 26.450 + 26.451 + // get interface klass 26.452 + Label no_such_interface; 26.453 + __ verify_oop(rdx_intf); 26.454 + __ lookup_interface_method(rax_klass, rdx_intf, 26.455 + // note: next two args must be the same: 26.456 + rbx_index, rbx_method, 26.457 + rcx_temp, 26.458 + no_such_interface); 26.459 + 26.460 + __ verify_oop(rbx_method); 26.461 + __ jmp(rbx_method_fie); 26.462 + __ hlt(); 26.463 + 26.464 + __ bind(no_such_interface); 26.465 + // Throw an exception. 26.466 + // For historical reasons, it will be IncompatibleClassChangeError. 26.467 + __ should_not_reach_here(); // %%% FIXME NYI 26.468 + } 26.469 + break; 26.470 + 26.471 + case _bound_ref_mh: 26.472 + case _bound_int_mh: 26.473 + case _bound_long_mh: 26.474 + case _bound_ref_direct_mh: 26.475 + case _bound_int_direct_mh: 26.476 + case _bound_long_direct_mh: 26.477 + { 26.478 + bool direct_to_method = (ek >= _bound_ref_direct_mh); 26.479 + BasicType arg_type = T_ILLEGAL; 26.480 + if (ek == _bound_long_mh || ek == _bound_long_direct_mh) { 26.481 + arg_type = T_LONG; 26.482 + } else if (ek == _bound_int_mh || ek == _bound_int_direct_mh) { 26.483 + arg_type = T_INT; 26.484 + } else { 26.485 + assert(ek == _bound_ref_mh || ek == _bound_ref_direct_mh, "must be ref"); 26.486 + arg_type = T_OBJECT; 26.487 + } 26.488 + int arg_slots = type2size[arg_type]; 26.489 + int arg_mask = (arg_type == T_OBJECT ? _INSERT_REF_MASK : 26.490 + arg_slots == 1 ? _INSERT_INT_MASK : _INSERT_LONG_MASK); 26.491 + 26.492 + // make room for the new argument: 26.493 + __ movl(rax_argslot, rcx_bmh_vmargslot); 26.494 + __ lea(rax_argslot, __ argument_address(rax_argslot)); 26.495 + insert_arg_slots(_masm, arg_slots * stack_move_unit(), arg_mask, 26.496 + rax_argslot, rbx_temp, rdx_temp); 26.497 + 26.498 + // store bound argument into the new stack slot: 26.499 + __ movptr(rbx_temp, rcx_bmh_argument); 26.500 + Address prim_value_addr(rbx_temp, java_lang_boxing_object::value_offset_in_bytes(arg_type)); 26.501 + if (arg_type == T_OBJECT) { 26.502 + __ movptr(Address(rax_argslot, 0), rbx_temp); 26.503 + } else { 26.504 + __ load_sized_value(rbx_temp, prim_value_addr, 26.505 + type2aelembytes(arg_type), is_signed_subword_type(arg_type)); 26.506 + __ movptr(Address(rax_argslot, 0), rbx_temp); 26.507 +#ifndef _LP64 26.508 + if (arg_slots == 2) { 26.509 + __ movl(rbx_temp, prim_value_addr.plus_disp(wordSize)); 26.510 + __ movl(Address(rax_argslot, Interpreter::stackElementSize()), rbx_temp); 26.511 + } 26.512 +#endif //_LP64 26.513 + break; 26.514 + } 26.515 + 26.516 + if (direct_to_method) { 26.517 + Register rbx_method = rbx_temp; 26.518 + __ movptr(rbx_method, rcx_mh_vmtarget); 26.519 + __ verify_oop(rbx_method); 26.520 + __ jmp(rbx_method_fie); 26.521 + } else { 26.522 + __ movptr(rcx_recv, rcx_mh_vmtarget); 26.523 + __ verify_oop(rcx_recv); 26.524 + __ jump_to_method_handle_entry(rcx_recv, rdx_temp); 26.525 + } 26.526 + } 26.527 + break; 26.528 + 26.529 + case _adapter_retype_only: 26.530 + // immediately jump to the next MH layer: 26.531 + __ movptr(rcx_recv, rcx_mh_vmtarget); 26.532 + __ verify_oop(rcx_recv); 26.533 + __ jump_to_method_handle_entry(rcx_recv, rdx_temp); 26.534 + // This is OK when all parameter types widen. 26.535 + // It is also OK when a return type narrows. 26.536 + break; 26.537 + 26.538 + case _adapter_check_cast: 26.539 + { 26.540 + // temps: 26.541 + Register rbx_klass = rbx_temp; // interesting AMH data 26.542 + 26.543 + // check a reference argument before jumping to the next layer of MH: 26.544 + __ movl(rax_argslot, rcx_amh_vmargslot); 26.545 + vmarg = __ argument_address(rax_argslot); 26.546 + 26.547 + // What class are we casting to? 26.548 + __ movptr(rbx_klass, rcx_amh_argument); // this is a Class object! 26.549 + __ movptr(rbx_klass, Address(rbx_klass, java_lang_Class::klass_offset_in_bytes())); 26.550 + 26.551 + // get the new MH: 26.552 + __ movptr(rcx_recv, rcx_mh_vmtarget); 26.553 + // (now we are done with the old MH) 26.554 + 26.555 + Label done; 26.556 + __ movptr(rdx_temp, vmarg); 26.557 + __ testl(rdx_temp, rdx_temp); 26.558 + __ jcc(Assembler::zero, done); // no cast if null 26.559 + __ load_klass(rdx_temp, rdx_temp); 26.560 + 26.561 + // live at this point: 26.562 + // - rbx_klass: klass required by the target method 26.563 + // - rdx_temp: argument klass to test 26.564 + // - rcx_recv: method handle to invoke (after cast succeeds) 26.565 + __ check_klass_subtype(rdx_temp, rbx_klass, rax_argslot, done); 26.566 + 26.567 + // If we get here, the type check failed! 26.568 + // Call the wrong_method_type stub, passing the failing argument type in rax. 26.569 + Register rax_mtype = rax_argslot; 26.570 + __ push(rbx_klass); // missed klass (required type) 26.571 + __ push(rdx_temp); // bad actual type (1st stacked argument) 26.572 + __ jump(ExternalAddress(Interpreter::throw_WrongMethodType_entry())); 26.573 + 26.574 + __ bind(done); 26.575 + __ jump_to_method_handle_entry(rcx_recv, rdx_temp); 26.576 + } 26.577 + break; 26.578 + 26.579 + case _adapter_prim_to_prim: 26.580 + case _adapter_ref_to_prim: 26.581 + // handled completely by optimized cases 26.582 + __ stop("init_AdapterMethodHandle should not issue this"); 26.583 + break; 26.584 + 26.585 + case _adapter_opt_i2i: // optimized subcase of adapt_prim_to_prim 26.586 +//case _adapter_opt_f2i: // optimized subcase of adapt_prim_to_prim 26.587 + case _adapter_opt_l2i: // optimized subcase of adapt_prim_to_prim 26.588 + case _adapter_opt_unboxi: // optimized subcase of adapt_ref_to_prim 26.589 + { 26.590 + // perform an in-place conversion to int or an int subword 26.591 + __ movl(rax_argslot, rcx_amh_vmargslot); 26.592 + vmarg = __ argument_address(rax_argslot); 26.593 + 26.594 + switch (ek) { 26.595 + case _adapter_opt_i2i: 26.596 + __ movl(rdx_temp, vmarg); 26.597 + break; 26.598 + case _adapter_opt_l2i: 26.599 + { 26.600 + // just delete the extra slot; on a little-endian machine we keep the first 26.601 + __ lea(rax_argslot, __ argument_address(rax_argslot, 1)); 26.602 + remove_arg_slots(_masm, -stack_move_unit(), 26.603 + rax_argslot, rbx_temp, rdx_temp); 26.604 + vmarg = Address(rax_argslot, -Interpreter::stackElementSize()); 26.605 + __ movl(rdx_temp, vmarg); 26.606 + } 26.607 + break; 26.608 + case _adapter_opt_unboxi: 26.609 + { 26.610 + // Load the value up from the heap. 26.611 + __ movptr(rdx_temp, vmarg); 26.612 + int value_offset = java_lang_boxing_object::value_offset_in_bytes(T_INT); 26.613 +#ifdef ASSERT 26.614 + for (int bt = T_BOOLEAN; bt < T_INT; bt++) { 26.615 + if (is_subword_type(BasicType(bt))) 26.616 + assert(value_offset == java_lang_boxing_object::value_offset_in_bytes(BasicType(bt)), ""); 26.617 + } 26.618 +#endif 26.619 + __ null_check(rdx_temp, value_offset); 26.620 + __ movl(rdx_temp, Address(rdx_temp, value_offset)); 26.621 + // We load this as a word. Because we are little-endian, 26.622 + // the low bits will be correct, but the high bits may need cleaning. 26.623 + // The vminfo will guide us to clean those bits. 26.624 + } 26.625 + break; 26.626 + default: 26.627 + assert(false, ""); 26.628 + } 26.629 + goto finish_int_conversion; 26.630 + } 26.631 + 26.632 + finish_int_conversion: 26.633 + { 26.634 + Register rbx_vminfo = rbx_temp; 26.635 + __ movl(rbx_vminfo, rcx_amh_conversion); 26.636 + assert(CONV_VMINFO_SHIFT == 0, "preshifted"); 26.637 + 26.638 + // get the new MH: 26.639 + __ movptr(rcx_recv, rcx_mh_vmtarget); 26.640 + // (now we are done with the old MH) 26.641 + 26.642 + // original 32-bit vmdata word must be of this form: 26.643 + // | MBZ:16 | signBitCount:8 | srcDstTypes:8 | conversionOp:8 | 26.644 + __ xchgl(rcx, rbx_vminfo); // free rcx for shifts 26.645 + __ shll(rdx_temp /*, rcx*/); 26.646 + Label zero_extend, done; 26.647 + __ testl(rcx, CONV_VMINFO_SIGN_FLAG); 26.648 + __ jcc(Assembler::zero, zero_extend); 26.649 + 26.650 + // this path is taken for int->byte, int->short 26.651 + __ sarl(rdx_temp /*, rcx*/); 26.652 + __ jmp(done); 26.653 + 26.654 + __ bind(zero_extend); 26.655 + // this is taken for int->char 26.656 + __ shrl(rdx_temp /*, rcx*/); 26.657 + 26.658 + __ bind(done); 26.659 + __ movptr(vmarg, rdx_temp); 26.660 + __ xchgl(rcx, rbx_vminfo); // restore rcx_recv 26.661 + 26.662 + __ jump_to_method_handle_entry(rcx_recv, rdx_temp); 26.663 + } 26.664 + break; 26.665 + 26.666 + case _adapter_opt_i2l: // optimized subcase of adapt_prim_to_prim 26.667 + case _adapter_opt_unboxl: // optimized subcase of adapt_ref_to_prim 26.668 + { 26.669 + // perform an in-place int-to-long or ref-to-long conversion 26.670 + __ movl(rax_argslot, rcx_amh_vmargslot); 26.671 + 26.672 + // on a little-endian machine we keep the first slot and add another after 26.673 + __ lea(rax_argslot, __ argument_address(rax_argslot, 1)); 26.674 + insert_arg_slots(_masm, stack_move_unit(), _INSERT_INT_MASK, 26.675 + rax_argslot, rbx_temp, rdx_temp); 26.676 + Address vmarg1(rax_argslot, -Interpreter::stackElementSize()); 26.677 + Address vmarg2 = vmarg1.plus_disp(Interpreter::stackElementSize()); 26.678 + 26.679 + switch (ek) { 26.680 + case _adapter_opt_i2l: 26.681 + { 26.682 + __ movl(rdx_temp, vmarg1); 26.683 + __ sarl(rdx_temp, 31); // __ extend_sign() 26.684 + __ movl(vmarg2, rdx_temp); // store second word 26.685 + } 26.686 + break; 26.687 + case _adapter_opt_unboxl: 26.688 + { 26.689 + // Load the value up from the heap. 26.690 + __ movptr(rdx_temp, vmarg1); 26.691 + int value_offset = java_lang_boxing_object::value_offset_in_bytes(T_LONG); 26.692 + assert(value_offset == java_lang_boxing_object::value_offset_in_bytes(T_DOUBLE), ""); 26.693 + __ null_check(rdx_temp, value_offset); 26.694 + __ movl(rbx_temp, Address(rdx_temp, value_offset + 0*BytesPerInt)); 26.695 + __ movl(rdx_temp, Address(rdx_temp, value_offset + 1*BytesPerInt)); 26.696 + __ movl(vmarg1, rbx_temp); 26.697 + __ movl(vmarg2, rdx_temp); 26.698 + } 26.699 + break; 26.700 + default: 26.701 + assert(false, ""); 26.702 + } 26.703 + 26.704 + __ movptr(rcx_recv, rcx_mh_vmtarget); 26.705 + __ jump_to_method_handle_entry(rcx_recv, rdx_temp); 26.706 + } 26.707 + break; 26.708 + 26.709 + case _adapter_opt_f2d: // optimized subcase of adapt_prim_to_prim 26.710 + case _adapter_opt_d2f: // optimized subcase of adapt_prim_to_prim 26.711 + { 26.712 + // perform an in-place floating primitive conversion 26.713 + __ movl(rax_argslot, rcx_amh_vmargslot); 26.714 + __ lea(rax_argslot, __ argument_address(rax_argslot, 1)); 26.715 + if (ek == _adapter_opt_f2d) { 26.716 + insert_arg_slots(_masm, stack_move_unit(), _INSERT_INT_MASK, 26.717 + rax_argslot, rbx_temp, rdx_temp); 26.718 + } 26.719 + Address vmarg(rax_argslot, -Interpreter::stackElementSize()); 26.720 + 26.721 +#ifdef _LP64 26.722 + if (ek == _adapter_opt_f2d) { 26.723 + __ movflt(xmm0, vmarg); 26.724 + __ cvtss2sd(xmm0, xmm0); 26.725 + __ movdbl(vmarg, xmm0); 26.726 + } else { 26.727 + __ movdbl(xmm0, vmarg); 26.728 + __ cvtsd2ss(xmm0, xmm0); 26.729 + __ movflt(vmarg, xmm0); 26.730 + } 26.731 +#else //_LP64 26.732 + if (ek == _adapter_opt_f2d) { 26.733 + __ fld_s(vmarg); // load float to ST0 26.734 + __ fstp_s(vmarg); // store single 26.735 + } else if (!TaggedStackInterpreter) { 26.736 + __ fld_d(vmarg); // load double to ST0 26.737 + __ fstp_s(vmarg); // store single 26.738 + } else { 26.739 + Address vmarg_tag = vmarg.plus_disp(tag_offset); 26.740 + Address vmarg2 = vmarg.plus_disp(Interpreter::stackElementSize()); 26.741 + // vmarg2_tag does not participate in this code 26.742 + Register rbx_tag = rbx_temp; 26.743 + __ movl(rbx_tag, vmarg_tag); // preserve tag 26.744 + __ movl(rdx_temp, vmarg2); // get second word of double 26.745 + __ movl(vmarg_tag, rdx_temp); // align with first word 26.746 + __ fld_d(vmarg); // load double to ST0 26.747 + __ movl(vmarg_tag, rbx_tag); // restore tag 26.748 + __ fstp_s(vmarg); // store single 26.749 + } 26.750 +#endif //_LP64 26.751 + 26.752 + if (ek == _adapter_opt_d2f) { 26.753 + remove_arg_slots(_masm, -stack_move_unit(), 26.754 + rax_argslot, rbx_temp, rdx_temp); 26.755 + } 26.756 + 26.757 + __ movptr(rcx_recv, rcx_mh_vmtarget); 26.758 + __ jump_to_method_handle_entry(rcx_recv, rdx_temp); 26.759 + } 26.760 + break; 26.761 + 26.762 + case _adapter_prim_to_ref: 26.763 + __ unimplemented(entry_name(ek)); // %%% FIXME: NYI 26.764 + break; 26.765 + 26.766 + case _adapter_swap_args: 26.767 + case _adapter_rot_args: 26.768 + // handled completely by optimized cases 26.769 + __ stop("init_AdapterMethodHandle should not issue this"); 26.770 + break; 26.771 + 26.772 + case _adapter_opt_swap_1: 26.773 + case _adapter_opt_swap_2: 26.774 + case _adapter_opt_rot_1_up: 26.775 + case _adapter_opt_rot_1_down: 26.776 + case _adapter_opt_rot_2_up: 26.777 + case _adapter_opt_rot_2_down: 26.778 + { 26.779 + int rotate = 0, swap_slots = 0; 26.780 + switch ((int)ek) { 26.781 + case _adapter_opt_swap_1: swap_slots = 1; break; 26.782 + case _adapter_opt_swap_2: swap_slots = 2; break; 26.783 + case _adapter_opt_rot_1_up: swap_slots = 1; rotate++; break; 26.784 + case _adapter_opt_rot_1_down: swap_slots = 1; rotate--; break; 26.785 + case _adapter_opt_rot_2_up: swap_slots = 2; rotate++; break; 26.786 + case _adapter_opt_rot_2_down: swap_slots = 2; rotate--; break; 26.787 + default: assert(false, ""); 26.788 + } 26.789 + 26.790 + // the real size of the move must be doubled if TaggedStackInterpreter: 26.791 + int swap_bytes = (int)( swap_slots * Interpreter::stackElementWords() * wordSize ); 26.792 + 26.793 + // 'argslot' is the position of the first argument to swap 26.794 + __ movl(rax_argslot, rcx_amh_vmargslot); 26.795 + __ lea(rax_argslot, __ argument_address(rax_argslot)); 26.796 + 26.797 + // 'vminfo' is the second 26.798 + Register rbx_destslot = rbx_temp; 26.799 + __ movl(rbx_destslot, rcx_amh_conversion); 26.800 + assert(CONV_VMINFO_SHIFT == 0, "preshifted"); 26.801 + __ andl(rbx_destslot, CONV_VMINFO_MASK); 26.802 + __ lea(rbx_destslot, __ argument_address(rbx_destslot)); 26.803 + DEBUG_ONLY(verify_argslot(_masm, rbx_destslot, "swap point must fall within current frame")); 26.804 + 26.805 + if (!rotate) { 26.806 + for (int i = 0; i < swap_bytes; i += wordSize) { 26.807 + __ movptr(rdx_temp, Address(rax_argslot , i)); 26.808 + __ push(rdx_temp); 26.809 + __ movptr(rdx_temp, Address(rbx_destslot, i)); 26.810 + __ movptr(Address(rax_argslot, i), rdx_temp); 26.811 + __ pop(rdx_temp); 26.812 + __ movptr(Address(rbx_destslot, i), rdx_temp); 26.813 + } 26.814 + } else { 26.815 + // push the first chunk, which is going to get overwritten 26.816 + for (int i = swap_bytes; (i -= wordSize) >= 0; ) { 26.817 + __ movptr(rdx_temp, Address(rax_argslot, i)); 26.818 + __ push(rdx_temp); 26.819 + } 26.820 + 26.821 + if (rotate > 0) { 26.822 + // rotate upward 26.823 + __ subptr(rax_argslot, swap_bytes); 26.824 +#ifdef ASSERT 26.825 + { 26.826 + // Verify that argslot > destslot, by at least swap_bytes. 26.827 + Label L_ok; 26.828 + __ cmpptr(rax_argslot, rbx_destslot); 26.829 + __ jcc(Assembler::aboveEqual, L_ok); 26.830 + __ stop("source must be above destination (upward rotation)"); 26.831 + __ bind(L_ok); 26.832 + } 26.833 +#endif 26.834 + // work argslot down to destslot, copying contiguous data upwards 26.835 + // pseudo-code: 26.836 + // rax = src_addr - swap_bytes 26.837 + // rbx = dest_addr 26.838 + // while (rax >= rbx) *(rax + swap_bytes) = *(rax + 0), rax--; 26.839 + Label loop; 26.840 + __ bind(loop); 26.841 + __ movptr(rdx_temp, Address(rax_argslot, 0)); 26.842 + __ movptr(Address(rax_argslot, swap_bytes), rdx_temp); 26.843 + __ addptr(rax_argslot, -wordSize); 26.844 + __ cmpptr(rax_argslot, rbx_destslot); 26.845 + __ jcc(Assembler::aboveEqual, loop); 26.846 + } else { 26.847 + __ addptr(rax_argslot, swap_bytes); 26.848 +#ifdef ASSERT 26.849 + { 26.850 + // Verify that argslot < destslot, by at least swap_bytes. 26.851 + Label L_ok; 26.852 + __ cmpptr(rax_argslot, rbx_destslot); 26.853 + __ jcc(Assembler::belowEqual, L_ok); 26.854 + __ stop("source must be below destination (downward rotation)"); 26.855 + __ bind(L_ok); 26.856 + } 26.857 +#endif 26.858 + // work argslot up to destslot, copying contiguous data downwards 26.859 + // pseudo-code: 26.860 + // rax = src_addr + swap_bytes 26.861 + // rbx = dest_addr 26.862 + // while (rax <= rbx) *(rax - swap_bytes) = *(rax + 0), rax++; 26.863 + Label loop; 26.864 + __ bind(loop); 26.865 + __ movptr(rdx_temp, Address(rax_argslot, 0)); 26.866 + __ movptr(Address(rax_argslot, -swap_bytes), rdx_temp); 26.867 + __ addptr(rax_argslot, wordSize); 26.868 + __ cmpptr(rax_argslot, rbx_destslot); 26.869 + __ jcc(Assembler::belowEqual, loop); 26.870 + } 26.871 + 26.872 + // pop the original first chunk into the destination slot, now free 26.873 + for (int i = 0; i < swap_bytes; i += wordSize) { 26.874 + __ pop(rdx_temp); 26.875 + __ movptr(Address(rbx_destslot, i), rdx_temp); 26.876 + } 26.877 + } 26.878 + 26.879 + __ movptr(rcx_recv, rcx_mh_vmtarget); 26.880 + __ jump_to_method_handle_entry(rcx_recv, rdx_temp); 26.881 + } 26.882 + break; 26.883 + 26.884 + case _adapter_dup_args: 26.885 + { 26.886 + // 'argslot' is the position of the first argument to duplicate 26.887 + __ movl(rax_argslot, rcx_amh_vmargslot); 26.888 + __ lea(rax_argslot, __ argument_address(rax_argslot)); 26.889 + 26.890 + // 'stack_move' is negative number of words to duplicate 26.891 + Register rdx_stack_move = rdx_temp; 26.892 + __ movl(rdx_stack_move, rcx_amh_conversion); 26.893 + __ sarl(rdx_stack_move, CONV_STACK_MOVE_SHIFT); 26.894 + 26.895 + int argslot0_num = 0; 26.896 + Address argslot0 = __ argument_address(RegisterOrConstant(argslot0_num)); 26.897 + assert(argslot0.base() == rsp, ""); 26.898 + int pre_arg_size = argslot0.disp(); 26.899 + assert(pre_arg_size % wordSize == 0, ""); 26.900 + assert(pre_arg_size > 0, "must include PC"); 26.901 + 26.902 + // remember the old rsp+1 (argslot[0]) 26.903 + Register rbx_oldarg = rbx_temp; 26.904 + __ lea(rbx_oldarg, argslot0); 26.905 + 26.906 + // move rsp down to make room for dups 26.907 + __ lea(rsp, Address(rsp, rdx_stack_move, Address::times_ptr)); 26.908 + 26.909 + // compute the new rsp+1 (argslot[0]) 26.910 + Register rdx_newarg = rdx_temp; 26.911 + __ lea(rdx_newarg, argslot0); 26.912 + 26.913 + __ push(rdi); // need a temp 26.914 + // (preceding push must be done after arg addresses are taken!) 26.915 + 26.916 + // pull down the pre_arg_size data (PC) 26.917 + for (int i = -pre_arg_size; i < 0; i += wordSize) { 26.918 + __ movptr(rdi, Address(rbx_oldarg, i)); 26.919 + __ movptr(Address(rdx_newarg, i), rdi); 26.920 + } 26.921 + 26.922 + // copy from rax_argslot[0...] down to new_rsp[1...] 26.923 + // pseudo-code: 26.924 + // rbx = old_rsp+1 26.925 + // rdx = new_rsp+1 26.926 + // rax = argslot 26.927 + // while (rdx < rbx) *rdx++ = *rax++ 26.928 + Label loop; 26.929 + __ bind(loop); 26.930 + __ movptr(rdi, Address(rax_argslot, 0)); 26.931 + __ movptr(Address(rdx_newarg, 0), rdi); 26.932 + __ addptr(rax_argslot, wordSize); 26.933 + __ addptr(rdx_newarg, wordSize); 26.934 + __ cmpptr(rdx_newarg, rbx_oldarg); 26.935 + __ jcc(Assembler::less, loop); 26.936 + 26.937 + __ pop(rdi); // restore temp 26.938 + 26.939 + __ movptr(rcx_recv, rcx_mh_vmtarget); 26.940 + __ jump_to_method_handle_entry(rcx_recv, rdx_temp); 26.941 + } 26.942 + break; 26.943 + 26.944 + case _adapter_drop_args: 26.945 + { 26.946 + // 'argslot' is the position of the first argument to nuke 26.947 + __ movl(rax_argslot, rcx_amh_vmargslot); 26.948 + __ lea(rax_argslot, __ argument_address(rax_argslot)); 26.949 + 26.950 + __ push(rdi); // need a temp 26.951 + // (must do previous push after argslot address is taken) 26.952 + 26.953 + // 'stack_move' is number of words to drop 26.954 + Register rdi_stack_move = rdi; 26.955 + __ movl(rdi_stack_move, rcx_amh_conversion); 26.956 + __ sarl(rdi_stack_move, CONV_STACK_MOVE_SHIFT); 26.957 + remove_arg_slots(_masm, rdi_stack_move, 26.958 + rax_argslot, rbx_temp, rdx_temp); 26.959 + 26.960 + __ pop(rdi); // restore temp 26.961 + 26.962 + __ movptr(rcx_recv, rcx_mh_vmtarget); 26.963 + __ jump_to_method_handle_entry(rcx_recv, rdx_temp); 26.964 + } 26.965 + break; 26.966 + 26.967 + case _adapter_collect_args: 26.968 + __ unimplemented(entry_name(ek)); // %%% FIXME: NYI 26.969 + break; 26.970 + 26.971 + case _adapter_spread_args: 26.972 + // handled completely by optimized cases 26.973 + __ stop("init_AdapterMethodHandle should not issue this"); 26.974 + break; 26.975 + 26.976 + case _adapter_opt_spread_0: 26.977 + case _adapter_opt_spread_1: 26.978 + case _adapter_opt_spread_more: 26.979 + { 26.980 + // spread an array out into a group of arguments 26.981 + int length_constant = -1; 26.982 + switch (ek) { 26.983 + case _adapter_opt_spread_0: length_constant = 0; break; 26.984 + case _adapter_opt_spread_1: length_constant = 1; break; 26.985 + } 26.986 + 26.987 + // find the address of the array argument 26.988 + __ movl(rax_argslot, rcx_amh_vmargslot); 26.989 + __ lea(rax_argslot, __ argument_address(rax_argslot)); 26.990 + 26.991 + // grab some temps 26.992 + { __ push(rsi); __ push(rdi); } 26.993 + // (preceding pushes must be done after argslot address is taken!) 26.994 +#define UNPUSH_RSI_RDI \ 26.995 + { __ pop(rdi); __ pop(rsi); } 26.996 + 26.997 + // arx_argslot points both to the array and to the first output arg 26.998 + vmarg = Address(rax_argslot, 0); 26.999 + 26.1000 + // Get the array value. 26.1001 + Register rsi_array = rsi; 26.1002 + Register rdx_array_klass = rdx_temp; 26.1003 + BasicType elem_type = T_OBJECT; 26.1004 + int length_offset = arrayOopDesc::length_offset_in_bytes(); 26.1005 + int elem0_offset = arrayOopDesc::base_offset_in_bytes(elem_type); 26.1006 + __ movptr(rsi_array, vmarg); 26.1007 + Label skip_array_check; 26.1008 + if (length_constant == 0) { 26.1009 + __ testptr(rsi_array, rsi_array); 26.1010 + __ jcc(Assembler::zero, skip_array_check); 26.1011 + } 26.1012 + __ null_check(rsi_array, oopDesc::klass_offset_in_bytes()); 26.1013 + __ load_klass(rdx_array_klass, rsi_array); 26.1014 + 26.1015 + // Check the array type. 26.1016 + Register rbx_klass = rbx_temp; 26.1017 + __ movptr(rbx_klass, rcx_amh_argument); // this is a Class object! 26.1018 + __ movptr(rbx_klass, Address(rbx_klass, java_lang_Class::klass_offset_in_bytes())); 26.1019 + 26.1020 + Label ok_array_klass, bad_array_klass, bad_array_length; 26.1021 + __ check_klass_subtype(rdx_array_klass, rbx_klass, rdi, ok_array_klass); 26.1022 + // If we get here, the type check failed! 26.1023 + __ jmp(bad_array_klass); 26.1024 + __ bind(ok_array_klass); 26.1025 + 26.1026 + // Check length. 26.1027 + if (length_constant >= 0) { 26.1028 + __ cmpl(Address(rsi_array, length_offset), length_constant); 26.1029 + } else { 26.1030 + Register rbx_vminfo = rbx_temp; 26.1031 + __ movl(rbx_vminfo, rcx_amh_conversion); 26.1032 + assert(CONV_VMINFO_SHIFT == 0, "preshifted"); 26.1033 + __ andl(rbx_vminfo, CONV_VMINFO_MASK); 26.1034 + __ cmpl(rbx_vminfo, Address(rsi_array, length_offset)); 26.1035 + } 26.1036 + __ jcc(Assembler::notEqual, bad_array_length); 26.1037 + 26.1038 + Register rdx_argslot_limit = rdx_temp; 26.1039 + 26.1040 + // Array length checks out. Now insert any required stack slots. 26.1041 + if (length_constant == -1) { 26.1042 + // Form a pointer to the end of the affected region. 26.1043 + __ lea(rdx_argslot_limit, Address(rax_argslot, Interpreter::stackElementSize())); 26.1044 + // 'stack_move' is negative number of words to insert 26.1045 + Register rdi_stack_move = rdi; 26.1046 + __ movl(rdi_stack_move, rcx_amh_conversion); 26.1047 + __ sarl(rdi_stack_move, CONV_STACK_MOVE_SHIFT); 26.1048 + Register rsi_temp = rsi_array; // spill this 26.1049 + insert_arg_slots(_masm, rdi_stack_move, -1, 26.1050 + rax_argslot, rbx_temp, rsi_temp); 26.1051 + // reload the array (since rsi was killed) 26.1052 + __ movptr(rsi_array, vmarg); 26.1053 + } else if (length_constant > 1) { 26.1054 + int arg_mask = 0; 26.1055 + int new_slots = (length_constant - 1); 26.1056 + for (int i = 0; i < new_slots; i++) { 26.1057 + arg_mask <<= 1; 26.1058 + arg_mask |= _INSERT_REF_MASK; 26.1059 + } 26.1060 + insert_arg_slots(_masm, new_slots * stack_move_unit(), arg_mask, 26.1061 + rax_argslot, rbx_temp, rdx_temp); 26.1062 + } else if (length_constant == 1) { 26.1063 + // no stack resizing required 26.1064 + } else if (length_constant == 0) { 26.1065 + remove_arg_slots(_masm, -stack_move_unit(), 26.1066 + rax_argslot, rbx_temp, rdx_temp); 26.1067 + } 26.1068 + 26.1069 + // Copy from the array to the new slots. 26.1070 + // Note: Stack change code preserves integrity of rax_argslot pointer. 26.1071 + // So even after slot insertions, rax_argslot still points to first argument. 26.1072 + if (length_constant == -1) { 26.1073 + // [rax_argslot, rdx_argslot_limit) is the area we are inserting into. 26.1074 + Register rsi_source = rsi_array; 26.1075 + __ lea(rsi_source, Address(rsi_array, elem0_offset)); 26.1076 + Label loop; 26.1077 + __ bind(loop); 26.1078 + __ movptr(rbx_temp, Address(rsi_source, 0)); 26.1079 + __ movptr(Address(rax_argslot, 0), rbx_temp); 26.1080 + __ addptr(rsi_source, type2aelembytes(elem_type)); 26.1081 + if (TaggedStackInterpreter) { 26.1082 + __ movptr(Address(rax_argslot, tag_offset), 26.1083 + frame::tag_for_basic_type(elem_type)); 26.1084 + } 26.1085 + __ addptr(rax_argslot, Interpreter::stackElementSize()); 26.1086 + __ cmpptr(rax_argslot, rdx_argslot_limit); 26.1087 + __ jcc(Assembler::less, loop); 26.1088 + } else if (length_constant == 0) { 26.1089 + __ bind(skip_array_check); 26.1090 + // nothing to copy 26.1091 + } else { 26.1092 + int elem_offset = elem0_offset; 26.1093 + int slot_offset = 0; 26.1094 + for (int index = 0; index < length_constant; index++) { 26.1095 + __ movptr(rbx_temp, Address(rsi_array, elem_offset)); 26.1096 + __ movptr(Address(rax_argslot, slot_offset), rbx_temp); 26.1097 + elem_offset += type2aelembytes(elem_type); 26.1098 + if (TaggedStackInterpreter) { 26.1099 + __ movptr(Address(rax_argslot, slot_offset + tag_offset), 26.1100 + frame::tag_for_basic_type(elem_type)); 26.1101 + } 26.1102 + slot_offset += Interpreter::stackElementSize(); 26.1103 + } 26.1104 + } 26.1105 + 26.1106 + // Arguments are spread. Move to next method handle. 26.1107 + UNPUSH_RSI_RDI; 26.1108 + __ movptr(rcx_recv, rcx_mh_vmtarget); 26.1109 + __ jump_to_method_handle_entry(rcx_recv, rdx_temp); 26.1110 + 26.1111 + __ bind(bad_array_klass); 26.1112 + UNPUSH_RSI_RDI; 26.1113 + __ stop("bad array klass NYI"); 26.1114 + 26.1115 + __ bind(bad_array_length); 26.1116 + UNPUSH_RSI_RDI; 26.1117 + __ stop("bad array length NYI"); 26.1118 + 26.1119 +#undef UNPUSH_RSI_RDI 26.1120 + } 26.1121 + break; 26.1122 + 26.1123 + case _adapter_flyby: 26.1124 + case _adapter_ricochet: 26.1125 + __ unimplemented(entry_name(ek)); // %%% FIXME: NYI 26.1126 + break; 26.1127 + 26.1128 + default: ShouldNotReachHere(); 26.1129 + } 26.1130 + __ hlt(); 26.1131 + 26.1132 + address me_cookie = MethodHandleEntry::start_compiled_entry(_masm, interp_entry); 26.1133 + __ unimplemented(entry_name(ek)); // %%% FIXME: NYI 26.1134 + 26.1135 + init_entry(ek, MethodHandleEntry::finish_compiled_entry(_masm, me_cookie)); 26.1136 +}
27.1 --- a/src/cpu/x86/vm/stubGenerator_x86_32.cpp Thu Apr 09 13:59:45 2009 -0700 27.2 +++ b/src/cpu/x86/vm/stubGenerator_x86_32.cpp Tue Apr 14 12:25:54 2009 -0700 27.3 @@ -2219,6 +2219,16 @@ 27.4 27.5 // arraycopy stubs used by compilers 27.6 generate_arraycopy_stubs(); 27.7 + 27.8 + // generic method handle stubs 27.9 + if (EnableMethodHandles && SystemDictionary::MethodHandle_klass() != NULL) { 27.10 + for (MethodHandles::EntryKind ek = MethodHandles::_EK_FIRST; 27.11 + ek < MethodHandles::_EK_LIMIT; 27.12 + ek = MethodHandles::EntryKind(1 + (int)ek)) { 27.13 + StubCodeMark mark(this, "MethodHandle", MethodHandles::entry_name(ek)); 27.14 + MethodHandles::generate_method_handle_stub(_masm, ek); 27.15 + } 27.16 + } 27.17 } 27.18 27.19
28.1 --- a/src/cpu/x86/vm/templateInterpreter_x86_32.cpp Thu Apr 09 13:59:45 2009 -0700 28.2 +++ b/src/cpu/x86/vm/templateInterpreter_x86_32.cpp Tue Apr 14 12:25:54 2009 -0700 28.3 @@ -92,6 +92,33 @@ 28.4 return entry; 28.5 } 28.6 28.7 +// Arguments are: required type at TOS+8, failing object (or NULL) at TOS+4. 28.8 +// pc at TOS (just for debugging) 28.9 +address TemplateInterpreterGenerator::generate_WrongMethodType_handler() { 28.10 + address entry = __ pc(); 28.11 + 28.12 + __ pop(rbx); // actual failing object is at TOS 28.13 + __ pop(rax); // required type is at TOS+4 28.14 + 28.15 + __ verify_oop(rbx); 28.16 + __ verify_oop(rax); 28.17 + 28.18 + // Various method handle types use interpreter registers as temps. 28.19 + __ restore_bcp(); 28.20 + __ restore_locals(); 28.21 + 28.22 + // Expression stack must be empty before entering the VM for an exception. 28.23 + __ empty_expression_stack(); 28.24 + __ empty_FPU_stack(); 28.25 + __ call_VM(noreg, 28.26 + CAST_FROM_FN_PTR(address, 28.27 + InterpreterRuntime::throw_WrongMethodTypeException), 28.28 + // pass required type, failing object (or NULL) 28.29 + rax, rbx); 28.30 + return entry; 28.31 +} 28.32 + 28.33 + 28.34 address TemplateInterpreterGenerator::generate_exception_handler_common(const char* name, const char* message, bool pass_oop) { 28.35 assert(!pass_oop || message == NULL, "either oop or message but not both"); 28.36 address entry = __ pc(); 28.37 @@ -1370,6 +1397,7 @@ 28.38 case Interpreter::empty : entry_point = ((InterpreterGenerator*)this)->generate_empty_entry(); break; 28.39 case Interpreter::accessor : entry_point = ((InterpreterGenerator*)this)->generate_accessor_entry(); break; 28.40 case Interpreter::abstract : entry_point = ((InterpreterGenerator*)this)->generate_abstract_entry(); break; 28.41 + case Interpreter::method_handle : entry_point = ((InterpreterGenerator*)this)->generate_method_handle_entry(); break; 28.42 28.43 case Interpreter::java_lang_math_sin : // fall thru 28.44 case Interpreter::java_lang_math_cos : // fall thru 28.45 @@ -1400,7 +1428,8 @@ 28.46 // be sure to change this if you add/subtract anything to/from the overhead area 28.47 const int overhead_size = -frame::interpreter_frame_initial_sp_offset; 28.48 28.49 - const int method_stack = (method->max_locals() + method->max_stack()) * 28.50 + const int extra_stack = methodOopDesc::extra_stack_entries(); 28.51 + const int method_stack = (method->max_locals() + method->max_stack() + extra_stack) * 28.52 Interpreter::stackElementWords(); 28.53 return overhead_size + method_stack + stub_code; 28.54 }
29.1 --- a/src/cpu/x86/vm/templateInterpreter_x86_64.cpp Thu Apr 09 13:59:45 2009 -0700 29.2 +++ b/src/cpu/x86/vm/templateInterpreter_x86_64.cpp Tue Apr 14 12:25:54 2009 -0700 29.3 @@ -1,5 +1,5 @@ 29.4 /* 29.5 - * Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved. 29.6 + * Copyright 2003-2009 Sun Microsystems, Inc. All Rights Reserved. 29.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 29.8 * 29.9 * This code is free software; you can redistribute it and/or modify it 29.10 @@ -100,6 +100,26 @@ 29.11 return entry; 29.12 } 29.13 29.14 +// Arguments are: required type in rarg1, failing object (or NULL) in rarg2 29.15 +address TemplateInterpreterGenerator::generate_WrongMethodType_handler() { 29.16 + address entry = __ pc(); 29.17 + 29.18 + __ pop(c_rarg2); // failing object is at TOS 29.19 + __ pop(c_rarg1); // required type is at TOS+8 29.20 + 29.21 + // expression stack must be empty before entering the VM if an 29.22 + // exception happened 29.23 + __ empty_expression_stack(); 29.24 + 29.25 + __ call_VM(noreg, 29.26 + CAST_FROM_FN_PTR(address, 29.27 + InterpreterRuntime:: 29.28 + throw_WrongMethodTypeException), 29.29 + // pass required type, failing object (or NULL) 29.30 + c_rarg1, c_rarg2); 29.31 + return entry; 29.32 +} 29.33 + 29.34 address TemplateInterpreterGenerator::generate_exception_handler_common( 29.35 const char* name, const char* message, bool pass_oop) { 29.36 assert(!pass_oop || message == NULL, "either oop or message but not both"); 29.37 @@ -1393,12 +1413,14 @@ 29.38 case Interpreter::empty : entry_point = ((InterpreterGenerator*) this)->generate_empty_entry(); break; 29.39 case Interpreter::accessor : entry_point = ((InterpreterGenerator*) this)->generate_accessor_entry(); break; 29.40 case Interpreter::abstract : entry_point = ((InterpreterGenerator*) this)->generate_abstract_entry(); break; 29.41 - case Interpreter::java_lang_math_sin : break; 29.42 - case Interpreter::java_lang_math_cos : break; 29.43 - case Interpreter::java_lang_math_tan : break; 29.44 - case Interpreter::java_lang_math_abs : break; 29.45 - case Interpreter::java_lang_math_log : break; 29.46 - case Interpreter::java_lang_math_log10 : break; 29.47 + case Interpreter::method_handle : entry_point = ((InterpreterGenerator*) this)->generate_method_handle_entry();break; 29.48 + 29.49 + case Interpreter::java_lang_math_sin : // fall thru 29.50 + case Interpreter::java_lang_math_cos : // fall thru 29.51 + case Interpreter::java_lang_math_tan : // fall thru 29.52 + case Interpreter::java_lang_math_abs : // fall thru 29.53 + case Interpreter::java_lang_math_log : // fall thru 29.54 + case Interpreter::java_lang_math_log10 : // fall thru 29.55 case Interpreter::java_lang_math_sqrt : entry_point = ((InterpreterGenerator*) this)->generate_math_entry(kind); break; 29.56 default : ShouldNotReachHere(); break; 29.57 } 29.58 @@ -1422,7 +1444,8 @@ 29.59 -(frame::interpreter_frame_initial_sp_offset) + entry_size; 29.60 29.61 const int stub_code = frame::entry_frame_after_call_words; 29.62 - const int method_stack = (method->max_locals() + method->max_stack()) * 29.63 + const int extra_stack = methodOopDesc::extra_stack_entries(); 29.64 + const int method_stack = (method->max_locals() + method->max_stack() + extra_stack) * 29.65 Interpreter::stackElementWords(); 29.66 return (overhead_size + method_stack + stub_code); 29.67 }
30.1 --- a/src/cpu/x86/vm/vtableStubs_x86_32.cpp Thu Apr 09 13:59:45 2009 -0700 30.2 +++ b/src/cpu/x86/vm/vtableStubs_x86_32.cpp Tue Apr 14 12:25:54 2009 -0700 30.3 @@ -108,6 +108,9 @@ 30.4 (int)(s->code_end() - __ pc())); 30.5 } 30.6 guarantee(__ pc() <= s->code_end(), "overflowed buffer"); 30.7 + // shut the door on sizing bugs 30.8 + int slop = 3; // 32-bit offset is this much larger than an 8-bit one 30.9 + assert(vtable_index > 10 || __ pc() + slop <= s->code_end(), "room for 32-bit offset"); 30.10 30.11 s->set_exception_points(npe_addr, ame_addr); 30.12 return s; 30.13 @@ -181,6 +184,9 @@ 30.14 (int)(s->code_end() - __ pc())); 30.15 } 30.16 guarantee(__ pc() <= s->code_end(), "overflowed buffer"); 30.17 + // shut the door on sizing bugs 30.18 + int slop = 3; // 32-bit offset is this much larger than an 8-bit one 30.19 + assert(itable_index > 10 || __ pc() + slop <= s->code_end(), "room for 32-bit offset"); 30.20 30.21 s->set_exception_points(npe_addr, ame_addr); 30.22 return s; 30.23 @@ -196,6 +202,41 @@ 30.24 // Itable stub size 30.25 return (DebugVtables ? 256 : 66) + (CountCompiledCalls ? 6 : 0); 30.26 } 30.27 + // In order to tune these parameters, run the JVM with VM options 30.28 + // +PrintMiscellaneous and +WizardMode to see information about 30.29 + // actual itable stubs. Look for lines like this: 30.30 + // itable #1 at 0x5551212[65] left over: 3 30.31 + // Reduce the constants so that the "left over" number is >=3 30.32 + // for the common cases. 30.33 + // Do not aim at a left-over number of zero, because a 30.34 + // large vtable or itable index (> 16) will require a 32-bit 30.35 + // immediate displacement instead of an 8-bit one. 30.36 + // 30.37 + // The JVM98 app. _202_jess has a megamorphic interface call. 30.38 + // The itable code looks like this: 30.39 + // Decoding VtableStub itbl[1]@1 30.40 + // mov 0x4(%ecx),%esi 30.41 + // mov 0xe8(%esi),%edi 30.42 + // lea 0x130(%esi,%edi,4),%edi 30.43 + // add $0x7,%edi 30.44 + // and $0xfffffff8,%edi 30.45 + // lea 0x4(%esi),%esi 30.46 + // mov (%edi),%ebx 30.47 + // cmp %ebx,%eax 30.48 + // je success 30.49 + // loop: 30.50 + // test %ebx,%ebx 30.51 + // je throw_icce 30.52 + // add $0x8,%edi 30.53 + // mov (%edi),%ebx 30.54 + // cmp %ebx,%eax 30.55 + // jne loop 30.56 + // success: 30.57 + // mov 0x4(%edi),%edi 30.58 + // mov (%esi,%edi,1),%ebx 30.59 + // jmp *0x44(%ebx) 30.60 + // throw_icce: 30.61 + // jmp throw_ICCE_entry 30.62 } 30.63 30.64 int VtableStub::pd_code_alignment() {
31.1 --- a/src/cpu/x86/vm/vtableStubs_x86_64.cpp Thu Apr 09 13:59:45 2009 -0700 31.2 +++ b/src/cpu/x86/vm/vtableStubs_x86_64.cpp Tue Apr 14 12:25:54 2009 -0700 31.3 @@ -106,6 +106,9 @@ 31.4 (int)(s->code_end() - __ pc())); 31.5 } 31.6 guarantee(__ pc() <= s->code_end(), "overflowed buffer"); 31.7 + // shut the door on sizing bugs 31.8 + int slop = 3; // 32-bit offset is this much larger than an 8-bit one 31.9 + assert(vtable_index > 10 || __ pc() + slop <= s->code_end(), "room for 32-bit offset"); 31.10 31.11 s->set_exception_points(npe_addr, ame_addr); 31.12 return s; 31.13 @@ -191,6 +194,9 @@ 31.14 (int)(s->code_end() - __ pc())); 31.15 } 31.16 guarantee(__ pc() <= s->code_end(), "overflowed buffer"); 31.17 + // shut the door on sizing bugs 31.18 + int slop = 3; // 32-bit offset is this much larger than an 8-bit one 31.19 + assert(itable_index > 10 || __ pc() + slop <= s->code_end(), "room for 32-bit offset"); 31.20 31.21 s->set_exception_points(npe_addr, ame_addr); 31.22 return s; 31.23 @@ -206,6 +212,39 @@ 31.24 return (DebugVtables ? 512 : 72) + (CountCompiledCalls ? 13 : 0) + 31.25 (UseCompressedOops ? 32 : 0); // 2 leaqs 31.26 } 31.27 + // In order to tune these parameters, run the JVM with VM options 31.28 + // +PrintMiscellaneous and +WizardMode to see information about 31.29 + // actual itable stubs. Look for lines like this: 31.30 + // itable #1 at 0x5551212[71] left over: 3 31.31 + // Reduce the constants so that the "left over" number is >=3 31.32 + // for the common cases. 31.33 + // Do not aim at a left-over number of zero, because a 31.34 + // large vtable or itable index (>= 32) will require a 32-bit 31.35 + // immediate displacement instead of an 8-bit one. 31.36 + // 31.37 + // The JVM98 app. _202_jess has a megamorphic interface call. 31.38 + // The itable code looks like this: 31.39 + // Decoding VtableStub itbl[1]@12 31.40 + // mov 0x8(%rsi),%r10 31.41 + // mov 0x198(%r10),%r11d 31.42 + // lea 0x218(%r10,%r11,8),%r11 31.43 + // lea 0x8(%r10),%r10 31.44 + // mov (%r11),%rbx 31.45 + // cmp %rbx,%rax 31.46 + // je success 31.47 + // loop: 31.48 + // test %rbx,%rbx 31.49 + // je throw_icce 31.50 + // add $0x10,%r11 31.51 + // mov (%r11),%rbx 31.52 + // cmp %rbx,%rax 31.53 + // jne loop 31.54 + // success: 31.55 + // mov 0x8(%r11),%r11d 31.56 + // mov (%r10,%r11,1),%rbx 31.57 + // jmpq *0x60(%rbx) 31.58 + // throw_icce: 31.59 + // jmpq throw_ICCE_entry 31.60 } 31.61 31.62 int VtableStub::pd_code_alignment() {
32.1 --- a/src/share/vm/ci/ciMethod.cpp Thu Apr 09 13:59:45 2009 -0700 32.2 +++ b/src/share/vm/ci/ciMethod.cpp Tue Apr 14 12:25:54 2009 -0700 32.3 @@ -1,5 +1,5 @@ 32.4 /* 32.5 - * Copyright 1999-2008 Sun Microsystems, Inc. All Rights Reserved. 32.6 + * Copyright 1999-2009 Sun Microsystems, Inc. All Rights Reserved. 32.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 32.8 * 32.9 * This code is free software; you can redistribute it and/or modify it 32.10 @@ -675,6 +675,30 @@ 32.11 } 32.12 32.13 // ------------------------------------------------------------------ 32.14 +// invokedynamic support 32.15 +// 32.16 +bool ciMethod::is_method_handle_invoke() { 32.17 + check_is_loaded(); 32.18 + bool flag = ((flags().as_int() & JVM_MH_INVOKE_BITS) == JVM_MH_INVOKE_BITS); 32.19 +#ifdef ASSERT 32.20 + { 32.21 + VM_ENTRY_MARK; 32.22 + bool flag2 = get_methodOop()->is_method_handle_invoke(); 32.23 + assert(flag == flag2, "consistent"); 32.24 + } 32.25 +#endif //ASSERT 32.26 + return flag; 32.27 +} 32.28 + 32.29 +ciInstance* ciMethod::method_handle_type() { 32.30 + check_is_loaded(); 32.31 + VM_ENTRY_MARK; 32.32 + oop mtype = get_methodOop()->method_handle_type(); 32.33 + return CURRENT_THREAD_ENV->get_object(mtype)->as_instance(); 32.34 +} 32.35 + 32.36 + 32.37 +// ------------------------------------------------------------------ 32.38 // ciMethod::build_method_data 32.39 // 32.40 // Generate new methodDataOop objects at compile time.
33.1 --- a/src/share/vm/ci/ciMethod.hpp Thu Apr 09 13:59:45 2009 -0700 33.2 +++ b/src/share/vm/ci/ciMethod.hpp Tue Apr 14 12:25:54 2009 -0700 33.3 @@ -1,5 +1,5 @@ 33.4 /* 33.5 - * Copyright 1999-2007 Sun Microsystems, Inc. All Rights Reserved. 33.6 + * Copyright 1999-2009 Sun Microsystems, Inc. All Rights Reserved. 33.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 33.8 * 33.9 * This code is free software; you can redistribute it and/or modify it 33.10 @@ -207,6 +207,8 @@ 33.11 bool check_call(int refinfo_index, bool is_static) const; 33.12 void build_method_data(); // make sure it exists in the VM also 33.13 int scale_count(int count, float prof_factor = 1.); // make MDO count commensurate with IIC 33.14 + bool is_method_handle_invoke(); 33.15 + ciInstance* method_handle_type(); 33.16 33.17 // What kind of ciObject is this? 33.18 bool is_method() { return true; }
34.1 --- a/src/share/vm/classfile/classFileParser.cpp Thu Apr 09 13:59:45 2009 -0700 34.2 +++ b/src/share/vm/classfile/classFileParser.cpp Tue Apr 14 12:25:54 2009 -0700 34.3 @@ -1842,6 +1842,11 @@ 34.4 _has_vanilla_constructor = true; 34.5 } 34.6 34.7 + if (EnableMethodHandles && m->is_method_handle_invoke()) { 34.8 + THROW_MSG_(vmSymbols::java_lang_VirtualMachineError(), 34.9 + "Method handle invokers must be defined internally to the VM", nullHandle); 34.10 + } 34.11 + 34.12 return m; 34.13 } 34.14 34.15 @@ -2465,9 +2470,84 @@ 34.16 } 34.17 34.18 34.19 +// Force MethodHandle.vmentry to be an unmanaged pointer. 34.20 +// There is no way for a classfile to express this, so we must help it. 34.21 +void ClassFileParser::java_dyn_MethodHandle_fix_pre(constantPoolHandle cp, 34.22 + typeArrayHandle* fields_ptr, 34.23 + FieldAllocationCount *fac_ptr, 34.24 + TRAPS) { 34.25 + // Add fake fields for java.dyn.MethodHandle instances 34.26 + // 34.27 + // This is not particularly nice, but since there is no way to express 34.28 + // a native wordSize field in Java, we must do it at this level. 34.29 + 34.30 + if (!EnableMethodHandles) return; 34.31 + 34.32 + int word_sig_index = 0; 34.33 + const int cp_size = cp->length(); 34.34 + for (int index = 1; index < cp_size; index++) { 34.35 + if (cp->tag_at(index).is_utf8() && 34.36 + cp->symbol_at(index) == vmSymbols::machine_word_signature()) { 34.37 + word_sig_index = index; 34.38 + break; 34.39 + } 34.40 + } 34.41 + 34.42 + if (word_sig_index == 0) 34.43 + THROW_MSG(vmSymbols::java_lang_VirtualMachineError(), 34.44 + "missing I or J signature (for vmentry) in java.dyn.MethodHandle"); 34.45 + 34.46 + bool found_vmentry = false; 34.47 + 34.48 + const int n = (*fields_ptr)()->length(); 34.49 + for (int i = 0; i < n; i += instanceKlass::next_offset) { 34.50 + int name_index = (*fields_ptr)->ushort_at(i + instanceKlass::name_index_offset); 34.51 + int sig_index = (*fields_ptr)->ushort_at(i + instanceKlass::signature_index_offset); 34.52 + int acc_flags = (*fields_ptr)->ushort_at(i + instanceKlass::access_flags_offset); 34.53 + symbolOop f_name = cp->symbol_at(name_index); 34.54 + symbolOop f_sig = cp->symbol_at(sig_index); 34.55 + if (f_sig == vmSymbols::byte_signature() && 34.56 + f_name == vmSymbols::vmentry_name() && 34.57 + (acc_flags & JVM_ACC_STATIC) == 0) { 34.58 + // Adjust the field type from byte to an unmanaged pointer. 34.59 + assert(fac_ptr->nonstatic_byte_count > 0, ""); 34.60 + fac_ptr->nonstatic_byte_count -= 1; 34.61 + (*fields_ptr)->ushort_at_put(i + instanceKlass::signature_index_offset, 34.62 + word_sig_index); 34.63 + if (wordSize == jintSize) { 34.64 + fac_ptr->nonstatic_word_count += 1; 34.65 + } else { 34.66 + fac_ptr->nonstatic_double_count += 1; 34.67 + } 34.68 + 34.69 + FieldAllocationType atype = (FieldAllocationType) (*fields_ptr)->ushort_at(i+4); 34.70 + assert(atype == NONSTATIC_BYTE, ""); 34.71 + FieldAllocationType new_atype = NONSTATIC_WORD; 34.72 + if (wordSize > jintSize) { 34.73 + if (Universe::field_type_should_be_aligned(T_LONG)) { 34.74 + atype = NONSTATIC_ALIGNED_DOUBLE; 34.75 + } else { 34.76 + atype = NONSTATIC_DOUBLE; 34.77 + } 34.78 + } 34.79 + (*fields_ptr)->ushort_at_put(i+4, new_atype); 34.80 + 34.81 + found_vmentry = true; 34.82 + break; 34.83 + } 34.84 + } 34.85 + 34.86 + if (!found_vmentry) 34.87 + THROW_MSG(vmSymbols::java_lang_VirtualMachineError(), 34.88 + "missing vmentry byte field in java.dyn.MethodHandle"); 34.89 + 34.90 +} 34.91 + 34.92 + 34.93 instanceKlassHandle ClassFileParser::parseClassFile(symbolHandle name, 34.94 Handle class_loader, 34.95 Handle protection_domain, 34.96 + KlassHandle host_klass, 34.97 GrowableArray<Handle>* cp_patches, 34.98 symbolHandle& parsed_name, 34.99 TRAPS) { 34.100 @@ -2500,6 +2580,7 @@ 34.101 } 34.102 } 34.103 34.104 + _host_klass = host_klass; 34.105 _cp_patches = cp_patches; 34.106 34.107 instanceKlassHandle nullHandle; 34.108 @@ -2808,6 +2889,11 @@ 34.109 java_lang_Class_fix_pre(&methods, &fac, CHECK_(nullHandle)); 34.110 } 34.111 34.112 + // adjust the vmentry field declaration in java.dyn.MethodHandle 34.113 + if (EnableMethodHandles && class_name() == vmSymbols::sun_dyn_MethodHandleImpl() && class_loader.is_null()) { 34.114 + java_dyn_MethodHandle_fix_pre(cp, &fields, &fac, CHECK_(nullHandle)); 34.115 + } 34.116 + 34.117 // Add a fake "discovered" field if it is not present 34.118 // for compatibility with earlier jdk's. 34.119 if (class_name() == vmSymbols::java_lang_ref_Reference() 34.120 @@ -3134,7 +3220,7 @@ 34.121 this_klass->set_method_ordering(method_ordering()); 34.122 this_klass->set_initial_method_idnum(methods->length()); 34.123 this_klass->set_name(cp->klass_name_at(this_class_index)); 34.124 - if (LinkWellKnownClasses) // I am well known to myself 34.125 + if (LinkWellKnownClasses || is_anonymous()) // I am well known to myself 34.126 cp->klass_at_put(this_class_index, this_klass()); // eagerly resolve 34.127 this_klass->set_protection_domain(protection_domain()); 34.128 this_klass->set_fields_annotations(fields_annotations());
35.1 --- a/src/share/vm/classfile/classFileParser.hpp Thu Apr 09 13:59:45 2009 -0700 35.2 +++ b/src/share/vm/classfile/classFileParser.hpp Tue Apr 14 12:25:54 2009 -0700 35.3 @@ -1,5 +1,5 @@ 35.4 /* 35.5 - * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved. 35.6 + * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved. 35.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 35.8 * 35.9 * This code is free software; you can redistribute it and/or modify it 35.10 @@ -33,6 +33,7 @@ 35.11 u2 _major_version; 35.12 u2 _minor_version; 35.13 symbolHandle _class_name; 35.14 + KlassHandle _host_klass; 35.15 GrowableArray<Handle>* _cp_patches; // overrides for CP entries 35.16 35.17 bool _has_finalizer; 35.18 @@ -145,6 +146,11 @@ 35.19 // Adjust the next_nonstatic_oop_offset to place the fake fields 35.20 // before any Java fields. 35.21 void java_lang_Class_fix_post(int* next_nonstatic_oop_offset); 35.22 + // Adjust the field allocation counts for java.dyn.MethodHandle to add 35.23 + // a fake address (void*) field. 35.24 + void java_dyn_MethodHandle_fix_pre(constantPoolHandle cp, 35.25 + typeArrayHandle* fields_ptr, 35.26 + FieldAllocationCount *fac_ptr, TRAPS); 35.27 35.28 // Format checker methods 35.29 void classfile_parse_error(const char* msg, TRAPS); 35.30 @@ -204,6 +210,10 @@ 35.31 char* skip_over_field_name(char* name, bool slash_ok, unsigned int length); 35.32 char* skip_over_field_signature(char* signature, bool void_ok, unsigned int length, TRAPS); 35.33 35.34 + bool is_anonymous() { 35.35 + assert(AnonymousClasses || _host_klass.is_null(), ""); 35.36 + return _host_klass.not_null(); 35.37 + } 35.38 bool has_cp_patch_at(int index) { 35.39 assert(AnonymousClasses, ""); 35.40 assert(index >= 0, "oob"); 35.41 @@ -249,11 +259,13 @@ 35.42 Handle protection_domain, 35.43 symbolHandle& parsed_name, 35.44 TRAPS) { 35.45 - return parseClassFile(name, class_loader, protection_domain, NULL, parsed_name, THREAD); 35.46 + KlassHandle no_host_klass; 35.47 + return parseClassFile(name, class_loader, protection_domain, no_host_klass, NULL, parsed_name, THREAD); 35.48 } 35.49 instanceKlassHandle parseClassFile(symbolHandle name, 35.50 Handle class_loader, 35.51 Handle protection_domain, 35.52 + KlassHandle host_klass, 35.53 GrowableArray<Handle>* cp_patches, 35.54 symbolHandle& parsed_name, 35.55 TRAPS);
36.1 --- a/src/share/vm/classfile/dictionary.cpp Thu Apr 09 13:59:45 2009 -0700 36.2 +++ b/src/share/vm/classfile/dictionary.cpp Tue Apr 14 12:25:54 2009 -0700 36.3 @@ -1,5 +1,5 @@ 36.4 /* 36.5 - * Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved. 36.6 + * Copyright 2003-2009 Sun Microsystems, Inc. All Rights Reserved. 36.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 36.8 * 36.9 * This code is free software; you can redistribute it and/or modify it 36.10 @@ -549,6 +549,63 @@ 36.11 } 36.12 } 36.13 36.14 +SymbolPropertyTable::SymbolPropertyTable(int table_size) 36.15 + : Hashtable(table_size, sizeof(SymbolPropertyEntry)) 36.16 +{ 36.17 +} 36.18 +SymbolPropertyTable::SymbolPropertyTable(int table_size, HashtableBucket* t, 36.19 + int number_of_entries) 36.20 + : Hashtable(table_size, sizeof(SymbolPropertyEntry), t, number_of_entries) 36.21 +{ 36.22 +} 36.23 + 36.24 + 36.25 +SymbolPropertyEntry* SymbolPropertyTable::find_entry(int index, unsigned int hash, 36.26 + symbolHandle sym) { 36.27 + assert(index == index_for(sym), "incorrect index?"); 36.28 + for (SymbolPropertyEntry* p = bucket(index); p != NULL; p = p->next()) { 36.29 + if (p->hash() == hash && p->symbol() == sym()) { 36.30 + return p; 36.31 + } 36.32 + } 36.33 + return NULL; 36.34 +} 36.35 + 36.36 + 36.37 +SymbolPropertyEntry* SymbolPropertyTable::add_entry(int index, unsigned int hash, 36.38 + symbolHandle sym) { 36.39 + assert_locked_or_safepoint(SystemDictionary_lock); 36.40 + assert(index == index_for(sym), "incorrect index?"); 36.41 + assert(find_entry(index, hash, sym) == NULL, "no double entry"); 36.42 + 36.43 + SymbolPropertyEntry* p = new_entry(hash, sym()); 36.44 + Hashtable::add_entry(index, p); 36.45 + return p; 36.46 +} 36.47 + 36.48 + 36.49 +void SymbolPropertyTable::oops_do(OopClosure* f) { 36.50 + for (int index = 0; index < table_size(); index++) { 36.51 + for (SymbolPropertyEntry* p = bucket(index); p != NULL; p = p->next()) { 36.52 + f->do_oop((oop*) p->symbol_addr()); 36.53 + if (p->property_oop() != NULL) { 36.54 + f->do_oop(p->property_oop_addr()); 36.55 + } 36.56 + } 36.57 + } 36.58 +} 36.59 + 36.60 +void SymbolPropertyTable::methods_do(void f(methodOop)) { 36.61 + for (int index = 0; index < table_size(); index++) { 36.62 + for (SymbolPropertyEntry* p = bucket(index); p != NULL; p = p->next()) { 36.63 + oop prop = p->property_oop(); 36.64 + if (prop != NULL && prop->is_method()) { 36.65 + f((methodOop)prop); 36.66 + } 36.67 + } 36.68 + } 36.69 +} 36.70 + 36.71 36.72 // ---------------------------------------------------------------------------- 36.73 #ifndef PRODUCT
37.1 --- a/src/share/vm/classfile/dictionary.hpp Thu Apr 09 13:59:45 2009 -0700 37.2 +++ b/src/share/vm/classfile/dictionary.hpp Tue Apr 14 12:25:54 2009 -0700 37.3 @@ -1,5 +1,5 @@ 37.4 /* 37.5 - * Copyright 2003-2006 Sun Microsystems, Inc. All Rights Reserved. 37.6 + * Copyright 2003-2009 Sun Microsystems, Inc. All Rights Reserved. 37.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 37.8 * 37.9 * This code is free software; you can redistribute it and/or modify it 37.10 @@ -217,3 +217,112 @@ 37.11 tty->print_cr("pd set = #%d", count); 37.12 } 37.13 }; 37.14 + 37.15 +// Entry in a SymbolPropertyTable, mapping a single symbolOop 37.16 +// to a managed and an unmanaged pointer. 37.17 +class SymbolPropertyEntry : public HashtableEntry { 37.18 + friend class VMStructs; 37.19 + private: 37.20 + oop _property_oop; 37.21 + address _property_data; 37.22 + 37.23 + public: 37.24 + symbolOop symbol() const { return (symbolOop) literal(); } 37.25 + 37.26 + oop property_oop() const { return _property_oop; } 37.27 + void set_property_oop(oop p) { _property_oop = p; } 37.28 + 37.29 + address property_data() const { return _property_data; } 37.30 + void set_property_data(address p) { _property_data = p; } 37.31 + 37.32 + SymbolPropertyEntry* next() const { 37.33 + return (SymbolPropertyEntry*)HashtableEntry::next(); 37.34 + } 37.35 + 37.36 + SymbolPropertyEntry** next_addr() { 37.37 + return (SymbolPropertyEntry**)HashtableEntry::next_addr(); 37.38 + } 37.39 + 37.40 + oop* symbol_addr() { return literal_addr(); } 37.41 + oop* property_oop_addr() { return &_property_oop; } 37.42 + 37.43 + void print_on(outputStream* st) const { 37.44 + symbol()->print_value_on(st); 37.45 + st->print(" -> "); 37.46 + bool printed = false; 37.47 + if (property_oop() != NULL) { 37.48 + property_oop()->print_value_on(st); 37.49 + printed = true; 37.50 + } 37.51 + if (property_data() != NULL) { 37.52 + if (printed) st->print(" and "); 37.53 + st->print(INTPTR_FORMAT, property_data()); 37.54 + printed = true; 37.55 + } 37.56 + st->print_cr(printed ? "" : "(empty)"); 37.57 + } 37.58 +}; 37.59 + 37.60 +// A system-internal mapping of symbols to pointers, both managed 37.61 +// and unmanaged. Used to record the auto-generation of each method 37.62 +// MethodHandle.invoke(S)T, for all signatures (S)T. 37.63 +class SymbolPropertyTable : public Hashtable { 37.64 + friend class VMStructs; 37.65 +private: 37.66 + SymbolPropertyEntry* bucket(int i) { 37.67 + return (SymbolPropertyEntry*) Hashtable::bucket(i); 37.68 + } 37.69 + 37.70 + // The following method is not MT-safe and must be done under lock. 37.71 + SymbolPropertyEntry** bucket_addr(int i) { 37.72 + return (SymbolPropertyEntry**) Hashtable::bucket_addr(i); 37.73 + } 37.74 + 37.75 + void add_entry(int index, SymbolPropertyEntry* new_entry) { 37.76 + ShouldNotReachHere(); 37.77 + } 37.78 + void set_entry(int index, SymbolPropertyEntry* new_entry) { 37.79 + ShouldNotReachHere(); 37.80 + } 37.81 + 37.82 + SymbolPropertyEntry* new_entry(unsigned int hash, symbolOop symbol) { 37.83 + SymbolPropertyEntry* entry = (SymbolPropertyEntry*) Hashtable::new_entry(hash, symbol); 37.84 + entry->set_property_oop(NULL); 37.85 + entry->set_property_data(NULL); 37.86 + return entry; 37.87 + } 37.88 + 37.89 +public: 37.90 + SymbolPropertyTable(int table_size); 37.91 + SymbolPropertyTable(int table_size, HashtableBucket* t, int number_of_entries); 37.92 + 37.93 + void free_entry(SymbolPropertyEntry* entry) { 37.94 + Hashtable::free_entry(entry); 37.95 + } 37.96 + 37.97 + unsigned int compute_hash(symbolHandle sym) { 37.98 + // Use the regular identity_hash. 37.99 + return Hashtable::compute_hash(sym); 37.100 + } 37.101 + 37.102 + // need not be locked; no state change 37.103 + SymbolPropertyEntry* find_entry(int index, unsigned int hash, symbolHandle name); 37.104 + 37.105 + // must be done under SystemDictionary_lock 37.106 + SymbolPropertyEntry* add_entry(int index, unsigned int hash, symbolHandle name); 37.107 + 37.108 + // GC support 37.109 + void oops_do(OopClosure* f); 37.110 + void methods_do(void f(methodOop)); 37.111 + 37.112 + // Sharing support 37.113 + void dump(SerializeOopClosure* soc); 37.114 + void restore(SerializeOopClosure* soc); 37.115 + void reorder_dictionary(); 37.116 + 37.117 +#ifndef PRODUCT 37.118 + void print(); 37.119 +#endif 37.120 + void verify(); 37.121 +}; 37.122 +
38.1 --- a/src/share/vm/classfile/javaClasses.cpp Thu Apr 09 13:59:45 2009 -0700 38.2 +++ b/src/share/vm/classfile/javaClasses.cpp Tue Apr 14 12:25:54 2009 -0700 38.3 @@ -25,13 +25,24 @@ 38.4 # include "incls/_precompiled.incl" 38.5 # include "incls/_javaClasses.cpp.incl" 38.6 38.7 +static bool find_field(instanceKlass* ik, 38.8 + symbolOop name_symbol, symbolOop signature_symbol, 38.9 + fieldDescriptor* fd, 38.10 + bool allow_super = false) { 38.11 + if (allow_super) 38.12 + return ik->find_field(name_symbol, signature_symbol, fd) != NULL; 38.13 + else 38.14 + return ik->find_local_field(name_symbol, signature_symbol, fd); 38.15 +} 38.16 + 38.17 // Helpful routine for computing field offsets at run time rather than hardcoding them 38.18 static void 38.19 compute_offset(int &dest_offset, 38.20 - klassOop klass_oop, symbolOop name_symbol, symbolOop signature_symbol) { 38.21 + klassOop klass_oop, symbolOop name_symbol, symbolOop signature_symbol, 38.22 + bool allow_super = false) { 38.23 fieldDescriptor fd; 38.24 instanceKlass* ik = instanceKlass::cast(klass_oop); 38.25 - if (!ik->find_local_field(name_symbol, signature_symbol, &fd)) { 38.26 + if (!find_field(ik, name_symbol, signature_symbol, &fd, allow_super)) { 38.27 ResourceMark rm; 38.28 tty->print_cr("Invalid layout of %s at %s", ik->external_name(), name_symbol->as_C_string()); 38.29 fatal("Invalid layout of preloaded class"); 38.30 @@ -42,14 +53,16 @@ 38.31 // Same as above but for "optional" offsets that might not be present in certain JDK versions 38.32 static void 38.33 compute_optional_offset(int& dest_offset, 38.34 - klassOop klass_oop, symbolOop name_symbol, symbolOop signature_symbol) { 38.35 + klassOop klass_oop, symbolOop name_symbol, symbolOop signature_symbol, 38.36 + bool allow_super = false) { 38.37 fieldDescriptor fd; 38.38 instanceKlass* ik = instanceKlass::cast(klass_oop); 38.39 - if (ik->find_local_field(name_symbol, signature_symbol, &fd)) { 38.40 + if (find_field(ik, name_symbol, signature_symbol, &fd, allow_super)) { 38.41 dest_offset = fd.offset(); 38.42 } 38.43 } 38.44 38.45 + 38.46 Handle java_lang_String::basic_create(int length, bool tenured, TRAPS) { 38.47 // Create the String object first, so there's a chance that the String 38.48 // and the char array it points to end up in the same cache line. 38.49 @@ -2107,13 +2120,324 @@ 38.50 } 38.51 38.52 38.53 +// Support for java_dyn_MethodHandle 38.54 + 38.55 +int java_dyn_MethodHandle::_type_offset; 38.56 +int java_dyn_MethodHandle::_vmtarget_offset; 38.57 +int java_dyn_MethodHandle::_vmentry_offset; 38.58 +int java_dyn_MethodHandle::_vmslots_offset; 38.59 + 38.60 +int sun_dyn_MemberName::_clazz_offset; 38.61 +int sun_dyn_MemberName::_name_offset; 38.62 +int sun_dyn_MemberName::_type_offset; 38.63 +int sun_dyn_MemberName::_flags_offset; 38.64 +int sun_dyn_MemberName::_vmtarget_offset; 38.65 +int sun_dyn_MemberName::_vmindex_offset; 38.66 + 38.67 +int sun_dyn_DirectMethodHandle::_vmindex_offset; 38.68 + 38.69 +int sun_dyn_BoundMethodHandle::_argument_offset; 38.70 +int sun_dyn_BoundMethodHandle::_vmargslot_offset; 38.71 + 38.72 +int sun_dyn_AdapterMethodHandle::_conversion_offset; 38.73 + 38.74 +void java_dyn_MethodHandle::compute_offsets() { 38.75 + klassOop k = SystemDictionary::MethodHandle_klass(); 38.76 + if (k != NULL && EnableMethodHandles) { 38.77 + compute_offset(_type_offset, k, vmSymbols::type_name(), vmSymbols::java_dyn_MethodType_signature(), true); 38.78 + compute_offset(_vmtarget_offset, k, vmSymbols::vmtarget_name(), vmSymbols::object_signature(), true); 38.79 + compute_offset(_vmentry_offset, k, vmSymbols::vmentry_name(), vmSymbols::machine_word_signature(), true); 38.80 + 38.81 + // Note: MH.vmslots (if it is present) is a hoisted copy of MH.type.form.vmslots. 38.82 + // It is optional pending experiments to keep or toss. 38.83 + compute_optional_offset(_vmslots_offset, k, vmSymbols::vmslots_name(), vmSymbols::int_signature(), true); 38.84 + } 38.85 +} 38.86 + 38.87 +void sun_dyn_MemberName::compute_offsets() { 38.88 + klassOop k = SystemDictionary::MemberName_klass(); 38.89 + if (k != NULL && EnableMethodHandles) { 38.90 + compute_offset(_clazz_offset, k, vmSymbols::clazz_name(), vmSymbols::class_signature()); 38.91 + compute_offset(_name_offset, k, vmSymbols::name_name(), vmSymbols::string_signature()); 38.92 + compute_offset(_type_offset, k, vmSymbols::type_name(), vmSymbols::object_signature()); 38.93 + compute_offset(_flags_offset, k, vmSymbols::flags_name(), vmSymbols::int_signature()); 38.94 + compute_offset(_vmtarget_offset, k, vmSymbols::vmtarget_name(), vmSymbols::object_signature()); 38.95 + compute_offset(_vmindex_offset, k, vmSymbols::vmindex_name(), vmSymbols::int_signature()); 38.96 + } 38.97 +} 38.98 + 38.99 +void sun_dyn_DirectMethodHandle::compute_offsets() { 38.100 + klassOop k = SystemDictionary::DirectMethodHandle_klass(); 38.101 + if (k != NULL && EnableMethodHandles) { 38.102 + compute_offset(_vmindex_offset, k, vmSymbols::vmindex_name(), vmSymbols::int_signature(), true); 38.103 + } 38.104 +} 38.105 + 38.106 +void sun_dyn_BoundMethodHandle::compute_offsets() { 38.107 + klassOop k = SystemDictionary::BoundMethodHandle_klass(); 38.108 + if (k != NULL && EnableMethodHandles) { 38.109 + compute_offset(_vmargslot_offset, k, vmSymbols::vmargslot_name(), vmSymbols::int_signature(), true); 38.110 + compute_offset(_argument_offset, k, vmSymbols::argument_name(), vmSymbols::object_signature(), true); 38.111 + } 38.112 +} 38.113 + 38.114 +void sun_dyn_AdapterMethodHandle::compute_offsets() { 38.115 + klassOop k = SystemDictionary::AdapterMethodHandle_klass(); 38.116 + if (k != NULL && EnableMethodHandles) { 38.117 + compute_offset(_conversion_offset, k, vmSymbols::conversion_name(), vmSymbols::int_signature(), true); 38.118 + } 38.119 +} 38.120 + 38.121 +oop java_dyn_MethodHandle::type(oop mh) { 38.122 + return mh->obj_field(_type_offset); 38.123 +} 38.124 + 38.125 +void java_dyn_MethodHandle::set_type(oop mh, oop mtype) { 38.126 + mh->obj_field_put(_type_offset, mtype); 38.127 +} 38.128 + 38.129 +int java_dyn_MethodHandle::vmslots(oop mh) { 38.130 + int vmslots_offset = _vmslots_offset; 38.131 + if (vmslots_offset != 0) { 38.132 +#ifdef ASSERT 38.133 + int x = mh->int_field(vmslots_offset); 38.134 + int y = compute_vmslots(mh); 38.135 + assert(x == y, "correct hoisted value"); 38.136 +#endif 38.137 + return mh->int_field(vmslots_offset); 38.138 + } else { 38.139 + return compute_vmslots(mh); 38.140 + } 38.141 +} 38.142 + 38.143 +// if MH.vmslots exists, hoist into it the value of type.form.vmslots 38.144 +void java_dyn_MethodHandle::init_vmslots(oop mh) { 38.145 + int vmslots_offset = _vmslots_offset; 38.146 + if (vmslots_offset != 0) { 38.147 + mh->int_field_put(vmslots_offset, compute_vmslots(mh)); 38.148 + } 38.149 +} 38.150 + 38.151 +// fetch type.form.vmslots, which is the number of JVM stack slots 38.152 +// required to carry the arguments of this MH 38.153 +int java_dyn_MethodHandle::compute_vmslots(oop mh) { 38.154 + oop mtype = type(mh); 38.155 + if (mtype == NULL) return 0; // Java code would get NPE 38.156 + oop form = java_dyn_MethodType::form(mtype); 38.157 + if (form == NULL) return 0; // Java code would get NPE 38.158 + return java_dyn_MethodTypeForm::vmslots(form); 38.159 +} 38.160 + 38.161 +// fetch the low-level entry point for this mh 38.162 +MethodHandleEntry* java_dyn_MethodHandle::vmentry(oop mh) { 38.163 + return (MethodHandleEntry*) mh->address_field(_vmentry_offset); 38.164 +} 38.165 + 38.166 +void java_dyn_MethodHandle::set_vmentry(oop mh, MethodHandleEntry* me) { 38.167 + assert(_vmentry_offset != 0, "must be present"); 38.168 + 38.169 + // This is always the final step that initializes a valid method handle: 38.170 + mh->release_address_field_put(_vmentry_offset, (address) me); 38.171 + 38.172 + // There should be enough memory barriers on exit from native methods 38.173 + // to ensure that the MH is fully initialized to all threads before 38.174 + // Java code can publish it in global data structures. 38.175 + // But just in case, we use release_address_field_put. 38.176 +} 38.177 + 38.178 +/// MemberName accessors 38.179 + 38.180 +oop sun_dyn_MemberName::clazz(oop mname) { 38.181 + assert(is_instance(mname), "wrong type"); 38.182 + return mname->obj_field(_clazz_offset); 38.183 +} 38.184 + 38.185 +void sun_dyn_MemberName::set_clazz(oop mname, oop clazz) { 38.186 + assert(is_instance(mname), "wrong type"); 38.187 + mname->obj_field_put(_clazz_offset, clazz); 38.188 +} 38.189 + 38.190 +oop sun_dyn_MemberName::name(oop mname) { 38.191 + assert(is_instance(mname), "wrong type"); 38.192 + return mname->obj_field(_name_offset); 38.193 +} 38.194 + 38.195 +void sun_dyn_MemberName::set_name(oop mname, oop name) { 38.196 + assert(is_instance(mname), "wrong type"); 38.197 + mname->obj_field_put(_name_offset, name); 38.198 +} 38.199 + 38.200 +oop sun_dyn_MemberName::type(oop mname) { 38.201 + assert(is_instance(mname), "wrong type"); 38.202 + return mname->obj_field(_type_offset); 38.203 +} 38.204 + 38.205 +void sun_dyn_MemberName::set_type(oop mname, oop type) { 38.206 + assert(is_instance(mname), "wrong type"); 38.207 + mname->obj_field_put(_type_offset, type); 38.208 +} 38.209 + 38.210 +int sun_dyn_MemberName::flags(oop mname) { 38.211 + assert(is_instance(mname), "wrong type"); 38.212 + return mname->int_field(_flags_offset); 38.213 +} 38.214 + 38.215 +void sun_dyn_MemberName::set_flags(oop mname, int flags) { 38.216 + assert(is_instance(mname), "wrong type"); 38.217 + mname->int_field_put(_flags_offset, flags); 38.218 +} 38.219 + 38.220 +oop sun_dyn_MemberName::vmtarget(oop mname) { 38.221 + assert(is_instance(mname), "wrong type"); 38.222 + return mname->obj_field(_vmtarget_offset); 38.223 +} 38.224 + 38.225 +void sun_dyn_MemberName::set_vmtarget(oop mname, oop ref) { 38.226 + assert(is_instance(mname), "wrong type"); 38.227 + mname->obj_field_put(_vmtarget_offset, ref); 38.228 +} 38.229 + 38.230 +int sun_dyn_MemberName::vmindex(oop mname) { 38.231 + assert(is_instance(mname), "wrong type"); 38.232 + return mname->int_field(_vmindex_offset); 38.233 +} 38.234 + 38.235 +void sun_dyn_MemberName::set_vmindex(oop mname, int index) { 38.236 + assert(is_instance(mname), "wrong type"); 38.237 + mname->int_field_put(_vmindex_offset, index); 38.238 +} 38.239 + 38.240 +oop java_dyn_MethodHandle::vmtarget(oop mh) { 38.241 + assert(is_instance(mh), "MH only"); 38.242 + return mh->obj_field(_vmtarget_offset); 38.243 +} 38.244 + 38.245 +void java_dyn_MethodHandle::set_vmtarget(oop mh, oop ref) { 38.246 + assert(is_instance(mh), "MH only"); 38.247 + mh->obj_field_put(_vmtarget_offset, ref); 38.248 +} 38.249 + 38.250 +int sun_dyn_DirectMethodHandle::vmindex(oop mh) { 38.251 + assert(is_instance(mh), "DMH only"); 38.252 + return mh->int_field(_vmindex_offset); 38.253 +} 38.254 + 38.255 +void sun_dyn_DirectMethodHandle::set_vmindex(oop mh, int index) { 38.256 + assert(is_instance(mh), "DMH only"); 38.257 + mh->int_field_put(_vmindex_offset, index); 38.258 +} 38.259 + 38.260 +int sun_dyn_BoundMethodHandle::vmargslot(oop mh) { 38.261 + assert(is_instance(mh), "BMH only"); 38.262 + return mh->int_field(_vmargslot_offset); 38.263 +} 38.264 + 38.265 +oop sun_dyn_BoundMethodHandle::argument(oop mh) { 38.266 + assert(is_instance(mh), "BMH only"); 38.267 + return mh->obj_field(_argument_offset); 38.268 +} 38.269 + 38.270 +int sun_dyn_AdapterMethodHandle::conversion(oop mh) { 38.271 + assert(is_instance(mh), "AMH only"); 38.272 + return mh->int_field(_conversion_offset); 38.273 +} 38.274 + 38.275 +void sun_dyn_AdapterMethodHandle::set_conversion(oop mh, int conv) { 38.276 + assert(is_instance(mh), "AMH only"); 38.277 + mh->int_field_put(_conversion_offset, conv); 38.278 +} 38.279 + 38.280 + 38.281 +// Support for java_dyn_MethodType 38.282 + 38.283 +int java_dyn_MethodType::_rtype_offset; 38.284 +int java_dyn_MethodType::_ptypes_offset; 38.285 +int java_dyn_MethodType::_form_offset; 38.286 + 38.287 +void java_dyn_MethodType::compute_offsets() { 38.288 + klassOop k = SystemDictionary::MethodType_klass(); 38.289 + if (k != NULL) { 38.290 + compute_offset(_rtype_offset, k, vmSymbols::rtype_name(), vmSymbols::class_signature()); 38.291 + compute_offset(_ptypes_offset, k, vmSymbols::ptypes_name(), vmSymbols::class_array_signature()); 38.292 + compute_offset(_form_offset, k, vmSymbols::form_name(), vmSymbols::java_dyn_MethodTypeForm_signature()); 38.293 + } 38.294 +} 38.295 + 38.296 +void java_dyn_MethodType::print_signature(oop mt, outputStream* st) { 38.297 + st->print("("); 38.298 + objArrayOop pts = ptypes(mt); 38.299 + for (int i = 0, limit = pts->length(); i < limit; i++) { 38.300 + java_lang_Class::print_signature(pts->obj_at(i), st); 38.301 + } 38.302 + st->print(")"); 38.303 + java_lang_Class::print_signature(rtype(mt), st); 38.304 +} 38.305 + 38.306 +symbolOop java_dyn_MethodType::as_signature(oop mt, bool intern_if_not_found, TRAPS) { 38.307 + ResourceMark rm; 38.308 + stringStream buffer(128); 38.309 + print_signature(mt, &buffer); 38.310 + const char* sigstr = buffer.base(); 38.311 + int siglen = (int) buffer.size(); 38.312 + if (!intern_if_not_found) 38.313 + return SymbolTable::probe(sigstr, siglen); 38.314 + else 38.315 + return oopFactory::new_symbol(sigstr, siglen, THREAD); 38.316 +} 38.317 + 38.318 +oop java_dyn_MethodType::rtype(oop mt) { 38.319 + assert(is_instance(mt), "must be a MethodType"); 38.320 + return mt->obj_field(_rtype_offset); 38.321 +} 38.322 + 38.323 +objArrayOop java_dyn_MethodType::ptypes(oop mt) { 38.324 + assert(is_instance(mt), "must be a MethodType"); 38.325 + return (objArrayOop) mt->obj_field(_ptypes_offset); 38.326 +} 38.327 + 38.328 +oop java_dyn_MethodType::form(oop mt) { 38.329 + assert(is_instance(mt), "must be a MethodType"); 38.330 + return mt->obj_field(_form_offset); 38.331 +} 38.332 + 38.333 +oop java_dyn_MethodType::ptype(oop mt, int idx) { 38.334 + return ptypes(mt)->obj_at(idx); 38.335 +} 38.336 + 38.337 + 38.338 + 38.339 +// Support for java_dyn_MethodTypeForm 38.340 + 38.341 +int java_dyn_MethodTypeForm::_vmslots_offset; 38.342 +int java_dyn_MethodTypeForm::_erasedType_offset; 38.343 + 38.344 +void java_dyn_MethodTypeForm::compute_offsets() { 38.345 + klassOop k = SystemDictionary::MethodTypeForm_klass(); 38.346 + if (k != NULL) { 38.347 + compute_optional_offset(_vmslots_offset, k, vmSymbols::vmslots_name(), vmSymbols::int_signature(), true); 38.348 + compute_optional_offset(_erasedType_offset, k, vmSymbols::erasedType_name(), vmSymbols::java_dyn_MethodType_signature(), true); 38.349 + } 38.350 +} 38.351 + 38.352 +int java_dyn_MethodTypeForm::vmslots(oop mtform) { 38.353 + assert(mtform->klass() == SystemDictionary::MethodTypeForm_klass(), "MTForm only"); 38.354 + return mtform->int_field(_vmslots_offset); 38.355 +} 38.356 + 38.357 +oop java_dyn_MethodTypeForm::erasedType(oop mtform) { 38.358 + assert(mtform->klass() == SystemDictionary::MethodTypeForm_klass(), "MTForm only"); 38.359 + return mtform->obj_field(_erasedType_offset); 38.360 +} 38.361 + 38.362 + 38.363 + 38.364 + 38.365 // Support for java_security_AccessControlContext 38.366 38.367 int java_security_AccessControlContext::_context_offset = 0; 38.368 int java_security_AccessControlContext::_privilegedContext_offset = 0; 38.369 int java_security_AccessControlContext::_isPrivileged_offset = 0; 38.370 38.371 - 38.372 void java_security_AccessControlContext::compute_offsets() { 38.373 assert(_isPrivileged_offset == 0, "offsets should be initialized only once"); 38.374 fieldDescriptor fd; 38.375 @@ -2442,6 +2766,15 @@ 38.376 java_lang_System::compute_offsets(); 38.377 java_lang_Thread::compute_offsets(); 38.378 java_lang_ThreadGroup::compute_offsets(); 38.379 + if (EnableMethodHandles) { 38.380 + java_dyn_MethodHandle::compute_offsets(); 38.381 + sun_dyn_MemberName::compute_offsets(); 38.382 + sun_dyn_DirectMethodHandle::compute_offsets(); 38.383 + sun_dyn_BoundMethodHandle::compute_offsets(); 38.384 + sun_dyn_AdapterMethodHandle::compute_offsets(); 38.385 + java_dyn_MethodType::compute_offsets(); 38.386 + java_dyn_MethodTypeForm::compute_offsets(); 38.387 + } 38.388 java_security_AccessControlContext::compute_offsets(); 38.389 // Initialize reflection classes. The layouts of these classes 38.390 // changed with the new reflection implementation in JDK 1.4, and 38.391 @@ -2459,6 +2792,9 @@ 38.392 sun_reflect_UnsafeStaticFieldAccessorImpl::compute_offsets(); 38.393 } 38.394 sun_misc_AtomicLongCSImpl::compute_offsets(); 38.395 + 38.396 + // generated interpreter code wants to know about the offsets we just computed: 38.397 + AbstractAssembler::update_delayed_values(); 38.398 } 38.399 38.400 #ifndef PRODUCT
39.1 --- a/src/share/vm/classfile/javaClasses.hpp Thu Apr 09 13:59:45 2009 -0700 39.2 +++ b/src/share/vm/classfile/javaClasses.hpp Tue Apr 14 12:25:54 2009 -0700 39.3 @@ -151,6 +151,12 @@ 39.4 // Conversion 39.5 static klassOop as_klassOop(oop java_class); 39.6 static BasicType as_BasicType(oop java_class, klassOop* reference_klass = NULL); 39.7 + static BasicType as_BasicType(oop java_class, KlassHandle* reference_klass) { 39.8 + klassOop refk_oop = NULL; 39.9 + BasicType result = as_BasicType(java_class, &refk_oop); 39.10 + (*reference_klass) = KlassHandle(refk_oop); 39.11 + return result; 39.12 + } 39.13 static symbolOop as_signature(oop java_class, bool intern_if_not_found, TRAPS); 39.14 static void print_signature(oop java_class, outputStream *st); 39.15 // Testing 39.16 @@ -778,6 +784,284 @@ 39.17 }; 39.18 39.19 39.20 +// Interface to java.dyn.MethodHandle objects 39.21 + 39.22 +class MethodHandleEntry; 39.23 + 39.24 +class java_dyn_MethodHandle: AllStatic { 39.25 + friend class JavaClasses; 39.26 + 39.27 + private: 39.28 + static int _vmentry_offset; // assembly code trampoline for MH 39.29 + static int _vmtarget_offset; // class-specific target reference 39.30 + static int _type_offset; // the MethodType of this MH 39.31 + static int _vmslots_offset; // OPTIONAL hoisted type.form.vmslots 39.32 + 39.33 + static void compute_offsets(); 39.34 + 39.35 + public: 39.36 + // Accessors 39.37 + static oop type(oop mh); 39.38 + static void set_type(oop mh, oop mtype); 39.39 + 39.40 + static oop vmtarget(oop mh); 39.41 + static void set_vmtarget(oop mh, oop target); 39.42 + 39.43 + static MethodHandleEntry* vmentry(oop mh); 39.44 + static void set_vmentry(oop mh, MethodHandleEntry* data); 39.45 + 39.46 + static int vmslots(oop mh); 39.47 + static void init_vmslots(oop mh); 39.48 + static int compute_vmslots(oop mh); 39.49 + 39.50 + // Testers 39.51 + static bool is_subclass(klassOop klass) { 39.52 + return Klass::cast(klass)->is_subclass_of(SystemDictionary::MethodHandle_klass()); 39.53 + } 39.54 + static bool is_instance(oop obj) { 39.55 + return obj != NULL && is_subclass(obj->klass()); 39.56 + } 39.57 + 39.58 + // Accessors for code generation: 39.59 + static int type_offset_in_bytes() { return _type_offset; } 39.60 + static int vmtarget_offset_in_bytes() { return _vmtarget_offset; } 39.61 + static int vmentry_offset_in_bytes() { return _vmentry_offset; } 39.62 + static int vmslots_offset_in_bytes() { return _vmslots_offset; } 39.63 +}; 39.64 + 39.65 +class sun_dyn_DirectMethodHandle: public java_dyn_MethodHandle { 39.66 + friend class JavaClasses; 39.67 + 39.68 + private: 39.69 + // _vmtarget_offset; // method or class or interface 39.70 + static int _vmindex_offset; // negative or vtable idx or itable idx 39.71 + static void compute_offsets(); 39.72 + 39.73 + public: 39.74 + // Accessors 39.75 + static int vmindex(oop mh); 39.76 + static void set_vmindex(oop mh, int index); 39.77 + 39.78 + // Testers 39.79 + static bool is_subclass(klassOop klass) { 39.80 + return Klass::cast(klass)->is_subclass_of(SystemDictionary::DirectMethodHandle_klass()); 39.81 + } 39.82 + static bool is_instance(oop obj) { 39.83 + return obj != NULL && is_subclass(obj->klass()); 39.84 + } 39.85 + 39.86 + // Accessors for code generation: 39.87 + static int vmindex_offset_in_bytes() { return _vmindex_offset; } 39.88 +}; 39.89 + 39.90 +class sun_dyn_BoundMethodHandle: public java_dyn_MethodHandle { 39.91 + friend class JavaClasses; 39.92 + 39.93 + private: 39.94 + static int _argument_offset; // argument value bound into this MH 39.95 + static int _vmargslot_offset; // relevant argument slot (<= vmslots) 39.96 + static void compute_offsets(); 39.97 + 39.98 +public: 39.99 + static oop argument(oop mh); 39.100 + static void set_argument(oop mh, oop ref); 39.101 + 39.102 + static jint vmargslot(oop mh); 39.103 + static void set_vmargslot(oop mh, jint slot); 39.104 + 39.105 + // Testers 39.106 + static bool is_subclass(klassOop klass) { 39.107 + return Klass::cast(klass)->is_subclass_of(SystemDictionary::BoundMethodHandle_klass()); 39.108 + } 39.109 + static bool is_instance(oop obj) { 39.110 + return obj != NULL && is_subclass(obj->klass()); 39.111 + } 39.112 + 39.113 + static int argument_offset_in_bytes() { return _argument_offset; } 39.114 + static int vmargslot_offset_in_bytes() { return _vmargslot_offset; } 39.115 +}; 39.116 + 39.117 +class sun_dyn_AdapterMethodHandle: public sun_dyn_BoundMethodHandle { 39.118 + friend class JavaClasses; 39.119 + 39.120 + private: 39.121 + static int _conversion_offset; // type of conversion to apply 39.122 + static void compute_offsets(); 39.123 + 39.124 + public: 39.125 + static int conversion(oop mh); 39.126 + static void set_conversion(oop mh, int conv); 39.127 + 39.128 + // Testers 39.129 + static bool is_subclass(klassOop klass) { 39.130 + return Klass::cast(klass)->is_subclass_of(SystemDictionary::AdapterMethodHandle_klass()); 39.131 + } 39.132 + static bool is_instance(oop obj) { 39.133 + return obj != NULL && is_subclass(obj->klass()); 39.134 + } 39.135 + 39.136 + // Relevant integer codes (keep these in synch. with MethodHandleNatives.Constants): 39.137 + enum { 39.138 + OP_RETYPE_ONLY = 0x0, // no argument changes; straight retype 39.139 + OP_CHECK_CAST = 0x1, // ref-to-ref conversion; requires a Class argument 39.140 + OP_PRIM_TO_PRIM = 0x2, // converts from one primitive to another 39.141 + OP_REF_TO_PRIM = 0x3, // unboxes a wrapper to produce a primitive 39.142 + OP_PRIM_TO_REF = 0x4, // boxes a primitive into a wrapper (NYI) 39.143 + OP_SWAP_ARGS = 0x5, // swap arguments (vminfo is 2nd arg) 39.144 + OP_ROT_ARGS = 0x6, // rotate arguments (vminfo is displaced arg) 39.145 + OP_DUP_ARGS = 0x7, // duplicates one or more arguments (at TOS) 39.146 + OP_DROP_ARGS = 0x8, // remove one or more argument slots 39.147 + OP_COLLECT_ARGS = 0x9, // combine one or more arguments into a varargs (NYI) 39.148 + OP_SPREAD_ARGS = 0xA, // expand in place a varargs array (of known size) 39.149 + OP_FLYBY = 0xB, // operate first on reified argument list (NYI) 39.150 + OP_RICOCHET = 0xC, // run an adapter chain on the return value (NYI) 39.151 + CONV_OP_LIMIT = 0xD, // limit of CONV_OP enumeration 39.152 + 39.153 + CONV_OP_MASK = 0xF00, // this nybble contains the conversion op field 39.154 + CONV_VMINFO_MASK = 0x0FF, // LSB is reserved for JVM use 39.155 + CONV_VMINFO_SHIFT = 0, // position of bits in CONV_VMINFO_MASK 39.156 + CONV_OP_SHIFT = 8, // position of bits in CONV_OP_MASK 39.157 + CONV_DEST_TYPE_SHIFT = 12, // byte 2 has the adapter BasicType (if needed) 39.158 + CONV_SRC_TYPE_SHIFT = 16, // byte 2 has the source BasicType (if needed) 39.159 + CONV_STACK_MOVE_SHIFT = 20, // high 12 bits give signed SP change 39.160 + CONV_STACK_MOVE_MASK = (1 << (32 - CONV_STACK_MOVE_SHIFT)) - 1 39.161 + }; 39.162 + 39.163 + static int conversion_offset_in_bytes() { return _conversion_offset; } 39.164 +}; 39.165 + 39.166 + 39.167 +// Interface to sun.dyn.MemberName objects 39.168 +// (These are a private interface for Java code to query the class hierarchy.) 39.169 + 39.170 +class sun_dyn_MemberName: AllStatic { 39.171 + friend class JavaClasses; 39.172 + 39.173 + private: 39.174 + // From java.dyn.MemberName: 39.175 + // private Class<?> clazz; // class in which the method is defined 39.176 + // private String name; // may be null if not yet materialized 39.177 + // private Object type; // may be null if not yet materialized 39.178 + // private int flags; // modifier bits; see reflect.Modifier 39.179 + // private Object vmtarget; // VM-specific target value 39.180 + // private int vmindex; // method index within class or interface 39.181 + static int _clazz_offset; 39.182 + static int _name_offset; 39.183 + static int _type_offset; 39.184 + static int _flags_offset; 39.185 + static int _vmtarget_offset; 39.186 + static int _vmindex_offset; 39.187 + 39.188 + static void compute_offsets(); 39.189 + 39.190 + public: 39.191 + // Accessors 39.192 + static oop clazz(oop mname); 39.193 + static void set_clazz(oop mname, oop clazz); 39.194 + 39.195 + static oop type(oop mname); 39.196 + static void set_type(oop mname, oop type); 39.197 + 39.198 + static oop name(oop mname); 39.199 + static void set_name(oop mname, oop name); 39.200 + 39.201 + static int flags(oop mname); 39.202 + static void set_flags(oop mname, int flags); 39.203 + 39.204 + static int modifiers(oop mname) { return (u2) flags(mname); } 39.205 + static void set_modifiers(oop mname, int mods) 39.206 + { set_flags(mname, (flags(mname) &~ (u2)-1) | (u2)mods); } 39.207 + 39.208 + static oop vmtarget(oop mname); 39.209 + static void set_vmtarget(oop mname, oop target); 39.210 + 39.211 + static int vmindex(oop mname); 39.212 + static void set_vmindex(oop mname, int index); 39.213 + 39.214 + // Testers 39.215 + static bool is_subclass(klassOop klass) { 39.216 + return Klass::cast(klass)->is_subclass_of(SystemDictionary::MemberName_klass()); 39.217 + } 39.218 + static bool is_instance(oop obj) { 39.219 + return obj != NULL && is_subclass(obj->klass()); 39.220 + } 39.221 + 39.222 + // Relevant integer codes (keep these in synch. with MethodHandleNatives.Constants): 39.223 + enum { 39.224 + MN_IS_METHOD = 0x00010000, // method (not constructor) 39.225 + MN_IS_CONSTRUCTOR = 0x00020000, // constructor 39.226 + MN_IS_FIELD = 0x00040000, // field 39.227 + MN_IS_TYPE = 0x00080000, // nested type 39.228 + MN_SEARCH_SUPERCLASSES = 0x00100000, // for MHN.getMembers 39.229 + MN_SEARCH_INTERFACES = 0x00200000, // for MHN.getMembers 39.230 + VM_INDEX_UNINITIALIZED = -99 39.231 + }; 39.232 + 39.233 + // Accessors for code generation: 39.234 + static int clazz_offset_in_bytes() { return _clazz_offset; } 39.235 + static int type_offset_in_bytes() { return _type_offset; } 39.236 + static int name_offset_in_bytes() { return _name_offset; } 39.237 + static int flags_offset_in_bytes() { return _flags_offset; } 39.238 + static int vmtarget_offset_in_bytes() { return _vmtarget_offset; } 39.239 + static int vmindex_offset_in_bytes() { return _vmindex_offset; } 39.240 +}; 39.241 + 39.242 + 39.243 +// Interface to java.dyn.MethodType objects 39.244 + 39.245 +class java_dyn_MethodType: AllStatic { 39.246 + friend class JavaClasses; 39.247 + 39.248 + private: 39.249 + static int _rtype_offset; 39.250 + static int _ptypes_offset; 39.251 + static int _form_offset; 39.252 + 39.253 + static void compute_offsets(); 39.254 + 39.255 + public: 39.256 + // Accessors 39.257 + static oop rtype(oop mt); 39.258 + static objArrayOop ptypes(oop mt); 39.259 + static oop form(oop mt); 39.260 + 39.261 + static oop ptype(oop mt, int index); 39.262 + 39.263 + static symbolOop as_signature(oop mt, bool intern_if_not_found, TRAPS); 39.264 + static void print_signature(oop mt, outputStream* st); 39.265 + 39.266 + static bool is_instance(oop obj) { 39.267 + return obj != NULL && obj->klass() == SystemDictionary::MethodType_klass(); 39.268 + } 39.269 + 39.270 + // Accessors for code generation: 39.271 + static int rtype_offset_in_bytes() { return _rtype_offset; } 39.272 + static int ptypes_offset_in_bytes() { return _ptypes_offset; } 39.273 + static int form_offset_in_bytes() { return _form_offset; } 39.274 +}; 39.275 + 39.276 +class java_dyn_MethodTypeForm: AllStatic { 39.277 + friend class JavaClasses; 39.278 + 39.279 + private: 39.280 + static int _vmslots_offset; // number of argument slots needed 39.281 + static int _erasedType_offset; // erasedType = canonical MethodType 39.282 + 39.283 + static void compute_offsets(); 39.284 + 39.285 + public: 39.286 + // Accessors 39.287 + static int vmslots(oop mtform); 39.288 + static oop erasedType(oop mtform); 39.289 + 39.290 + // Accessors for code generation: 39.291 + static int vmslots_offset_in_bytes() { return _vmslots_offset; } 39.292 + static int erasedType_offset_in_bytes() { return _erasedType_offset; } 39.293 +}; 39.294 + 39.295 + 39.296 + 39.297 + 39.298 // Interface to java.security.AccessControlContext objects 39.299 39.300 class java_security_AccessControlContext: AllStatic {
40.1 --- a/src/share/vm/classfile/systemDictionary.cpp Thu Apr 09 13:59:45 2009 -0700 40.2 +++ b/src/share/vm/classfile/systemDictionary.cpp Tue Apr 14 12:25:54 2009 -0700 40.3 @@ -31,6 +31,7 @@ 40.4 Dictionary* SystemDictionary::_shared_dictionary = NULL; 40.5 LoaderConstraintTable* SystemDictionary::_loader_constraints = NULL; 40.6 ResolutionErrorTable* SystemDictionary::_resolution_errors = NULL; 40.7 +SymbolPropertyTable* SystemDictionary::_invoke_method_table = NULL; 40.8 40.9 40.10 int SystemDictionary::_number_of_modifications = 0; 40.11 @@ -966,6 +967,8 @@ 40.12 instanceKlassHandle k = ClassFileParser(st).parseClassFile(class_name, 40.13 class_loader, 40.14 protection_domain, 40.15 + host_klass, 40.16 + cp_patches, 40.17 parsed_name, 40.18 THREAD); 40.19 40.20 @@ -1691,6 +1694,10 @@ 40.21 // represent classes we're actively loading. 40.22 placeholders_do(blk); 40.23 40.24 + // Visit extra methods 40.25 + if (invoke_method_table() != NULL) 40.26 + invoke_method_table()->oops_do(blk); 40.27 + 40.28 // Loader constraints. We must keep the symbolOop used in the name alive. 40.29 constraints()->always_strong_classes_do(blk); 40.30 40.31 @@ -1726,6 +1733,10 @@ 40.32 // Adjust dictionary 40.33 dictionary()->oops_do(f); 40.34 40.35 + // Visit extra methods 40.36 + if (invoke_method_table() != NULL) 40.37 + invoke_method_table()->oops_do(f); 40.38 + 40.39 // Partially loaded classes 40.40 placeholders()->oops_do(f); 40.41 40.42 @@ -1798,6 +1809,8 @@ 40.43 40.44 void SystemDictionary::methods_do(void f(methodOop)) { 40.45 dictionary()->methods_do(f); 40.46 + if (invoke_method_table() != NULL) 40.47 + invoke_method_table()->methods_do(f); 40.48 } 40.49 40.50 // ---------------------------------------------------------------------------- 40.51 @@ -1830,6 +1843,7 @@ 40.52 _number_of_modifications = 0; 40.53 _loader_constraints = new LoaderConstraintTable(_loader_constraint_size); 40.54 _resolution_errors = new ResolutionErrorTable(_resolution_error_size); 40.55 + // _invoke_method_table is allocated lazily in find_method_handle_invoke() 40.56 40.57 // Allocate private object used as system class loader lock 40.58 _system_loader_lock_obj = oopFactory::new_system_objArray(0, CHECK); 40.59 @@ -1891,6 +1905,9 @@ 40.60 wk_klass_name_limits[0] = s; 40.61 } 40.62 } 40.63 + 40.64 + // move the starting value forward to the limit: 40.65 + start_id = limit_id; 40.66 } 40.67 40.68 40.69 @@ -1924,6 +1941,17 @@ 40.70 instanceKlass::cast(WK_KLASS(final_reference_klass))->set_reference_type(REF_FINAL); 40.71 instanceKlass::cast(WK_KLASS(phantom_reference_klass))->set_reference_type(REF_PHANTOM); 40.72 40.73 + WKID meth_group_start = WK_KLASS_ENUM_NAME(MethodHandle_klass); 40.74 + WKID meth_group_end = WK_KLASS_ENUM_NAME(WrongMethodTypeException_klass); 40.75 + initialize_wk_klasses_until(meth_group_start, scan, CHECK); 40.76 + if (EnableMethodHandles) { 40.77 + initialize_wk_klasses_through(meth_group_start, scan, CHECK); 40.78 + } 40.79 + if (_well_known_klasses[meth_group_start] == NULL) { 40.80 + // Skip the rest of the method handle classes, if MethodHandle is not loaded. 40.81 + scan = WKID(meth_group_end+1); 40.82 + } 40.83 + 40.84 initialize_wk_klasses_until(WKID_LIMIT, scan, CHECK); 40.85 40.86 _box_klasses[T_BOOLEAN] = WK_KLASS(boolean_klass); 40.87 @@ -2254,6 +2282,91 @@ 40.88 } 40.89 40.90 40.91 +methodOop SystemDictionary::find_method_handle_invoke(symbolHandle signature, 40.92 + Handle class_loader, 40.93 + Handle protection_domain, 40.94 + TRAPS) { 40.95 + if (!EnableMethodHandles) return NULL; 40.96 + assert(class_loader.is_null() && protection_domain.is_null(), 40.97 + "cannot load specialized versions of MethodHandle.invoke"); 40.98 + if (invoke_method_table() == NULL) { 40.99 + // create this side table lazily 40.100 + _invoke_method_table = new SymbolPropertyTable(_invoke_method_size); 40.101 + } 40.102 + unsigned int hash = invoke_method_table()->compute_hash(signature); 40.103 + int index = invoke_method_table()->hash_to_index(hash); 40.104 + SymbolPropertyEntry* spe = invoke_method_table()->find_entry(index, hash, signature); 40.105 + if (spe == NULL || spe->property_oop() == NULL) { 40.106 + // Must create lots of stuff here, but outside of the SystemDictionary lock. 40.107 + Handle mt = compute_method_handle_type(signature(), 40.108 + class_loader, protection_domain, 40.109 + CHECK_NULL); 40.110 + KlassHandle mh_klass = SystemDictionaryHandles::MethodHandle_klass(); 40.111 + methodHandle m = methodOopDesc::make_invoke_method(mh_klass, signature, 40.112 + mt, CHECK_NULL); 40.113 + // Now grab the lock. We might have to throw away the new method, 40.114 + // if a racing thread has managed to install one at the same time. 40.115 + { 40.116 + MutexLocker ml(SystemDictionary_lock, Thread::current()); 40.117 + spe = invoke_method_table()->find_entry(index, hash, signature); 40.118 + if (spe == NULL) 40.119 + spe = invoke_method_table()->add_entry(index, hash, signature); 40.120 + if (spe->property_oop() == NULL) 40.121 + spe->set_property_oop(m()); 40.122 + } 40.123 + } 40.124 + methodOop m = (methodOop) spe->property_oop(); 40.125 + assert(m->is_method(), ""); 40.126 + return m; 40.127 +} 40.128 + 40.129 +// Ask Java code to find or construct a java.dyn.MethodType for the given 40.130 +// signature, as interpreted relative to the given class loader. 40.131 +// Because of class loader constraints, all method handle usage must be 40.132 +// consistent with this loader. 40.133 +Handle SystemDictionary::compute_method_handle_type(symbolHandle signature, 40.134 + Handle class_loader, 40.135 + Handle protection_domain, 40.136 + TRAPS) { 40.137 + Handle empty; 40.138 + int npts = ArgumentCount(signature()).size(); 40.139 + objArrayHandle pts = oopFactory::new_objArray(SystemDictionary::class_klass(), npts, CHECK_(empty)); 40.140 + int arg = 0; 40.141 + Handle rt; // the return type from the signature 40.142 + for (SignatureStream ss(signature()); !ss.is_done(); ss.next()) { 40.143 + oop mirror; 40.144 + if (!ss.is_object()) { 40.145 + mirror = Universe::java_mirror(ss.type()); 40.146 + } else { 40.147 + symbolOop name_oop = ss.as_symbol(CHECK_(empty)); 40.148 + symbolHandle name(THREAD, name_oop); 40.149 + klassOop klass = resolve_or_fail(name, 40.150 + class_loader, protection_domain, 40.151 + true, CHECK_(empty)); 40.152 + mirror = Klass::cast(klass)->java_mirror(); 40.153 + } 40.154 + if (ss.at_return_type()) 40.155 + rt = Handle(THREAD, mirror); 40.156 + else 40.157 + pts->obj_at_put(arg++, mirror); 40.158 + } 40.159 + assert(arg == npts, ""); 40.160 + 40.161 + // call MethodType java.dyn.MethodType::makeImpl(Class rt, Class[] pts, false, true) 40.162 + bool varargs = false, trusted = true; 40.163 + JavaCallArguments args(Handle(THREAD, rt())); 40.164 + args.push_oop(pts()); 40.165 + args.push_int(false); 40.166 + args.push_int(trusted); 40.167 + JavaValue result(T_OBJECT); 40.168 + JavaCalls::call_static(&result, 40.169 + SystemDictionary::MethodType_klass(), 40.170 + vmSymbols::makeImpl_name(), vmSymbols::makeImpl_signature(), 40.171 + &args, CHECK_(empty)); 40.172 + return Handle(THREAD, (oop) result.get_jobject()); 40.173 +} 40.174 + 40.175 + 40.176 // Since the identity hash code for symbols changes when the symbols are 40.177 // moved from the regular perm gen (hash in the mark word) to the shared 40.178 // spaces (hash is the address), the classes loaded into the dictionary
41.1 --- a/src/share/vm/classfile/systemDictionary.hpp Thu Apr 09 13:59:45 2009 -0700 41.2 +++ b/src/share/vm/classfile/systemDictionary.hpp Tue Apr 14 12:25:54 2009 -0700 41.3 @@ -63,6 +63,7 @@ 41.4 class LoaderConstraintTable; 41.5 class HashtableBucket; 41.6 class ResolutionErrorTable; 41.7 +class SymbolPropertyTable; 41.8 41.9 // Certain classes are preloaded, such as java.lang.Object and java.lang.String. 41.10 // They are all "well-known", in the sense that no class loader is allowed 41.11 @@ -131,6 +132,16 @@ 41.12 template(reflect_constant_pool_klass, sun_reflect_ConstantPool, Opt_Only_JDK15) \ 41.13 template(reflect_unsafe_static_field_accessor_impl_klass, sun_reflect_UnsafeStaticFieldAccessorImpl, Opt_Only_JDK15) \ 41.14 \ 41.15 + /* support for dynamic typing; it's OK if these are NULL in earlier JDKs */ \ 41.16 + template(MethodHandle_klass, java_dyn_MethodHandle, Opt) \ 41.17 + template(MemberName_klass, sun_dyn_MemberName, Opt) \ 41.18 + template(MethodHandleImpl_klass, sun_dyn_MethodHandleImpl, Opt) \ 41.19 + template(AdapterMethodHandle_klass, sun_dyn_AdapterMethodHandle, Opt) \ 41.20 + template(BoundMethodHandle_klass, sun_dyn_BoundMethodHandle, Opt) \ 41.21 + template(DirectMethodHandle_klass, sun_dyn_DirectMethodHandle, Opt) \ 41.22 + template(MethodType_klass, java_dyn_MethodType, Opt) \ 41.23 + template(MethodTypeForm_klass, java_dyn_MethodTypeForm, Opt) \ 41.24 + template(WrongMethodTypeException_klass, java_dyn_WrongMethodTypeException, Opt) \ 41.25 template(vector_klass, java_util_Vector, Pre) \ 41.26 template(hashtable_klass, java_util_Hashtable, Pre) \ 41.27 template(stringBuffer_klass, java_lang_StringBuffer, Pre) \ 41.28 @@ -444,6 +455,17 @@ 41.29 static char* check_signature_loaders(symbolHandle signature, Handle loader1, 41.30 Handle loader2, bool is_method, TRAPS); 41.31 41.32 + // JSR 292 41.33 + // find the java.dyn.MethodHandles::invoke method for a given signature 41.34 + static methodOop find_method_handle_invoke(symbolHandle signature, 41.35 + Handle class_loader, 41.36 + Handle protection_domain, 41.37 + TRAPS); 41.38 + // ask Java to compute the java.dyn.MethodType object for a given signature 41.39 + static Handle compute_method_handle_type(symbolHandle signature, 41.40 + Handle class_loader, 41.41 + Handle protection_domain, 41.42 + TRAPS); 41.43 // Utility for printing loader "name" as part of tracing constraints 41.44 static const char* loader_name(oop loader) { 41.45 return ((loader) == NULL ? "<bootloader>" : 41.46 @@ -460,6 +482,7 @@ 41.47 enum Constants { 41.48 _loader_constraint_size = 107, // number of entries in constraint table 41.49 _resolution_error_size = 107, // number of entries in resolution error table 41.50 + _invoke_method_size = 139, // number of entries in invoke method table 41.51 _nof_buckets = 1009 // number of buckets in hash table 41.52 }; 41.53 41.54 @@ -489,6 +512,9 @@ 41.55 // Resolution errors 41.56 static ResolutionErrorTable* _resolution_errors; 41.57 41.58 + // Invoke methods (JSR 292) 41.59 + static SymbolPropertyTable* _invoke_method_table; 41.60 + 41.61 public: 41.62 // for VM_CounterDecay iteration support 41.63 friend class CounterDecay; 41.64 @@ -506,6 +532,7 @@ 41.65 static PlaceholderTable* placeholders() { return _placeholders; } 41.66 static LoaderConstraintTable* constraints() { return _loader_constraints; } 41.67 static ResolutionErrorTable* resolution_errors() { return _resolution_errors; } 41.68 + static SymbolPropertyTable* invoke_method_table() { return _invoke_method_table; } 41.69 41.70 // Basic loading operations 41.71 static klassOop resolve_instance_class_or_null(symbolHandle class_name, Handle class_loader, Handle protection_domain, TRAPS);
42.1 --- a/src/share/vm/classfile/vmSymbols.hpp Thu Apr 09 13:59:45 2009 -0700 42.2 +++ b/src/share/vm/classfile/vmSymbols.hpp Tue Apr 14 12:25:54 2009 -0700 42.3 @@ -216,7 +216,26 @@ 42.4 template(sun_reflect_UnsafeStaticFieldAccessorImpl, "sun/reflect/UnsafeStaticFieldAccessorImpl")\ 42.5 template(base_name, "base") \ 42.6 \ 42.7 - /* common method names */ \ 42.8 + /* Support for JSR 292 & invokedynamic (JDK 1.7 and above) */ \ 42.9 + template(java_dyn_MethodHandle, "java/dyn/MethodHandle") \ 42.10 + template(java_dyn_MethodType, "java/dyn/MethodType") \ 42.11 + template(java_dyn_WrongMethodTypeException, "java/dyn/WrongMethodTypeException") \ 42.12 + template(java_dyn_MethodType_signature, "Ljava/dyn/MethodType;") \ 42.13 + template(java_dyn_MethodHandle_signature, "Ljava/dyn/MethodHandle;") \ 42.14 + /* internal classes known only to the JVM: */ \ 42.15 + template(java_dyn_MethodTypeForm, "java/dyn/MethodTypeForm") \ 42.16 + template(java_dyn_MethodTypeForm_signature, "Ljava/dyn/MethodTypeForm;") \ 42.17 + template(sun_dyn_MemberName, "sun/dyn/MemberName") \ 42.18 + template(sun_dyn_MethodHandleImpl, "sun/dyn/MethodHandleImpl") \ 42.19 + template(sun_dyn_AdapterMethodHandle, "sun/dyn/AdapterMethodHandle") \ 42.20 + template(sun_dyn_BoundMethodHandle, "sun/dyn/BoundMethodHandle") \ 42.21 + template(sun_dyn_DirectMethodHandle, "sun/dyn/DirectMethodHandle") \ 42.22 + template(makeImpl_name, "makeImpl") /*MethodType::makeImpl*/ \ 42.23 + template(makeImpl_signature, "(Ljava/lang/Class;[Ljava/lang/Class;ZZ)Ljava/dyn/MethodType;") \ 42.24 + NOT_LP64( do_alias(machine_word_signature, int_signature) ) \ 42.25 + LP64_ONLY( do_alias(machine_word_signature, long_signature) ) \ 42.26 + \ 42.27 + /* common method and field names */ \ 42.28 template(object_initializer_name, "<init>") \ 42.29 template(class_initializer_name, "<clinit>") \ 42.30 template(println_name, "println") \ 42.31 @@ -289,6 +308,21 @@ 42.32 template(bitCount_name, "bitCount") \ 42.33 template(profile_name, "profile") \ 42.34 template(equals_name, "equals") \ 42.35 + template(toString_name, "toString") \ 42.36 + template(values_name, "values") \ 42.37 + template(receiver_name, "receiver") \ 42.38 + template(vmtarget_name, "vmtarget") \ 42.39 + template(vmentry_name, "vmentry") \ 42.40 + template(vmslots_name, "vmslots") \ 42.41 + template(vmindex_name, "vmindex") \ 42.42 + template(vmargslot_name, "vmargslot") \ 42.43 + template(flags_name, "flags") \ 42.44 + template(argument_name, "argument") \ 42.45 + template(conversion_name, "conversion") \ 42.46 + template(rtype_name, "rtype") \ 42.47 + template(ptypes_name, "ptypes") \ 42.48 + template(form_name, "form") \ 42.49 + template(erasedType_name, "erasedType") \ 42.50 \ 42.51 /* non-intrinsic name/signature pairs: */ \ 42.52 template(register_method_name, "register") \ 42.53 @@ -353,6 +387,7 @@ 42.54 template(void_classloader_signature, "()Ljava/lang/ClassLoader;") \ 42.55 template(void_object_signature, "()Ljava/lang/Object;") \ 42.56 template(void_class_signature, "()Ljava/lang/Class;") \ 42.57 + template(void_string_signature, "()Ljava/lang/String;") \ 42.58 template(object_array_object_object_signature, "(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;")\ 42.59 template(exception_void_signature, "(Ljava/lang/Exception;)V") \ 42.60 template(protectiondomain_signature, "[Ljava/security/ProtectionDomain;") \
43.1 --- a/src/share/vm/code/vtableStubs.cpp Thu Apr 09 13:59:45 2009 -0700 43.2 +++ b/src/share/vm/code/vtableStubs.cpp Tue Apr 14 12:25:54 2009 -0700 43.3 @@ -107,13 +107,11 @@ 43.4 s = create_itable_stub(vtable_index); 43.5 } 43.6 enter(is_vtable_stub, vtable_index, s); 43.7 -#ifndef PRODUCT 43.8 if (PrintAdapterHandlers) { 43.9 tty->print_cr("Decoding VtableStub %s[%d]@%d", 43.10 is_vtable_stub? "vtbl": "itbl", vtable_index, VtableStub::receiver_location()); 43.11 Disassembler::decode(s->code_begin(), s->code_end()); 43.12 } 43.13 -#endif 43.14 } 43.15 return s->entry_point(); 43.16 }
44.1 --- a/src/share/vm/includeDB_core Thu Apr 09 13:59:45 2009 -0700 44.2 +++ b/src/share/vm/includeDB_core Tue Apr 14 12:25:54 2009 -0700 44.3 @@ -254,6 +254,7 @@ 44.4 assembler_<arch>.cpp collectedHeap.inline.hpp 44.5 assembler_<arch>.cpp interfaceSupport.hpp 44.6 assembler_<arch>.cpp interpreter.hpp 44.7 +assembler_<arch>.cpp methodHandles.hpp 44.8 assembler_<arch>.cpp objectMonitor.hpp 44.9 assembler_<arch>.cpp os.hpp 44.10 assembler_<arch>.cpp resourceArea.hpp 44.11 @@ -1274,6 +1275,7 @@ 44.12 cpCacheKlass.cpp collectedHeap.hpp 44.13 cpCacheKlass.cpp constantPoolOop.hpp 44.14 cpCacheKlass.cpp cpCacheKlass.hpp 44.15 +cpCacheKlass.cpp genOopClosures.inline.hpp 44.16 cpCacheKlass.cpp handles.inline.hpp 44.17 cpCacheKlass.cpp javaClasses.hpp 44.18 cpCacheKlass.cpp markSweep.inline.hpp 44.19 @@ -2202,6 +2204,7 @@ 44.20 interpreter_<arch_model>.cpp jvmtiExport.hpp 44.21 interpreter_<arch_model>.cpp jvmtiThreadState.hpp 44.22 interpreter_<arch_model>.cpp methodDataOop.hpp 44.23 +interpreter_<arch_model>.cpp methodHandles.hpp 44.24 interpreter_<arch_model>.cpp methodOop.hpp 44.25 interpreter_<arch_model>.cpp oop.inline.hpp 44.26 interpreter_<arch_model>.cpp sharedRuntime.hpp 44.27 @@ -2596,6 +2599,7 @@ 44.28 linkResolver.cpp instanceKlass.hpp 44.29 linkResolver.cpp interpreterRuntime.hpp 44.30 linkResolver.cpp linkResolver.hpp 44.31 +linkResolver.cpp methodHandles.hpp 44.32 linkResolver.cpp nativeLookup.hpp 44.33 linkResolver.cpp objArrayOop.hpp 44.34 linkResolver.cpp reflection.hpp 44.35 @@ -2812,6 +2816,25 @@ 44.36 methodDataOop.hpp orderAccess.hpp 44.37 methodDataOop.hpp universe.hpp 44.38 44.39 +methodHandles.hpp frame.inline.hpp 44.40 +methodHandles.hpp globals.hpp 44.41 +methodHandles.hpp interfaceSupport.hpp 44.42 +methodHandles.hpp javaClasses.hpp 44.43 +methodHandles.hpp vmSymbols.hpp 44.44 + 44.45 +methodHandles.cpp allocation.inline.hpp 44.46 +methodHandles.cpp interpreter.hpp 44.47 +methodHandles.cpp javaCalls.hpp 44.48 +methodHandles.cpp methodHandles.hpp 44.49 +methodHandles.cpp oopFactory.hpp 44.50 +methodHandles.cpp reflection.hpp 44.51 +methodHandles.cpp signature.hpp 44.52 +methodHandles.cpp symbolTable.hpp 44.53 + 44.54 +methodHandles_<arch>.cpp allocation.inline.hpp 44.55 +methodHandles_<arch>.cpp interpreter.hpp 44.56 +methodHandles_<arch>.cpp methodHandles.hpp 44.57 + 44.58 methodKlass.cpp collectedHeap.inline.hpp 44.59 methodKlass.cpp constMethodKlass.hpp 44.60 methodKlass.cpp gcLocker.hpp 44.61 @@ -3061,6 +3084,7 @@ 44.62 oop.inline.hpp arrayOop.hpp 44.63 oop.inline.hpp atomic.hpp 44.64 oop.inline.hpp barrierSet.inline.hpp 44.65 +oop.inline.hpp bytes_<arch>.hpp 44.66 oop.inline.hpp cardTableModRefBS.hpp 44.67 oop.inline.hpp collectedHeap.inline.hpp 44.68 oop.inline.hpp compactingPermGenGen.hpp 44.69 @@ -3674,6 +3698,7 @@ 44.70 sharedRuntime.cpp interpreter.hpp 44.71 sharedRuntime.cpp javaCalls.hpp 44.72 sharedRuntime.cpp jvmtiExport.hpp 44.73 +sharedRuntime.cpp methodHandles.hpp 44.74 sharedRuntime.cpp jvmtiRedefineClassesTrace.hpp 44.75 sharedRuntime.cpp nativeInst_<arch>.hpp 44.76 sharedRuntime.cpp nativeLookup.hpp 44.77 @@ -3862,6 +3887,7 @@ 44.78 stubGenerator_<arch_model>.cpp handles.inline.hpp 44.79 stubGenerator_<arch_model>.cpp instanceOop.hpp 44.80 stubGenerator_<arch_model>.cpp interpreter.hpp 44.81 +stubGenerator_<arch_model>.cpp methodHandles.hpp 44.82 stubGenerator_<arch_model>.cpp methodOop.hpp 44.83 stubGenerator_<arch_model>.cpp nativeInst_<arch>.hpp 44.84 stubGenerator_<arch_model>.cpp objArrayKlass.hpp
45.1 --- a/src/share/vm/includeDB_gc_parallel Thu Apr 09 13:59:45 2009 -0700 45.2 +++ b/src/share/vm/includeDB_gc_parallel Tue Apr 14 12:25:54 2009 -0700 45.3 @@ -36,6 +36,12 @@ 45.4 constantPoolKlass.cpp psScavenge.inline.hpp 45.5 constantPoolKlass.cpp parOopClosures.inline.hpp 45.6 45.7 +constantPoolKlass.cpp cardTableRS.hpp 45.8 +constantPoolKlass.cpp oop.pcgc.inline.hpp 45.9 +constantPoolKlass.cpp psPromotionManager.inline.hpp 45.10 +constantPoolKlass.cpp psScavenge.inline.hpp 45.11 +constantPoolKlass.cpp parOopClosures.inline.hpp 45.12 + 45.13 genCollectedHeap.cpp concurrentMarkSweepThread.hpp 45.14 genCollectedHeap.cpp vmCMSOperations.hpp 45.15
46.1 --- a/src/share/vm/interpreter/abstractInterpreter.hpp Thu Apr 09 13:59:45 2009 -0700 46.2 +++ b/src/share/vm/interpreter/abstractInterpreter.hpp Tue Apr 14 12:25:54 2009 -0700 46.3 @@ -1,5 +1,5 @@ 46.4 /* 46.5 - * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved. 46.6 + * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved. 46.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 46.8 * 46.9 * This code is free software; you can redistribute it and/or modify it 46.10 @@ -61,6 +61,7 @@ 46.11 empty, // empty method (code: _return) 46.12 accessor, // accessor method (code: _aload_0, _getfield, _(a|i)return) 46.13 abstract, // abstract method (throws an AbstractMethodException) 46.14 + method_handle, // java.dyn.MethodHandles::invoke 46.15 java_lang_math_sin, // implementation of java.lang.Math.sin (x) 46.16 java_lang_math_cos, // implementation of java.lang.Math.cos (x) 46.17 java_lang_math_tan, // implementation of java.lang.Math.tan (x) 46.18 @@ -91,8 +92,6 @@ 46.19 46.20 static address _rethrow_exception_entry; // rethrows an activation in previous frame 46.21 46.22 - 46.23 - 46.24 friend class AbstractInterpreterGenerator; 46.25 friend class InterpreterGenerator; 46.26 friend class InterpreterMacroAssembler;
47.1 --- a/src/share/vm/interpreter/cppInterpreter.cpp Thu Apr 09 13:59:45 2009 -0700 47.2 +++ b/src/share/vm/interpreter/cppInterpreter.cpp Tue Apr 14 12:25:54 2009 -0700 47.3 @@ -1,5 +1,5 @@ 47.4 /* 47.5 - * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved. 47.6 + * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved. 47.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 47.8 * 47.9 * This code is free software; you can redistribute it and/or modify it 47.10 @@ -114,6 +114,7 @@ 47.11 method_entry(empty); 47.12 method_entry(accessor); 47.13 method_entry(abstract); 47.14 + method_entry(method_handle); 47.15 method_entry(java_lang_math_sin ); 47.16 method_entry(java_lang_math_cos ); 47.17 method_entry(java_lang_math_tan );
48.1 --- a/src/share/vm/interpreter/interpreter.cpp Thu Apr 09 13:59:45 2009 -0700 48.2 +++ b/src/share/vm/interpreter/interpreter.cpp Tue Apr 14 12:25:54 2009 -0700 48.3 @@ -1,5 +1,5 @@ 48.4 /* 48.5 - * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved. 48.6 + * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved. 48.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 48.8 * 48.9 * This code is free software; you can redistribute it and/or modify it 48.10 @@ -168,10 +168,14 @@ 48.11 // Abstract method? 48.12 if (m->is_abstract()) return abstract; 48.13 48.14 + // Invoker for method handles? 48.15 + if (m->is_method_handle_invoke()) return method_handle; 48.16 + 48.17 // Native method? 48.18 // Note: This test must come _before_ the test for intrinsic 48.19 // methods. See also comments below. 48.20 if (m->is_native()) { 48.21 + assert(!m->is_method_handle_invoke(), "overlapping bits here, watch out"); 48.22 return m->is_synchronized() ? native_synchronized : native; 48.23 } 48.24 48.25 @@ -249,6 +253,7 @@ 48.26 case empty : tty->print("empty" ); break; 48.27 case accessor : tty->print("accessor" ); break; 48.28 case abstract : tty->print("abstract" ); break; 48.29 + case method_handle : tty->print("method_handle" ); break; 48.30 case java_lang_math_sin : tty->print("java_lang_math_sin" ); break; 48.31 case java_lang_math_cos : tty->print("java_lang_math_cos" ); break; 48.32 case java_lang_math_tan : tty->print("java_lang_math_tan" ); break;
49.1 --- a/src/share/vm/interpreter/interpreterRuntime.cpp Thu Apr 09 13:59:45 2009 -0700 49.2 +++ b/src/share/vm/interpreter/interpreterRuntime.cpp Tue Apr 14 12:25:54 2009 -0700 49.3 @@ -1,5 +1,5 @@ 49.4 /* 49.5 - * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved. 49.6 + * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved. 49.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 49.8 * 49.9 * This code is free software; you can redistribute it and/or modify it 49.10 @@ -293,6 +293,24 @@ 49.11 THROW_MSG(vmSymbols::java_lang_ClassCastException(), message); 49.12 IRT_END 49.13 49.14 +// required can be either a MethodType, or a Class (for a single argument) 49.15 +// actual (if not null) can be either a MethodHandle, or an arbitrary value (for a single argument) 49.16 +IRT_ENTRY(void, InterpreterRuntime::throw_WrongMethodTypeException(JavaThread* thread, 49.17 + oopDesc* required, 49.18 + oopDesc* actual)) { 49.19 + ResourceMark rm(thread); 49.20 + char* message = SharedRuntime::generate_wrong_method_type_message(thread, required, actual); 49.21 + 49.22 + if (ProfileTraps) { 49.23 + note_trap(thread, Deoptimization::Reason_constraint, CHECK); 49.24 + } 49.25 + 49.26 + // create exception 49.27 + THROW_MSG(vmSymbols::java_dyn_WrongMethodTypeException(), message); 49.28 +} 49.29 +IRT_END 49.30 + 49.31 + 49.32 49.33 // exception_handler_for_exception(...) returns the continuation address, 49.34 // the exception oop (via TLS) and sets the bci/bcp for the continuation.
50.1 --- a/src/share/vm/interpreter/interpreterRuntime.hpp Thu Apr 09 13:59:45 2009 -0700 50.2 +++ b/src/share/vm/interpreter/interpreterRuntime.hpp Tue Apr 14 12:25:54 2009 -0700 50.3 @@ -1,5 +1,5 @@ 50.4 /* 50.5 - * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved. 50.6 + * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved. 50.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 50.8 * 50.9 * This code is free software; you can redistribute it and/or modify it 50.10 @@ -66,6 +66,7 @@ 50.11 static void throw_StackOverflowError(JavaThread* thread); 50.12 static void throw_ArrayIndexOutOfBoundsException(JavaThread* thread, char* name, jint index); 50.13 static void throw_ClassCastException(JavaThread* thread, oopDesc* obj); 50.14 + static void throw_WrongMethodTypeException(JavaThread* thread, oopDesc* mtype = NULL, oopDesc* mhandle = NULL); 50.15 static void create_exception(JavaThread* thread, char* name, char* message); 50.16 static void create_klass_exception(JavaThread* thread, char* name, oopDesc* obj); 50.17 static address exception_handler_for_exception(JavaThread* thread, oopDesc* exception);
51.1 --- a/src/share/vm/interpreter/linkResolver.cpp Thu Apr 09 13:59:45 2009 -0700 51.2 +++ b/src/share/vm/interpreter/linkResolver.cpp Tue Apr 14 12:25:54 2009 -0700 51.3 @@ -1,5 +1,5 @@ 51.4 /* 51.5 - * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved. 51.6 + * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved. 51.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 51.8 * 51.9 * This code is free software; you can redistribute it and/or modify it 51.10 @@ -151,6 +151,20 @@ 51.11 result = methodHandle(THREAD, ik->lookup_method_in_all_interfaces(name(), signature())); 51.12 } 51.13 51.14 +void LinkResolver::lookup_implicit_method(methodHandle& result, KlassHandle klass, symbolHandle name, symbolHandle signature, TRAPS) { 51.15 + if (EnableMethodHandles && MethodHandles::enabled() && 51.16 + name == vmSymbolHandles::invoke_name() && klass() == SystemDictionary::MethodHandle_klass()) { 51.17 + methodOop result_oop = SystemDictionary::find_method_handle_invoke(signature, 51.18 + Handle(), 51.19 + Handle(), 51.20 + CHECK); 51.21 + if (result_oop != NULL) { 51.22 + assert(result_oop->is_method_handle_invoke() && result_oop->signature() == signature(), "consistent"); 51.23 + result = methodHandle(THREAD, result_oop); 51.24 + } 51.25 + } 51.26 +} 51.27 + 51.28 void LinkResolver::check_method_accessability(KlassHandle ref_klass, 51.29 KlassHandle resolved_klass, 51.30 KlassHandle sel_klass, 51.31 @@ -240,6 +254,11 @@ 51.32 lookup_method_in_interfaces(resolved_method, resolved_klass, method_name, method_signature, CHECK); 51.33 51.34 if (resolved_method.is_null()) { 51.35 + // JSR 292: see if this is an implicitly generated method MethodHandle.invoke(*...) 51.36 + lookup_implicit_method(resolved_method, resolved_klass, method_name, method_signature, CHECK); 51.37 + } 51.38 + 51.39 + if (resolved_method.is_null()) { 51.40 // 4. method lookup failed 51.41 ResourceMark rm(THREAD); 51.42 THROW_MSG(vmSymbols::java_lang_NoSuchMethodError(),
52.1 --- a/src/share/vm/interpreter/linkResolver.hpp Thu Apr 09 13:59:45 2009 -0700 52.2 +++ b/src/share/vm/interpreter/linkResolver.hpp Tue Apr 14 12:25:54 2009 -0700 52.3 @@ -1,5 +1,5 @@ 52.4 /* 52.5 - * Copyright 1997-2005 Sun Microsystems, Inc. All Rights Reserved. 52.6 + * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved. 52.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 52.8 * 52.9 * This code is free software; you can redistribute it and/or modify it 52.10 @@ -103,6 +103,7 @@ 52.11 static void lookup_method_in_klasses (methodHandle& result, KlassHandle klass, symbolHandle name, symbolHandle signature, TRAPS); 52.12 static void lookup_instance_method_in_klasses (methodHandle& result, KlassHandle klass, symbolHandle name, symbolHandle signature, TRAPS); 52.13 static void lookup_method_in_interfaces (methodHandle& result, KlassHandle klass, symbolHandle name, symbolHandle signature, TRAPS); 52.14 + static void lookup_implicit_method (methodHandle& result, KlassHandle klass, symbolHandle name, symbolHandle signature, TRAPS); 52.15 52.16 static int vtable_index_of_miranda_method(KlassHandle klass, symbolHandle name, symbolHandle signature, TRAPS); 52.17
53.1 --- a/src/share/vm/interpreter/templateInterpreter.cpp Thu Apr 09 13:59:45 2009 -0700 53.2 +++ b/src/share/vm/interpreter/templateInterpreter.cpp Tue Apr 14 12:25:54 2009 -0700 53.3 @@ -1,5 +1,5 @@ 53.4 /* 53.5 - * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved. 53.6 + * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved. 53.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 53.8 * 53.9 * This code is free software; you can redistribute it and/or modify it 53.10 @@ -168,6 +168,7 @@ 53.11 address TemplateInterpreter::_throw_ArrayStoreException_entry = NULL; 53.12 address TemplateInterpreter::_throw_ArithmeticException_entry = NULL; 53.13 address TemplateInterpreter::_throw_ClassCastException_entry = NULL; 53.14 +address TemplateInterpreter::_throw_WrongMethodType_entry = NULL; 53.15 address TemplateInterpreter::_throw_NullPointerException_entry = NULL; 53.16 address TemplateInterpreter::_throw_StackOverflowError_entry = NULL; 53.17 address TemplateInterpreter::_throw_exception_entry = NULL; 53.18 @@ -341,6 +342,7 @@ 53.19 Interpreter::_throw_ArrayStoreException_entry = generate_klass_exception_handler("java/lang/ArrayStoreException" ); 53.20 Interpreter::_throw_ArithmeticException_entry = generate_exception_handler("java/lang/ArithmeticException" , "/ by zero"); 53.21 Interpreter::_throw_ClassCastException_entry = generate_ClassCastException_handler(); 53.22 + Interpreter::_throw_WrongMethodType_entry = generate_WrongMethodType_handler(); 53.23 Interpreter::_throw_NullPointerException_entry = generate_exception_handler("java/lang/NullPointerException" , NULL ); 53.24 Interpreter::_throw_StackOverflowError_entry = generate_StackOverflowError_handler(); 53.25 } 53.26 @@ -358,6 +360,7 @@ 53.27 method_entry(empty) 53.28 method_entry(accessor) 53.29 method_entry(abstract) 53.30 + method_entry(method_handle) 53.31 method_entry(java_lang_math_sin ) 53.32 method_entry(java_lang_math_cos ) 53.33 method_entry(java_lang_math_tan )
54.1 --- a/src/share/vm/interpreter/templateInterpreter.hpp Thu Apr 09 13:59:45 2009 -0700 54.2 +++ b/src/share/vm/interpreter/templateInterpreter.hpp Tue Apr 14 12:25:54 2009 -0700 54.3 @@ -1,5 +1,5 @@ 54.4 /* 54.5 - * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved. 54.6 + * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved. 54.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 54.8 * 54.9 * This code is free software; you can redistribute it and/or modify it 54.10 @@ -77,6 +77,7 @@ 54.11 friend class VMStructs; 54.12 friend class InterpreterMacroAssembler; 54.13 friend class TemplateInterpreterGenerator; 54.14 + friend class InterpreterGenerator; 54.15 friend class TemplateTable; 54.16 // friend class Interpreter; 54.17 public: 54.18 @@ -93,6 +94,7 @@ 54.19 static address _throw_ArrayStoreException_entry; 54.20 static address _throw_ArithmeticException_entry; 54.21 static address _throw_ClassCastException_entry; 54.22 + static address _throw_WrongMethodType_entry; 54.23 static address _throw_NullPointerException_entry; 54.24 static address _throw_exception_entry; 54.25 54.26 @@ -137,6 +139,7 @@ 54.27 static address remove_activation_entry() { return _remove_activation_entry; } 54.28 static address throw_exception_entry() { return _throw_exception_entry; } 54.29 static address throw_ArithmeticException_entry() { return _throw_ArithmeticException_entry; } 54.30 + static address throw_WrongMethodType_entry() { return _throw_WrongMethodType_entry; } 54.31 static address throw_NullPointerException_entry() { return _throw_NullPointerException_entry; } 54.32 static address throw_StackOverflowError_entry() { return _throw_StackOverflowError_entry; } 54.33
55.1 --- a/src/share/vm/interpreter/templateInterpreterGenerator.hpp Thu Apr 09 13:59:45 2009 -0700 55.2 +++ b/src/share/vm/interpreter/templateInterpreterGenerator.hpp Tue Apr 14 12:25:54 2009 -0700 55.3 @@ -1,5 +1,5 @@ 55.4 /* 55.5 - * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved. 55.6 + * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved. 55.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 55.8 * 55.9 * This code is free software; you can redistribute it and/or modify it 55.10 @@ -48,6 +48,7 @@ 55.11 } 55.12 address generate_exception_handler_common(const char* name, const char* message, bool pass_oop); 55.13 address generate_ClassCastException_handler(); 55.14 + address generate_WrongMethodType_handler(); 55.15 address generate_ArrayIndexOutOfBounds_handler(const char* name); 55.16 address generate_continuation_for(TosState state); 55.17 address generate_return_entry_for(TosState state, int step);
56.1 --- a/src/share/vm/memory/dump.cpp Thu Apr 09 13:59:45 2009 -0700 56.2 +++ b/src/share/vm/memory/dump.cpp Tue Apr 14 12:25:54 2009 -0700 56.3 @@ -1,5 +1,5 @@ 56.4 /* 56.5 - * Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved. 56.6 + * Copyright 2003-2009 Sun Microsystems, Inc. All Rights Reserved. 56.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 56.8 * 56.9 * This code is free software; you can redistribute it and/or modify it 56.10 @@ -928,6 +928,9 @@ 56.11 // shared classes at runtime, where constraints were previously created. 56.12 guarantee(SystemDictionary::constraints()->number_of_entries() == 0, 56.13 "loader constraints are not saved"); 56.14 + // Revisit and implement this if we prelink method handle call sites: 56.15 + guarantee(SystemDictionary::invoke_method_table()->number_of_entries() == 0, 56.16 + "invoke method table is not saved"); 56.17 GenCollectedHeap* gch = GenCollectedHeap::heap(); 56.18 56.19 // At this point, many classes have been loaded.
57.1 --- a/src/share/vm/oops/methodKlass.cpp Thu Apr 09 13:59:45 2009 -0700 57.2 +++ b/src/share/vm/oops/methodKlass.cpp Tue Apr 14 12:25:54 2009 -0700 57.3 @@ -298,7 +298,11 @@ 57.4 m->code()->print_value_on(st); 57.5 st->cr(); 57.6 } 57.7 - if (m->is_native()) { 57.8 + if (m->is_method_handle_invoke()) { 57.9 + st->print_cr(" - invoke method type: " INTPTR_FORMAT, (address) m->method_handle_type()); 57.10 + // m is classified as native, but it does not have an interesting 57.11 + // native_function or signature handler 57.12 + } else if (m->is_native()) { 57.13 st->print_cr(" - native function: " INTPTR_FORMAT, m->native_function()); 57.14 st->print_cr(" - signature handler: " INTPTR_FORMAT, m->signature_handler()); 57.15 }
58.1 --- a/src/share/vm/oops/methodOop.cpp Thu Apr 09 13:59:45 2009 -0700 58.2 +++ b/src/share/vm/oops/methodOop.cpp Tue Apr 14 12:25:54 2009 -0700 58.3 @@ -304,6 +304,12 @@ 58.4 } 58.5 58.6 58.7 +int methodOopDesc::extra_stack_words() { 58.8 + // not an inline function, to avoid a header dependency on Interpreter 58.9 + return extra_stack_entries() * Interpreter::stackElementSize(); 58.10 +} 58.11 + 58.12 + 58.13 void methodOopDesc::compute_size_of_parameters(Thread *thread) { 58.14 symbolHandle h_signature(thread, signature()); 58.15 ArgumentSizeComputer asc(h_signature); 58.16 @@ -564,6 +570,11 @@ 58.17 58.18 58.19 bool methodOopDesc::is_not_compilable(int comp_level) const { 58.20 + if (is_method_handle_invoke()) { 58.21 + // compilers must recognize this method specially, or not at all 58.22 + return true; 58.23 + } 58.24 + 58.25 methodDataOop mdo = method_data(); 58.26 if (mdo != NULL 58.27 && (uint)mdo->decompile_count() > (uint)PerMethodRecompilationCutoff) { 58.28 @@ -651,7 +662,7 @@ 58.29 assert(entry != NULL, "interpreter entry must be non-null"); 58.30 // Sets both _i2i_entry and _from_interpreted_entry 58.31 set_interpreter_entry(entry); 58.32 - if (is_native()) { 58.33 + if (is_native() && !is_method_handle_invoke()) { 58.34 set_native_function( 58.35 SharedRuntime::native_method_throw_unsatisfied_link_error_entry(), 58.36 !native_bind_event_is_interesting); 58.37 @@ -783,6 +794,100 @@ 58.38 return false; 58.39 } 58.40 58.41 +// Constant pool structure for invoke methods: 58.42 +enum { 58.43 + _imcp_invoke_name = 1, // utf8: 'invoke' 58.44 + _imcp_invoke_signature, // utf8: (variable symbolOop) 58.45 + _imcp_method_type_value, // string: (variable java/dyn/MethodType, sic) 58.46 + _imcp_limit 58.47 +}; 58.48 + 58.49 +oop methodOopDesc::method_handle_type() const { 58.50 + if (!is_method_handle_invoke()) { assert(false, "caller resp."); return NULL; } 58.51 + oop mt = constants()->resolved_string_at(_imcp_method_type_value); 58.52 + assert(mt->klass() == SystemDictionary::MethodType_klass(), ""); 58.53 + return mt; 58.54 +} 58.55 + 58.56 +jint* methodOopDesc::method_type_offsets_chain() { 58.57 + static jint pchase[] = { -1, -1, -1 }; 58.58 + if (pchase[0] == -1) { 58.59 + jint step0 = in_bytes(constants_offset()); 58.60 + jint step1 = (constantPoolOopDesc::header_size() + _imcp_method_type_value) * HeapWordSize; 58.61 + // do this in reverse to avoid races: 58.62 + OrderAccess::release_store(&pchase[1], step1); 58.63 + OrderAccess::release_store(&pchase[0], step0); 58.64 + } 58.65 + return pchase; 58.66 +} 58.67 + 58.68 +methodHandle methodOopDesc::make_invoke_method(KlassHandle holder, 58.69 + symbolHandle signature, 58.70 + Handle method_type, TRAPS) { 58.71 + methodHandle empty; 58.72 + 58.73 + assert(holder() == SystemDictionary::MethodHandle_klass(), 58.74 + "must be a JSR 292 magic type"); 58.75 + 58.76 + if (TraceMethodHandles) { 58.77 + tty->print("Creating invoke method for "); 58.78 + signature->print_value(); 58.79 + tty->cr(); 58.80 + } 58.81 + 58.82 + constantPoolHandle cp; 58.83 + { 58.84 + constantPoolOop cp_oop = oopFactory::new_constantPool(_imcp_limit, IsSafeConc, CHECK_(empty)); 58.85 + cp = constantPoolHandle(THREAD, cp_oop); 58.86 + } 58.87 + cp->symbol_at_put(_imcp_invoke_name, vmSymbols::invoke_name()); 58.88 + cp->symbol_at_put(_imcp_invoke_signature, signature()); 58.89 + cp->string_at_put(_imcp_method_type_value, vmSymbols::void_signature()); 58.90 + cp->set_pool_holder(holder()); 58.91 + 58.92 + // set up the fancy stuff: 58.93 + cp->pseudo_string_at_put(_imcp_method_type_value, method_type()); 58.94 + methodHandle m; 58.95 + { 58.96 + int flags_bits = (JVM_MH_INVOKE_BITS | JVM_ACC_PUBLIC | JVM_ACC_FINAL); 58.97 + methodOop m_oop = oopFactory::new_method(0, accessFlags_from(flags_bits), 58.98 + 0, 0, 0, IsSafeConc, CHECK_(empty)); 58.99 + m = methodHandle(THREAD, m_oop); 58.100 + } 58.101 + m->set_constants(cp()); 58.102 + m->set_name_index(_imcp_invoke_name); 58.103 + m->set_signature_index(_imcp_invoke_signature); 58.104 + assert(m->name() == vmSymbols::invoke_name(), ""); 58.105 + assert(m->signature() == signature(), ""); 58.106 +#ifdef CC_INTERP 58.107 + ResultTypeFinder rtf(signature()); 58.108 + m->set_result_index(rtf.type()); 58.109 +#endif 58.110 + m->compute_size_of_parameters(THREAD); 58.111 + m->set_exception_table(Universe::the_empty_int_array()); 58.112 + 58.113 + // Finally, set up its entry points. 58.114 + assert(m->method_handle_type() == method_type(), ""); 58.115 + assert(m->can_be_statically_bound(), ""); 58.116 + m->set_vtable_index(methodOopDesc::nonvirtual_vtable_index); 58.117 + m->link_method(m, CHECK_(empty)); 58.118 + 58.119 +#ifdef ASSERT 58.120 + // Make sure the pointer chase works. 58.121 + address p = (address) m(); 58.122 + for (jint* pchase = method_type_offsets_chain(); (*pchase) != -1; pchase++) { 58.123 + p = *(address*)(p + (*pchase)); 58.124 + } 58.125 + assert((oop)p == method_type(), "pointer chase is correct"); 58.126 +#endif 58.127 + 58.128 + if (TraceMethodHandles) 58.129 + m->print_on(tty); 58.130 + 58.131 + return m; 58.132 +} 58.133 + 58.134 + 58.135 58.136 methodHandle methodOopDesc:: clone_with_new_data(methodHandle m, u_char* new_code, int new_code_length, 58.137 u_char* new_compressed_linenumber_table, int new_compressed_linenumber_size, TRAPS) {
59.1 --- a/src/share/vm/oops/methodOop.hpp Thu Apr 09 13:59:45 2009 -0700 59.2 +++ b/src/share/vm/oops/methodOop.hpp Tue Apr 14 12:25:54 2009 -0700 59.3 @@ -320,6 +320,7 @@ 59.4 enum VtableIndexFlag { 59.5 // Valid vtable indexes are non-negative (>= 0). 59.6 // These few negative values are used as sentinels. 59.7 + highest_unused_vtable_index_value = -5, 59.8 invalid_vtable_index = -4, // distinct from any valid vtable index 59.9 garbage_vtable_index = -3, // not yet linked; no vtable layout yet 59.10 nonvirtual_vtable_index = -2 // there is no need for vtable dispatch 59.11 @@ -523,6 +524,18 @@ 59.12 // Reflection support 59.13 bool is_overridden_in(klassOop k) const; 59.14 59.15 + // JSR 292 support 59.16 + bool is_method_handle_invoke() const { return access_flags().is_method_handle_invoke(); } 59.17 + static methodHandle make_invoke_method(KlassHandle holder, 59.18 + symbolHandle signature, 59.19 + Handle method_type, 59.20 + TRAPS); 59.21 + // these operate only on invoke methods: 59.22 + oop method_handle_type() const; 59.23 + static jint* method_type_offsets_chain(); // series of pointer-offsets, terminated by -1 59.24 + // presize interpreter frames for extra interpreter stack entries, if needed 59.25 + static int extra_stack_entries() { return EnableMethodHandles ? (int)MethodHandlePushLimit : 0; } 59.26 + static int extra_stack_words(); // = extra_stack_entries() * Interpreter::stackElementSize() 59.27 // RedefineClasses() support: 59.28 bool is_old() const { return access_flags().is_old(); } 59.29 void set_is_old() { _access_flags.set_is_old(); }
60.1 --- a/src/share/vm/oops/oop.hpp Thu Apr 09 13:59:45 2009 -0700 60.2 +++ b/src/share/vm/oops/oop.hpp Tue Apr 14 12:25:54 2009 -0700 60.3 @@ -263,6 +263,9 @@ 60.4 jdouble double_field_acquire(int offset) const; 60.5 void release_double_field_put(int offset, jdouble contents); 60.6 60.7 + address address_field_acquire(int offset) const; 60.8 + void release_address_field_put(int offset, address contents); 60.9 + 60.10 // printing functions for VM debugging 60.11 void print_on(outputStream* st) const; // First level print 60.12 void print_value_on(outputStream* st) const; // Second level print.
61.1 --- a/src/share/vm/oops/oop.inline.hpp Thu Apr 09 13:59:45 2009 -0700 61.2 +++ b/src/share/vm/oops/oop.inline.hpp Tue Apr 14 12:25:54 2009 -0700 61.3 @@ -349,6 +349,9 @@ 61.4 inline jdouble oopDesc::double_field_acquire(int offset) const { return OrderAccess::load_acquire(double_field_addr(offset)); } 61.5 inline void oopDesc::release_double_field_put(int offset, jdouble contents) { OrderAccess::release_store(double_field_addr(offset), contents); } 61.6 61.7 +inline address oopDesc::address_field_acquire(int offset) const { return (address) OrderAccess::load_ptr_acquire(address_field_addr(offset)); } 61.8 +inline void oopDesc::release_address_field_put(int offset, address contents) { OrderAccess::release_store_ptr(address_field_addr(offset), contents); } 61.9 + 61.10 inline int oopDesc::size_given_klass(Klass* klass) { 61.11 int lh = klass->layout_helper(); 61.12 int s = lh >> LogHeapWordSize; // deliver size scaled by wordSize
62.1 --- a/src/share/vm/opto/callnode.cpp Thu Apr 09 13:59:45 2009 -0700 62.2 +++ b/src/share/vm/opto/callnode.cpp Tue Apr 14 12:25:54 2009 -0700 62.3 @@ -1043,6 +1043,51 @@ 62.4 //============================================================================= 62.5 uint AllocateArrayNode::size_of() const { return sizeof(*this); } 62.6 62.7 +Node* AllocateArrayNode::Ideal(PhaseGVN *phase, bool can_reshape) { 62.8 + if (remove_dead_region(phase, can_reshape)) return this; 62.9 + 62.10 + const Type* type = phase->type(Ideal_length()); 62.11 + if (type->isa_int() && type->is_int()->_hi < 0) { 62.12 + if (can_reshape) { 62.13 + PhaseIterGVN *igvn = phase->is_IterGVN(); 62.14 + // Unreachable fall through path (negative array length), 62.15 + // the allocation can only throw so disconnect it. 62.16 + Node* proj = proj_out(TypeFunc::Control); 62.17 + Node* catchproj = NULL; 62.18 + if (proj != NULL) { 62.19 + for (DUIterator_Fast imax, i = proj->fast_outs(imax); i < imax; i++) { 62.20 + Node *cn = proj->fast_out(i); 62.21 + if (cn->is_Catch()) { 62.22 + catchproj = cn->as_Multi()->proj_out(CatchProjNode::fall_through_index); 62.23 + break; 62.24 + } 62.25 + } 62.26 + } 62.27 + if (catchproj != NULL && catchproj->outcnt() > 0 && 62.28 + (catchproj->outcnt() > 1 || 62.29 + catchproj->unique_out()->Opcode() != Op_Halt)) { 62.30 + assert(catchproj->is_CatchProj(), "must be a CatchProjNode"); 62.31 + Node* nproj = catchproj->clone(); 62.32 + igvn->register_new_node_with_optimizer(nproj); 62.33 + 62.34 + Node *frame = new (phase->C, 1) ParmNode( phase->C->start(), TypeFunc::FramePtr ); 62.35 + frame = phase->transform(frame); 62.36 + // Halt & Catch Fire 62.37 + Node *halt = new (phase->C, TypeFunc::Parms) HaltNode( nproj, frame ); 62.38 + phase->C->root()->add_req(halt); 62.39 + phase->transform(halt); 62.40 + 62.41 + igvn->replace_node(catchproj, phase->C->top()); 62.42 + return this; 62.43 + } 62.44 + } else { 62.45 + // Can't correct it during regular GVN so register for IGVN 62.46 + phase->C->record_for_igvn(this); 62.47 + } 62.48 + } 62.49 + return NULL; 62.50 +} 62.51 + 62.52 // Retrieve the length from the AllocateArrayNode. Narrow the type with a 62.53 // CastII, if appropriate. If we are not allowed to create new nodes, and 62.54 // a CastII is appropriate, return NULL.
63.1 --- a/src/share/vm/opto/callnode.hpp Thu Apr 09 13:59:45 2009 -0700 63.2 +++ b/src/share/vm/opto/callnode.hpp Tue Apr 14 12:25:54 2009 -0700 63.3 @@ -762,6 +762,7 @@ 63.4 } 63.5 virtual int Opcode() const; 63.6 virtual uint size_of() const; // Size is bigger 63.7 + virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); 63.8 63.9 // Dig the length operand out of a array allocation site. 63.10 Node* Ideal_length() {
64.1 --- a/src/share/vm/opto/macro.cpp Thu Apr 09 13:59:45 2009 -0700 64.2 +++ b/src/share/vm/opto/macro.cpp Tue Apr 14 12:25:54 2009 -0700 64.3 @@ -806,8 +806,7 @@ 64.4 } 64.5 } else if (use->is_AddP()) { 64.6 // raw memory addresses used only by the initialization 64.7 - _igvn.hash_delete(use); 64.8 - _igvn.subsume_node(use, C->top()); 64.9 + _igvn.replace_node(use, C->top()); 64.10 } else { 64.11 assert(false, "only Initialize or AddP expected"); 64.12 } 64.13 @@ -1291,8 +1290,7 @@ 64.14 if (_fallthroughcatchproj != NULL) { 64.15 ctrl = _fallthroughcatchproj->clone(); 64.16 transform_later(ctrl); 64.17 - _igvn.hash_delete(_fallthroughcatchproj); 64.18 - _igvn.subsume_node(_fallthroughcatchproj, result_region); 64.19 + _igvn.replace_node(_fallthroughcatchproj, result_region); 64.20 } else { 64.21 ctrl = top(); 64.22 } 64.23 @@ -1303,8 +1301,7 @@ 64.24 } else { 64.25 slow_result = _resproj->clone(); 64.26 transform_later(slow_result); 64.27 - _igvn.hash_delete(_resproj); 64.28 - _igvn.subsume_node(_resproj, result_phi_rawoop); 64.29 + _igvn.replace_node(_resproj, result_phi_rawoop); 64.30 } 64.31 64.32 // Plug slow-path into result merge point 64.33 @@ -1613,18 +1610,15 @@ 64.34 assert(membar != NULL && membar->Opcode() == Op_MemBarAcquire, ""); 64.35 Node* ctrlproj = membar->proj_out(TypeFunc::Control); 64.36 Node* memproj = membar->proj_out(TypeFunc::Memory); 64.37 - _igvn.hash_delete(ctrlproj); 64.38 - _igvn.subsume_node(ctrlproj, fallthroughproj); 64.39 - _igvn.hash_delete(memproj); 64.40 - _igvn.subsume_node(memproj, memproj_fallthrough); 64.41 + _igvn.replace_node(ctrlproj, fallthroughproj); 64.42 + _igvn.replace_node(memproj, memproj_fallthrough); 64.43 64.44 // Delete FastLock node also if this Lock node is unique user 64.45 // (a loop peeling may clone a Lock node). 64.46 Node* flock = alock->as_Lock()->fastlock_node(); 64.47 if (flock->outcnt() == 1) { 64.48 assert(flock->unique_out() == alock, "sanity"); 64.49 - _igvn.hash_delete(flock); 64.50 - _igvn.subsume_node(flock, top()); 64.51 + _igvn.replace_node(flock, top()); 64.52 } 64.53 } 64.54 64.55 @@ -1634,20 +1628,16 @@ 64.56 MemBarNode* membar = ctrl->in(0)->as_MemBar(); 64.57 assert(membar->Opcode() == Op_MemBarRelease && 64.58 mem->is_Proj() && membar == mem->in(0), ""); 64.59 - _igvn.hash_delete(fallthroughproj); 64.60 - _igvn.subsume_node(fallthroughproj, ctrl); 64.61 - _igvn.hash_delete(memproj_fallthrough); 64.62 - _igvn.subsume_node(memproj_fallthrough, mem); 64.63 + _igvn.replace_node(fallthroughproj, ctrl); 64.64 + _igvn.replace_node(memproj_fallthrough, mem); 64.65 fallthroughproj = ctrl; 64.66 memproj_fallthrough = mem; 64.67 ctrl = membar->in(TypeFunc::Control); 64.68 mem = membar->in(TypeFunc::Memory); 64.69 } 64.70 64.71 - _igvn.hash_delete(fallthroughproj); 64.72 - _igvn.subsume_node(fallthroughproj, ctrl); 64.73 - _igvn.hash_delete(memproj_fallthrough); 64.74 - _igvn.subsume_node(memproj_fallthrough, mem); 64.75 + _igvn.replace_node(fallthroughproj, ctrl); 64.76 + _igvn.replace_node(memproj_fallthrough, mem); 64.77 return true; 64.78 } 64.79 64.80 @@ -1879,13 +1869,12 @@ 64.81 region->init_req(1, slow_ctrl); 64.82 // region inputs are now complete 64.83 transform_later(region); 64.84 - _igvn.subsume_node(_fallthroughproj, region); 64.85 + _igvn.replace_node(_fallthroughproj, region); 64.86 64.87 Node *memproj = transform_later( new(C, 1) ProjNode(call, TypeFunc::Memory) ); 64.88 mem_phi->init_req(1, memproj ); 64.89 transform_later(mem_phi); 64.90 - _igvn.hash_delete(_memproj_fallthrough); 64.91 - _igvn.subsume_node(_memproj_fallthrough, mem_phi); 64.92 + _igvn.replace_node(_memproj_fallthrough, mem_phi); 64.93 } 64.94 64.95 //------------------------------expand_unlock_node---------------------- 64.96 @@ -1943,14 +1932,13 @@ 64.97 region->init_req(1, slow_ctrl); 64.98 // region inputs are now complete 64.99 transform_later(region); 64.100 - _igvn.subsume_node(_fallthroughproj, region); 64.101 + _igvn.replace_node(_fallthroughproj, region); 64.102 64.103 Node *memproj = transform_later( new(C, 1) ProjNode(call, TypeFunc::Memory) ); 64.104 mem_phi->init_req(1, memproj ); 64.105 mem_phi->init_req(2, mem); 64.106 transform_later(mem_phi); 64.107 - _igvn.hash_delete(_memproj_fallthrough); 64.108 - _igvn.subsume_node(_memproj_fallthrough, mem_phi); 64.109 + _igvn.replace_node(_memproj_fallthrough, mem_phi); 64.110 } 64.111 64.112 //------------------------------expand_macro_nodes---------------------- 64.113 @@ -1969,9 +1957,7 @@ 64.114 if (n->is_AbstractLock()) { 64.115 success = eliminate_locking_node(n->as_AbstractLock()); 64.116 } else if (n->Opcode() == Op_Opaque1 || n->Opcode() == Op_Opaque2) { 64.117 - _igvn.add_users_to_worklist(n); 64.118 - _igvn.hash_delete(n); 64.119 - _igvn.subsume_node(n, n->in(1)); 64.120 + _igvn.replace_node(n, n->in(1)); 64.121 success = true; 64.122 } 64.123 assert(success == (C->macro_count() < old_macro_count), "elimination reduces macro count");
65.1 --- a/src/share/vm/opto/memnode.cpp Thu Apr 09 13:59:45 2009 -0700 65.2 +++ b/src/share/vm/opto/memnode.cpp Tue Apr 14 12:25:54 2009 -0700 65.3 @@ -218,6 +218,26 @@ 65.4 // Don't bother trying to transform a dead node 65.5 if( ctl && ctl->is_top() ) return NodeSentinel; 65.6 65.7 + PhaseIterGVN *igvn = phase->is_IterGVN(); 65.8 + // Wait if control on the worklist. 65.9 + if (ctl && can_reshape && igvn != NULL) { 65.10 + Node* bol = NULL; 65.11 + Node* cmp = NULL; 65.12 + if (ctl->in(0)->is_If()) { 65.13 + assert(ctl->is_IfTrue() || ctl->is_IfFalse(), "sanity"); 65.14 + bol = ctl->in(0)->in(1); 65.15 + if (bol->is_Bool()) 65.16 + cmp = ctl->in(0)->in(1)->in(1); 65.17 + } 65.18 + if (igvn->_worklist.member(ctl) || 65.19 + (bol != NULL && igvn->_worklist.member(bol)) || 65.20 + (cmp != NULL && igvn->_worklist.member(cmp)) ) { 65.21 + // This control path may be dead. 65.22 + // Delay this memory node transformation until the control is processed. 65.23 + phase->is_IterGVN()->_worklist.push(this); 65.24 + return NodeSentinel; // caller will return NULL 65.25 + } 65.26 + } 65.27 // Ignore if memory is dead, or self-loop 65.28 Node *mem = in(MemNode::Memory); 65.29 if( phase->type( mem ) == Type::TOP ) return NodeSentinel; // caller will return NULL 65.30 @@ -227,14 +247,22 @@ 65.31 const Type *t_adr = phase->type( address ); 65.32 if( t_adr == Type::TOP ) return NodeSentinel; // caller will return NULL 65.33 65.34 - PhaseIterGVN *igvn = phase->is_IterGVN(); 65.35 - if( can_reshape && igvn != NULL && igvn->_worklist.member(address) ) { 65.36 + if( can_reshape && igvn != NULL && 65.37 + (igvn->_worklist.member(address) || phase->type(address) != adr_type()) ) { 65.38 // The address's base and type may change when the address is processed. 65.39 // Delay this mem node transformation until the address is processed. 65.40 phase->is_IterGVN()->_worklist.push(this); 65.41 return NodeSentinel; // caller will return NULL 65.42 } 65.43 65.44 +#ifdef ASSERT 65.45 + Node* base = NULL; 65.46 + if (address->is_AddP()) 65.47 + base = address->in(AddPNode::Base); 65.48 + assert(base == NULL || t_adr->isa_rawptr() || 65.49 + !phase->type(base)->higher_equal(TypePtr::NULL_PTR), "NULL+offs not RAW address?"); 65.50 +#endif 65.51 + 65.52 // Avoid independent memory operations 65.53 Node* old_mem = mem; 65.54 65.55 @@ -1307,22 +1335,20 @@ 65.56 set_req(MemNode::Control,ctrl); 65.57 } 65.58 65.59 - // Check for useless control edge in some common special cases 65.60 - if (in(MemNode::Control) != NULL) { 65.61 - intptr_t ignore = 0; 65.62 - Node* base = AddPNode::Ideal_base_and_offset(address, phase, ignore); 65.63 - if (base != NULL 65.64 + intptr_t ignore = 0; 65.65 + Node* base = AddPNode::Ideal_base_and_offset(address, phase, ignore); 65.66 + if (base != NULL 65.67 + && phase->C->get_alias_index(phase->type(address)->is_ptr()) != Compile::AliasIdxRaw) { 65.68 + // Check for useless control edge in some common special cases 65.69 + if (in(MemNode::Control) != NULL 65.70 && phase->type(base)->higher_equal(TypePtr::NOTNULL) 65.71 - && phase->C->get_alias_index(phase->type(address)->is_ptr()) != Compile::AliasIdxRaw 65.72 && all_controls_dominate(base, phase->C->start())) { 65.73 // A method-invariant, non-null address (constant or 'this' argument). 65.74 set_req(MemNode::Control, NULL); 65.75 } 65.76 - } 65.77 - 65.78 - if (EliminateAutoBox && can_reshape && in(Address)->is_AddP()) { 65.79 - Node* base = in(Address)->in(AddPNode::Base); 65.80 - if (base != NULL) { 65.81 + 65.82 + if (EliminateAutoBox && can_reshape) { 65.83 + assert(!phase->type(base)->higher_equal(TypePtr::NULL_PTR), "the autobox pointer should be non-null"); 65.84 Compile::AliasType* atp = phase->C->alias_type(adr_type()); 65.85 if (is_autobox_object(atp)) { 65.86 Node* result = eliminate_autobox(phase); 65.87 @@ -1455,10 +1481,11 @@ 65.88 jt = _type; 65.89 } 65.90 65.91 - if (EliminateAutoBox) { 65.92 + if (EliminateAutoBox && adr->is_AddP()) { 65.93 // The pointers in the autobox arrays are always non-null 65.94 - Node* base = in(Address)->in(AddPNode::Base); 65.95 - if (base != NULL) { 65.96 + Node* base = adr->in(AddPNode::Base); 65.97 + if (base != NULL && 65.98 + !phase->type(base)->higher_equal(TypePtr::NULL_PTR)) { 65.99 Compile::AliasType* atp = phase->C->alias_type(base->adr_type()); 65.100 if (is_autobox_cache(atp)) { 65.101 return jt->join(TypePtr::NOTNULL)->is_ptr();
66.1 --- a/src/share/vm/opto/output.cpp Thu Apr 09 13:59:45 2009 -0700 66.2 +++ b/src/share/vm/opto/output.cpp Tue Apr 14 12:25:54 2009 -0700 66.3 @@ -2256,7 +2256,8 @@ 66.4 // bother scheduling them. 66.5 Node *last = bb->_nodes[_bb_end]; 66.6 if( last->is_Catch() || 66.7 - (last->is_Mach() && last->as_Mach()->ideal_Opcode() == Op_Halt) ) { 66.8 + // Exclude unreachable path case when Halt node is in a separate block. 66.9 + (_bb_end > 1 && last->is_Mach() && last->as_Mach()->ideal_Opcode() == Op_Halt) ) { 66.10 // There must be a prior call. Skip it. 66.11 while( !bb->_nodes[--_bb_end]->is_Call() ) { 66.12 assert( bb->_nodes[_bb_end]->is_Proj(), "skipping projections after expected call" );
67.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 67.2 +++ b/src/share/vm/prims/methodHandles.cpp Tue Apr 14 12:25:54 2009 -0700 67.3 @@ -0,0 +1,2347 @@ 67.4 +/* 67.5 + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. 67.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 67.7 + * 67.8 + * This code is free software; you can redistribute it and/or modify it 67.9 + * under the terms of the GNU General Public License version 2 only, as 67.10 + * published by the Free Software Foundation. 67.11 + * 67.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 67.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 67.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 67.15 + * version 2 for more details (a copy is included in the LICENSE file that 67.16 + * accompanied this code). 67.17 + * 67.18 + * You should have received a copy of the GNU General Public License version 67.19 + * 2 along with this work; if not, write to the Free Software Foundation, 67.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 67.21 + * 67.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 67.23 + * CA 95054 USA or visit www.sun.com if you need additional information or 67.24 + * have any questions. 67.25 + * 67.26 + */ 67.27 + 67.28 +/* 67.29 + * JSR 292 reference implementation: method handles 67.30 + */ 67.31 + 67.32 +#include "incls/_precompiled.incl" 67.33 +#include "incls/_methodHandles.cpp.incl" 67.34 + 67.35 +bool MethodHandles::_enabled = false; // set true after successful native linkage 67.36 + 67.37 +MethodHandleEntry* MethodHandles::_entries[MethodHandles::_EK_LIMIT] = {NULL}; 67.38 +const char* MethodHandles::_entry_names[_EK_LIMIT+1] = { 67.39 + "check_mtype", 67.40 + "wrong_method_type", // what happens when there is a type mismatch 67.41 + "invokestatic", // how a MH emulates invokestatic 67.42 + "invokespecial", // ditto for the other invokes... 67.43 + "invokevirtual", 67.44 + "invokeinterface", 67.45 + "bound_ref", // these are for BMH... 67.46 + "bound_int", 67.47 + "bound_long", 67.48 + "bound_ref_direct", // (direct versions have a direct methodOop) 67.49 + "bound_int_direct", 67.50 + "bound_long_direct", 67.51 + 67.52 + // starting at _adapter_mh_first: 67.53 + "adapter_retype_only", // these are for AMH... 67.54 + "adapter_check_cast", 67.55 + "adapter_prim_to_prim", 67.56 + "adapter_ref_to_prim", 67.57 + "adapter_prim_to_ref", 67.58 + "adapter_swap_args", 67.59 + "adapter_rot_args", 67.60 + "adapter_dup_args", 67.61 + "adapter_drop_args", 67.62 + "adapter_collect_args", 67.63 + "adapter_spread_args", 67.64 + "adapter_flyby", 67.65 + "adapter_ricochet", 67.66 + 67.67 + // optimized adapter types: 67.68 + "adapter_swap_args/1", 67.69 + "adapter_swap_args/2", 67.70 + "adapter_rot_args/1,up", 67.71 + "adapter_rot_args/1,down", 67.72 + "adapter_rot_args/2,up", 67.73 + "adapter_rot_args/2,down", 67.74 + "adapter_prim_to_prim/i2i", 67.75 + "adapter_prim_to_prim/l2i", 67.76 + "adapter_prim_to_prim/d2f", 67.77 + "adapter_prim_to_prim/i2l", 67.78 + "adapter_prim_to_prim/f2d", 67.79 + "adapter_ref_to_prim/unboxi", 67.80 + "adapter_ref_to_prim/unboxl", 67.81 + "adapter_spread_args/0", 67.82 + "adapter_spread_args/1", 67.83 + "adapter_spread_args/more", 67.84 + 67.85 + NULL 67.86 +}; 67.87 + 67.88 +#ifdef ASSERT 67.89 +bool MethodHandles::spot_check_entry_names() { 67.90 + assert(!strcmp(entry_name(_invokestatic_mh), "invokestatic"), ""); 67.91 + assert(!strcmp(entry_name(_bound_ref_mh), "bound_ref"), ""); 67.92 + assert(!strcmp(entry_name(_adapter_retype_only), "adapter_retype_only"), ""); 67.93 + assert(!strcmp(entry_name(_adapter_ricochet), "adapter_ricochet"), ""); 67.94 + assert(!strcmp(entry_name(_adapter_opt_unboxi), "adapter_ref_to_prim/unboxi"), ""); 67.95 + return true; 67.96 +} 67.97 +#endif 67.98 + 67.99 +void MethodHandles::set_enabled(bool z) { 67.100 + if (_enabled != z) { 67.101 + guarantee(z && EnableMethodHandles, "can only enable once, and only if -XX:+EnableMethodHandles"); 67.102 + _enabled = z; 67.103 + } 67.104 +} 67.105 + 67.106 +// Note: A method which does not have a TRAPS argument cannot block in the GC 67.107 +// or throw exceptions. Such methods are used in this file to do something quick 67.108 +// and local, like parse a data structure. For speed, such methods work on plain 67.109 +// oops, not handles. Trapping methods uniformly operate on handles. 67.110 + 67.111 +methodOop MethodHandles::decode_vmtarget(oop vmtarget, int vmindex, oop mtype, 67.112 + klassOop& receiver_limit_result, int& decode_flags_result) { 67.113 + if (vmtarget == NULL) return NULL; 67.114 + assert(methodOopDesc::nonvirtual_vtable_index < 0, "encoding"); 67.115 + if (vmindex < 0) { 67.116 + // this DMH performs no dispatch; it is directly bound to a methodOop 67.117 + // A MemberName may either be directly bound to a methodOop, 67.118 + // or it may use the klass/index form; both forms mean the same thing. 67.119 + methodOop m = decode_methodOop(methodOop(vmtarget), decode_flags_result); 67.120 + if ((decode_flags_result & _dmf_has_receiver) != 0 67.121 + && java_dyn_MethodType::is_instance(mtype)) { 67.122 + // Extract receiver type restriction from mtype.ptypes[0]. 67.123 + objArrayOop ptypes = java_dyn_MethodType::ptypes(mtype); 67.124 + oop ptype0 = (ptypes == NULL || ptypes->length() < 1) ? oop(NULL) : ptypes->obj_at(0); 67.125 + if (java_lang_Class::is_instance(ptype0)) 67.126 + receiver_limit_result = java_lang_Class::as_klassOop(ptype0); 67.127 + } 67.128 + if (vmindex == methodOopDesc::nonvirtual_vtable_index) { 67.129 + // this DMH can be an "invokespecial" version 67.130 + decode_flags_result &= ~_dmf_does_dispatch; 67.131 + } else { 67.132 + assert(vmindex == methodOopDesc::invalid_vtable_index, "random vmindex?"); 67.133 + } 67.134 + return m; 67.135 + } else { 67.136 + decode_flags_result |= MethodHandles::_dmf_does_dispatch; 67.137 + assert(vmtarget->is_klass(), "must be class or interface"); 67.138 + receiver_limit_result = (klassOop)vmtarget; 67.139 + Klass* tk = Klass::cast((klassOop)vmtarget); 67.140 + if (tk->is_interface()) { 67.141 + // an itable linkage is <interface, itable index> 67.142 + decode_flags_result |= MethodHandles::_dmf_from_interface; 67.143 + return klassItable::method_for_itable_index((klassOop)vmtarget, vmindex); 67.144 + } else { 67.145 + if (!tk->oop_is_instance()) 67.146 + tk = instanceKlass::cast(SystemDictionary::object_klass()); 67.147 + return ((instanceKlass*)tk)->method_at_vtable(vmindex); 67.148 + } 67.149 + } 67.150 +} 67.151 + 67.152 +// MemberName and DirectMethodHandle have the same linkage to the JVM internals. 67.153 +// (MemberName is the non-operational name used for queries and setup.) 67.154 + 67.155 +methodOop MethodHandles::decode_DirectMethodHandle(oop mh, klassOop& receiver_limit_result, int& decode_flags_result) { 67.156 + oop vmtarget = sun_dyn_DirectMethodHandle::vmtarget(mh); 67.157 + int vmindex = sun_dyn_DirectMethodHandle::vmindex(mh); 67.158 + oop mtype = sun_dyn_DirectMethodHandle::type(mh); 67.159 + return decode_vmtarget(vmtarget, vmindex, mtype, receiver_limit_result, decode_flags_result); 67.160 +} 67.161 + 67.162 +methodOop MethodHandles::decode_BoundMethodHandle(oop mh, klassOop& receiver_limit_result, int& decode_flags_result) { 67.163 + assert(mh->klass() == SystemDictionary::BoundMethodHandle_klass(), ""); 67.164 + for (oop bmh = mh;;) { 67.165 + // Bound MHs can be stacked to bind several arguments. 67.166 + oop target = java_dyn_MethodHandle::vmtarget(bmh); 67.167 + if (target == NULL) return NULL; 67.168 + decode_flags_result |= MethodHandles::_dmf_binds_argument; 67.169 + klassOop tk = target->klass(); 67.170 + if (tk == SystemDictionary::BoundMethodHandle_klass()) { 67.171 + bmh = target; 67.172 + continue; 67.173 + } else { 67.174 + if (java_dyn_MethodHandle::is_subclass(tk)) { 67.175 + //assert(tk == SystemDictionary::DirectMethodHandle_klass(), "end of BMH chain must be DMH"); 67.176 + return decode_MethodHandle(target, receiver_limit_result, decode_flags_result); 67.177 + } else { 67.178 + // Optimized case: binding a receiver to a non-dispatched DMH 67.179 + // short-circuits directly to the methodOop. 67.180 + assert(target->is_method(), "must be a simple method"); 67.181 + methodOop m = (methodOop) target; 67.182 + DEBUG_ONLY(int argslot = sun_dyn_BoundMethodHandle::vmargslot(bmh)); 67.183 + assert(argslot == m->size_of_parameters() - 1, "must be initial argument (receiver)"); 67.184 + decode_flags_result |= MethodHandles::_dmf_binds_method; 67.185 + return m; 67.186 + } 67.187 + } 67.188 + } 67.189 +} 67.190 + 67.191 +methodOop MethodHandles::decode_AdapterMethodHandle(oop mh, klassOop& receiver_limit_result, int& decode_flags_result) { 67.192 + assert(mh->klass() == SystemDictionary::AdapterMethodHandle_klass(), ""); 67.193 + for (oop amh = mh;;) { 67.194 + // Adapter MHs can be stacked to convert several arguments. 67.195 + int conv_op = adapter_conversion_op(sun_dyn_AdapterMethodHandle::conversion(amh)); 67.196 + decode_flags_result |= (_dmf_adapter_lsb << conv_op) & _DMF_ADAPTER_MASK; 67.197 + oop target = java_dyn_MethodHandle::vmtarget(amh); 67.198 + if (target == NULL) return NULL; 67.199 + klassOop tk = target->klass(); 67.200 + if (tk == SystemDictionary::AdapterMethodHandle_klass()) { 67.201 + amh = target; 67.202 + continue; 67.203 + } else { 67.204 + // must be a BMH (which will bind some more arguments) or a DMH (for the final call) 67.205 + return MethodHandles::decode_MethodHandle(target, receiver_limit_result, decode_flags_result); 67.206 + } 67.207 + } 67.208 +} 67.209 + 67.210 +methodOop MethodHandles::decode_MethodHandle(oop mh, klassOop& receiver_limit_result, int& decode_flags_result) { 67.211 + if (mh == NULL) return NULL; 67.212 + klassOop mhk = mh->klass(); 67.213 + assert(java_dyn_MethodHandle::is_subclass(mhk), "must be a MethodHandle"); 67.214 + if (mhk == SystemDictionary::DirectMethodHandle_klass()) { 67.215 + return decode_DirectMethodHandle(mh, receiver_limit_result, decode_flags_result); 67.216 + } else if (mhk == SystemDictionary::BoundMethodHandle_klass()) { 67.217 + return decode_BoundMethodHandle(mh, receiver_limit_result, decode_flags_result); 67.218 + } else if (mhk == SystemDictionary::AdapterMethodHandle_klass()) { 67.219 + return decode_AdapterMethodHandle(mh, receiver_limit_result, decode_flags_result); 67.220 + } else { 67.221 + assert(false, "cannot parse this MH"); 67.222 + return NULL; // random MH? 67.223 + } 67.224 +} 67.225 + 67.226 +methodOop MethodHandles::decode_methodOop(methodOop m, int& decode_flags_result) { 67.227 + assert(m->is_method(), ""); 67.228 + if (m->is_static()) { 67.229 + // check that signature begins '(L' or '([' (not '(I', '()', etc.) 67.230 + symbolOop sig = m->signature(); 67.231 + BasicType recv_bt = char2type(sig->byte_at(1)); 67.232 + // Note: recv_bt might be T_ILLEGAL if byte_at(2) is ')' 67.233 + assert(sig->byte_at(0) == '(', "must be method sig"); 67.234 + if (recv_bt == T_OBJECT || recv_bt == T_ARRAY) 67.235 + decode_flags_result |= _dmf_has_receiver; 67.236 + } else { 67.237 + // non-static method 67.238 + decode_flags_result |= _dmf_has_receiver; 67.239 + if (!m->can_be_statically_bound() && !m->is_initializer()) { 67.240 + decode_flags_result |= _dmf_does_dispatch; 67.241 + if (Klass::cast(m->method_holder())->is_interface()) 67.242 + decode_flags_result |= _dmf_from_interface; 67.243 + } 67.244 + } 67.245 + return m; 67.246 +} 67.247 + 67.248 + 67.249 +// A trusted party is handing us a cookie to determine a method. 67.250 +// Let's boil it down to the method oop they really want. 67.251 +methodOop MethodHandles::decode_method(oop x, klassOop& receiver_limit_result, int& decode_flags_result) { 67.252 + decode_flags_result = 0; 67.253 + receiver_limit_result = NULL; 67.254 + klassOop xk = x->klass(); 67.255 + if (xk == Universe::methodKlassObj()) { 67.256 + return decode_methodOop((methodOop) x, decode_flags_result); 67.257 + } else if (xk == SystemDictionary::MemberName_klass()) { 67.258 + // Note: This only works if the MemberName has already been resolved. 67.259 + return decode_MemberName(x, receiver_limit_result, decode_flags_result); 67.260 + } else if (java_dyn_MethodHandle::is_subclass(xk)) { 67.261 + return decode_MethodHandle(x, receiver_limit_result, decode_flags_result); 67.262 + } else if (xk == SystemDictionary::reflect_method_klass()) { 67.263 + oop clazz = java_lang_reflect_Method::clazz(x); 67.264 + int slot = java_lang_reflect_Method::slot(x); 67.265 + klassOop k = java_lang_Class::as_klassOop(clazz); 67.266 + if (k != NULL && Klass::cast(k)->oop_is_instance()) 67.267 + return decode_methodOop(instanceKlass::cast(k)->method_with_idnum(slot), 67.268 + decode_flags_result); 67.269 + } else if (xk == SystemDictionary::reflect_constructor_klass()) { 67.270 + oop clazz = java_lang_reflect_Constructor::clazz(x); 67.271 + int slot = java_lang_reflect_Constructor::slot(x); 67.272 + klassOop k = java_lang_Class::as_klassOop(clazz); 67.273 + if (k != NULL && Klass::cast(k)->oop_is_instance()) 67.274 + return decode_methodOop(instanceKlass::cast(k)->method_with_idnum(slot), 67.275 + decode_flags_result); 67.276 + } else { 67.277 + // unrecognized object 67.278 + assert(!x->is_method(), "already checked"); 67.279 + assert(!sun_dyn_MemberName::is_instance(x), "already checked"); 67.280 + } 67.281 + return NULL; 67.282 +} 67.283 + 67.284 + 67.285 +int MethodHandles::decode_MethodHandle_stack_pushes(oop mh) { 67.286 + if (mh->klass() == SystemDictionary::DirectMethodHandle_klass()) 67.287 + return 0; // no push/pop 67.288 + int this_vmslots = java_dyn_MethodHandle::vmslots(mh); 67.289 + int last_vmslots = 0; 67.290 + oop last_mh = mh; 67.291 + for (;;) { 67.292 + oop target = java_dyn_MethodHandle::vmtarget(last_mh); 67.293 + if (target->klass() == SystemDictionary::DirectMethodHandle_klass()) { 67.294 + last_vmslots = java_dyn_MethodHandle::vmslots(target); 67.295 + break; 67.296 + } else if (!java_dyn_MethodHandle::is_instance(target)) { 67.297 + // might be klass or method 67.298 + assert(target->is_method(), "must get here with a direct ref to method"); 67.299 + last_vmslots = methodOop(target)->size_of_parameters(); 67.300 + break; 67.301 + } 67.302 + last_mh = target; 67.303 + } 67.304 + // If I am called with fewer VM slots than my ultimate callee, 67.305 + // it must be that I push the additionally needed slots. 67.306 + // Likewise if am called with more VM slots, I will pop them. 67.307 + return (last_vmslots - this_vmslots); 67.308 +} 67.309 + 67.310 + 67.311 +// MemberName support 67.312 + 67.313 +// import sun_dyn_MemberName.* 67.314 +enum { 67.315 + IS_METHOD = sun_dyn_MemberName::MN_IS_METHOD, 67.316 + IS_CONSTRUCTOR = sun_dyn_MemberName::MN_IS_CONSTRUCTOR, 67.317 + IS_FIELD = sun_dyn_MemberName::MN_IS_FIELD, 67.318 + IS_TYPE = sun_dyn_MemberName::MN_IS_TYPE, 67.319 + SEARCH_SUPERCLASSES = sun_dyn_MemberName::MN_SEARCH_SUPERCLASSES, 67.320 + SEARCH_INTERFACES = sun_dyn_MemberName::MN_SEARCH_INTERFACES, 67.321 + ALL_KINDS = IS_METHOD | IS_CONSTRUCTOR | IS_FIELD | IS_TYPE, 67.322 + VM_INDEX_UNINITIALIZED = sun_dyn_MemberName::VM_INDEX_UNINITIALIZED 67.323 +}; 67.324 + 67.325 +void MethodHandles::init_MemberName(oop mname_oop, oop target_oop) { 67.326 + if (target_oop->klass() == SystemDictionary::reflect_field_klass()) { 67.327 + oop clazz = java_lang_reflect_Field::clazz(target_oop); // fd.field_holder() 67.328 + int slot = java_lang_reflect_Field::slot(target_oop); // fd.index() 67.329 + int mods = java_lang_reflect_Field::modifiers(target_oop); 67.330 + klassOop k = java_lang_Class::as_klassOop(clazz); 67.331 + int offset = instanceKlass::cast(k)->offset_from_fields(slot); 67.332 + init_MemberName(mname_oop, k, accessFlags_from(mods), offset); 67.333 + } else { 67.334 + int decode_flags = 0; klassOop receiver_limit = NULL; 67.335 + methodOop m = MethodHandles::decode_method(target_oop, 67.336 + receiver_limit, decode_flags); 67.337 + bool do_dispatch = ((decode_flags & MethodHandles::_dmf_does_dispatch) != 0); 67.338 + init_MemberName(mname_oop, m, do_dispatch); 67.339 + } 67.340 +} 67.341 + 67.342 +void MethodHandles::init_MemberName(oop mname_oop, methodOop m, bool do_dispatch) { 67.343 + int flags = ((m->is_initializer() ? IS_CONSTRUCTOR : IS_METHOD) 67.344 + | (jushort)( m->access_flags().as_short() & JVM_RECOGNIZED_METHOD_MODIFIERS )); 67.345 + oop vmtarget = m; 67.346 + int vmindex = methodOopDesc::invalid_vtable_index; // implies no info yet 67.347 + if (!do_dispatch || (flags & IS_CONSTRUCTOR) || m->can_be_statically_bound()) 67.348 + vmindex = methodOopDesc::nonvirtual_vtable_index; // implies never any dispatch 67.349 + assert(vmindex != VM_INDEX_UNINITIALIZED, "Java sentinel value"); 67.350 + sun_dyn_MemberName::set_vmtarget(mname_oop, vmtarget); 67.351 + sun_dyn_MemberName::set_vmindex(mname_oop, vmindex); 67.352 + sun_dyn_MemberName::set_flags(mname_oop, flags); 67.353 +} 67.354 + 67.355 +void MethodHandles::init_MemberName(oop mname_oop, klassOop field_holder, AccessFlags mods, int offset) { 67.356 + int flags = (IS_FIELD | (jushort)( mods.as_short() & JVM_RECOGNIZED_FIELD_MODIFIERS )); 67.357 + oop vmtarget = field_holder; 67.358 + int vmindex = offset; // implies no info yet 67.359 + assert(vmindex != VM_INDEX_UNINITIALIZED, "bad alias on vmindex"); 67.360 + sun_dyn_MemberName::set_vmtarget(mname_oop, vmtarget); 67.361 + sun_dyn_MemberName::set_vmindex(mname_oop, vmindex); 67.362 + sun_dyn_MemberName::set_flags(mname_oop, flags); 67.363 +} 67.364 + 67.365 + 67.366 +methodOop MethodHandles::decode_MemberName(oop mname, klassOop& receiver_limit_result, int& decode_flags_result) { 67.367 + int flags = sun_dyn_MemberName::flags(mname); 67.368 + if ((flags & (IS_METHOD | IS_CONSTRUCTOR)) == 0) return NULL; // not invocable 67.369 + oop vmtarget = sun_dyn_MemberName::vmtarget(mname); 67.370 + int vmindex = sun_dyn_MemberName::vmindex(mname); 67.371 + if (vmindex == VM_INDEX_UNINITIALIZED) return NULL; // not resolved 67.372 + return decode_vmtarget(vmtarget, vmindex, NULL, receiver_limit_result, decode_flags_result); 67.373 +} 67.374 + 67.375 +// An unresolved member name is a mere symbolic reference. 67.376 +// Resolving it plants a vmtarget/vmindex in it, 67.377 +// which refers dirctly to JVM internals. 67.378 +void MethodHandles::resolve_MemberName(Handle mname, TRAPS) { 67.379 + assert(sun_dyn_MemberName::is_instance(mname()), ""); 67.380 +#ifdef ASSERT 67.381 + // If this assert throws, renegotiate the sentinel value used by the Java code, 67.382 + // so that it is distinct from any valid vtable index value, and any special 67.383 + // values defined in methodOopDesc::VtableIndexFlag. 67.384 + // The point of the slop is to give the Java code and the JVM some room 67.385 + // to independently specify sentinel values. 67.386 + const int sentinel_slop = 10; 67.387 + const int sentinel_limit = methodOopDesc::highest_unused_vtable_index_value - sentinel_slop; 67.388 + assert(VM_INDEX_UNINITIALIZED < sentinel_limit, "Java sentinel != JVM sentinels"); 67.389 +#endif 67.390 + if (sun_dyn_MemberName::vmindex(mname()) != VM_INDEX_UNINITIALIZED) 67.391 + return; // already resolved 67.392 + oop defc_oop = sun_dyn_MemberName::clazz(mname()); 67.393 + oop name_str = sun_dyn_MemberName::name(mname()); 67.394 + oop type_str = sun_dyn_MemberName::type(mname()); 67.395 + int flags = sun_dyn_MemberName::flags(mname()); 67.396 + 67.397 + if (defc_oop == NULL || name_str == NULL || type_str == NULL) { 67.398 + THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "nothing to resolve"); 67.399 + } 67.400 + klassOop defc_klassOop = java_lang_Class::as_klassOop(defc_oop); 67.401 + defc_oop = NULL; // safety 67.402 + if (defc_klassOop == NULL) return; // a primitive; no resolution possible 67.403 + if (!Klass::cast(defc_klassOop)->oop_is_instance()) { 67.404 + if (!Klass::cast(defc_klassOop)->oop_is_array()) return; 67.405 + defc_klassOop = SystemDictionary::object_klass(); 67.406 + } 67.407 + instanceKlassHandle defc(THREAD, defc_klassOop); 67.408 + defc_klassOop = NULL; // safety 67.409 + if (defc.is_null()) { 67.410 + THROW_MSG(vmSymbols::java_lang_InternalError(), "primitive class"); 67.411 + } 67.412 + defc->link_class(CHECK); 67.413 + 67.414 + // convert the external string name to an internal symbol 67.415 + symbolHandle name(THREAD, java_lang_String::as_symbol_or_null(name_str)); 67.416 + if (name.is_null()) return; // no such name 67.417 + name_str = NULL; // safety 67.418 + 67.419 + // convert the external string or reflective type to an internal signature 67.420 + bool force_signature = (name() == vmSymbols::invoke_name()); 67.421 + symbolHandle type; { 67.422 + symbolOop type_sym = NULL; 67.423 + if (java_dyn_MethodType::is_instance(type_str)) { 67.424 + type_sym = java_dyn_MethodType::as_signature(type_str, force_signature, CHECK); 67.425 + } else if (java_lang_Class::is_instance(type_str)) { 67.426 + type_sym = java_lang_Class::as_signature(type_str, force_signature, CHECK); 67.427 + } else if (java_lang_String::is_instance(type_str)) { 67.428 + if (force_signature) { 67.429 + type = java_lang_String::as_symbol(type_str, CHECK); 67.430 + } else { 67.431 + type_sym = java_lang_String::as_symbol_or_null(type_str); 67.432 + } 67.433 + } else { 67.434 + THROW_MSG(vmSymbols::java_lang_InternalError(), "unrecognized type"); 67.435 + } 67.436 + if (type_sym != NULL) 67.437 + type = symbolHandle(THREAD, type_sym); 67.438 + } 67.439 + if (type.is_null()) return; // no such signature exists in the VM 67.440 + type_str = NULL; // safety 67.441 + 67.442 + // Time to do the lookup. 67.443 + switch (flags & ALL_KINDS) { 67.444 + case IS_METHOD: 67.445 + { 67.446 + CallInfo result; 67.447 + { 67.448 + EXCEPTION_MARK; 67.449 + if ((flags & JVM_ACC_STATIC) != 0) { 67.450 + LinkResolver::resolve_static_call(result, 67.451 + defc, name, type, KlassHandle(), false, false, THREAD); 67.452 + } else if (defc->is_interface()) { 67.453 + LinkResolver::resolve_interface_call(result, Handle(), defc, 67.454 + defc, name, type, KlassHandle(), false, false, THREAD); 67.455 + } else { 67.456 + LinkResolver::resolve_virtual_call(result, Handle(), defc, 67.457 + defc, name, type, KlassHandle(), false, false, THREAD); 67.458 + } 67.459 + if (HAS_PENDING_EXCEPTION) { 67.460 + CLEAR_PENDING_EXCEPTION; 67.461 + return; 67.462 + } 67.463 + } 67.464 + methodHandle m = result.resolved_method(); 67.465 + oop vmtarget = NULL; 67.466 + int vmindex = methodOopDesc::nonvirtual_vtable_index; 67.467 + if (defc->is_interface()) { 67.468 + vmindex = klassItable::compute_itable_index(m()); 67.469 + assert(vmindex >= 0, ""); 67.470 + } else if (result.has_vtable_index()) { 67.471 + vmindex = result.vtable_index(); 67.472 + assert(vmindex >= 0, ""); 67.473 + } 67.474 + assert(vmindex != VM_INDEX_UNINITIALIZED, ""); 67.475 + if (vmindex < 0) { 67.476 + assert(result.is_statically_bound(), ""); 67.477 + vmtarget = m(); 67.478 + } else { 67.479 + vmtarget = result.resolved_klass()->as_klassOop(); 67.480 + } 67.481 + int mods = (m->access_flags().as_short() & JVM_RECOGNIZED_METHOD_MODIFIERS); 67.482 + sun_dyn_MemberName::set_vmtarget(mname(), vmtarget); 67.483 + sun_dyn_MemberName::set_vmindex(mname(), vmindex); 67.484 + sun_dyn_MemberName::set_modifiers(mname(), mods); 67.485 + DEBUG_ONLY(int junk; klassOop junk2); 67.486 + assert(decode_MemberName(mname(), junk2, junk) == result.resolved_method()(), 67.487 + "properly stored for later decoding"); 67.488 + return; 67.489 + } 67.490 + case IS_CONSTRUCTOR: 67.491 + { 67.492 + CallInfo result; 67.493 + { 67.494 + EXCEPTION_MARK; 67.495 + if (name() == vmSymbols::object_initializer_name()) { 67.496 + LinkResolver::resolve_special_call(result, 67.497 + defc, name, type, KlassHandle(), false, THREAD); 67.498 + } else { 67.499 + break; // will throw after end of switch 67.500 + } 67.501 + if (HAS_PENDING_EXCEPTION) { 67.502 + CLEAR_PENDING_EXCEPTION; 67.503 + return; 67.504 + } 67.505 + } 67.506 + assert(result.is_statically_bound(), ""); 67.507 + methodHandle m = result.resolved_method(); 67.508 + oop vmtarget = m(); 67.509 + int vmindex = methodOopDesc::nonvirtual_vtable_index; 67.510 + int mods = (m->access_flags().as_short() & JVM_RECOGNIZED_METHOD_MODIFIERS); 67.511 + sun_dyn_MemberName::set_vmtarget(mname(), vmtarget); 67.512 + sun_dyn_MemberName::set_vmindex(mname(), vmindex); 67.513 + sun_dyn_MemberName::set_modifiers(mname(), mods); 67.514 + DEBUG_ONLY(int junk; klassOop junk2); 67.515 + assert(decode_MemberName(mname(), junk2, junk) == result.resolved_method()(), 67.516 + "properly stored for later decoding"); 67.517 + return; 67.518 + } 67.519 + case IS_FIELD: 67.520 + { 67.521 + // This is taken from LinkResolver::resolve_field, sans access checks. 67.522 + fieldDescriptor fd; // find_field initializes fd if found 67.523 + KlassHandle sel_klass(THREAD, instanceKlass::cast(defc())->find_field(name(), type(), &fd)); 67.524 + // check if field exists; i.e., if a klass containing the field def has been selected 67.525 + if (sel_klass.is_null()) return; 67.526 + oop vmtarget = sel_klass->as_klassOop(); 67.527 + int vmindex = fd.offset(); 67.528 + int mods = (fd.access_flags().as_short() & JVM_RECOGNIZED_FIELD_MODIFIERS); 67.529 + if (vmindex == VM_INDEX_UNINITIALIZED) break; // should not happen 67.530 + sun_dyn_MemberName::set_vmtarget(mname(), vmtarget); 67.531 + sun_dyn_MemberName::set_vmindex(mname(), vmindex); 67.532 + sun_dyn_MemberName::set_modifiers(mname(), mods); 67.533 + return; 67.534 + } 67.535 + } 67.536 + THROW_MSG(vmSymbols::java_lang_InternalError(), "unrecognized MemberName format"); 67.537 +} 67.538 + 67.539 +// Conversely, a member name which is only initialized from JVM internals 67.540 +// may have null defc, name, and type fields. 67.541 +// Resolving it plants a vmtarget/vmindex in it, 67.542 +// which refers directly to JVM internals. 67.543 +void MethodHandles::expand_MemberName(Handle mname, int suppress, TRAPS) { 67.544 + assert(sun_dyn_MemberName::is_instance(mname()), ""); 67.545 + oop vmtarget = sun_dyn_MemberName::vmtarget(mname()); 67.546 + int vmindex = sun_dyn_MemberName::vmindex(mname()); 67.547 + if (vmtarget == NULL || vmindex == VM_INDEX_UNINITIALIZED) { 67.548 + THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "nothing to expand"); 67.549 + } 67.550 + 67.551 + bool have_defc = (sun_dyn_MemberName::clazz(mname()) != NULL); 67.552 + bool have_name = (sun_dyn_MemberName::name(mname()) != NULL); 67.553 + bool have_type = (sun_dyn_MemberName::type(mname()) != NULL); 67.554 + int flags = sun_dyn_MemberName::flags(mname()); 67.555 + 67.556 + if (suppress != 0) { 67.557 + if (suppress & _suppress_defc) have_defc = true; 67.558 + if (suppress & _suppress_name) have_name = true; 67.559 + if (suppress & _suppress_type) have_type = true; 67.560 + } 67.561 + 67.562 + if (have_defc && have_name && have_type) return; // nothing needed 67.563 + 67.564 + switch (flags & ALL_KINDS) { 67.565 + case IS_METHOD: 67.566 + case IS_CONSTRUCTOR: 67.567 + { 67.568 + klassOop receiver_limit = NULL; 67.569 + int decode_flags = 0; 67.570 + methodHandle m(THREAD, decode_vmtarget(vmtarget, vmindex, NULL, 67.571 + receiver_limit, decode_flags)); 67.572 + if (m.is_null()) break; 67.573 + if (!have_defc) { 67.574 + klassOop defc = m->method_holder(); 67.575 + if (receiver_limit != NULL && receiver_limit != defc 67.576 + && Klass::cast(receiver_limit)->is_subtype_of(defc)) 67.577 + defc = receiver_limit; 67.578 + sun_dyn_MemberName::set_clazz(mname(), Klass::cast(defc)->java_mirror()); 67.579 + } 67.580 + if (!have_name) { 67.581 + //not java_lang_String::create_from_symbol; let's intern member names 67.582 + Handle name = StringTable::intern(m->name(), CHECK); 67.583 + sun_dyn_MemberName::set_name(mname(), name()); 67.584 + } 67.585 + if (!have_type) { 67.586 + Handle type = java_lang_String::create_from_symbol(m->signature(), CHECK); 67.587 + sun_dyn_MemberName::set_type(mname(), type()); 67.588 + } 67.589 + return; 67.590 + } 67.591 + case IS_FIELD: 67.592 + { 67.593 + // This is taken from LinkResolver::resolve_field, sans access checks. 67.594 + if (!vmtarget->is_klass()) break; 67.595 + if (!Klass::cast((klassOop) vmtarget)->oop_is_instance()) break; 67.596 + instanceKlassHandle defc(THREAD, (klassOop) vmtarget); 67.597 + bool is_static = ((flags & JVM_ACC_STATIC) != 0); 67.598 + fieldDescriptor fd; // find_field initializes fd if found 67.599 + if (!defc->find_field_from_offset(vmindex, is_static, &fd)) 67.600 + break; // cannot expand 67.601 + if (!have_defc) { 67.602 + sun_dyn_MemberName::set_clazz(mname(), defc->java_mirror()); 67.603 + } 67.604 + if (!have_name) { 67.605 + //not java_lang_String::create_from_symbol; let's intern member names 67.606 + Handle name = StringTable::intern(fd.name(), CHECK); 67.607 + sun_dyn_MemberName::set_name(mname(), name()); 67.608 + } 67.609 + if (!have_type) { 67.610 + Handle type = java_lang_String::create_from_symbol(fd.signature(), CHECK); 67.611 + sun_dyn_MemberName::set_type(mname(), type()); 67.612 + } 67.613 + return; 67.614 + } 67.615 + } 67.616 + THROW_MSG(vmSymbols::java_lang_InternalError(), "unrecognized MemberName format"); 67.617 +} 67.618 + 67.619 +int MethodHandles::find_MemberNames(klassOop k, 67.620 + symbolOop name, symbolOop sig, 67.621 + int mflags, klassOop caller, 67.622 + int skip, objArrayOop results) { 67.623 + DEBUG_ONLY(No_Safepoint_Verifier nsv); 67.624 + // this code contains no safepoints! 67.625 + 67.626 + // %%% take caller into account! 67.627 + 67.628 + if (k == NULL || !Klass::cast(k)->oop_is_instance()) return -1; 67.629 + 67.630 + int rfill = 0, rlimit = results->length(), rskip = skip; 67.631 + // overflow measurement: 67.632 + int overflow = 0, overflow_limit = MAX2(1000, rlimit); 67.633 + 67.634 + int match_flags = mflags; 67.635 + bool search_superc = ((match_flags & SEARCH_SUPERCLASSES) != 0); 67.636 + bool search_intfc = ((match_flags & SEARCH_INTERFACES) != 0); 67.637 + bool local_only = !(search_superc | search_intfc); 67.638 + bool classes_only = false; 67.639 + 67.640 + if (name != NULL) { 67.641 + if (name->utf8_length() == 0) return 0; // a match is not possible 67.642 + } 67.643 + if (sig != NULL) { 67.644 + if (sig->utf8_length() == 0) return 0; // a match is not possible 67.645 + if (sig->byte_at(0) == '(') 67.646 + match_flags &= ~(IS_FIELD | IS_TYPE); 67.647 + else 67.648 + match_flags &= ~(IS_CONSTRUCTOR | IS_METHOD); 67.649 + } 67.650 + 67.651 + if ((match_flags & IS_TYPE) != 0) { 67.652 + // NYI, and Core Reflection works quite well for this query 67.653 + } 67.654 + 67.655 + if ((match_flags & IS_FIELD) != 0) { 67.656 + for (FieldStream st(k, local_only, !search_intfc); !st.eos(); st.next()) { 67.657 + if (name != NULL && st.name() != name) 67.658 + continue; 67.659 + if (sig != NULL && st.signature() != sig) 67.660 + continue; 67.661 + // passed the filters 67.662 + if (rskip > 0) { 67.663 + --rskip; 67.664 + } else if (rfill < rlimit) { 67.665 + oop result = results->obj_at(rfill++); 67.666 + if (!sun_dyn_MemberName::is_instance(result)) 67.667 + return -99; // caller bug! 67.668 + MethodHandles::init_MemberName(result, st.klass()->as_klassOop(), st.access_flags(), st.offset()); 67.669 + } else if (++overflow >= overflow_limit) { 67.670 + match_flags = 0; break; // got tired of looking at overflow 67.671 + } 67.672 + } 67.673 + } 67.674 + 67.675 + if ((match_flags & (IS_METHOD | IS_CONSTRUCTOR)) != 0) { 67.676 + // watch out for these guys: 67.677 + symbolOop init_name = vmSymbols::object_initializer_name(); 67.678 + symbolOop clinit_name = vmSymbols::class_initializer_name(); 67.679 + if (name == clinit_name) clinit_name = NULL; // hack for exposing <clinit> 67.680 + bool negate_name_test = false; 67.681 + // fix name so that it captures the intention of IS_CONSTRUCTOR 67.682 + if (!(match_flags & IS_METHOD)) { 67.683 + // constructors only 67.684 + if (name == NULL) { 67.685 + name = init_name; 67.686 + } else if (name != init_name) { 67.687 + return 0; // no constructors of this method name 67.688 + } 67.689 + } else if (!(match_flags & IS_CONSTRUCTOR)) { 67.690 + // methods only 67.691 + if (name == NULL) { 67.692 + name = init_name; 67.693 + negate_name_test = true; // if we see the name, we *omit* the entry 67.694 + } else if (name == init_name) { 67.695 + return 0; // no methods of this constructor name 67.696 + } 67.697 + } else { 67.698 + // caller will accept either sort; no need to adjust name 67.699 + } 67.700 + for (MethodStream st(k, local_only, !search_intfc); !st.eos(); st.next()) { 67.701 + methodOop m = st.method(); 67.702 + symbolOop m_name = m->name(); 67.703 + if (m_name == clinit_name) 67.704 + continue; 67.705 + if (name != NULL && ((m_name != name) ^ negate_name_test)) 67.706 + continue; 67.707 + if (sig != NULL && m->signature() != sig) 67.708 + continue; 67.709 + // passed the filters 67.710 + if (rskip > 0) { 67.711 + --rskip; 67.712 + } else if (rfill < rlimit) { 67.713 + oop result = results->obj_at(rfill++); 67.714 + if (!sun_dyn_MemberName::is_instance(result)) 67.715 + return -99; // caller bug! 67.716 + MethodHandles::init_MemberName(result, m, true); 67.717 + } else if (++overflow >= overflow_limit) { 67.718 + match_flags = 0; break; // got tired of looking at overflow 67.719 + } 67.720 + } 67.721 + } 67.722 + 67.723 + // return number of elements we at leasted wanted to initialize 67.724 + return rfill + overflow; 67.725 +} 67.726 + 67.727 + 67.728 + 67.729 + 67.730 +// Decode the vmtarget field of a method handle. 67.731 +// Sanitize out methodOops, klassOops, and any other non-Java data. 67.732 +// This is for debugging and reflection. 67.733 +oop MethodHandles::encode_target(Handle mh, int format, TRAPS) { 67.734 + assert(java_dyn_MethodHandle::is_instance(mh()), "must be a MH"); 67.735 + if (format == ETF_HANDLE_OR_METHOD_NAME) { 67.736 + oop target = java_dyn_MethodHandle::vmtarget(mh()); 67.737 + if (target == NULL) { 67.738 + return NULL; // unformed MH 67.739 + } 67.740 + klassOop tklass = target->klass(); 67.741 + if (Klass::cast(tklass)->is_subclass_of(SystemDictionary::object_klass())) { 67.742 + return target; // target is another MH (or something else?) 67.743 + } 67.744 + } 67.745 + if (format == ETF_DIRECT_HANDLE) { 67.746 + oop target = mh(); 67.747 + for (;;) { 67.748 + if (target->klass() == SystemDictionary::DirectMethodHandle_klass()) { 67.749 + return target; 67.750 + } 67.751 + if (!java_dyn_MethodHandle::is_instance(target)){ 67.752 + return NULL; // unformed MH 67.753 + } 67.754 + target = java_dyn_MethodHandle::vmtarget(target); 67.755 + } 67.756 + } 67.757 + // cases of metadata in MH.vmtarget: 67.758 + // - AMH can have methodOop for static invoke with bound receiver 67.759 + // - DMH can have methodOop for static invoke (on variable receiver) 67.760 + // - DMH can have klassOop for dispatched (non-static) invoke 67.761 + klassOop receiver_limit = NULL; 67.762 + int decode_flags = 0; 67.763 + methodOop m = decode_MethodHandle(mh(), receiver_limit, decode_flags); 67.764 + if (m == NULL) return NULL; 67.765 + switch (format) { 67.766 + case ETF_REFLECT_METHOD: 67.767 + // same as jni_ToReflectedMethod: 67.768 + if (m->is_initializer()) { 67.769 + return Reflection::new_constructor(m, THREAD); 67.770 + } else { 67.771 + return Reflection::new_method(m, UseNewReflection, false, THREAD); 67.772 + } 67.773 + 67.774 + case ETF_HANDLE_OR_METHOD_NAME: // method, not handle 67.775 + case ETF_METHOD_NAME: 67.776 + { 67.777 + if (SystemDictionary::MemberName_klass() == NULL) break; 67.778 + instanceKlassHandle mname_klass(THREAD, SystemDictionary::MemberName_klass()); 67.779 + mname_klass->initialize(CHECK_NULL); 67.780 + Handle mname = mname_klass->allocate_instance_handle(CHECK_NULL); 67.781 + sun_dyn_MemberName::set_vmindex(mname(), VM_INDEX_UNINITIALIZED); 67.782 + bool do_dispatch = ((decode_flags & MethodHandles::_dmf_does_dispatch) != 0); 67.783 + init_MemberName(mname(), m, do_dispatch); 67.784 + expand_MemberName(mname, 0, CHECK_NULL); 67.785 + return mname(); 67.786 + } 67.787 + } 67.788 + 67.789 + // Unknown format code. 67.790 + char msg[50]; 67.791 + jio_snprintf(msg, sizeof(msg), "unknown getTarget format=%d", format); 67.792 + THROW_MSG_NULL(vmSymbols::java_lang_IllegalArgumentException(), msg); 67.793 +} 67.794 + 67.795 +bool MethodHandles::class_cast_needed(klassOop src, klassOop dst) { 67.796 + if (src == dst || dst == SystemDictionary::object_klass()) 67.797 + return false; // quickest checks 67.798 + Klass* srck = Klass::cast(src); 67.799 + Klass* dstk = Klass::cast(dst); 67.800 + if (dstk->is_interface()) { 67.801 + // interface receivers can safely be viewed as untyped, 67.802 + // because interface calls always include a dynamic check 67.803 + //dstk = Klass::cast(SystemDictionary::object_klass()); 67.804 + return false; 67.805 + } 67.806 + if (srck->is_interface()) { 67.807 + // interface arguments must be viewed as untyped 67.808 + //srck = Klass::cast(SystemDictionary::object_klass()); 67.809 + return true; 67.810 + } 67.811 + return !srck->is_subclass_of(dstk->as_klassOop()); 67.812 +} 67.813 + 67.814 +static oop object_java_mirror() { 67.815 + return Klass::cast(SystemDictionary::object_klass())->java_mirror(); 67.816 +} 67.817 + 67.818 +bool MethodHandles::same_basic_type_for_arguments(BasicType src, 67.819 + BasicType dst, 67.820 + bool for_return) { 67.821 + // return values can always be forgotten: 67.822 + if (for_return && dst == T_VOID) return true; 67.823 + assert(src != T_VOID && dst != T_VOID, "should not be here"); 67.824 + if (src == dst) return true; 67.825 + if (type2size[src] != type2size[dst]) return false; 67.826 + // allow reinterpretation casts for integral widening 67.827 + if (is_subword_type(src)) { // subwords can fit in int or other subwords 67.828 + if (dst == T_INT) // any subword fits in an int 67.829 + return true; 67.830 + if (src == T_BOOLEAN) // boolean fits in any subword 67.831 + return is_subword_type(dst); 67.832 + if (src == T_BYTE && dst == T_SHORT) 67.833 + return true; // remaining case: byte fits in short 67.834 + } 67.835 + // allow float/fixed reinterpretation casts 67.836 + if (src == T_FLOAT) return dst == T_INT; 67.837 + if (src == T_INT) return dst == T_FLOAT; 67.838 + if (src == T_DOUBLE) return dst == T_LONG; 67.839 + if (src == T_LONG) return dst == T_DOUBLE; 67.840 + return false; 67.841 +} 67.842 + 67.843 +const char* MethodHandles::check_method_receiver(methodOop m, 67.844 + klassOop passed_recv_type) { 67.845 + assert(!m->is_static(), "caller resp."); 67.846 + if (passed_recv_type == NULL) 67.847 + return "receiver type is primitive"; 67.848 + if (class_cast_needed(passed_recv_type, m->method_holder())) { 67.849 + Klass* formal = Klass::cast(m->method_holder()); 67.850 + return SharedRuntime::generate_class_cast_message("receiver type", 67.851 + formal->external_name()); 67.852 + } 67.853 + return NULL; // checks passed 67.854 +} 67.855 + 67.856 +// Verify that m's signature can be called type-safely by a method handle 67.857 +// of the given method type 'mtype'. 67.858 +// It takes a TRAPS argument because it must perform symbol lookups. 67.859 +void MethodHandles::verify_method_signature(methodHandle m, 67.860 + Handle mtype, 67.861 + int first_ptype_pos, 67.862 + KlassHandle insert_ptype, 67.863 + TRAPS) { 67.864 + objArrayHandle ptypes(THREAD, java_dyn_MethodType::ptypes(mtype())); 67.865 + int pnum = first_ptype_pos; 67.866 + int pmax = ptypes->length(); 67.867 + int mnum = 0; // method argument 67.868 + const char* err = NULL; 67.869 + for (SignatureStream ss(m->signature()); !ss.is_done(); ss.next()) { 67.870 + oop ptype_oop = NULL; 67.871 + if (ss.at_return_type()) { 67.872 + if (pnum != pmax) 67.873 + { err = "too many arguments"; break; } 67.874 + ptype_oop = java_dyn_MethodType::rtype(mtype()); 67.875 + } else { 67.876 + if (pnum >= pmax) 67.877 + { err = "not enough arguments"; break; } 67.878 + if (pnum >= 0) 67.879 + ptype_oop = ptypes->obj_at(pnum); 67.880 + else if (insert_ptype.is_null()) 67.881 + ptype_oop = NULL; 67.882 + else 67.883 + ptype_oop = insert_ptype->java_mirror(); 67.884 + pnum += 1; 67.885 + mnum += 1; 67.886 + } 67.887 + klassOop mklass = NULL; 67.888 + BasicType mtype = ss.type(); 67.889 + if (mtype == T_ARRAY) mtype = T_OBJECT; // fold all refs to T_OBJECT 67.890 + if (mtype == T_OBJECT) { 67.891 + if (ptype_oop == NULL) { 67.892 + // null matches any reference 67.893 + continue; 67.894 + } 67.895 + // If we fail to resolve types at this point, we will throw an error. 67.896 + symbolOop name_oop = ss.as_symbol(CHECK); 67.897 + symbolHandle name(THREAD, name_oop); 67.898 + instanceKlass* mk = instanceKlass::cast(m->method_holder()); 67.899 + Handle loader(THREAD, mk->class_loader()); 67.900 + Handle domain(THREAD, mk->protection_domain()); 67.901 + mklass = SystemDictionary::resolve_or_fail(name, loader, domain, 67.902 + true, CHECK); 67.903 + } 67.904 + if (ptype_oop == NULL) { 67.905 + // null does not match any non-reference; use Object to report the error 67.906 + ptype_oop = object_java_mirror(); 67.907 + } 67.908 + klassOop pklass = NULL; 67.909 + BasicType ptype = java_lang_Class::as_BasicType(ptype_oop, &pklass); 67.910 + if (!ss.at_return_type()) { 67.911 + err = check_argument_type_change(ptype, pklass, mtype, mklass, mnum); 67.912 + } else { 67.913 + err = check_return_type_change(mtype, mklass, ptype, pklass); // note reversal! 67.914 + } 67.915 + if (err != NULL) break; 67.916 + } 67.917 + 67.918 + if (err != NULL) { 67.919 + THROW_MSG(vmSymbols::java_lang_InternalError(), err); 67.920 + } 67.921 +} 67.922 + 67.923 +// Main routine for verifying the MethodHandle.type of a proposed 67.924 +// direct or bound-direct method handle. 67.925 +void MethodHandles::verify_method_type(methodHandle m, 67.926 + Handle mtype, 67.927 + bool has_bound_recv, 67.928 + KlassHandle bound_recv_type, 67.929 + TRAPS) { 67.930 + bool m_needs_receiver = !m->is_static(); 67.931 + 67.932 + const char* err = NULL; 67.933 + 67.934 + int first_ptype_pos = m_needs_receiver ? 1 : 0; 67.935 + if (has_bound_recv && err == NULL) { 67.936 + first_ptype_pos -= 1; 67.937 + if (m_needs_receiver && bound_recv_type.is_null()) 67.938 + { err = "bound receiver is not an object"; goto die; } 67.939 + } 67.940 + 67.941 + if (m_needs_receiver && err == NULL) { 67.942 + objArrayOop ptypes = java_dyn_MethodType::ptypes(mtype()); 67.943 + if (ptypes->length() < first_ptype_pos) 67.944 + { err = "receiver argument is missing"; goto die; } 67.945 + if (first_ptype_pos == -1) 67.946 + err = check_method_receiver(m(), bound_recv_type->as_klassOop()); 67.947 + else 67.948 + err = check_method_receiver(m(), java_lang_Class::as_klassOop(ptypes->obj_at(0))); 67.949 + if (err != NULL) goto die; 67.950 + } 67.951 + 67.952 + // Check the other arguments for mistypes. 67.953 + verify_method_signature(m, mtype, first_ptype_pos, bound_recv_type, CHECK); 67.954 + return; 67.955 + 67.956 + die: 67.957 + THROW_MSG(vmSymbols::java_lang_InternalError(), err); 67.958 +} 67.959 + 67.960 +void MethodHandles::verify_vmslots(Handle mh, TRAPS) { 67.961 + // Verify vmslots. 67.962 + int check_slots = argument_slot_count(java_dyn_MethodHandle::type(mh())); 67.963 + if (java_dyn_MethodHandle::vmslots(mh()) != check_slots) { 67.964 + THROW_MSG(vmSymbols::java_lang_InternalError(), "bad vmslots in BMH"); 67.965 + } 67.966 +} 67.967 + 67.968 +void MethodHandles::verify_vmargslot(Handle mh, int argnum, int argslot, TRAPS) { 67.969 + // Verify that argslot points at the given argnum. 67.970 + int check_slot = argument_slot(java_dyn_MethodHandle::type(mh()), argnum); 67.971 + if (argslot != check_slot || argslot < 0) { 67.972 + const char* fmt = "for argnum of %d, vmargslot is %d, should be %d"; 67.973 + size_t msglen = strlen(fmt) + 3*11 + 1; 67.974 + char* msg = NEW_RESOURCE_ARRAY(char, msglen); 67.975 + jio_snprintf(msg, msglen, fmt, argnum, argslot, check_slot); 67.976 + THROW_MSG(vmSymbols::java_lang_InternalError(), msg); 67.977 + } 67.978 +} 67.979 + 67.980 +// Verify the correspondence between two method types. 67.981 +// Apart from the advertised changes, caller method type X must 67.982 +// be able to invoke the callee method Y type with no violations 67.983 +// of type integrity. 67.984 +// Return NULL if all is well, else a short error message. 67.985 +const char* MethodHandles::check_method_type_change(oop src_mtype, int src_beg, int src_end, 67.986 + int insert_argnum, oop insert_type, 67.987 + int change_argnum, oop change_type, 67.988 + int delete_argnum, 67.989 + oop dst_mtype, int dst_beg, int dst_end) { 67.990 + objArrayOop src_ptypes = java_dyn_MethodType::ptypes(src_mtype); 67.991 + objArrayOop dst_ptypes = java_dyn_MethodType::ptypes(dst_mtype); 67.992 + 67.993 + int src_max = src_ptypes->length(); 67.994 + int dst_max = dst_ptypes->length(); 67.995 + 67.996 + if (src_end == -1) src_end = src_max; 67.997 + if (dst_end == -1) dst_end = dst_max; 67.998 + 67.999 + assert(0 <= src_beg && src_beg <= src_end && src_end <= src_max, "oob"); 67.1000 + assert(0 <= dst_beg && dst_beg <= dst_end && dst_end <= dst_max, "oob"); 67.1001 + 67.1002 + // pending actions; set to -1 when done: 67.1003 + int ins_idx = insert_argnum, chg_idx = change_argnum, del_idx = delete_argnum; 67.1004 + 67.1005 + const char* err = NULL; 67.1006 + 67.1007 + // Walk along each array of parameter types, including a virtual 67.1008 + // NULL end marker at the end of each. 67.1009 + for (int src_idx = src_beg, dst_idx = dst_beg; 67.1010 + (src_idx <= src_end && dst_idx <= dst_end); 67.1011 + src_idx++, dst_idx++) { 67.1012 + oop src_type = (src_idx == src_end) ? oop(NULL) : src_ptypes->obj_at(src_idx); 67.1013 + oop dst_type = (dst_idx == dst_end) ? oop(NULL) : dst_ptypes->obj_at(dst_idx); 67.1014 + bool fix_null_src_type = false; 67.1015 + 67.1016 + // Perform requested edits. 67.1017 + if (ins_idx == src_idx) { 67.1018 + // note that the inserted guy is never affected by a change or deletion 67.1019 + ins_idx = -1; 67.1020 + src_type = insert_type; 67.1021 + fix_null_src_type = true; 67.1022 + --src_idx; // back up to process src type on next loop 67.1023 + src_idx = src_end; 67.1024 + } else { 67.1025 + // note that the changed guy can be immediately deleted 67.1026 + if (chg_idx == src_idx) { 67.1027 + chg_idx = -1; 67.1028 + assert(src_idx < src_end, "oob"); 67.1029 + src_type = change_type; 67.1030 + fix_null_src_type = true; 67.1031 + } 67.1032 + if (del_idx == src_idx) { 67.1033 + del_idx = -1; 67.1034 + assert(src_idx < src_end, "oob"); 67.1035 + --dst_idx; 67.1036 + continue; // rerun loop after skipping this position 67.1037 + } 67.1038 + } 67.1039 + 67.1040 + if (src_type == NULL && fix_null_src_type) 67.1041 + // explicit null in this case matches any dest reference 67.1042 + src_type = (java_lang_Class::is_primitive(dst_type) ? object_java_mirror() : dst_type); 67.1043 + 67.1044 + // Compare the two argument types. 67.1045 + if (src_type != dst_type) { 67.1046 + if (src_type == NULL) return "not enough arguments"; 67.1047 + if (dst_type == NULL) return "too many arguments"; 67.1048 + err = check_argument_type_change(src_type, dst_type, dst_idx); 67.1049 + if (err != NULL) return err; 67.1050 + } 67.1051 + } 67.1052 + 67.1053 + // Now compare return types also. 67.1054 + oop src_rtype = java_dyn_MethodType::rtype(src_mtype); 67.1055 + oop dst_rtype = java_dyn_MethodType::rtype(dst_mtype); 67.1056 + if (src_rtype != dst_rtype) { 67.1057 + err = check_return_type_change(dst_rtype, src_rtype); // note reversal! 67.1058 + if (err != NULL) return err; 67.1059 + } 67.1060 + 67.1061 + assert(err == NULL, ""); 67.1062 + return NULL; // all is well 67.1063 +} 67.1064 + 67.1065 + 67.1066 +const char* MethodHandles::check_argument_type_change(BasicType src_type, 67.1067 + klassOop src_klass, 67.1068 + BasicType dst_type, 67.1069 + klassOop dst_klass, 67.1070 + int argnum) { 67.1071 + const char* err = NULL; 67.1072 + 67.1073 + // just in case: 67.1074 + if (src_type == T_ARRAY) src_type = T_OBJECT; 67.1075 + if (dst_type == T_ARRAY) dst_type = T_OBJECT; 67.1076 + 67.1077 + // Produce some nice messages if VerifyMethodHandles is turned on: 67.1078 + if (!same_basic_type_for_arguments(src_type, dst_type, (argnum < 0))) { 67.1079 + if (src_type == T_OBJECT) { 67.1080 + err = ((argnum >= 0) 67.1081 + ? "type mismatch: passing a %s for method argument #%d, which expects primitive %s" 67.1082 + : "type mismatch: returning a %s, but caller expects primitive %s"); 67.1083 + } else if (dst_type == T_OBJECT) { 67.1084 + err = ((argnum < 0) 67.1085 + ? "type mismatch: passing a primitive %s for method argument #%d, which expects %s" 67.1086 + : "type mismatch: returning a primitive %s, but caller expects %s"); 67.1087 + } else { 67.1088 + err = ((argnum < 0) 67.1089 + ? "type mismatch: passing a %s for method argument #%d, which expects %s" 67.1090 + : "type mismatch: returning a %s, but caller expects %s"); 67.1091 + } 67.1092 + } else if (src_type == T_OBJECT && class_cast_needed(src_klass, dst_klass)) { 67.1093 + if (!class_cast_needed(dst_klass, src_klass)) { 67.1094 + err = ((argnum < 0) 67.1095 + ? "cast required: passing a %s for method argument #%d, which expects %s" 67.1096 + : "cast required: returning a %s, but caller expects %s"); 67.1097 + } else { 67.1098 + err = ((argnum < 0) 67.1099 + ? "reference mismatch: passing a %s for method argument #%d, which expects %s" 67.1100 + : "reference mismatch: returning a %s, but caller expects %s"); 67.1101 + } 67.1102 + } else { 67.1103 + // passed the obstacle course 67.1104 + return NULL; 67.1105 + } 67.1106 + 67.1107 + // format, format, format 67.1108 + const char* src_name = type2name(src_type); 67.1109 + const char* dst_name = type2name(dst_type); 67.1110 + if (src_type == T_OBJECT) src_name = Klass::cast(src_klass)->external_name(); 67.1111 + if (dst_type == T_OBJECT) dst_name = Klass::cast(dst_klass)->external_name(); 67.1112 + if (src_name == NULL) src_name = "unknown type"; 67.1113 + if (dst_name == NULL) dst_name = "unknown type"; 67.1114 + 67.1115 + size_t msglen = strlen(err) + strlen(src_name) + strlen(dst_name) + (argnum < 10 ? 1 : 11); 67.1116 + char* msg = NEW_RESOURCE_ARRAY(char, msglen + 1); 67.1117 + if (argnum >= 0) { 67.1118 + assert(strstr(err, "%d") != NULL, ""); 67.1119 + jio_snprintf(msg, msglen, err, src_name, argnum, dst_name); 67.1120 + } else { 67.1121 + assert(strstr(err, "%d") == NULL, ""); 67.1122 + jio_snprintf(msg, msglen, err, src_name, dst_name); 67.1123 + } 67.1124 + return msg; 67.1125 +} 67.1126 + 67.1127 +// Compute the depth within the stack of the given argument, i.e., 67.1128 +// the combined size of arguments to the right of the given argument. 67.1129 +// For the last argument (ptypes.length-1) this will be zero. 67.1130 +// For the first argument (0) this will be the size of all 67.1131 +// arguments but that one. For the special number -1, this 67.1132 +// will be the size of all arguments, including the first. 67.1133 +// If the argument is neither -1 nor a valid argument index, 67.1134 +// then return a negative number. Otherwise, the result 67.1135 +// is in the range [0..vmslots] inclusive. 67.1136 +int MethodHandles::argument_slot(oop method_type, int arg) { 67.1137 + objArrayOop ptypes = java_dyn_MethodType::ptypes(method_type); 67.1138 + int argslot = 0; 67.1139 + int len = ptypes->length(); 67.1140 + if (arg < -1 || arg >= len) return -99; 67.1141 + for (int i = len-1; i > arg; i--) { 67.1142 + BasicType bt = java_lang_Class::as_BasicType(ptypes->obj_at(i)); 67.1143 + argslot += type2size[bt]; 67.1144 + } 67.1145 + assert(argument_slot_to_argnum(method_type, argslot) == arg, "inverse works"); 67.1146 + return argslot; 67.1147 +} 67.1148 + 67.1149 +// Given a slot number, return the argument number. 67.1150 +int MethodHandles::argument_slot_to_argnum(oop method_type, int query_argslot) { 67.1151 + objArrayOop ptypes = java_dyn_MethodType::ptypes(method_type); 67.1152 + int argslot = 0; 67.1153 + int len = ptypes->length(); 67.1154 + for (int i = len-1; i >= 0; i--) { 67.1155 + if (query_argslot == argslot) return i; 67.1156 + BasicType bt = java_lang_Class::as_BasicType(ptypes->obj_at(i)); 67.1157 + argslot += type2size[bt]; 67.1158 + } 67.1159 + // return pseudo-arg deepest in stack: 67.1160 + if (query_argslot == argslot) return -1; 67.1161 + return -99; // oob slot, or splitting a double-slot arg 67.1162 +} 67.1163 + 67.1164 +methodHandle MethodHandles::dispatch_decoded_method(methodHandle m, 67.1165 + KlassHandle receiver_limit, 67.1166 + int decode_flags, 67.1167 + KlassHandle receiver_klass, 67.1168 + TRAPS) { 67.1169 + assert((decode_flags & ~_DMF_DIRECT_MASK) == 0, "must be direct method reference"); 67.1170 + assert((decode_flags & _dmf_has_receiver) != 0, "must have a receiver or first reference argument"); 67.1171 + 67.1172 + if (!m->is_static() && 67.1173 + (receiver_klass.is_null() || !receiver_klass->is_subtype_of(m->method_holder()))) 67.1174 + // given type does not match class of method, or receiver is null! 67.1175 + // caller should have checked this, but let's be extra careful... 67.1176 + return methodHandle(); 67.1177 + 67.1178 + if (receiver_limit.not_null() && 67.1179 + (receiver_klass.not_null() && !receiver_klass->is_subtype_of(receiver_limit()))) 67.1180 + // given type is not limited to the receiver type 67.1181 + // note that a null receiver can match any reference value, for a static method 67.1182 + return methodHandle(); 67.1183 + 67.1184 + if (!(decode_flags & MethodHandles::_dmf_does_dispatch)) { 67.1185 + // pre-dispatched or static method (null receiver is OK for static) 67.1186 + return m; 67.1187 + 67.1188 + } else if (receiver_klass.is_null()) { 67.1189 + // null receiver value; cannot dispatch 67.1190 + return methodHandle(); 67.1191 + 67.1192 + } else if (!(decode_flags & MethodHandles::_dmf_from_interface)) { 67.1193 + // perform virtual dispatch 67.1194 + int vtable_index = m->vtable_index(); 67.1195 + guarantee(vtable_index >= 0, "valid vtable index"); 67.1196 + 67.1197 + // receiver_klass might be an arrayKlassOop but all vtables start at 67.1198 + // the same place. The cast is to avoid virtual call and assertion. 67.1199 + // See also LinkResolver::runtime_resolve_virtual_method. 67.1200 + instanceKlass* inst = (instanceKlass*)Klass::cast(receiver_klass()); 67.1201 + DEBUG_ONLY(inst->verify_vtable_index(vtable_index)); 67.1202 + methodOop m_oop = inst->method_at_vtable(vtable_index); 67.1203 + return methodHandle(THREAD, m_oop); 67.1204 + 67.1205 + } else { 67.1206 + // perform interface dispatch 67.1207 + int itable_index = klassItable::compute_itable_index(m()); 67.1208 + guarantee(itable_index >= 0, "valid itable index"); 67.1209 + instanceKlass* inst = instanceKlass::cast(receiver_klass()); 67.1210 + methodOop m_oop = inst->method_at_itable(m->method_holder(), itable_index, THREAD); 67.1211 + return methodHandle(THREAD, m_oop); 67.1212 + } 67.1213 +} 67.1214 + 67.1215 +void MethodHandles::verify_DirectMethodHandle(Handle mh, methodHandle m, TRAPS) { 67.1216 + // Verify type. 67.1217 + Handle mtype(THREAD, java_dyn_MethodHandle::type(mh())); 67.1218 + verify_method_type(m, mtype, false, KlassHandle(), CHECK); 67.1219 + 67.1220 + // Verify vmslots. 67.1221 + if (java_dyn_MethodHandle::vmslots(mh()) != m->size_of_parameters()) { 67.1222 + THROW_MSG(vmSymbols::java_lang_InternalError(), "bad vmslots in DMH"); 67.1223 + } 67.1224 +} 67.1225 + 67.1226 +void MethodHandles::init_DirectMethodHandle(Handle mh, methodHandle m, bool do_dispatch, TRAPS) { 67.1227 + // Check arguments. 67.1228 + if (mh.is_null() || m.is_null() || 67.1229 + (!do_dispatch && m->is_abstract())) { 67.1230 + THROW(vmSymbols::java_lang_InternalError()); 67.1231 + } 67.1232 + 67.1233 + java_dyn_MethodHandle::init_vmslots(mh()); 67.1234 + 67.1235 + if (VerifyMethodHandles) { 67.1236 + // The privileged code which invokes this routine should not make 67.1237 + // a mistake about types, but it's better to verify. 67.1238 + verify_DirectMethodHandle(mh, m, CHECK); 67.1239 + } 67.1240 + 67.1241 + // Finally, after safety checks are done, link to the target method. 67.1242 + // We will follow the same path as the latter part of 67.1243 + // InterpreterRuntime::resolve_invoke(), which first finds the method 67.1244 + // and then decides how to populate the constant pool cache entry 67.1245 + // that links the interpreter calls to the method. We need the same 67.1246 + // bits, and will use the same calling sequence code. 67.1247 + 67.1248 + int vmindex = methodOopDesc::garbage_vtable_index; 67.1249 + oop vmtarget = NULL; 67.1250 + 67.1251 + instanceKlass::cast(m->method_holder())->link_class(CHECK); 67.1252 + 67.1253 + MethodHandleEntry* me = NULL; 67.1254 + if (do_dispatch && Klass::cast(m->method_holder())->is_interface()) { 67.1255 + // We are simulating an invokeinterface instruction. 67.1256 + // (We might also be simulating an invokevirtual on a miranda method, 67.1257 + // but it is safe to treat it as an invokeinterface.) 67.1258 + assert(!m->can_be_statically_bound(), "no final methods on interfaces"); 67.1259 + vmindex = klassItable::compute_itable_index(m()); 67.1260 + assert(vmindex >= 0, "(>=0) == do_dispatch"); 67.1261 + // Set up same bits as ConstantPoolCacheEntry::set_interface_call(). 67.1262 + vmtarget = m->method_holder(); // the interface 67.1263 + me = MethodHandles::entry(MethodHandles::_invokeinterface_mh); 67.1264 + } else if (!do_dispatch || m->can_be_statically_bound()) { 67.1265 + // We are simulating an invokestatic or invokespecial instruction. 67.1266 + // Set up the method pointer, just like ConstantPoolCacheEntry::set_method(). 67.1267 + vmtarget = m(); 67.1268 + // this does not help dispatch, but it will make it possible to parse this MH: 67.1269 + vmindex = methodOopDesc::nonvirtual_vtable_index; 67.1270 + assert(vmindex < 0, "(>=0) == do_dispatch"); 67.1271 + if (!m->is_static()) { 67.1272 + me = MethodHandles::entry(MethodHandles::_invokespecial_mh); 67.1273 + } else { 67.1274 + me = MethodHandles::entry(MethodHandles::_invokestatic_mh); 67.1275 + // Part of the semantics of a static call is an initialization barrier. 67.1276 + // For a DMH, it is done now, when the handle is created. 67.1277 + Klass* k = Klass::cast(m->method_holder()); 67.1278 + if (k->should_be_initialized()) { 67.1279 + k->initialize(CHECK); 67.1280 + } 67.1281 + } 67.1282 + } else { 67.1283 + // We are simulating an invokevirtual instruction. 67.1284 + // Set up the vtable index, just like ConstantPoolCacheEntry::set_method(). 67.1285 + // The key logic is LinkResolver::runtime_resolve_virtual_method. 67.1286 + vmindex = m->vtable_index(); 67.1287 + vmtarget = m->method_holder(); 67.1288 + me = MethodHandles::entry(MethodHandles::_invokevirtual_mh); 67.1289 + } 67.1290 + 67.1291 + if (me == NULL) { THROW(vmSymbols::java_lang_InternalError()); } 67.1292 + 67.1293 + sun_dyn_DirectMethodHandle::set_vmtarget(mh(), vmtarget); 67.1294 + sun_dyn_DirectMethodHandle::set_vmindex(mh(), vmindex); 67.1295 + DEBUG_ONLY(int flags; klassOop rlimit); 67.1296 + assert(MethodHandles::decode_method(mh(), rlimit, flags) == m(), 67.1297 + "properly stored for later decoding"); 67.1298 + DEBUG_ONLY(bool actual_do_dispatch = ((flags & _dmf_does_dispatch) != 0)); 67.1299 + assert(!(actual_do_dispatch && !do_dispatch), 67.1300 + "do not perform dispatch if !do_dispatch specified"); 67.1301 + assert(actual_do_dispatch == (vmindex >= 0), "proper later decoding of do_dispatch"); 67.1302 + assert(decode_MethodHandle_stack_pushes(mh()) == 0, "DMH does not move stack"); 67.1303 + 67.1304 + // Done! 67.1305 + java_dyn_MethodHandle::set_vmentry(mh(), me); 67.1306 +} 67.1307 + 67.1308 +void MethodHandles::verify_BoundMethodHandle_with_receiver(Handle mh, 67.1309 + methodHandle m, 67.1310 + TRAPS) { 67.1311 + // Verify type. 67.1312 + oop receiver = sun_dyn_BoundMethodHandle::argument(mh()); 67.1313 + Handle mtype(THREAD, java_dyn_MethodHandle::type(mh())); 67.1314 + KlassHandle bound_recv_type; 67.1315 + if (receiver != NULL) bound_recv_type = KlassHandle(THREAD, receiver->klass()); 67.1316 + verify_method_type(m, mtype, true, bound_recv_type, CHECK); 67.1317 + 67.1318 + int receiver_pos = m->size_of_parameters() - 1; 67.1319 + 67.1320 + // Verify MH.vmargslot, which should point at the bound receiver. 67.1321 + verify_vmargslot(mh, -1, sun_dyn_BoundMethodHandle::vmargslot(mh()), CHECK); 67.1322 + //verify_vmslots(mh, CHECK); 67.1323 + 67.1324 + // Verify vmslots. 67.1325 + if (java_dyn_MethodHandle::vmslots(mh()) != receiver_pos) { 67.1326 + THROW_MSG(vmSymbols::java_lang_InternalError(), "bad vmslots in BMH (receiver)"); 67.1327 + } 67.1328 +} 67.1329 + 67.1330 +// Initialize a BMH with a receiver bound directly to a methodOop. 67.1331 +void MethodHandles::init_BoundMethodHandle_with_receiver(Handle mh, 67.1332 + methodHandle original_m, 67.1333 + KlassHandle receiver_limit, 67.1334 + int decode_flags, 67.1335 + TRAPS) { 67.1336 + // Check arguments. 67.1337 + if (mh.is_null() || original_m.is_null()) { 67.1338 + THROW(vmSymbols::java_lang_InternalError()); 67.1339 + } 67.1340 + 67.1341 + KlassHandle receiver_klass; 67.1342 + { 67.1343 + oop receiver_oop = sun_dyn_BoundMethodHandle::argument(mh()); 67.1344 + if (receiver_oop != NULL) 67.1345 + receiver_klass = KlassHandle(THREAD, receiver_oop->klass()); 67.1346 + } 67.1347 + methodHandle m = dispatch_decoded_method(original_m, 67.1348 + receiver_limit, decode_flags, 67.1349 + receiver_klass, 67.1350 + CHECK); 67.1351 + if (m.is_null()) { THROW(vmSymbols::java_lang_InternalError()); } 67.1352 + if (m->is_abstract()) { THROW(vmSymbols::java_lang_AbstractMethodError()); } 67.1353 + 67.1354 + java_dyn_MethodHandle::init_vmslots(mh()); 67.1355 + 67.1356 + if (VerifyMethodHandles) { 67.1357 + verify_BoundMethodHandle_with_receiver(mh, m, CHECK); 67.1358 + } 67.1359 + 67.1360 + sun_dyn_BoundMethodHandle::set_vmtarget(mh(), m()); 67.1361 + 67.1362 + DEBUG_ONLY(int junk; klassOop junk2); 67.1363 + assert(MethodHandles::decode_method(mh(), junk2, junk) == m(), "properly stored for later decoding"); 67.1364 + assert(decode_MethodHandle_stack_pushes(mh()) == 1, "BMH pushes one stack slot"); 67.1365 + 67.1366 + // Done! 67.1367 + java_dyn_MethodHandle::set_vmentry(mh(), MethodHandles::entry(MethodHandles::_bound_ref_direct_mh)); 67.1368 +} 67.1369 + 67.1370 +void MethodHandles::verify_BoundMethodHandle(Handle mh, Handle target, int argnum, 67.1371 + bool direct_to_method, TRAPS) { 67.1372 + Handle ptype_handle(THREAD, 67.1373 + java_dyn_MethodType::ptype(java_dyn_MethodHandle::type(target()), argnum)); 67.1374 + KlassHandle ptype_klass; 67.1375 + BasicType ptype = java_lang_Class::as_BasicType(ptype_handle(), &ptype_klass); 67.1376 + int slots_pushed = type2size[ptype]; 67.1377 + 67.1378 + oop argument = sun_dyn_BoundMethodHandle::argument(mh()); 67.1379 + 67.1380 + const char* err = NULL; 67.1381 + 67.1382 + switch (ptype) { 67.1383 + case T_OBJECT: 67.1384 + if (argument != NULL) 67.1385 + // we must implicitly convert from the arg type to the outgoing ptype 67.1386 + err = check_argument_type_change(T_OBJECT, argument->klass(), ptype, ptype_klass(), argnum); 67.1387 + break; 67.1388 + 67.1389 + case T_ARRAY: case T_VOID: 67.1390 + assert(false, "array, void do not appear here"); 67.1391 + default: 67.1392 + if (ptype != T_INT && !is_subword_type(ptype)) { 67.1393 + err = "unexpected parameter type"; 67.1394 + break; 67.1395 + } 67.1396 + // check subrange of Integer.value, if necessary 67.1397 + if (argument == NULL || argument->klass() != SystemDictionary::int_klass()) { 67.1398 + err = "bound integer argument must be of type java.lang.Integer"; 67.1399 + break; 67.1400 + } 67.1401 + if (ptype != T_INT) { 67.1402 + int value_offset = java_lang_boxing_object::value_offset_in_bytes(T_INT); 67.1403 + jint value = argument->int_field(value_offset); 67.1404 + int vminfo = adapter_subword_vminfo(ptype); 67.1405 + jint subword = truncate_subword_from_vminfo(value, vminfo); 67.1406 + if (value != subword) { 67.1407 + err = "bound subword value does not fit into the subword type"; 67.1408 + break; 67.1409 + } 67.1410 + } 67.1411 + break; 67.1412 + case T_FLOAT: 67.1413 + case T_DOUBLE: 67.1414 + case T_LONG: 67.1415 + { 67.1416 + // we must implicitly convert from the unboxed arg type to the outgoing ptype 67.1417 + BasicType argbox = java_lang_boxing_object::basic_type(argument); 67.1418 + if (argbox != ptype) { 67.1419 + err = check_argument_type_change(T_OBJECT, (argument == NULL 67.1420 + ? SystemDictionary::object_klass() 67.1421 + : argument->klass()), 67.1422 + ptype, ptype_klass(), argnum); 67.1423 + assert(err != NULL, "this must be an error"); 67.1424 + } 67.1425 + break; 67.1426 + } 67.1427 + } 67.1428 + 67.1429 + if (err == NULL) { 67.1430 + DEBUG_ONLY(int this_pushes = decode_MethodHandle_stack_pushes(mh())); 67.1431 + if (direct_to_method) { 67.1432 + assert(this_pushes == slots_pushed, "BMH pushes one or two stack slots"); 67.1433 + assert(slots_pushed <= MethodHandlePushLimit, ""); 67.1434 + } else { 67.1435 + int prev_pushes = decode_MethodHandle_stack_pushes(target()); 67.1436 + assert(this_pushes == slots_pushed + prev_pushes, "BMH stack motion must be correct"); 67.1437 + // do not blow the stack; use a Java-based adapter if this limit is exceeded 67.1438 + if (slots_pushed + prev_pushes > MethodHandlePushLimit) 67.1439 + err = "too many bound parameters"; 67.1440 + } 67.1441 + } 67.1442 + 67.1443 + if (err == NULL) { 67.1444 + // Verify the rest of the method type. 67.1445 + err = check_method_type_insertion(java_dyn_MethodHandle::type(mh()), 67.1446 + argnum, ptype_handle(), 67.1447 + java_dyn_MethodHandle::type(target())); 67.1448 + } 67.1449 + 67.1450 + if (err != NULL) { 67.1451 + THROW_MSG(vmSymbols::java_lang_InternalError(), err); 67.1452 + } 67.1453 +} 67.1454 + 67.1455 +void MethodHandles::init_BoundMethodHandle(Handle mh, Handle target, int argnum, TRAPS) { 67.1456 + // Check arguments. 67.1457 + if (mh.is_null() || target.is_null() || !java_dyn_MethodHandle::is_instance(target())) { 67.1458 + THROW(vmSymbols::java_lang_InternalError()); 67.1459 + } 67.1460 + 67.1461 + java_dyn_MethodHandle::init_vmslots(mh()); 67.1462 + 67.1463 + if (VerifyMethodHandles) { 67.1464 + int insert_after = argnum - 1; 67.1465 + verify_vmargslot(mh, insert_after, sun_dyn_BoundMethodHandle::vmargslot(mh()), CHECK); 67.1466 + verify_vmslots(mh, CHECK); 67.1467 + } 67.1468 + 67.1469 + // If (a) the target is a direct non-dispatched method handle, 67.1470 + // or (b) the target is a dispatched direct method handle and we 67.1471 + // are binding the receiver, cut out the middle-man. 67.1472 + // Do this by decoding the DMH and using its methodOop directly as vmtarget. 67.1473 + bool direct_to_method = false; 67.1474 + if (OptimizeMethodHandles && 67.1475 + target->klass() == SystemDictionary::DirectMethodHandle_klass() && 67.1476 + (argnum == 0 || sun_dyn_DirectMethodHandle::vmindex(target()) < 0)) { 67.1477 + int decode_flags = 0; klassOop receiver_limit_oop = NULL; 67.1478 + methodHandle m(THREAD, decode_method(target(), receiver_limit_oop, decode_flags)); 67.1479 + if (m.is_null()) { THROW_MSG(vmSymbols::java_lang_InternalError(), "DMH failed to decode"); } 67.1480 + DEBUG_ONLY(int m_vmslots = m->size_of_parameters() - 1); // pos. of 1st arg. 67.1481 + assert(sun_dyn_BoundMethodHandle::vmslots(mh()) == m_vmslots, "type w/ m sig"); 67.1482 + if (argnum == 0 && (decode_flags & _dmf_has_receiver) != 0) { 67.1483 + KlassHandle receiver_limit(THREAD, receiver_limit_oop); 67.1484 + init_BoundMethodHandle_with_receiver(mh, m, 67.1485 + receiver_limit, decode_flags, 67.1486 + CHECK); 67.1487 + return; 67.1488 + } 67.1489 + 67.1490 + // Even if it is not a bound receiver, we still might be able 67.1491 + // to bind another argument and still invoke the methodOop directly. 67.1492 + if (!(decode_flags & _dmf_does_dispatch)) { 67.1493 + direct_to_method = true; 67.1494 + sun_dyn_BoundMethodHandle::set_vmtarget(mh(), m()); 67.1495 + } 67.1496 + } 67.1497 + if (!direct_to_method) 67.1498 + sun_dyn_BoundMethodHandle::set_vmtarget(mh(), target()); 67.1499 + 67.1500 + if (VerifyMethodHandles) { 67.1501 + verify_BoundMethodHandle(mh, target, argnum, direct_to_method, CHECK); 67.1502 + } 67.1503 + 67.1504 + // Next question: Is this a ref, int, or long bound value? 67.1505 + oop ptype_oop = java_dyn_MethodType::ptype(java_dyn_MethodHandle::type(target()), argnum); 67.1506 + BasicType ptype = java_lang_Class::as_BasicType(ptype_oop); 67.1507 + int slots_pushed = type2size[ptype]; 67.1508 + 67.1509 + MethodHandleEntry* me = NULL; 67.1510 + if (ptype == T_OBJECT) { 67.1511 + if (direct_to_method) me = MethodHandles::entry(_bound_ref_direct_mh); 67.1512 + else me = MethodHandles::entry(_bound_ref_mh); 67.1513 + } else if (slots_pushed == 2) { 67.1514 + if (direct_to_method) me = MethodHandles::entry(_bound_long_direct_mh); 67.1515 + else me = MethodHandles::entry(_bound_long_mh); 67.1516 + } else if (slots_pushed == 1) { 67.1517 + if (direct_to_method) me = MethodHandles::entry(_bound_int_direct_mh); 67.1518 + else me = MethodHandles::entry(_bound_int_mh); 67.1519 + } else { 67.1520 + assert(false, ""); 67.1521 + } 67.1522 + 67.1523 + // Done! 67.1524 + java_dyn_MethodHandle::set_vmentry(mh(), me); 67.1525 +} 67.1526 + 67.1527 +static void throw_InternalError_for_bad_conversion(int conversion, const char* err, TRAPS) { 67.1528 + char msg[200]; 67.1529 + jio_snprintf(msg, sizeof(msg), "bad adapter (conversion=0x%08x): %s", conversion, err); 67.1530 + THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), msg); 67.1531 +} 67.1532 + 67.1533 +void MethodHandles::verify_AdapterMethodHandle(Handle mh, int argnum, TRAPS) { 67.1534 + jint conversion = sun_dyn_AdapterMethodHandle::conversion(mh()); 67.1535 + int argslot = sun_dyn_AdapterMethodHandle::vmargslot(mh()); 67.1536 + 67.1537 + verify_vmargslot(mh, argnum, argslot, CHECK); 67.1538 + verify_vmslots(mh, CHECK); 67.1539 + 67.1540 + jint conv_op = adapter_conversion_op(conversion); 67.1541 + if (!conv_op_valid(conv_op)) { 67.1542 + throw_InternalError_for_bad_conversion(conversion, "unknown conversion op", THREAD); 67.1543 + return; 67.1544 + } 67.1545 + EntryKind ek = adapter_entry_kind(conv_op); 67.1546 + 67.1547 + int stack_move = adapter_conversion_stack_move(conversion); 67.1548 + BasicType src = adapter_conversion_src_type(conversion); 67.1549 + BasicType dest = adapter_conversion_dest_type(conversion); 67.1550 + int vminfo = adapter_conversion_vminfo(conversion); // should be zero 67.1551 + 67.1552 + Handle argument(THREAD, sun_dyn_AdapterMethodHandle::argument(mh())); 67.1553 + Handle target(THREAD, sun_dyn_AdapterMethodHandle::vmtarget(mh())); 67.1554 + Handle src_mtype(THREAD, java_dyn_MethodHandle::type(mh())); 67.1555 + Handle dst_mtype(THREAD, java_dyn_MethodHandle::type(target())); 67.1556 + 67.1557 + const char* err = NULL; 67.1558 + 67.1559 + if (err == NULL) { 67.1560 + // Check that the correct argument is supplied, but only if it is required. 67.1561 + switch (ek) { 67.1562 + case _adapter_check_cast: // target type of cast 67.1563 + case _adapter_ref_to_prim: // wrapper type from which to unbox 67.1564 + case _adapter_prim_to_ref: // wrapper type to box into 67.1565 + case _adapter_collect_args: // array type to collect into 67.1566 + case _adapter_spread_args: // array type to spread from 67.1567 + if (!java_lang_Class::is_instance(argument()) 67.1568 + || java_lang_Class::is_primitive(argument())) 67.1569 + { err = "adapter requires argument of type java.lang.Class"; break; } 67.1570 + if (ek == _adapter_collect_args || 67.1571 + ek == _adapter_spread_args) { 67.1572 + // Make sure it is a suitable collection type. (Array, for now.) 67.1573 + Klass* ak = Klass::cast(java_lang_Class::as_klassOop(argument())); 67.1574 + if (!ak->oop_is_objArray()) { 67.1575 + { err = "adapter requires argument of type java.lang.Class<Object[]>"; break; } 67.1576 + } 67.1577 + } 67.1578 + break; 67.1579 + case _adapter_flyby: 67.1580 + case _adapter_ricochet: 67.1581 + if (!java_dyn_MethodHandle::is_instance(argument())) 67.1582 + { err = "MethodHandle adapter argument required"; break; } 67.1583 + break; 67.1584 + default: 67.1585 + if (argument.not_null()) 67.1586 + { err = "adapter has spurious argument"; break; } 67.1587 + break; 67.1588 + } 67.1589 + } 67.1590 + 67.1591 + if (err == NULL) { 67.1592 + // Check that the src/dest types are supplied if needed. 67.1593 + switch (ek) { 67.1594 + case _adapter_prim_to_prim: 67.1595 + if (!is_java_primitive(src) || !is_java_primitive(dest) || src == dest) { 67.1596 + err = "adapter requires primitive src/dest conversion subfields"; break; 67.1597 + } 67.1598 + if ( (src == T_FLOAT || src == T_DOUBLE) && !(dest == T_FLOAT || dest == T_DOUBLE) || 67.1599 + !(src == T_FLOAT || src == T_DOUBLE) && (dest == T_FLOAT || dest == T_DOUBLE)) { 67.1600 + err = "adapter cannot convert beween floating and fixed-point"; break; 67.1601 + } 67.1602 + break; 67.1603 + case _adapter_ref_to_prim: 67.1604 + if (src != T_OBJECT || !is_java_primitive(dest) 67.1605 + || argument() != Klass::cast(SystemDictionary::box_klass(dest))->java_mirror()) { 67.1606 + err = "adapter requires primitive dest conversion subfield"; break; 67.1607 + } 67.1608 + break; 67.1609 + case _adapter_prim_to_ref: 67.1610 + if (!is_java_primitive(src) || dest != T_OBJECT 67.1611 + || argument() != Klass::cast(SystemDictionary::box_klass(src))->java_mirror()) { 67.1612 + err = "adapter requires primitive src conversion subfield"; break; 67.1613 + } 67.1614 + break; 67.1615 + case _adapter_swap_args: 67.1616 + case _adapter_rot_args: 67.1617 + { 67.1618 + if (!src || src != dest) { 67.1619 + err = "adapter requires src/dest conversion subfields for swap"; break; 67.1620 + } 67.1621 + int swap_size = type2size[src]; 67.1622 + oop src_mtype = sun_dyn_AdapterMethodHandle::type(target()); 67.1623 + oop dest_mtype = sun_dyn_AdapterMethodHandle::type(mh()); 67.1624 + int slot_limit = sun_dyn_AdapterMethodHandle::vmslots(src_mtype); 67.1625 + int src_slot = argslot; 67.1626 + int dest_slot = vminfo; 67.1627 + bool rotate_up = (src_slot > dest_slot); // upward rotation 67.1628 + int src_arg = argnum; 67.1629 + int dest_arg = argument_slot_to_argnum(dest_mtype, dest_slot); 67.1630 + verify_vmargslot(mh, dest_arg, dest_slot, CHECK); 67.1631 + if (!(dest_slot >= src_slot + swap_size) && 67.1632 + !(src_slot >= dest_slot + swap_size)) { 67.1633 + err = "source, destination slots must be distinct"; 67.1634 + } else if (ek == _adapter_swap_args && !(src_slot > dest_slot)) { 67.1635 + err = "source of swap must be deeper in stack"; 67.1636 + } else if (ek == _adapter_swap_args) { 67.1637 + err = check_argument_type_change(java_dyn_MethodType::ptype(src_mtype, dest_arg), 67.1638 + java_dyn_MethodType::ptype(dest_mtype, src_arg), 67.1639 + dest_arg); 67.1640 + } else if (ek == _adapter_rot_args) { 67.1641 + if (rotate_up) { 67.1642 + assert((src_slot > dest_slot) && (src_arg < dest_arg), ""); 67.1643 + // rotate up: [dest_slot..src_slot-ss] --> [dest_slot+ss..src_slot] 67.1644 + // that is: [src_arg+1..dest_arg] --> [src_arg..dest_arg-1] 67.1645 + for (int i = src_arg+1; i <= dest_arg && err == NULL; i++) { 67.1646 + err = check_argument_type_change(java_dyn_MethodType::ptype(src_mtype, i), 67.1647 + java_dyn_MethodType::ptype(dest_mtype, i-1), 67.1648 + i); 67.1649 + } 67.1650 + } else { // rotate down 67.1651 + assert((src_slot < dest_slot) && (src_arg > dest_arg), ""); 67.1652 + // rotate down: [src_slot+ss..dest_slot] --> [src_slot..dest_slot-ss] 67.1653 + // that is: [dest_arg..src_arg-1] --> [dst_arg+1..src_arg] 67.1654 + for (int i = dest_arg; i <= src_arg-1 && err == NULL; i++) { 67.1655 + err = check_argument_type_change(java_dyn_MethodType::ptype(src_mtype, i), 67.1656 + java_dyn_MethodType::ptype(dest_mtype, i+1), 67.1657 + i); 67.1658 + } 67.1659 + } 67.1660 + } 67.1661 + if (err == NULL) 67.1662 + err = check_argument_type_change(java_dyn_MethodType::ptype(src_mtype, src_arg), 67.1663 + java_dyn_MethodType::ptype(dest_mtype, dest_arg), 67.1664 + src_arg); 67.1665 + } 67.1666 + break; 67.1667 + case _adapter_collect_args: 67.1668 + case _adapter_spread_args: 67.1669 + { 67.1670 + BasicType coll_type = (ek == _adapter_collect_args) ? dest : src; 67.1671 + BasicType elem_type = (ek == _adapter_collect_args) ? src : dest; 67.1672 + if (coll_type != T_OBJECT || elem_type != T_OBJECT) { 67.1673 + err = "adapter requires src/dest subfields"; break; 67.1674 + // later: 67.1675 + // - consider making coll be a primitive array 67.1676 + // - consider making coll be a heterogeneous collection 67.1677 + } 67.1678 + } 67.1679 + break; 67.1680 + default: 67.1681 + if (src != 0 || dest != 0) { 67.1682 + err = "adapter has spurious src/dest conversion subfields"; break; 67.1683 + } 67.1684 + break; 67.1685 + } 67.1686 + } 67.1687 + 67.1688 + if (err == NULL) { 67.1689 + // Check the stack_move subfield. 67.1690 + // It must always report the net change in stack size, positive or negative. 67.1691 + int slots_pushed = stack_move / stack_move_unit(); 67.1692 + switch (ek) { 67.1693 + case _adapter_prim_to_prim: 67.1694 + case _adapter_ref_to_prim: 67.1695 + case _adapter_prim_to_ref: 67.1696 + if (slots_pushed != type2size[dest] - type2size[src]) { 67.1697 + err = "wrong stack motion for primitive conversion"; 67.1698 + } 67.1699 + break; 67.1700 + case _adapter_dup_args: 67.1701 + if (slots_pushed <= 0) { 67.1702 + err = "adapter requires conversion subfield slots_pushed > 0"; 67.1703 + } 67.1704 + break; 67.1705 + case _adapter_drop_args: 67.1706 + if (slots_pushed >= 0) { 67.1707 + err = "adapter requires conversion subfield slots_pushed < 0"; 67.1708 + } 67.1709 + break; 67.1710 + case _adapter_collect_args: 67.1711 + if (slots_pushed > 1) { 67.1712 + err = "adapter requires conversion subfield slots_pushed <= 1"; 67.1713 + } 67.1714 + break; 67.1715 + case _adapter_spread_args: 67.1716 + if (slots_pushed < -1) { 67.1717 + err = "adapter requires conversion subfield slots_pushed >= -1"; 67.1718 + } 67.1719 + break; 67.1720 + default: 67.1721 + if (stack_move != 0) { 67.1722 + err = "adapter has spurious stack_move conversion subfield"; 67.1723 + } 67.1724 + break; 67.1725 + } 67.1726 + if (err == NULL && stack_move != slots_pushed * stack_move_unit()) { 67.1727 + err = "stack_move conversion subfield must be multiple of stack_move_unit"; 67.1728 + } 67.1729 + } 67.1730 + 67.1731 + if (err == NULL) { 67.1732 + // Make sure this adapter does not push too deeply. 67.1733 + int slots_pushed = stack_move / stack_move_unit(); 67.1734 + int this_vmslots = java_dyn_MethodHandle::vmslots(mh()); 67.1735 + int prev_vmslots = java_dyn_MethodHandle::vmslots(target()); 67.1736 + if (slots_pushed != (this_vmslots - prev_vmslots)) { 67.1737 + err = "stack_move inconsistent with previous and current MethodType vmslots"; 67.1738 + } else if (slots_pushed > 0) { 67.1739 + // verify stack_move against MethodHandlePushLimit 67.1740 + int prev_pushes = decode_MethodHandle_stack_pushes(target()); 67.1741 + // do not blow the stack; use a Java-based adapter if this limit is exceeded 67.1742 + if (slots_pushed + prev_pushes > MethodHandlePushLimit) { 67.1743 + err = "adapter pushes too many parameters"; 67.1744 + } 67.1745 + } 67.1746 + 67.1747 + // While we're at it, check that the stack motion decoder works: 67.1748 + DEBUG_ONLY(int prev_pushes = decode_MethodHandle_stack_pushes(target())); 67.1749 + DEBUG_ONLY(int this_pushes = decode_MethodHandle_stack_pushes(mh())); 67.1750 + assert(this_pushes == slots_pushed + prev_pushes, "AMH stack motion must be correct"); 67.1751 + } 67.1752 + 67.1753 + if (err == NULL && vminfo != 0) { 67.1754 + switch (ek) { 67.1755 + case _adapter_swap_args: 67.1756 + case _adapter_rot_args: 67.1757 + break; // OK 67.1758 + default: 67.1759 + err = "vminfo subfield is reserved to the JVM"; 67.1760 + } 67.1761 + } 67.1762 + 67.1763 + // Do additional ad hoc checks. 67.1764 + if (err == NULL) { 67.1765 + switch (ek) { 67.1766 + case _adapter_retype_only: 67.1767 + err = check_method_type_passthrough(src_mtype(), dst_mtype()); 67.1768 + break; 67.1769 + 67.1770 + case _adapter_check_cast: 67.1771 + { 67.1772 + // The actual value being checked must be a reference: 67.1773 + err = check_argument_type_change(java_dyn_MethodType::ptype(src_mtype(), argnum), 67.1774 + object_java_mirror(), argnum); 67.1775 + if (err != NULL) break; 67.1776 + 67.1777 + // The output of the cast must fit with the destination argument: 67.1778 + Handle cast_class = argument; 67.1779 + err = check_method_type_conversion(src_mtype(), 67.1780 + argnum, cast_class(), 67.1781 + dst_mtype()); 67.1782 + } 67.1783 + break; 67.1784 + 67.1785 + // %%% TO DO: continue in remaining cases to verify src/dst_mtype if VerifyMethodHandles 67.1786 + } 67.1787 + } 67.1788 + 67.1789 + if (err != NULL) { 67.1790 + throw_InternalError_for_bad_conversion(conversion, err, THREAD); 67.1791 + return; 67.1792 + } 67.1793 + 67.1794 +} 67.1795 + 67.1796 +void MethodHandles::init_AdapterMethodHandle(Handle mh, Handle target, int argnum, TRAPS) { 67.1797 + oop argument = sun_dyn_AdapterMethodHandle::argument(mh()); 67.1798 + int argslot = sun_dyn_AdapterMethodHandle::vmargslot(mh()); 67.1799 + jint conversion = sun_dyn_AdapterMethodHandle::conversion(mh()); 67.1800 + jint conv_op = adapter_conversion_op(conversion); 67.1801 + 67.1802 + // adjust the adapter code to the internal EntryKind enumeration: 67.1803 + EntryKind ek_orig = adapter_entry_kind(conv_op); 67.1804 + EntryKind ek_opt = ek_orig; // may be optimized 67.1805 + 67.1806 + // Finalize the vmtarget field (Java initialized it to null). 67.1807 + if (!java_dyn_MethodHandle::is_instance(target())) { 67.1808 + throw_InternalError_for_bad_conversion(conversion, "bad target", THREAD); 67.1809 + return; 67.1810 + } 67.1811 + sun_dyn_AdapterMethodHandle::set_vmtarget(mh(), target()); 67.1812 + 67.1813 + if (VerifyMethodHandles) { 67.1814 + verify_AdapterMethodHandle(mh, argnum, CHECK); 67.1815 + } 67.1816 + 67.1817 + int stack_move = adapter_conversion_stack_move(conversion); 67.1818 + BasicType src = adapter_conversion_src_type(conversion); 67.1819 + BasicType dest = adapter_conversion_dest_type(conversion); 67.1820 + int vminfo = adapter_conversion_vminfo(conversion); // should be zero 67.1821 + 67.1822 + const char* err = NULL; 67.1823 + 67.1824 + // Now it's time to finish the case analysis and pick a MethodHandleEntry. 67.1825 + switch (ek_orig) { 67.1826 + case _adapter_retype_only: 67.1827 + case _adapter_check_cast: 67.1828 + case _adapter_dup_args: 67.1829 + case _adapter_drop_args: 67.1830 + // these work fine via general case code 67.1831 + break; 67.1832 + 67.1833 + case _adapter_prim_to_prim: 67.1834 + { 67.1835 + // Non-subword cases are {int,float,long,double} -> {int,float,long,double}. 67.1836 + // And, the {float,double} -> {int,long} cases must be handled by Java. 67.1837 + switch (type2size[src] *4+ type2size[dest]) { 67.1838 + case 1 *4+ 1: 67.1839 + assert(src == T_INT || is_subword_type(src), "source is not float"); 67.1840 + // Subword-related cases are int -> {boolean,byte,char,short}. 67.1841 + ek_opt = _adapter_opt_i2i; 67.1842 + vminfo = adapter_subword_vminfo(dest); 67.1843 + break; 67.1844 + case 2 *4+ 1: 67.1845 + if (src == T_LONG && (dest == T_INT || is_subword_type(dest))) { 67.1846 + ek_opt = _adapter_opt_l2i; 67.1847 + vminfo = adapter_subword_vminfo(dest); 67.1848 + } else if (src == T_DOUBLE && dest == T_FLOAT) { 67.1849 + ek_opt = _adapter_opt_d2f; 67.1850 + } else { 67.1851 + assert(false, ""); 67.1852 + } 67.1853 + break; 67.1854 + case 1 *4+ 2: 67.1855 + if (src == T_INT && dest == T_LONG) { 67.1856 + ek_opt = _adapter_opt_i2l; 67.1857 + } else if (src == T_FLOAT && dest == T_DOUBLE) { 67.1858 + ek_opt = _adapter_opt_f2d; 67.1859 + } else { 67.1860 + assert(false, ""); 67.1861 + } 67.1862 + break; 67.1863 + default: 67.1864 + assert(false, ""); 67.1865 + break; 67.1866 + } 67.1867 + } 67.1868 + break; 67.1869 + 67.1870 + case _adapter_ref_to_prim: 67.1871 + { 67.1872 + switch (type2size[dest]) { 67.1873 + case 1: 67.1874 + ek_opt = _adapter_opt_unboxi; 67.1875 + vminfo = adapter_subword_vminfo(dest); 67.1876 + break; 67.1877 + case 2: 67.1878 + ek_opt = _adapter_opt_unboxl; 67.1879 + break; 67.1880 + default: 67.1881 + assert(false, ""); 67.1882 + break; 67.1883 + } 67.1884 + } 67.1885 + break; 67.1886 + 67.1887 + case _adapter_prim_to_ref: 67.1888 + goto throw_not_impl; // allocates, hence could block 67.1889 + 67.1890 + case _adapter_swap_args: 67.1891 + case _adapter_rot_args: 67.1892 + { 67.1893 + int swap_slots = type2size[src]; 67.1894 + oop mtype = sun_dyn_AdapterMethodHandle::type(mh()); 67.1895 + int slot_limit = sun_dyn_AdapterMethodHandle::vmslots(mtype); 67.1896 + int src_slot = argslot; 67.1897 + int dest_slot = vminfo; 67.1898 + int rotate = (ek_orig == _adapter_swap_args) ? 0 : (src_slot > dest_slot) ? 1 : -1; 67.1899 + switch (swap_slots) { 67.1900 + case 1: 67.1901 + ek_opt = (!rotate ? _adapter_opt_swap_1 : 67.1902 + rotate > 0 ? _adapter_opt_rot_1_up : _adapter_opt_rot_1_down); 67.1903 + break; 67.1904 + case 2: 67.1905 + ek_opt = (!rotate ? _adapter_opt_swap_2 : 67.1906 + rotate > 0 ? _adapter_opt_rot_2_up : _adapter_opt_rot_2_down); 67.1907 + break; 67.1908 + default: 67.1909 + assert(false, ""); 67.1910 + break; 67.1911 + } 67.1912 + } 67.1913 + break; 67.1914 + 67.1915 + case _adapter_collect_args: 67.1916 + goto throw_not_impl; // allocates, hence could block 67.1917 + 67.1918 + case _adapter_spread_args: 67.1919 + { 67.1920 + // vminfo will be the required length of the array 67.1921 + int slots_pushed = stack_move / stack_move_unit(); 67.1922 + int array_size = slots_pushed + 1; 67.1923 + assert(array_size >= 0, ""); 67.1924 + vminfo = array_size; 67.1925 + switch (array_size) { 67.1926 + case 0: ek_opt = _adapter_opt_spread_0; break; 67.1927 + case 1: ek_opt = _adapter_opt_spread_1; break; 67.1928 + default: ek_opt = _adapter_opt_spread_more; break; 67.1929 + } 67.1930 + if ((vminfo & CONV_VMINFO_MASK) != vminfo) 67.1931 + goto throw_not_impl; // overflow 67.1932 + } 67.1933 + break; 67.1934 + 67.1935 + case _adapter_flyby: 67.1936 + case _adapter_ricochet: 67.1937 + goto throw_not_impl; // runs Java code, hence could block 67.1938 + 67.1939 + default: 67.1940 + // should have failed much earlier; must be a missing case here 67.1941 + assert(false, "incomplete switch"); 67.1942 + // and fall through: 67.1943 + 67.1944 + throw_not_impl: 67.1945 + // FIXME: these adapters are NYI 67.1946 + err = "adapter not yet implemented in the JVM"; 67.1947 + break; 67.1948 + } 67.1949 + 67.1950 + if (err != NULL) { 67.1951 + throw_InternalError_for_bad_conversion(conversion, err, THREAD); 67.1952 + return; 67.1953 + } 67.1954 + 67.1955 + // Rebuild the conversion value; maybe parts of it were changed. 67.1956 + jint new_conversion = adapter_conversion(conv_op, src, dest, stack_move, vminfo); 67.1957 + 67.1958 + // Finalize the conversion field. (Note that it is final to Java code.) 67.1959 + sun_dyn_AdapterMethodHandle::set_conversion(mh(), new_conversion); 67.1960 + 67.1961 + // Done! 67.1962 + java_dyn_MethodHandle::set_vmentry(mh(), entry(ek_opt)); 67.1963 + 67.1964 + // There should be enough memory barriers on exit from native methods 67.1965 + // to ensure that the MH is fully initialized to all threads before 67.1966 + // Java code can publish it in global data structures. 67.1967 +} 67.1968 + 67.1969 +// 67.1970 +// Here are the native methods on sun.dyn.MethodHandleImpl. 67.1971 +// They are the private interface between this JVM and the HotSpot-specific 67.1972 +// Java code that implements JSR 292 method handles. 67.1973 +// 67.1974 +// Note: We use a JVM_ENTRY macro to define each of these, for this is the way 67.1975 +// that intrinsic (non-JNI) native methods are defined in HotSpot. 67.1976 +// 67.1977 + 67.1978 +// direct method handles for invokestatic or invokespecial 67.1979 +// void init(DirectMethodHandle self, MemberName ref, boolean doDispatch, Class<?> caller); 67.1980 +JVM_ENTRY(void, MHI_init_DMH(JNIEnv *env, jobject igcls, jobject mh_jh, 67.1981 + jobject target_jh, jboolean do_dispatch, jobject caller_jh)) { 67.1982 + ResourceMark rm; // for error messages 67.1983 + 67.1984 + // This is the guy we are initializing: 67.1985 + if (mh_jh == NULL) { THROW(vmSymbols::java_lang_InternalError()); } 67.1986 + Handle mh(THREAD, JNIHandles::resolve_non_null(mh_jh)); 67.1987 + 67.1988 + // Early returns out of this method leave the DMH in an unfinished state. 67.1989 + assert(java_dyn_MethodHandle::vmentry(mh()) == NULL, "must be safely null"); 67.1990 + 67.1991 + // which method are we really talking about? 67.1992 + if (target_jh == NULL) { THROW(vmSymbols::java_lang_InternalError()); } 67.1993 + oop target_oop = JNIHandles::resolve_non_null(target_jh); 67.1994 + if (sun_dyn_MemberName::is_instance(target_oop) && 67.1995 + sun_dyn_MemberName::vmindex(target_oop) == VM_INDEX_UNINITIALIZED) { 67.1996 + Handle mname(THREAD, target_oop); 67.1997 + MethodHandles::resolve_MemberName(mname, CHECK); 67.1998 + target_oop = mname(); // in case of GC 67.1999 + } 67.2000 + 67.2001 + int decode_flags = 0; klassOop receiver_limit = NULL; 67.2002 + methodHandle m(THREAD, 67.2003 + MethodHandles::decode_method(target_oop, 67.2004 + receiver_limit, decode_flags)); 67.2005 + if (m.is_null()) { THROW_MSG(vmSymbols::java_lang_InternalError(), "no such method"); } 67.2006 + 67.2007 + // The trusted Java code that calls this method should already have performed 67.2008 + // access checks on behalf of the given caller. But, we can verify this. 67.2009 + if (VerifyMethodHandles && caller_jh != NULL) { 67.2010 + KlassHandle caller(THREAD, java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(caller_jh))); 67.2011 + // If this were a bytecode, the first access check would be against 67.2012 + // the "reference class" mentioned in the CONSTANT_Methodref. 67.2013 + // For that class, we use the defining class of m, 67.2014 + // or a more specific receiver limit if available. 67.2015 + klassOop reference_klass = m->method_holder(); // OK approximation 67.2016 + if (receiver_limit != NULL && receiver_limit != reference_klass) { 67.2017 + if (!Klass::cast(receiver_limit)->is_subtype_of(reference_klass)) 67.2018 + THROW_MSG(vmSymbols::java_lang_InternalError(), "receiver limit out of bounds"); // Java code bug 67.2019 + reference_klass = receiver_limit; 67.2020 + } 67.2021 + // Emulate LinkResolver::check_klass_accessability. 67.2022 + if (!Reflection::verify_class_access(caller->as_klassOop(), 67.2023 + reference_klass, 67.2024 + true)) { 67.2025 + THROW_MSG(vmSymbols::java_lang_InternalError(), Klass::cast(m->method_holder())->external_name()); 67.2026 + } 67.2027 + // If there were a bytecode, the next step would be to lookup the method 67.2028 + // in the reference class, then then check the method's access bits. 67.2029 + // Emulate LinkResolver::check_method_accessability. 67.2030 + klassOop resolved_klass = m->method_holder(); 67.2031 + if (!Reflection::verify_field_access(caller->as_klassOop(), 67.2032 + resolved_klass, reference_klass, 67.2033 + m->access_flags(), 67.2034 + true)) { 67.2035 + // %%% following cutout belongs in Reflection::verify_field_access? 67.2036 + bool same_pm = Reflection::is_same_package_member(caller->as_klassOop(), 67.2037 + reference_klass, THREAD); 67.2038 + if (!same_pm) { 67.2039 + THROW_MSG(vmSymbols::java_lang_InternalError(), m->name_and_sig_as_C_string()); 67.2040 + } 67.2041 + } 67.2042 + } 67.2043 + 67.2044 + MethodHandles::init_DirectMethodHandle(mh, m, (do_dispatch != JNI_FALSE), CHECK); 67.2045 +} 67.2046 +JVM_END 67.2047 + 67.2048 +// bound method handles 67.2049 +JVM_ENTRY(void, MHI_init_BMH(JNIEnv *env, jobject igcls, jobject mh_jh, 67.2050 + jobject target_jh, int argnum)) { 67.2051 + ResourceMark rm; // for error messages 67.2052 + 67.2053 + // This is the guy we are initializing: 67.2054 + if (mh_jh == NULL) { THROW(vmSymbols::java_lang_InternalError()); } 67.2055 + Handle mh(THREAD, JNIHandles::resolve_non_null(mh_jh)); 67.2056 + 67.2057 + // Early returns out of this method leave the BMH in an unfinished state. 67.2058 + assert(java_dyn_MethodHandle::vmentry(mh()) == NULL, "must be safely null"); 67.2059 + 67.2060 + if (target_jh == NULL) { THROW(vmSymbols::java_lang_InternalError()); } 67.2061 + Handle target(THREAD, JNIHandles::resolve_non_null(target_jh)); 67.2062 + 67.2063 + if (!java_dyn_MethodHandle::is_instance(target())) { 67.2064 + // Target object is a reflective method. (%%% Do we need this alternate path?) 67.2065 + Untested("init_BMH of non-MH"); 67.2066 + if (argnum != 0) { THROW(vmSymbols::java_lang_InternalError()); } 67.2067 + int decode_flags = 0; klassOop receiver_limit_oop = NULL; 67.2068 + methodHandle m(THREAD, 67.2069 + MethodHandles::decode_method(target(), 67.2070 + receiver_limit_oop, 67.2071 + decode_flags)); 67.2072 + KlassHandle receiver_limit(THREAD, receiver_limit_oop); 67.2073 + MethodHandles::init_BoundMethodHandle_with_receiver(mh, m, 67.2074 + receiver_limit, 67.2075 + decode_flags, 67.2076 + CHECK); 67.2077 + return; 67.2078 + } 67.2079 + 67.2080 + // Build a BMH on top of a DMH or another BMH: 67.2081 + MethodHandles::init_BoundMethodHandle(mh, target, argnum, CHECK); 67.2082 +} 67.2083 +JVM_END 67.2084 + 67.2085 +// adapter method handles 67.2086 +JVM_ENTRY(void, MHI_init_AMH(JNIEnv *env, jobject igcls, jobject mh_jh, 67.2087 + jobject target_jh, int argnum)) { 67.2088 + // This is the guy we are initializing: 67.2089 + if (mh_jh == NULL || target_jh == NULL) { 67.2090 + THROW(vmSymbols::java_lang_InternalError()); 67.2091 + } 67.2092 + Handle mh(THREAD, JNIHandles::resolve_non_null(mh_jh)); 67.2093 + Handle target(THREAD, JNIHandles::resolve_non_null(target_jh)); 67.2094 + 67.2095 + // Early returns out of this method leave the AMH in an unfinished state. 67.2096 + assert(java_dyn_MethodHandle::vmentry(mh()) == NULL, "must be safely null"); 67.2097 + 67.2098 + MethodHandles::init_AdapterMethodHandle(mh, target, argnum, CHECK); 67.2099 +} 67.2100 +JVM_END 67.2101 + 67.2102 +// method type forms 67.2103 +JVM_ENTRY(void, MHI_init_MT(JNIEnv *env, jobject igcls, jobject erased_jh)) { 67.2104 + if (erased_jh == NULL) return; 67.2105 + if (TraceMethodHandles) { 67.2106 + tty->print("creating MethodType form "); 67.2107 + if (WizardMode || Verbose) { // Warning: this calls Java code on the MH! 67.2108 + // call Object.toString() 67.2109 + symbolOop name = vmSymbols::toString_name(), sig = vmSymbols::void_string_signature(); 67.2110 + JavaCallArguments args(Handle(THREAD, JNIHandles::resolve_non_null(erased_jh))); 67.2111 + JavaValue result(T_OBJECT); 67.2112 + JavaCalls::call_virtual(&result, SystemDictionary::object_klass(), name, sig, 67.2113 + &args, CHECK); 67.2114 + Handle str(THREAD, (oop)result.get_jobject()); 67.2115 + java_lang_String::print(str, tty); 67.2116 + } 67.2117 + tty->cr(); 67.2118 + } 67.2119 +} 67.2120 +JVM_END 67.2121 + 67.2122 +// debugging and reflection 67.2123 +JVM_ENTRY(jobject, MHI_getTarget(JNIEnv *env, jobject igcls, jobject mh_jh, jint format)) { 67.2124 + Handle mh(THREAD, JNIHandles::resolve(mh_jh)); 67.2125 + if (!java_dyn_MethodHandle::is_instance(mh())) { 67.2126 + THROW_NULL(vmSymbols::java_lang_IllegalArgumentException()); 67.2127 + } 67.2128 + oop target = MethodHandles::encode_target(mh, format, CHECK_NULL); 67.2129 + return JNIHandles::make_local(THREAD, target); 67.2130 +} 67.2131 +JVM_END 67.2132 + 67.2133 +JVM_ENTRY(jint, MHI_getConstant(JNIEnv *env, jobject igcls, jint which)) { 67.2134 + switch (which) { 67.2135 + case MethodHandles::GC_JVM_PUSH_LIMIT: 67.2136 + guarantee(MethodHandlePushLimit >= 2 && MethodHandlePushLimit <= 0xFF, 67.2137 + "MethodHandlePushLimit parameter must be in valid range"); 67.2138 + return MethodHandlePushLimit; 67.2139 + case MethodHandles::GC_JVM_STACK_MOVE_LIMIT: 67.2140 + // return number of words per slot, signed according to stack direction 67.2141 + return MethodHandles::stack_move_unit(); 67.2142 + } 67.2143 + return 0; 67.2144 +} 67.2145 +JVM_END 67.2146 + 67.2147 +#ifndef PRODUCT 67.2148 +#define EACH_NAMED_CON(template) \ 67.2149 + template(MethodHandles,GC_JVM_PUSH_LIMIT) \ 67.2150 + template(MethodHandles,GC_JVM_STACK_MOVE_LIMIT) \ 67.2151 + template(MethodHandles,ETF_HANDLE_OR_METHOD_NAME) \ 67.2152 + template(MethodHandles,ETF_DIRECT_HANDLE) \ 67.2153 + template(MethodHandles,ETF_METHOD_NAME) \ 67.2154 + template(MethodHandles,ETF_REFLECT_METHOD) \ 67.2155 + template(sun_dyn_MemberName,MN_IS_METHOD) \ 67.2156 + template(sun_dyn_MemberName,MN_IS_CONSTRUCTOR) \ 67.2157 + template(sun_dyn_MemberName,MN_IS_FIELD) \ 67.2158 + template(sun_dyn_MemberName,MN_IS_TYPE) \ 67.2159 + template(sun_dyn_MemberName,MN_SEARCH_SUPERCLASSES) \ 67.2160 + template(sun_dyn_MemberName,MN_SEARCH_INTERFACES) \ 67.2161 + template(sun_dyn_MemberName,VM_INDEX_UNINITIALIZED) \ 67.2162 + template(sun_dyn_AdapterMethodHandle,OP_RETYPE_ONLY) \ 67.2163 + template(sun_dyn_AdapterMethodHandle,OP_CHECK_CAST) \ 67.2164 + template(sun_dyn_AdapterMethodHandle,OP_PRIM_TO_PRIM) \ 67.2165 + template(sun_dyn_AdapterMethodHandle,OP_REF_TO_PRIM) \ 67.2166 + template(sun_dyn_AdapterMethodHandle,OP_PRIM_TO_REF) \ 67.2167 + template(sun_dyn_AdapterMethodHandle,OP_SWAP_ARGS) \ 67.2168 + template(sun_dyn_AdapterMethodHandle,OP_ROT_ARGS) \ 67.2169 + template(sun_dyn_AdapterMethodHandle,OP_DUP_ARGS) \ 67.2170 + template(sun_dyn_AdapterMethodHandle,OP_DROP_ARGS) \ 67.2171 + template(sun_dyn_AdapterMethodHandle,OP_COLLECT_ARGS) \ 67.2172 + template(sun_dyn_AdapterMethodHandle,OP_SPREAD_ARGS) \ 67.2173 + template(sun_dyn_AdapterMethodHandle,OP_FLYBY) \ 67.2174 + template(sun_dyn_AdapterMethodHandle,OP_RICOCHET) \ 67.2175 + template(sun_dyn_AdapterMethodHandle,CONV_OP_LIMIT) \ 67.2176 + template(sun_dyn_AdapterMethodHandle,CONV_OP_MASK) \ 67.2177 + template(sun_dyn_AdapterMethodHandle,CONV_VMINFO_MASK) \ 67.2178 + template(sun_dyn_AdapterMethodHandle,CONV_VMINFO_SHIFT) \ 67.2179 + template(sun_dyn_AdapterMethodHandle,CONV_OP_SHIFT) \ 67.2180 + template(sun_dyn_AdapterMethodHandle,CONV_DEST_TYPE_SHIFT) \ 67.2181 + template(sun_dyn_AdapterMethodHandle,CONV_SRC_TYPE_SHIFT) \ 67.2182 + template(sun_dyn_AdapterMethodHandle,CONV_STACK_MOVE_SHIFT) \ 67.2183 + template(sun_dyn_AdapterMethodHandle,CONV_STACK_MOVE_MASK) \ 67.2184 + /*end*/ 67.2185 + 67.2186 +#define ONE_PLUS(scope,value) 1+ 67.2187 +static const int con_value_count = EACH_NAMED_CON(ONE_PLUS) 0; 67.2188 +#define VALUE_COMMA(scope,value) scope::value, 67.2189 +static const int con_values[con_value_count+1] = { EACH_NAMED_CON(VALUE_COMMA) 0 }; 67.2190 +#define STRING_NULL(scope,value) #value "\0" 67.2191 +static const char con_names[] = { EACH_NAMED_CON(STRING_NULL) }; 67.2192 + 67.2193 +#undef ONE_PLUS 67.2194 +#undef VALUE_COMMA 67.2195 +#undef STRING_NULL 67.2196 +#undef EACH_NAMED_CON 67.2197 +#endif 67.2198 + 67.2199 +JVM_ENTRY(jint, MHI_getNamedCon(JNIEnv *env, jobject igcls, jint which, jobjectArray box_jh)) { 67.2200 +#ifndef PRODUCT 67.2201 + if (which >= 0 && which < con_value_count) { 67.2202 + int con = con_values[which]; 67.2203 + objArrayOop box = (objArrayOop) JNIHandles::resolve(box_jh); 67.2204 + if (box != NULL && box->klass() == Universe::objectArrayKlassObj() && box->length() > 0) { 67.2205 + const char* str = &con_names[0]; 67.2206 + for (int i = 0; i < which; i++) 67.2207 + str += strlen(str) + 1; // skip name and null 67.2208 + oop name = java_lang_String::create_oop_from_str(str, CHECK_0); 67.2209 + box->obj_at_put(0, name); 67.2210 + } 67.2211 + return con; 67.2212 + } 67.2213 +#endif 67.2214 + return 0; 67.2215 +} 67.2216 +JVM_END 67.2217 + 67.2218 +// void init(MemberName self, AccessibleObject ref) 67.2219 +JVM_ENTRY(void, MHI_init_Mem(JNIEnv *env, jobject igcls, jobject mname_jh, jobject target_jh)) { 67.2220 + if (mname_jh == NULL || target_jh == NULL) { THROW(vmSymbols::java_lang_InternalError()); } 67.2221 + Handle mname(THREAD, JNIHandles::resolve_non_null(mname_jh)); 67.2222 + oop target_oop = JNIHandles::resolve_non_null(target_jh); 67.2223 + MethodHandles::init_MemberName(mname(), target_oop); 67.2224 +} 67.2225 +JVM_END 67.2226 + 67.2227 +// void expand(MemberName self) 67.2228 +JVM_ENTRY(void, MHI_expand_Mem(JNIEnv *env, jobject igcls, jobject mname_jh)) { 67.2229 + if (mname_jh == NULL) { THROW(vmSymbols::java_lang_InternalError()); } 67.2230 + Handle mname(THREAD, JNIHandles::resolve_non_null(mname_jh)); 67.2231 + MethodHandles::expand_MemberName(mname, 0, CHECK); 67.2232 +} 67.2233 +JVM_END 67.2234 + 67.2235 +// void resolve(MemberName self, Class<?> caller) 67.2236 +JVM_ENTRY(void, MHI_resolve_Mem(JNIEnv *env, jobject igcls, jobject mname_jh, jclass caller_jh)) { 67.2237 + if (mname_jh == NULL) { THROW(vmSymbols::java_lang_InternalError()); } 67.2238 + Handle mname(THREAD, JNIHandles::resolve_non_null(mname_jh)); 67.2239 + // %%% take caller into account! 67.2240 + MethodHandles::resolve_MemberName(mname, CHECK); 67.2241 +} 67.2242 +JVM_END 67.2243 + 67.2244 +// static native int getMembers(Class<?> defc, String matchName, String matchSig, 67.2245 +// int matchFlags, Class<?> caller, int skip, MemberName[] results); 67.2246 +JVM_ENTRY(jint, MHI_getMembers(JNIEnv *env, jobject igcls, 67.2247 + jclass clazz_jh, jstring name_jh, jstring sig_jh, 67.2248 + int mflags, jclass caller_jh, jint skip, jobjectArray results_jh)) { 67.2249 + if (clazz_jh == NULL || results_jh == NULL) return -1; 67.2250 + klassOop k_oop = java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(clazz_jh)); 67.2251 + 67.2252 + objArrayOop results = (objArrayOop) JNIHandles::resolve(results_jh); 67.2253 + if (results == NULL || !results->is_objArray()) return -1; 67.2254 + 67.2255 + symbolOop name = NULL, sig = NULL; 67.2256 + if (name_jh != NULL) { 67.2257 + name = java_lang_String::as_symbol_or_null(JNIHandles::resolve_non_null(name_jh)); 67.2258 + if (name == NULL) return 0; // a match is not possible 67.2259 + } 67.2260 + if (sig_jh != NULL) { 67.2261 + sig = java_lang_String::as_symbol_or_null(JNIHandles::resolve_non_null(sig_jh)); 67.2262 + if (sig == NULL) return 0; // a match is not possible 67.2263 + } 67.2264 + 67.2265 + klassOop caller = NULL; 67.2266 + if (caller_jh != NULL) { 67.2267 + oop caller_oop = JNIHandles::resolve_non_null(caller_jh); 67.2268 + if (!java_lang_Class::is_instance(caller_oop)) return -1; 67.2269 + caller = java_lang_Class::as_klassOop(caller_oop); 67.2270 + } 67.2271 + 67.2272 + if (name != NULL && sig != NULL && results != NULL) { 67.2273 + // try a direct resolve 67.2274 + // %%% TO DO 67.2275 + } 67.2276 + 67.2277 + int res = MethodHandles::find_MemberNames(k_oop, name, sig, mflags, 67.2278 + caller, skip, results); 67.2279 + // TO DO: expand at least some of the MemberNames, to avoid massive callbacks 67.2280 + return res; 67.2281 +} 67.2282 +JVM_END 67.2283 + 67.2284 + 67.2285 +/// JVM_RegisterMethodHandleMethods 67.2286 + 67.2287 +#define ADR "J" 67.2288 + 67.2289 +#define LANG "Ljava/lang/" 67.2290 +#define JDYN "Ljava/dyn/" 67.2291 +#define IDYN "Lsun/dyn/" 67.2292 + 67.2293 +#define OBJ LANG"Object;" 67.2294 +#define CLS LANG"Class;" 67.2295 +#define STRG LANG"String;" 67.2296 +#define MT JDYN"MethodType;" 67.2297 +#define MH JDYN"MethodHandle;" 67.2298 +#define MHI IDYN"MethodHandleImpl;" 67.2299 +#define MEM IDYN"MemberName;" 67.2300 +#define AMH IDYN"AdapterMethodHandle;" 67.2301 +#define BMH IDYN"BoundMethodHandle;" 67.2302 +#define DMH IDYN"DirectMethodHandle;" 67.2303 + 67.2304 +#define CC (char*) /*cast a literal from (const char*)*/ 67.2305 +#define FN_PTR(f) CAST_FROM_FN_PTR(void*, &f) 67.2306 + 67.2307 +// These are the native methods on sun.dyn.MethodHandleNatives. 67.2308 +static JNINativeMethod methods[] = { 67.2309 + // void init(MemberName self, AccessibleObject ref) 67.2310 + {CC"init", CC"("AMH""MH"I)V", FN_PTR(MHI_init_AMH)}, 67.2311 + {CC"init", CC"("BMH""OBJ"I)V", FN_PTR(MHI_init_BMH)}, 67.2312 + {CC"init", CC"("DMH""OBJ"Z"CLS")V", FN_PTR(MHI_init_DMH)}, 67.2313 + {CC"init", CC"("MT")V", FN_PTR(MHI_init_MT)}, 67.2314 + {CC"init", CC"("MEM""OBJ")V", FN_PTR(MHI_init_Mem)}, 67.2315 + {CC"expand", CC"("MEM")V", FN_PTR(MHI_expand_Mem)}, 67.2316 + {CC"resolve", CC"("MEM""CLS")V", FN_PTR(MHI_resolve_Mem)}, 67.2317 + {CC"getTarget", CC"("MH"I)"OBJ, FN_PTR(MHI_getTarget)}, 67.2318 + {CC"getConstant", CC"(I)I", FN_PTR(MHI_getConstant)}, 67.2319 + // static native int getNamedCon(int which, Object[] name) 67.2320 + {CC"getNamedCon", CC"(I["OBJ")I", FN_PTR(MHI_getNamedCon)}, 67.2321 + // static native int getMembers(Class<?> defc, String matchName, String matchSig, 67.2322 + // int matchFlags, Class<?> caller, int skip, MemberName[] results); 67.2323 + {CC"getMembers", CC"("CLS""STRG""STRG"I"CLS"I["MEM")I", FN_PTR(MHI_getMembers)} 67.2324 +}; 67.2325 + 67.2326 + 67.2327 +// This one function is exported, used by NativeLookup. 67.2328 + 67.2329 +JVM_ENTRY(void, JVM_RegisterMethodHandleMethods(JNIEnv *env, jclass MHN_class)) { 67.2330 + assert(MethodHandles::spot_check_entry_names(), "entry enum is OK"); 67.2331 + 67.2332 + if (!EnableMethodHandles) { 67.2333 + warning("JSR 292 method handles are disabled in this JVM. Use -XX:+EnableMethodHandles to enable."); 67.2334 + return; // bind nothing 67.2335 + } 67.2336 + 67.2337 + { 67.2338 + ThreadToNativeFromVM ttnfv(thread); 67.2339 + 67.2340 + int status = env->RegisterNatives(MHN_class, methods, sizeof(methods)/sizeof(JNINativeMethod)); 67.2341 + if (env->ExceptionOccurred()) { 67.2342 + MethodHandles::set_enabled(false); 67.2343 + warning("JSR 292 method handle code is mismatched to this JVM. Disabling support."); 67.2344 + env->ExceptionClear(); 67.2345 + } else { 67.2346 + MethodHandles::set_enabled(true); 67.2347 + } 67.2348 + } 67.2349 +} 67.2350 +JVM_END
68.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 68.2 +++ b/src/share/vm/prims/methodHandles.hpp Tue Apr 14 12:25:54 2009 -0700 68.3 @@ -0,0 +1,435 @@ 68.4 +/* 68.5 + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. 68.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 68.7 + * 68.8 + * This code is free software; you can redistribute it and/or modify it 68.9 + * under the terms of the GNU General Public License version 2 only, as 68.10 + * published by the Free Software Foundation. 68.11 + * 68.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 68.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 68.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 68.15 + * version 2 for more details (a copy is included in the LICENSE file that 68.16 + * accompanied this code). 68.17 + * 68.18 + * You should have received a copy of the GNU General Public License version 68.19 + * 2 along with this work; if not, write to the Free Software Foundation, 68.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 68.21 + * 68.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 68.23 + * CA 95054 USA or visit www.sun.com if you need additional information or 68.24 + * have any questions. 68.25 + * 68.26 + */ 68.27 + 68.28 +class MacroAssembler; 68.29 +class Label; 68.30 +class MethodHandleEntry; 68.31 + 68.32 +class MethodHandles: AllStatic { 68.33 + // JVM support for MethodHandle, MethodType, and related types 68.34 + // in java.dyn and java.dyn.hotspot. 68.35 + // See also javaClasses for layouts java_dyn_Method{Handle,Type,Type::Form}. 68.36 + public: 68.37 + enum EntryKind { 68.38 + _check_mtype, // how a caller calls a MH 68.39 + _wrong_method_type, // what happens when there is a type mismatch 68.40 + _invokestatic_mh, // how a MH emulates invokestatic 68.41 + _invokespecial_mh, // ditto for the other invokes... 68.42 + _invokevirtual_mh, 68.43 + _invokeinterface_mh, 68.44 + _bound_ref_mh, // reference argument is bound 68.45 + _bound_int_mh, // int argument is bound (via an Integer or Float) 68.46 + _bound_long_mh, // long argument is bound (via a Long or Double) 68.47 + _bound_ref_direct_mh, // same as above, with direct linkage to methodOop 68.48 + _bound_int_direct_mh, 68.49 + _bound_long_direct_mh, 68.50 + 68.51 + _adapter_mh_first, // adapter sequence goes here... 68.52 + _adapter_retype_only = _adapter_mh_first + sun_dyn_AdapterMethodHandle::OP_RETYPE_ONLY, 68.53 + _adapter_check_cast = _adapter_mh_first + sun_dyn_AdapterMethodHandle::OP_CHECK_CAST, 68.54 + _adapter_prim_to_prim = _adapter_mh_first + sun_dyn_AdapterMethodHandle::OP_PRIM_TO_PRIM, 68.55 + _adapter_ref_to_prim = _adapter_mh_first + sun_dyn_AdapterMethodHandle::OP_REF_TO_PRIM, 68.56 + _adapter_prim_to_ref = _adapter_mh_first + sun_dyn_AdapterMethodHandle::OP_PRIM_TO_REF, 68.57 + _adapter_swap_args = _adapter_mh_first + sun_dyn_AdapterMethodHandle::OP_SWAP_ARGS, 68.58 + _adapter_rot_args = _adapter_mh_first + sun_dyn_AdapterMethodHandle::OP_ROT_ARGS, 68.59 + _adapter_dup_args = _adapter_mh_first + sun_dyn_AdapterMethodHandle::OP_DUP_ARGS, 68.60 + _adapter_drop_args = _adapter_mh_first + sun_dyn_AdapterMethodHandle::OP_DROP_ARGS, 68.61 + _adapter_collect_args = _adapter_mh_first + sun_dyn_AdapterMethodHandle::OP_COLLECT_ARGS, 68.62 + _adapter_spread_args = _adapter_mh_first + sun_dyn_AdapterMethodHandle::OP_SPREAD_ARGS, 68.63 + _adapter_flyby = _adapter_mh_first + sun_dyn_AdapterMethodHandle::OP_FLYBY, 68.64 + _adapter_ricochet = _adapter_mh_first + sun_dyn_AdapterMethodHandle::OP_RICOCHET, 68.65 + _adapter_mh_last = _adapter_mh_first + sun_dyn_AdapterMethodHandle::CONV_OP_LIMIT - 1, 68.66 + 68.67 + // Optimized adapter types 68.68 + 68.69 + // argument list reordering 68.70 + _adapter_opt_swap_1, 68.71 + _adapter_opt_swap_2, 68.72 + _adapter_opt_rot_1_up, 68.73 + _adapter_opt_rot_1_down, 68.74 + _adapter_opt_rot_2_up, 68.75 + _adapter_opt_rot_2_down, 68.76 + // primitive single to single: 68.77 + _adapter_opt_i2i, // i2c, i2z, i2b, i2s 68.78 + // primitive double to single: 68.79 + _adapter_opt_l2i, 68.80 + _adapter_opt_d2f, 68.81 + // primitive single to double: 68.82 + _adapter_opt_i2l, 68.83 + _adapter_opt_f2d, 68.84 + // conversion between floating point and integer type is handled by Java 68.85 + 68.86 + // reference to primitive: 68.87 + _adapter_opt_unboxi, 68.88 + _adapter_opt_unboxl, 68.89 + 68.90 + // spreading (array length cases 0, 1, >=2) 68.91 + _adapter_opt_spread_0, 68.92 + _adapter_opt_spread_1, 68.93 + _adapter_opt_spread_more, 68.94 + 68.95 + _EK_LIMIT, 68.96 + _EK_FIRST = 0 68.97 + }; 68.98 + 68.99 + public: 68.100 + static bool enabled() { return _enabled; } 68.101 + static void set_enabled(bool z); 68.102 + 68.103 + private: 68.104 + enum { // import sun_dyn_AdapterMethodHandle::CONV_OP_* 68.105 + CONV_OP_LIMIT = sun_dyn_AdapterMethodHandle::CONV_OP_LIMIT, 68.106 + CONV_OP_MASK = sun_dyn_AdapterMethodHandle::CONV_OP_MASK, 68.107 + CONV_VMINFO_MASK = sun_dyn_AdapterMethodHandle::CONV_VMINFO_MASK, 68.108 + CONV_VMINFO_SHIFT = sun_dyn_AdapterMethodHandle::CONV_VMINFO_SHIFT, 68.109 + CONV_OP_SHIFT = sun_dyn_AdapterMethodHandle::CONV_OP_SHIFT, 68.110 + CONV_DEST_TYPE_SHIFT = sun_dyn_AdapterMethodHandle::CONV_DEST_TYPE_SHIFT, 68.111 + CONV_SRC_TYPE_SHIFT = sun_dyn_AdapterMethodHandle::CONV_SRC_TYPE_SHIFT, 68.112 + CONV_STACK_MOVE_SHIFT = sun_dyn_AdapterMethodHandle::CONV_STACK_MOVE_SHIFT, 68.113 + CONV_STACK_MOVE_MASK = sun_dyn_AdapterMethodHandle::CONV_STACK_MOVE_MASK 68.114 + }; 68.115 + 68.116 + static bool _enabled; 68.117 + static MethodHandleEntry* _entries[_EK_LIMIT]; 68.118 + static const char* _entry_names[_EK_LIMIT+1]; 68.119 + static bool ek_valid(EntryKind ek) { return (uint)ek < (uint)_EK_LIMIT; } 68.120 + static bool conv_op_valid(int op) { return (uint)op < (uint)CONV_OP_LIMIT; } 68.121 + 68.122 + public: 68.123 + static bool have_entry(EntryKind ek) { return ek_valid(ek) && _entries[ek] != NULL; } 68.124 + static MethodHandleEntry* entry(EntryKind ek) { assert(ek_valid(ek), "initialized"); 68.125 + return _entries[ek]; } 68.126 + static const char* entry_name(EntryKind ek) { assert(ek_valid(ek), "oob"); 68.127 + return _entry_names[ek]; } 68.128 + static EntryKind adapter_entry_kind(int op) { assert(conv_op_valid(op), "oob"); 68.129 + return EntryKind(_adapter_mh_first + op); } 68.130 + 68.131 + static void init_entry(EntryKind ek, MethodHandleEntry* me) { 68.132 + assert(ek_valid(ek), "oob"); 68.133 + assert(_entries[ek] == NULL, "no double initialization"); 68.134 + _entries[ek] = me; 68.135 + } 68.136 + 68.137 + static jint adapter_conversion(int conv_op, BasicType src, BasicType dest, 68.138 + int stack_move = 0, int vminfo = 0) { 68.139 + assert(conv_op_valid(conv_op), "oob"); 68.140 + jint conv = ((conv_op << CONV_OP_SHIFT) 68.141 + | (src << CONV_SRC_TYPE_SHIFT) 68.142 + | (dest << CONV_DEST_TYPE_SHIFT) 68.143 + | (stack_move << CONV_STACK_MOVE_SHIFT) 68.144 + | (vminfo << CONV_VMINFO_SHIFT) 68.145 + ); 68.146 + assert(adapter_conversion_op(conv) == conv_op, "decode conv_op"); 68.147 + assert(adapter_conversion_src_type(conv) == src, "decode src"); 68.148 + assert(adapter_conversion_dest_type(conv) == dest, "decode dest"); 68.149 + assert(adapter_conversion_stack_move(conv) == stack_move, "decode stack_move"); 68.150 + assert(adapter_conversion_vminfo(conv) == vminfo, "decode vminfo"); 68.151 + return conv; 68.152 + } 68.153 + static int adapter_conversion_op(jint conv) { 68.154 + return ((conv >> CONV_OP_SHIFT) & 0xF); 68.155 + } 68.156 + static BasicType adapter_conversion_src_type(jint conv) { 68.157 + return (BasicType)((conv >> CONV_SRC_TYPE_SHIFT) & 0xF); 68.158 + } 68.159 + static BasicType adapter_conversion_dest_type(jint conv) { 68.160 + return (BasicType)((conv >> CONV_DEST_TYPE_SHIFT) & 0xF); 68.161 + } 68.162 + static int adapter_conversion_stack_move(jint conv) { 68.163 + return (conv >> CONV_STACK_MOVE_SHIFT); 68.164 + } 68.165 + static int adapter_conversion_vminfo(jint conv) { 68.166 + return (conv >> CONV_VMINFO_SHIFT) & CONV_VMINFO_MASK; 68.167 + } 68.168 + 68.169 + // Offset in words that the interpreter stack pointer moves when an argument is pushed. 68.170 + // The stack_move value must always be a multiple of this. 68.171 + static int stack_move_unit() { 68.172 + return frame::interpreter_frame_expression_stack_direction() * Interpreter::stackElementWords(); 68.173 + } 68.174 + 68.175 + enum { CONV_VMINFO_SIGN_FLAG = 0x80 }; 68.176 + static int adapter_subword_vminfo(BasicType dest) { 68.177 + if (dest == T_BOOLEAN) return (BitsPerInt - 1); 68.178 + if (dest == T_CHAR) return (BitsPerInt - 16); 68.179 + if (dest == T_BYTE) return (BitsPerInt - 8) | CONV_VMINFO_SIGN_FLAG; 68.180 + if (dest == T_SHORT) return (BitsPerInt - 16) | CONV_VMINFO_SIGN_FLAG; 68.181 + return 0; // case T_INT 68.182 + } 68.183 + // Here is the transformation the i2i adapter must perform: 68.184 + static int truncate_subword_from_vminfo(jint value, int vminfo) { 68.185 + jint tem = value << vminfo; 68.186 + if ((vminfo & CONV_VMINFO_SIGN_FLAG) != 0) { 68.187 + return (jint)tem >> vminfo; 68.188 + } else { 68.189 + return (juint)tem >> vminfo; 68.190 + } 68.191 + } 68.192 + 68.193 + static inline address from_compiled_entry(EntryKind ek); 68.194 + static inline address from_interpreted_entry(EntryKind ek); 68.195 + 68.196 + // helpers for decode_method. 68.197 + static methodOop decode_methodOop(methodOop m, int& decode_flags_result); 68.198 + static methodOop decode_vmtarget(oop vmtarget, int vmindex, oop mtype, klassOop& receiver_limit_result, int& decode_flags_result); 68.199 + static methodOop decode_MemberName(oop mname, klassOop& receiver_limit_result, int& decode_flags_result); 68.200 + static methodOop decode_MethodHandle(oop mh, klassOop& receiver_limit_result, int& decode_flags_result); 68.201 + static methodOop decode_DirectMethodHandle(oop mh, klassOop& receiver_limit_result, int& decode_flags_result); 68.202 + static methodOop decode_BoundMethodHandle(oop mh, klassOop& receiver_limit_result, int& decode_flags_result); 68.203 + static methodOop decode_AdapterMethodHandle(oop mh, klassOop& receiver_limit_result, int& decode_flags_result); 68.204 + 68.205 + // Find out how many stack slots an mh pushes or pops. 68.206 + // The result is *not* reported as a multiple of stack_move_unit(); 68.207 + // It is a signed net number of pushes (a difference in vmslots). 68.208 + // To compare with a stack_move value, first multiply by stack_move_unit(). 68.209 + static int decode_MethodHandle_stack_pushes(oop mh); 68.210 + 68.211 + public: 68.212 + // working with member names 68.213 + static void resolve_MemberName(Handle mname, TRAPS); // compute vmtarget/vmindex from name/type 68.214 + static void expand_MemberName(Handle mname, int suppress, TRAPS); // expand defc/name/type if missing 68.215 + static void init_MemberName(oop mname_oop, oop target); // compute vmtarget/vmindex from target 68.216 + static void init_MemberName(oop mname_oop, methodOop m, bool do_dispatch); 68.217 + static void init_MemberName(oop mname_oop, klassOop field_holder, AccessFlags mods, int offset); 68.218 + static int find_MemberNames(klassOop k, symbolOop name, symbolOop sig, 68.219 + int mflags, klassOop caller, 68.220 + int skip, objArrayOop results); 68.221 + // bit values for suppress argument to expand_MemberName: 68.222 + enum { _suppress_defc = 1, _suppress_name = 2, _suppress_type = 4 }; 68.223 + 68.224 + // called from InterpreterGenerator and StubGenerator 68.225 + static address generate_method_handle_interpreter_entry(MacroAssembler* _masm); 68.226 + static void generate_method_handle_stub(MacroAssembler* _masm, EntryKind ek); 68.227 + 68.228 + // argument list parsing 68.229 + static int argument_slot(oop method_type, int arg); 68.230 + static int argument_slot_count(oop method_type) { return argument_slot(method_type, -1); } 68.231 + static int argument_slot_to_argnum(oop method_type, int argslot); 68.232 + 68.233 + // Runtime support 68.234 + enum { // bit-encoded flags from decode_method or decode_vmref 68.235 + _dmf_has_receiver = 0x01, // target method has leading reference argument 68.236 + _dmf_does_dispatch = 0x02, // method handle performs virtual or interface dispatch 68.237 + _dmf_from_interface = 0x04, // peforms interface dispatch 68.238 + _DMF_DIRECT_MASK = (_dmf_from_interface*2 - _dmf_has_receiver), 68.239 + _dmf_binds_method = 0x08, 68.240 + _dmf_binds_argument = 0x10, 68.241 + _DMF_BOUND_MASK = (_dmf_binds_argument*2 - _dmf_binds_method), 68.242 + _dmf_adapter_lsb = 0x20, 68.243 + _DMF_ADAPTER_MASK = (_dmf_adapter_lsb << CONV_OP_LIMIT) - _dmf_adapter_lsb 68.244 + }; 68.245 + static methodOop decode_method(oop x, klassOop& receiver_limit_result, int& decode_flags_result); 68.246 + enum { 68.247 + // format of query to getConstant: 68.248 + GC_JVM_PUSH_LIMIT = 0, 68.249 + GC_JVM_STACK_MOVE_LIMIT = 1, 68.250 + 68.251 + // format of result from getTarget / encode_target: 68.252 + ETF_HANDLE_OR_METHOD_NAME = 0, // all available data (immediate MH or method) 68.253 + ETF_DIRECT_HANDLE = 1, // ultimate method handle (will be a DMH, may be self) 68.254 + ETF_METHOD_NAME = 2, // ultimate method as MemberName 68.255 + ETF_REFLECT_METHOD = 3 // ultimate method as java.lang.reflect object (sans refClass) 68.256 + }; 68.257 + static int get_named_constant(int which, Handle name_box, TRAPS); 68.258 + static oop encode_target(Handle mh, int format, TRAPS); // report vmtarget (to Java code) 68.259 + static bool class_cast_needed(klassOop src, klassOop dst); 68.260 + 68.261 + private: 68.262 + // These checkers operate on a pair of whole MethodTypes: 68.263 + static const char* check_method_type_change(oop src_mtype, int src_beg, int src_end, 68.264 + int insert_argnum, oop insert_type, 68.265 + int change_argnum, oop change_type, 68.266 + int delete_argnum, 68.267 + oop dst_mtype, int dst_beg, int dst_end); 68.268 + static const char* check_method_type_insertion(oop src_mtype, 68.269 + int insert_argnum, oop insert_type, 68.270 + oop dst_mtype) { 68.271 + oop no_ref = NULL; 68.272 + return check_method_type_change(src_mtype, 0, -1, 68.273 + insert_argnum, insert_type, 68.274 + -1, no_ref, -1, dst_mtype, 0, -1); 68.275 + } 68.276 + static const char* check_method_type_conversion(oop src_mtype, 68.277 + int change_argnum, oop change_type, 68.278 + oop dst_mtype) { 68.279 + oop no_ref = NULL; 68.280 + return check_method_type_change(src_mtype, 0, -1, -1, no_ref, 68.281 + change_argnum, change_type, 68.282 + -1, dst_mtype, 0, -1); 68.283 + } 68.284 + static const char* check_method_type_passthrough(oop src_mtype, oop dst_mtype) { 68.285 + oop no_ref = NULL; 68.286 + return check_method_type_change(src_mtype, 0, -1, 68.287 + -1, no_ref, -1, no_ref, -1, 68.288 + dst_mtype, 0, -1); 68.289 + } 68.290 + 68.291 + // These checkers operate on pairs of argument or return types: 68.292 + static const char* check_argument_type_change(BasicType src_type, klassOop src_klass, 68.293 + BasicType dst_type, klassOop dst_klass, 68.294 + int argnum); 68.295 + 68.296 + static const char* check_argument_type_change(oop src_type, oop dst_type, 68.297 + int argnum) { 68.298 + klassOop src_klass = NULL, dst_klass = NULL; 68.299 + BasicType src_bt = java_lang_Class::as_BasicType(src_type, &src_klass); 68.300 + BasicType dst_bt = java_lang_Class::as_BasicType(dst_type, &dst_klass); 68.301 + return check_argument_type_change(src_bt, src_klass, 68.302 + dst_bt, dst_klass, argnum); 68.303 + } 68.304 + 68.305 + static const char* check_return_type_change(oop src_type, oop dst_type) { 68.306 + return check_argument_type_change(src_type, dst_type, -1); 68.307 + } 68.308 + 68.309 + static const char* check_return_type_change(BasicType src_type, klassOop src_klass, 68.310 + BasicType dst_type, klassOop dst_klass) { 68.311 + return check_argument_type_change(src_type, src_klass, dst_type, dst_klass, -1); 68.312 + } 68.313 + 68.314 + static const char* check_method_receiver(methodOop m, klassOop passed_recv_type); 68.315 + 68.316 + // These verifiers can block, and will throw an error if the checking fails: 68.317 + static void verify_vmslots(Handle mh, TRAPS); 68.318 + static void verify_vmargslot(Handle mh, int argnum, int argslot, TRAPS); 68.319 + 68.320 + static void verify_method_type(methodHandle m, Handle mtype, 68.321 + bool has_bound_oop, 68.322 + KlassHandle bound_oop_type, 68.323 + TRAPS); 68.324 + 68.325 + static void verify_method_signature(methodHandle m, Handle mtype, 68.326 + int first_ptype_pos, 68.327 + KlassHandle insert_ptype, TRAPS); 68.328 + 68.329 + static void verify_DirectMethodHandle(Handle mh, methodHandle m, TRAPS); 68.330 + static void verify_BoundMethodHandle(Handle mh, Handle target, int argnum, 68.331 + bool direct_to_method, TRAPS); 68.332 + static void verify_BoundMethodHandle_with_receiver(Handle mh, methodHandle m, TRAPS); 68.333 + static void verify_AdapterMethodHandle(Handle mh, int argnum, TRAPS); 68.334 + 68.335 + public: 68.336 + 68.337 + // Fill in the fields of a DirectMethodHandle mh. (MH.type must be pre-filled.) 68.338 + static void init_DirectMethodHandle(Handle mh, methodHandle method, bool do_dispatch, TRAPS); 68.339 + 68.340 + // Fill in the fields of a BoundMethodHandle mh. (MH.type, BMH.argument must be pre-filled.) 68.341 + static void init_BoundMethodHandle(Handle mh, Handle target, int argnum, TRAPS); 68.342 + static void init_BoundMethodHandle_with_receiver(Handle mh, 68.343 + methodHandle original_m, 68.344 + KlassHandle receiver_limit, 68.345 + int decode_flags, 68.346 + TRAPS); 68.347 + 68.348 + // Fill in the fields of an AdapterMethodHandle mh. (MH.type must be pre-filled.) 68.349 + static void init_AdapterMethodHandle(Handle mh, Handle target, int argnum, TRAPS); 68.350 + 68.351 +#ifdef ASSERT 68.352 + static bool spot_check_entry_names(); 68.353 +#endif 68.354 + 68.355 + private: 68.356 + static methodHandle dispatch_decoded_method(methodHandle m, 68.357 + KlassHandle receiver_limit, 68.358 + int decode_flags, 68.359 + KlassHandle receiver_klass, 68.360 + TRAPS); 68.361 + 68.362 + static bool same_basic_type_for_arguments(BasicType src, BasicType dst, 68.363 + bool for_return = false); 68.364 + static bool same_basic_type_for_returns(BasicType src, BasicType dst) { 68.365 + return same_basic_type_for_arguments(src, dst, true); 68.366 + } 68.367 + 68.368 + enum { // arg_mask values 68.369 + _INSERT_NO_MASK = -1, 68.370 + _INSERT_REF_MASK = 0, 68.371 + _INSERT_INT_MASK = 1, 68.372 + _INSERT_LONG_MASK = 3 68.373 + }; 68.374 + static void insert_arg_slots(MacroAssembler* _masm, 68.375 + RegisterOrConstant arg_slots, 68.376 + int arg_mask, 68.377 + Register rax_argslot, 68.378 + Register rbx_temp, Register rdx_temp); 68.379 + 68.380 + static void remove_arg_slots(MacroAssembler* _masm, 68.381 + RegisterOrConstant arg_slots, 68.382 + Register rax_argslot, 68.383 + Register rbx_temp, Register rdx_temp); 68.384 +}; 68.385 + 68.386 + 68.387 +// Access methods for the "entry" field of a java.dyn.MethodHandle. 68.388 +// The field is primarily a jump target for compiled calls. 68.389 +// However, we squirrel away some nice pointers for other uses, 68.390 +// just before the jump target. 68.391 +// Aspects of a method handle entry: 68.392 +// - from_compiled_entry - stub used when compiled code calls the MH 68.393 +// - from_interpreted_entry - stub used when the interpreter calls the MH 68.394 +// - type_checking_entry - stub for runtime casting between MHForm siblings (NYI) 68.395 +class MethodHandleEntry { 68.396 + public: 68.397 + class Data { 68.398 + friend class MethodHandleEntry; 68.399 + size_t _total_size; // size including Data and code stub 68.400 + MethodHandleEntry* _type_checking_entry; 68.401 + address _from_interpreted_entry; 68.402 + MethodHandleEntry* method_entry() { return (MethodHandleEntry*)(this + 1); } 68.403 + }; 68.404 + 68.405 + Data* data() { return (Data*)this - 1; } 68.406 + 68.407 + address start_address() { return (address) data(); } 68.408 + address end_address() { return start_address() + data()->_total_size; } 68.409 + 68.410 + address from_compiled_entry() { return (address) this; } 68.411 + 68.412 + address from_interpreted_entry() { return data()->_from_interpreted_entry; } 68.413 + void set_from_interpreted_entry(address e) { data()->_from_interpreted_entry = e; } 68.414 + 68.415 + MethodHandleEntry* type_checking_entry() { return data()->_type_checking_entry; } 68.416 + void set_type_checking_entry(MethodHandleEntry* e) { data()->_type_checking_entry = e; } 68.417 + 68.418 + void set_end_address(address end_addr) { 68.419 + size_t total_size = end_addr - start_address(); 68.420 + assert(total_size > 0 && total_size < 0x1000, "reasonable end address"); 68.421 + data()->_total_size = total_size; 68.422 + } 68.423 + 68.424 + // Compiler support: 68.425 + static int from_interpreted_entry_offset_in_bytes() { 68.426 + return (int)( offset_of(Data, _from_interpreted_entry) - sizeof(Data) ); 68.427 + } 68.428 + static int type_checking_entry_offset_in_bytes() { 68.429 + return (int)( offset_of(Data, _from_interpreted_entry) - sizeof(Data) ); 68.430 + } 68.431 + 68.432 + static address start_compiled_entry(MacroAssembler* _masm, 68.433 + address interpreted_entry = NULL); 68.434 + static MethodHandleEntry* finish_compiled_entry(MacroAssembler* masm, address start_addr); 68.435 +}; 68.436 + 68.437 +address MethodHandles::from_compiled_entry(EntryKind ek) { return entry(ek)->from_compiled_entry(); } 68.438 +address MethodHandles::from_interpreted_entry(EntryKind ek) { return entry(ek)->from_interpreted_entry(); }
69.1 --- a/src/share/vm/prims/nativeLookup.cpp Thu Apr 09 13:59:45 2009 -0700 69.2 +++ b/src/share/vm/prims/nativeLookup.cpp Tue Apr 14 12:25:54 2009 -0700 69.3 @@ -1,5 +1,5 @@ 69.4 /* 69.5 - * Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved. 69.6 + * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved. 69.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 69.8 * 69.9 * This code is free software; you can redistribute it and/or modify it 69.10 @@ -78,6 +78,7 @@ 69.11 69.12 extern "C" { 69.13 void JNICALL JVM_RegisterUnsafeMethods(JNIEnv *env, jclass unsafecls); 69.14 + void JNICALL JVM_RegisterMethodHandleMethods(JNIEnv *env, jclass unsafecls); 69.15 void JNICALL JVM_RegisterPerfMethods(JNIEnv *env, jclass perfclass); 69.16 } 69.17 69.18 @@ -97,6 +98,9 @@ 69.19 if (strstr(jni_name, "Java_sun_misc_Unsafe_registerNatives") != NULL) { 69.20 return CAST_FROM_FN_PTR(address, JVM_RegisterUnsafeMethods); 69.21 } 69.22 + if (strstr(jni_name, "Java_sun_dyn_MethodHandleNatives_registerNatives") != NULL) { 69.23 + return CAST_FROM_FN_PTR(address, JVM_RegisterMethodHandleMethods); 69.24 + } 69.25 if (strstr(jni_name, "Java_sun_misc_Perf_registerNatives") != NULL) { 69.26 return CAST_FROM_FN_PTR(address, JVM_RegisterPerfMethods); 69.27 }
70.1 --- a/src/share/vm/runtime/arguments.cpp Thu Apr 09 13:59:45 2009 -0700 70.2 +++ b/src/share/vm/runtime/arguments.cpp Tue Apr 14 12:25:54 2009 -0700 70.3 @@ -2627,6 +2627,13 @@ 70.4 } 70.5 #endif // PRODUCT 70.6 70.7 + if (EnableMethodHandles && !AnonymousClasses) { 70.8 + if (!FLAG_IS_DEFAULT(AnonymousClasses)) { 70.9 + warning("forcing AnonymousClasses true to enable EnableMethodHandles"); 70.10 + } 70.11 + AnonymousClasses = true; 70.12 + } 70.13 + 70.14 if (PrintGCDetails) { 70.15 // Turn on -verbose:gc options as well 70.16 PrintGC = true;
71.1 --- a/src/share/vm/runtime/globals.hpp Thu Apr 09 13:59:45 2009 -0700 71.2 +++ b/src/share/vm/runtime/globals.hpp Tue Apr 14 12:25:54 2009 -0700 71.3 @@ -3301,6 +3301,21 @@ 71.4 product(bool, AnonymousClasses, false, \ 71.5 "support sun.misc.Unsafe.defineAnonymousClass") \ 71.6 \ 71.7 + product(bool, EnableMethodHandles, false, \ 71.8 + "support method handles (true by default under JSR 292)") \ 71.9 + \ 71.10 + diagnostic(intx, MethodHandlePushLimit, 3, \ 71.11 + "number of additional stack slots a method handle may push") \ 71.12 + \ 71.13 + develop(bool, TraceMethodHandles, false, \ 71.14 + "trace internal method handle operations") \ 71.15 + \ 71.16 + diagnostic(bool, VerifyMethodHandles, trueInDebug, \ 71.17 + "perform extra checks when constructing method handles") \ 71.18 + \ 71.19 + diagnostic(bool, OptimizeMethodHandles, true, \ 71.20 + "when constructing method handles, try to improve them") \ 71.21 + \ 71.22 product(bool, TaggedStackInterpreter, false, \ 71.23 "Insert tags in interpreter execution stack for oopmap generaion")\ 71.24 \
72.1 --- a/src/share/vm/runtime/sharedRuntime.cpp Thu Apr 09 13:59:45 2009 -0700 72.2 +++ b/src/share/vm/runtime/sharedRuntime.cpp Tue Apr 14 12:25:54 2009 -0700 72.3 @@ -1471,9 +1471,73 @@ 72.4 return generate_class_cast_message(objName, targetKlass->external_name()); 72.5 } 72.6 72.7 +char* SharedRuntime::generate_wrong_method_type_message(JavaThread* thread, 72.8 + oopDesc* required, 72.9 + oopDesc* actual) { 72.10 + assert(EnableMethodHandles, ""); 72.11 + oop singleKlass = wrong_method_type_is_for_single_argument(thread, required); 72.12 + if (singleKlass != NULL) { 72.13 + const char* objName = "argument or return value"; 72.14 + if (actual != NULL) { 72.15 + // be flexible about the junk passed in: 72.16 + klassOop ak = (actual->is_klass() 72.17 + ? (klassOop)actual 72.18 + : actual->klass()); 72.19 + objName = Klass::cast(ak)->external_name(); 72.20 + } 72.21 + Klass* targetKlass = Klass::cast(required->is_klass() 72.22 + ? (klassOop)required 72.23 + : java_lang_Class::as_klassOop(required)); 72.24 + return generate_class_cast_message(objName, targetKlass->external_name()); 72.25 + } else { 72.26 + // %%% need to get the MethodType string, without messing around too much 72.27 + // Get a signature from the invoke instruction 72.28 + const char* mhName = "method handle"; 72.29 + const char* targetType = "the required signature"; 72.30 + vframeStream vfst(thread, true); 72.31 + if (!vfst.at_end()) { 72.32 + Bytecode_invoke* call = Bytecode_invoke_at(vfst.method(), vfst.bci()); 72.33 + methodHandle target; 72.34 + { 72.35 + EXCEPTION_MARK; 72.36 + target = call->static_target(THREAD); 72.37 + if (HAS_PENDING_EXCEPTION) { CLEAR_PENDING_EXCEPTION; } 72.38 + } 72.39 + if (target.not_null() 72.40 + && target->is_method_handle_invoke() 72.41 + && required == target->method_handle_type()) { 72.42 + targetType = target->signature()->as_C_string(); 72.43 + } 72.44 + } 72.45 + klassOop kignore; int fignore; 72.46 + methodOop actual_method = MethodHandles::decode_method(actual, 72.47 + kignore, fignore); 72.48 + if (actual_method != NULL) { 72.49 + if (actual_method->name() == vmSymbols::invoke_name()) 72.50 + mhName = "$"; 72.51 + else 72.52 + mhName = actual_method->signature()->as_C_string(); 72.53 + if (mhName[0] == '$') 72.54 + mhName = actual_method->signature()->as_C_string(); 72.55 + } 72.56 + return generate_class_cast_message(mhName, targetType, 72.57 + " cannot be called as "); 72.58 + } 72.59 +} 72.60 + 72.61 +oop SharedRuntime::wrong_method_type_is_for_single_argument(JavaThread* thr, 72.62 + oopDesc* required) { 72.63 + if (required == NULL) return NULL; 72.64 + if (required->klass() == SystemDictionary::class_klass()) 72.65 + return required; 72.66 + if (required->is_klass()) 72.67 + return Klass::cast(klassOop(required))->java_mirror(); 72.68 + return NULL; 72.69 +} 72.70 + 72.71 + 72.72 char* SharedRuntime::generate_class_cast_message( 72.73 - const char* objName, const char* targetKlassName) { 72.74 - const char* desc = " cannot be cast to "; 72.75 + const char* objName, const char* targetKlassName, const char* desc) { 72.76 size_t msglen = strlen(objName) + strlen(desc) + strlen(targetKlassName) + 1; 72.77 72.78 char* message = NEW_RESOURCE_ARRAY(char, msglen);
73.1 --- a/src/share/vm/runtime/sharedRuntime.hpp Thu Apr 09 13:59:45 2009 -0700 73.2 +++ b/src/share/vm/runtime/sharedRuntime.hpp Tue Apr 14 12:25:54 2009 -0700 73.3 @@ -212,10 +212,32 @@ 73.4 static char* generate_class_cast_message(JavaThread* thr, const char* name); 73.5 73.6 /** 73.7 + * Fill in the message for a WrongMethodTypeException 73.8 + * 73.9 + * @param thr the current thread 73.10 + * @param mtype (optional) expected method type (or argument class) 73.11 + * @param mhandle (optional) actual method handle (or argument) 73.12 + * @return the dynamically allocated exception message 73.13 + * 73.14 + * BCP for the frame on top of the stack must refer to an 73.15 + * 'invokevirtual' op for a method handle, or an 'invokedyamic' op. 73.16 + * The caller (or one of its callers) must use a ResourceMark 73.17 + * in order to correctly free the result. 73.18 + */ 73.19 + static char* generate_wrong_method_type_message(JavaThread* thr, 73.20 + oopDesc* mtype = NULL, 73.21 + oopDesc* mhandle = NULL); 73.22 + 73.23 + /** Return non-null if the mtype is a klass or Class, not a MethodType. */ 73.24 + static oop wrong_method_type_is_for_single_argument(JavaThread* thr, 73.25 + oopDesc* mtype); 73.26 + 73.27 + /** 73.28 * Fill in the "X cannot be cast to a Y" message for ClassCastException 73.29 * 73.30 * @param name the name of the class of the object attempted to be cast 73.31 * @param klass the name of the target klass attempt 73.32 + * @param gripe the specific kind of problem being reported 73.33 * @return the dynamically allocated exception message (must be freed 73.34 * by the caller using a resource mark) 73.35 * 73.36 @@ -224,7 +246,8 @@ 73.37 * The caller (or one of it's callers) must use a ResourceMark 73.38 * in order to correctly free the result. 73.39 */ 73.40 - static char* generate_class_cast_message(const char* name, const char* klass); 73.41 + static char* generate_class_cast_message(const char* name, const char* klass, 73.42 + const char* gripe = " cannot be cast to "); 73.43 73.44 // Resolves a call site- may patch in the destination of the call into the 73.45 // compiled code.
74.1 --- a/src/share/vm/utilities/accessFlags.hpp Thu Apr 09 13:59:45 2009 -0700 74.2 +++ b/src/share/vm/utilities/accessFlags.hpp Tue Apr 14 12:25:54 2009 -0700 74.3 @@ -1,5 +1,5 @@ 74.4 /* 74.5 - * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved. 74.6 + * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved. 74.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 74.8 * 74.9 * This code is free software; you can redistribute it and/or modify it 74.10 @@ -47,6 +47,8 @@ 74.11 JVM_ACC_IS_OLD = 0x00010000, // RedefineClasses() has replaced this method 74.12 JVM_ACC_IS_OBSOLETE = 0x00020000, // RedefineClasses() has made method obsolete 74.13 JVM_ACC_IS_PREFIXED_NATIVE = 0x00040000, // JVMTI has prefixed this native method 74.14 + JVM_MH_INVOKE_BITS // = 0x10001100 // MethodHandle.invoke quasi-native 74.15 + = (JVM_ACC_NATIVE | JVM_ACC_SYNTHETIC | JVM_ACC_MONITOR_MATCH), 74.16 74.17 // klassOop flags 74.18 JVM_ACC_HAS_MIRANDA_METHODS = 0x10000000, // True if this class has miranda methods in it's vtable 74.19 @@ -72,6 +74,7 @@ 74.20 74.21 // flags accepted by set_field_flags() 74.22 JVM_ACC_FIELD_FLAGS = 0x00008000 | JVM_ACC_WRITTEN_FLAGS 74.23 + 74.24 }; 74.25 74.26 74.27 @@ -114,6 +117,15 @@ 74.28 bool is_obsolete () const { return (_flags & JVM_ACC_IS_OBSOLETE ) != 0; } 74.29 bool is_prefixed_native () const { return (_flags & JVM_ACC_IS_PREFIXED_NATIVE ) != 0; } 74.30 74.31 + // JSR 292: A method of the form MethodHandle.invoke(A...)R method is 74.32 + // neither bytecoded nor a JNI native, but rather a fast call through 74.33 + // a lightweight method handle object. Because it is not bytecoded, 74.34 + // it has the native bit set, but the monitor-match bit is also set 74.35 + // to distinguish it from a JNI native (which never has the match bit set). 74.36 + // The synthetic bit is also present, because such a method is never 74.37 + // explicitly defined in Java code. 74.38 + bool is_method_handle_invoke () const { return (_flags & JVM_MH_INVOKE_BITS) == JVM_MH_INVOKE_BITS; } 74.39 + 74.40 // klassOop flags 74.41 bool has_miranda_methods () const { return (_flags & JVM_ACC_HAS_MIRANDA_METHODS ) != 0; } 74.42 bool has_vanilla_constructor () const { return (_flags & JVM_ACC_HAS_VANILLA_CONSTRUCTOR) != 0; } 74.43 @@ -199,6 +211,14 @@ 74.44 jshort as_short() { return (jshort)_flags; } 74.45 jint as_int() { return _flags; } 74.46 74.47 + inline friend AccessFlags accessFlags_from(jint flags); 74.48 + 74.49 // Printing/debugging 74.50 void print_on(outputStream* st) const PRODUCT_RETURN; 74.51 }; 74.52 + 74.53 +inline AccessFlags accessFlags_from(jint flags) { 74.54 + AccessFlags af; 74.55 + af._flags = flags; 74.56 + return af; 74.57 +}
75.1 --- a/src/share/vm/utilities/exceptions.hpp Thu Apr 09 13:59:45 2009 -0700 75.2 +++ b/src/share/vm/utilities/exceptions.hpp Tue Apr 14 12:25:54 2009 -0700 75.3 @@ -237,6 +237,9 @@ 75.4 #define THROW_ARG_0(name, signature, arg) THROW_ARG_(name, signature, arg, 0) 75.5 #define THROW_MSG_CAUSE_0(name, message, cause) THROW_MSG_CAUSE_(name, message, cause, 0) 75.6 75.7 +#define THROW_NULL(name) THROW_(name, NULL) 75.8 +#define THROW_MSG_NULL(name, message) THROW_MSG_(name, message, NULL) 75.9 + 75.10 // The CATCH macro checks that no exception has been thrown by a function; it is used at 75.11 // call sites about which is statically known that the callee cannot throw an exception 75.12 // even though it is declared with TRAPS.
76.1 --- a/src/share/vm/utilities/globalDefinitions.hpp Thu Apr 09 13:59:45 2009 -0700 76.2 +++ b/src/share/vm/utilities/globalDefinitions.hpp Tue Apr 14 12:25:54 2009 -0700 76.3 @@ -408,6 +408,15 @@ 76.4 return T_BOOLEAN <= t && t <= T_LONG; 76.5 } 76.6 76.7 +inline bool is_subword_type(BasicType t) { 76.8 + // these guys are processed exactly like T_INT in calling sequences: 76.9 + return (t == T_BOOLEAN || t == T_CHAR || t == T_BYTE || t == T_SHORT); 76.10 +} 76.11 + 76.12 +inline bool is_signed_subword_type(BasicType t) { 76.13 + return (t == T_BYTE || t == T_SHORT); 76.14 +} 76.15 + 76.16 // Convert a char from a classfile signature to a BasicType 76.17 inline BasicType char2type(char c) { 76.18 switch( c ) {
77.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 77.2 +++ b/test/compiler/6539464/Test.java Tue Apr 14 12:25:54 2009 -0700 77.3 @@ -0,0 +1,44 @@ 77.4 +/* 77.5 + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. 77.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 77.7 + * 77.8 + * This code is free software; you can redistribute it and/or modify it 77.9 + * under the terms of the GNU General Public License version 2 only, as 77.10 + * published by the Free Software Foundation. 77.11 + * 77.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 77.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 77.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 77.15 + * version 2 for more details (a copy is included in the LICENSE file that 77.16 + * accompanied this code). 77.17 + * 77.18 + * You should have received a copy of the GNU General Public License version 77.19 + * 2 along with this work; if not, write to the Free Software Foundation, 77.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 77.21 + * 77.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 77.23 + * CA 95054 USA or visit www.sun.com if you need additional information or 77.24 + * have any questions. 77.25 + */ 77.26 + 77.27 +/** 77.28 + * @test 77.29 + * @bug 6539464 77.30 + * @summary Math.log() produces inconsistent results between successive runs. 77.31 + * 77.32 + * @run main/othervm -Xcomp -XX:CompileOnly=Test.main Test 77.33 + */ 77.34 + 77.35 +public class Test { 77.36 + static double log_value = 17197; 77.37 + static double log_result = Math.log(log_value); 77.38 + 77.39 + public static void main(String[] args) throws Exception { 77.40 + for (int i = 0; i < 1000000; i++) { 77.41 + double log_result2 = Math.log(log_value); 77.42 + if (log_result2 != log_result) { 77.43 + throw new InternalError("Math.log produces inconsistent results: " + log_result2 + " != " + log_result); 77.44 + } 77.45 + } 77.46 + } 77.47 +}
78.1 --- a/test/compiler/6636138/Test1.java Thu Apr 09 13:59:45 2009 -0700 78.2 +++ b/test/compiler/6636138/Test1.java Tue Apr 14 12:25:54 2009 -0700 78.3 @@ -26,7 +26,7 @@ 78.4 * @bug 6636138 78.5 * @summary SuperWord::co_locate_pack(Node_List* p) generates memory graph that leads to memory order violation. 78.6 * 78.7 - * @run main/othervm -server -Xbatch -XX:CompileOnly=Test1.init -XX:+UseSuperword Test1 78.8 + * @run main/othervm -server -Xbatch -XX:CompileOnly=Test1.init Test1 78.9 */ 78.10 78.11 class Test1 {
79.1 --- a/test/compiler/6636138/Test2.java Thu Apr 09 13:59:45 2009 -0700 79.2 +++ b/test/compiler/6636138/Test2.java Tue Apr 14 12:25:54 2009 -0700 79.3 @@ -26,7 +26,7 @@ 79.4 * @bug 6636138 79.5 * @summary SuperWord::co_locate_pack(Node_List* p) generates memory graph that leads to memory order violation. 79.6 * 79.7 - * @run main/othervm -server -Xbatch -XX:CompileOnly=Test2.shift -XX:+UseSuperword Test2 79.8 + * @run main/othervm -server -Xbatch -XX:CompileOnly=Test2.shift Test2 79.9 */ 79.10 79.11 class Test2 {
80.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 80.2 +++ b/test/compiler/6711117/Test.java Tue Apr 14 12:25:54 2009 -0700 80.3 @@ -0,0 +1,849 @@ 80.4 +/* 80.5 + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. 80.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 80.7 + * 80.8 + * This code is free software; you can redistribute it and/or modify it 80.9 + * under the terms of the GNU General Public License version 2 only, as 80.10 + * published by the Free Software Foundation. 80.11 + * 80.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 80.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 80.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 80.15 + * version 2 for more details (a copy is included in the LICENSE file that 80.16 + * accompanied this code). 80.17 + * 80.18 + * You should have received a copy of the GNU General Public License version 80.19 + * 2 along with this work; if not, write to the Free Software Foundation, 80.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 80.21 + * 80.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 80.23 + * CA 95054 USA or visit www.sun.com if you need additional information or 80.24 + * have any questions. 80.25 + * 80.26 + */ 80.27 + 80.28 +/* 80.29 + * @test 80.30 + * @bug 6711117 80.31 + * @summary Assertion in 64bit server vm (flat != TypePtr::BOTTOM,"cannot alias-analyze an untyped ptr") 80.32 + * @run main/othervm -Xcomp -XX:+IgnoreUnrecognizedVMOptions -XX:+AggressiveOpts -XX:+UseCompressedOops Test 80.33 + */ 80.34 + 80.35 +final class Test_Class_0 { 80.36 + final static char var_1 = 'E'; 80.37 + short var_2 = 16213; 80.38 + final static String var_3 = "jiiibmmsk"; 80.39 + 80.40 + 80.41 + public Test_Class_0() 80.42 + { 80.43 + var_2 ^= 'M'; 80.44 + final String var_18 = var_3; 80.45 + var_2--; 80.46 + var_2 |= (byte)('D' / (byte)var_2) - ((byte)1.6680514E38F << + ((byte)'O') & 7320241275829036032L); 80.47 + func_2(((!false & false | false ? true : false) ? true : true | !true) ? var_2 : 834513107); 80.48 + var_2 >>>= var_1; 80.49 + "smiosoebk".codePointCount(true ^ (false ^ ! !false) ? (byte)- ((byte)430513598) : + ((byte)'_'), ~ (true ? (byte)']' : (byte)-2.8272547997066827E307)); 80.50 + var_2 -= true ? var_1 : var_1; 80.51 + var_2 ^= var_1; 80.52 + var_2 &= (var_2 |= ~ ((byte)(var_2 *= var_2))); 80.53 + long var_19 = 0L; 80.54 + short var_20 = var_2 += 'P'; 80.55 + while (var_19 < 1) 80.56 + { 80.57 + var_2 ^= true ? (byte)- +1.2219539475209E308 : (byte)1.2748408476894178E308; 80.58 + var_19++; 80.59 + var_2 = (byte)((1489358000 == (var_20 | 7816908224315289600L) ? var_1 : var_1) ^ var_19); 80.60 + var_20--; 80.61 + } 80.62 + var_20 -= 'f'; 80.63 + var_20 <<= (((new Test_Class_0[(byte)var_20])[(byte)var_2]).var_2 *= false ? 'g' : 'x'); 80.64 + } 80.65 + 80.66 + 80.67 + 80.68 + 80.69 + static float func_0() 80.70 + { 80.71 + ((new Test_Class_0[(byte)7.774490796987995E307])[(byte)'v']).var_2 <<= false ^ !false ? (short)'v' : "".codePointCount(594464985, 579036736); 80.72 + ((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; 80.73 + --((new Test_Class_0[false ? (byte)(short)1.4965069E36F : (byte)286322022])[(byte)- ((byte)2.742619E38F)]).var_2; 80.74 + long var_4; 80.75 + { 80.76 + double var_5; 80.77 + } 80.78 + var_4 = (byte)1.3509231E38F; 80.79 + ((new Test_Class_0[(byte)'_'])[('g' | 1427123046096105472L) < var_1 >> (byte)(int)(byte)7697616672011068416L ? (byte)var_1 : (byte)1251856579]).var_2--; 80.80 + 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) 80.81 + { 80.82 + case 99: 80.83 + 80.84 + } 80.85 + { 80.86 + byte var_6 = 13; 80.87 + } 80.88 + var_4 = --((new Test_Class_0[!var_3.endsWith("qaoioore") ^ false ? (byte)2.827362738392923E307 : (byte)~4890175967151316992L])[(byte)(short)var_1]).var_2; 80.89 + ++((new Test_Class_0[(byte)(1.0075552E38F + (short)2083553541)])[(byte)(short)(byte)(short)1.6872205E38F]).var_2; 80.90 + return ((new Test_Class_0[(byte)var_1])[(byte)+ +5760973323384750080L]).var_2 - (false ? (byte)'i' : (var_4 = (short)1.2458781351126844E308) + 2.131006E38F); 80.91 + } 80.92 + 80.93 + public static long func_1(String arg_0, Object arg_1, final long arg_2) 80.94 + { 80.95 + arg_0 = false ? arg_0 : "fgbrpgsq"; 80.96 + ((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); 80.97 + 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)); 80.98 + arg_0 = (arg_0 = arg_0.substring(699480935)); 80.99 + switch (((new Test_Class_0[(byte)(5415649243316856832L >> 861936806)])[true | true & !false ? (byte)(short)- -7.785169683394908E307 : (byte)+ ((byte)arg_2)]).var_2++) 80.100 + { 80.101 + case 42: 80.102 + 80.103 + case 102: 80.104 + 80.105 + } 80.106 + arg_1 = (true || false ? false : true) ? (arg_0 = (arg_0 = "jbfaru")) : arg_0; 80.107 + arg_1 = new byte[(byte)2.669957E38F]; 80.108 + boolean var_8 = ! ((false ? (short)1.4259420861834744E308 : (short)7.352115508157158E307) != 1.7635658130722812E308); 80.109 + arg_1 = new Object[(byte)- ((byte)(short)1.8950693E38F)]; 80.110 + arg_0 = arg_0; 80.111 + return (byte)1.4762239057269886E308 & 4923938844759802880L; 80.112 + } 80.113 + 80.114 + double[][] func_2(final int arg_0) 80.115 + { 80.116 + var_2 >>>= (var_2 >>= var_2++); 80.117 + float var_9 = 0F; 80.118 + var_2 %= var_2; 80.119 + do 80.120 + { 80.121 + ++var_2; 80.122 + var_9++; 80.123 + var_2++; 80.124 + } while (true && (var_9 < 1 && false)); 80.125 + double var_10 = 0; 80.126 + final int var_11 = 11903395; 80.127 + do 80.128 + { 80.129 + --var_2; 80.130 + var_10++; 80.131 + ++var_2; 80.132 + } while ((false & true || false) && (var_10 < 2 && ~ ((byte)'[') == (byte)(1.1943192E38F % ('c' << var_1) % (byte)((var_2 |= var_2) + 591679039 / ~5932100696448264192L)))); 80.133 + String var_12 = "jkwnk"; 80.134 + var_12 = var_3; 80.135 + var_12 = (var_12 = (var_12 = var_3)); 80.136 + var_12 = "qrhdwx"; 80.137 + var_12 = var_12; 80.138 + short var_13 = (true && true) ^ true | ! (!true || 1646418779 <= (byte)var_1) ? var_2 : var_2; 80.139 + return new double[(byte)var_1][true || false ^ !true ^ true ? (byte)arg_0 : (byte)var_10]; 80.140 + } 80.141 + 80.142 + private final int func_3() 80.143 + { 80.144 + long var_14 = 's' * (~ ~6656240461354863616L * 3151744928387344384L) << ~ (((var_2 >>>= 6600935261424147456L) % 1798503219359364096L | - ~3832249967647077376L / - ((byte)~1529201870915276800L)) / var_2); 80.145 + { 80.146 + var_14 |= !false | (byte)1078230528 >= (byte)1.3972878565417081E308 | (true | !true & !true & !false) ? var_1 : '_'; 80.147 + } 80.148 + long var_15 = 7589204885152164864L; 80.149 + var_2 ^= (var_1 < (byte)'r' ? 475314139 : 'Z') <= 1943074698 ? 'h' : var_1; 80.150 + return 'V' * (false ? (byte)5.498204E37F : (byte)1.0137001669765466E308); 80.151 + } 80.152 + 80.153 + protected static boolean func_4(boolean arg_0, byte arg_1, boolean arg_2) 80.154 + { 80.155 + arg_1++; 80.156 + 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)); 80.157 + arg_0 |= true; 80.158 + arg_1 %= (arg_1 |= ((new Test_Class_0[arg_1])[arg_1]).var_2--); 80.159 + if (false) 80.160 + { 80.161 + arg_0 |= arg_2; 80.162 + } 80.163 + else 80.164 + { 80.165 + ++(((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; 80.166 + } 80.167 + arg_1 &= +(new byte[arg_1])[arg_1]; 80.168 + arg_1 <<= 3632133838014908416L; 80.169 + byte[] var_16 = (new byte[arg_1][arg_1--])[arg_1]; 80.170 + long var_17; 80.171 + arg_1 ^= ~ arg_1--; 80.172 + arg_0 ^= (arg_2 ^= 1186877294 >= ((new Test_Class_0[arg_1][arg_1])[arg_1][arg_1]).var_2) & arg_2; 80.173 + return var_3.startsWith(var_3); 80.174 + } 80.175 + 80.176 + public String toString() 80.177 + { 80.178 + String result = "[\n"; 80.179 + result += "Test_Class_0.var_2 = "; result += Test.Printer.print(var_2); 80.180 + result += "\n"; 80.181 + result += "Test_Class_0.var_1 = "; result += Test.Printer.print(var_1); 80.182 + result += "\n"; 80.183 + result += "Test_Class_0.var_3 = "; result += Test.Printer.print(var_3); 80.184 + result += ""; 80.185 + result += "\n]"; 80.186 + return result; 80.187 + } 80.188 +} 80.189 + 80.190 + 80.191 +class Test_Class_1 { 80.192 + static int var_21 = 670918363; 80.193 + final float var_22 = 8.650798E37F; 80.194 + static int var_23 = 1774228457; 80.195 + final int var_24 = 1282736974; 80.196 + final byte var_25 = !false & false | true ? (byte)7.677121016144275E307 : (byte)'r'; 80.197 + static long var_26 = 2939310115459338240L; 80.198 + final long var_27 = var_25 - 7555453173456381952L; 80.199 + double var_28; 80.200 + static String var_29; 80.201 + 80.202 + 80.203 + public Test_Class_1() 80.204 + { 80.205 + var_29 = Test_Class_0.var_3; 80.206 + ((false ? false || ! !true : ! (! !true & !true)) ? new Test_Class_0() : new Test_Class_0()).var_2++; 80.207 + var_23 -= 2.963694E38F; 80.208 + } 80.209 + 80.210 + 80.211 + 80.212 + 80.213 + public String toString() 80.214 + { 80.215 + String result = "[\n"; 80.216 + result += "Test_Class_1.var_21 = "; result += Test.Printer.print(var_21); 80.217 + result += "\n"; 80.218 + result += "Test_Class_1.var_23 = "; result += Test.Printer.print(var_23); 80.219 + result += "\n"; 80.220 + result += "Test_Class_1.var_24 = "; result += Test.Printer.print(var_24); 80.221 + result += "\n"; 80.222 + result += "Test_Class_1.var_26 = "; result += Test.Printer.print(var_26); 80.223 + result += "\n"; 80.224 + result += "Test_Class_1.var_27 = "; result += Test.Printer.print(var_27); 80.225 + result += "\n"; 80.226 + result += "Test_Class_1.var_28 = "; result += Test.Printer.print(var_28); 80.227 + result += "\n"; 80.228 + result += "Test_Class_1.var_22 = "; result += Test.Printer.print(var_22); 80.229 + result += "\n"; 80.230 + result += "Test_Class_1.var_25 = "; result += Test.Printer.print(var_25); 80.231 + result += "\n"; 80.232 + result += "Test_Class_1.var_29 = "; result += Test.Printer.print(var_29); 80.233 + result += ""; 80.234 + result += "\n]"; 80.235 + return result; 80.236 + } 80.237 +} 80.238 + 80.239 + 80.240 +class Test_Class_2 { 80.241 + double var_30; 80.242 + static byte var_31; 80.243 + static char var_32; 80.244 + float var_33; 80.245 + double var_34 = !false & (true ? true : ! !true && false) ? 'q' - 4789231433793305600L - (var_33 = -1.0677024E38F) : 2.65473560313378E307; 80.246 + final double var_35 = ~Test_Class_1.var_26 == 5.145660681364723E307 | false ? 1.4134775E38F : 1.77223030708671E308; 80.247 + final int var_36 = Test_Class_1.var_23 |= Test_Class_1.var_21++; 80.248 + 80.249 + 80.250 + public Test_Class_2() 80.251 + { 80.252 + Test_Class_0.var_3.replace(Test_Class_0.var_1, 'Q'); 80.253 + var_32 = (var_32 = (var_32 = '_')); 80.254 + Test_Class_1.var_26 |= Test_Class_0.var_1; 80.255 + Test_Class_1.var_29 = (Test_Class_1.var_29 = Test_Class_0.var_3); 80.256 + var_32 = Test_Class_0.var_1; 80.257 + var_33 = ((new Test_Class_0[(byte)851412948463452160L])[var_31 = new Test_Class_1().var_25]).var_2; 80.258 + var_33 = ! (((!false | false) & (false || !true) ? false : ! !false) | false) ? new Test_Class_1().var_25 : (var_31 = new Test_Class_1().var_25); 80.259 + float var_38 = 0F; 80.260 + var_34 /= 5336005797857974272L; 80.261 + 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')) 80.262 + { 80.263 + var_32 = true ? 'a' : (var_32 = Test_Class_0.var_1); 80.264 + var_38++; 80.265 + var_33 = new Test_Class_1().var_24; 80.266 + var_32 = ! (true || true ? !false : (short)3.2844383E37F < 2.1400662E38F) ? (char)1.2691096999143248E308 : (! !false ^ true ? 's' : 'q'); 80.267 + } 80.268 + var_32 = 'B'; 80.269 + { 80.270 + var_32 = Test_Class_0.var_1; 80.271 + } 80.272 + var_32 = Test_Class_0.var_1; 80.273 + Test_Class_1.var_29 = "ov"; 80.274 + Test_Class_1.var_29 = "smtolghw"; 80.275 + } 80.276 + 80.277 + 80.278 + 80.279 + 80.280 + 80.281 + protected final static String func_0(final long[][] arg_0, byte arg_1, char arg_2) 80.282 + { 80.283 + 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; 80.284 + 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; 80.285 + float var_37 = 0F; 80.286 + arg_2 >>= ((new Test_Class_1[arg_1][arg_1])[arg_1][arg_1]).var_25; 80.287 + do 80.288 + { 80.289 + ((new Test_Class_2[arg_1 /= 2055714081])[arg_1]).var_34 = 'l'; 80.290 + var_37++; 80.291 + Test_Class_1.var_29 = Test_Class_0.var_3; 80.292 + } while ((false ? false : false) && var_37 < 7); 80.293 + Test_Class_1.var_29 = Test_Class_0.var_3 + ""; 80.294 + ((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; 80.295 + return "esb"; 80.296 + } 80.297 + 80.298 + public String toString() 80.299 + { 80.300 + String result = "[\n"; 80.301 + result += "Test_Class_2.var_32 = "; result += Test.Printer.print(var_32); 80.302 + result += "\n"; 80.303 + result += "Test_Class_2.var_36 = "; result += Test.Printer.print(var_36); 80.304 + result += "\n"; 80.305 + result += "Test_Class_2.var_30 = "; result += Test.Printer.print(var_30); 80.306 + result += "\n"; 80.307 + result += "Test_Class_2.var_34 = "; result += Test.Printer.print(var_34); 80.308 + result += "\n"; 80.309 + result += "Test_Class_2.var_35 = "; result += Test.Printer.print(var_35); 80.310 + result += "\n"; 80.311 + result += "Test_Class_2.var_33 = "; result += Test.Printer.print(var_33); 80.312 + result += "\n"; 80.313 + result += "Test_Class_2.var_31 = "; result += Test.Printer.print(var_31); 80.314 + result += ""; 80.315 + result += "\n]"; 80.316 + return result; 80.317 + } 80.318 +} 80.319 + 80.320 + 80.321 +final class Test_Class_3 extends Test_Class_2 { 80.322 + byte var_39 = 23; 80.323 + static boolean var_40 = false; 80.324 + 80.325 + 80.326 + public Test_Class_3() 80.327 + { 80.328 + if (true) 80.329 + { 80.330 + Test_Class_1.var_21 |= new Test_Class_1().var_27; 80.331 + } 80.332 + else 80.333 + { 80.334 + final float var_46 = 7.9266674E37F; 80.335 + ++Test_Class_1.var_26; 80.336 + } 80.337 + { 80.338 + Test_Class_1.var_23++; 80.339 + } 80.340 + var_30 = ((new Test_Class_1[var_39][var_39])[var_39][var_39]).var_25; 80.341 + if (var_40 &= (var_40 |= (var_40 |= var_40))) 80.342 + { 80.343 + 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); 80.344 + } 80.345 + else 80.346 + { 80.347 + var_40 &= var_40 && var_40; 80.348 + } 80.349 + ((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; 80.350 + switch (var_39) 80.351 + { 80.352 + case 24: 80.353 + 80.354 + } 80.355 + var_39 += (((var_40 ^= true) ? new Test_Class_0() : new Test_Class_0()).var_2 ^= var_40 & (var_40 | false) ? var_39-- : var_36); 80.356 + new Test_Class_0().var_2 %= (new Test_Class_0().var_2 += (var_39 ^= Test_Class_1.var_26)); 80.357 + } 80.358 + 80.359 + 80.360 + 80.361 + 80.362 + private static String func_0() 80.363 + { 80.364 + --Test_Class_1.var_26; 80.365 + { 80.366 + Test_Class_1.var_29 = var_40 ? Test_Class_0.var_3 : "rahqjhqf"; 80.367 + } 80.368 + if (var_40 ^= var_40) 80.369 + { 80.370 + Test_Class_1.var_26 >>= (Test_Class_2.var_32 = Test_Class_0.var_1) / new Test_Class_0().var_2; 80.371 + } 80.372 + else 80.373 + { 80.374 + ++Test_Class_1.var_21; 80.375 + } 80.376 + ++Test_Class_1.var_26; 80.377 + int var_41 = 0; 80.378 + ++Test_Class_1.var_26; 80.379 + do 80.380 + { 80.381 + var_40 = (var_40 = true); 80.382 + var_41++; 80.383 + Test_Class_0 var_42 = new Test_Class_0(); 80.384 + } while (var_41 < 1); 80.385 + Test_Class_1.var_29 = "f"; 80.386 + Test_Class_1 var_43; 80.387 + var_43 = (var_43 = new Test_Class_1()); 80.388 + Test_Class_2.var_32 = 'V'; 80.389 + long var_44 = 0L; 80.390 + Test_Class_1.var_23--; 80.391 + while (var_40 && (var_44 < 1 && var_40)) 80.392 + { 80.393 + Test_Class_1.var_29 = "bsgewkmk"; 80.394 + var_44++; 80.395 + Test_Class_1.var_29 = "ktegattny"; 80.396 + var_40 &= var_40 ^ (var_40 |= (short)4.4487427E37F < 'n') & true; 80.397 + } 80.398 + 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); 80.399 + float var_45; 80.400 + var_32 = (Test_Class_2.var_32 = Test_Class_0.var_1); 80.401 + return false ? "fluk" : "wt"; 80.402 + } 80.403 + 80.404 + public String toString() 80.405 + { 80.406 + String result = "[\n"; 80.407 + result += "Test_Class_3.var_32 = "; result += Test.Printer.print(var_32); 80.408 + result += "\n"; 80.409 + result += "Test_Class_3.var_36 = "; result += Test.Printer.print(var_36); 80.410 + result += "\n"; 80.411 + result += "Test_Class_3.var_30 = "; result += Test.Printer.print(var_30); 80.412 + result += "\n"; 80.413 + result += "Test_Class_3.var_34 = "; result += Test.Printer.print(var_34); 80.414 + result += "\n"; 80.415 + result += "Test_Class_3.var_35 = "; result += Test.Printer.print(var_35); 80.416 + result += "\n"; 80.417 + result += "Test_Class_3.var_33 = "; result += Test.Printer.print(var_33); 80.418 + result += "\n"; 80.419 + result += "Test_Class_3.var_31 = "; result += Test.Printer.print(var_31); 80.420 + result += "\n"; 80.421 + result += "Test_Class_3.var_39 = "; result += Test.Printer.print(var_39); 80.422 + result += "\n"; 80.423 + result += "Test_Class_3.var_40 = "; result += Test.Printer.print(var_40); 80.424 + result += ""; 80.425 + result += "\n]"; 80.426 + return result; 80.427 + } 80.428 +} 80.429 + 80.430 + 80.431 +class Test_Class_4 { 80.432 + final float var_47 = 1.9043434E38F; 80.433 + final byte var_48 = 32; 80.434 + final float var_49 = 2.8176504E38F; 80.435 + final char var_50 = 'r'; 80.436 + final String var_51 = "uwgmnjpg"; 80.437 + static int var_52; 80.438 + short[] var_53; 80.439 + Test_Class_1 var_54; 80.440 + 80.441 + 80.442 + public Test_Class_4() 80.443 + { 80.444 + 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; 80.445 + new Test_Class_0().var_2 = (new Test_Class_0().var_2 >>= +new Test_Class_1().var_25); 80.446 + ((Test_Class_1.var_29 = (Test_Class_1.var_29 = (Test_Class_1.var_29 = "l"))) + "").equalsIgnoreCase(Test_Class_1.var_29 = "garnio"); 80.447 + double var_56 = 0; 80.448 + Test_Class_1.var_29 = var_51; 80.449 + while (var_56 < 1) 80.450 + { 80.451 + ((Test_Class_3)(Test_Class_2)(new Object[var_48])[var_48]).var_33 = ++Test_Class_1.var_26; 80.452 + var_56++; 80.453 + Test_Class_1.var_29 = (Test_Class_1.var_29 = "fvyjrih"); 80.454 + float[] var_57; 80.455 + } 80.456 + { 80.457 + ((new Test_Class_2[var_48])[((new Test_Class_3[var_48][var_48])[var_48][var_48]).var_39]).var_34 *= 2.2119221943262553E307; 80.458 + Test_Class_2.var_32 = true ? 'q' : 't'; 80.459 + ((new Test_Class_3[--((Test_Class_3)new Test_Class_2()).var_39])[var_48]).var_33 = new Test_Class_0().var_2; 80.460 + int var_58 = 'i' >> (var_48 << Test_Class_0.var_1); 80.461 + } 80.462 + 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; 80.463 + ((Test_Class_3)(Test_Class_2)(new Object[var_48][var_48])[var_48][var_48]).var_34 += Test_Class_1.var_26--; 80.464 + var_54 = new Test_Class_1(); 80.465 + 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; 80.466 + (Test_Class_3.var_40 ? (true ? new Test_Class_0() : new Test_Class_0()) : new Test_Class_0()).var_2 &= var_48; 80.467 + (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; 80.468 + Test_Class_3 var_59; 80.469 + Test_Class_2.var_32 = 'H'; 80.470 + --Test_Class_1.var_26; 80.471 + } 80.472 + 80.473 + 80.474 + 80.475 + 80.476 + 80.477 + public String toString() 80.478 + { 80.479 + String result = "[\n"; 80.480 + result += "Test_Class_4.var_50 = "; result += Test.Printer.print(var_50); 80.481 + result += "\n"; 80.482 + result += "Test_Class_4.var_52 = "; result += Test.Printer.print(var_52); 80.483 + result += "\n"; 80.484 + result += "Test_Class_4.var_53 = "; result += Test.Printer.print(var_53); 80.485 + result += "\n"; 80.486 + result += "Test_Class_4.var_47 = "; result += Test.Printer.print(var_47); 80.487 + result += "\n"; 80.488 + result += "Test_Class_4.var_49 = "; result += Test.Printer.print(var_49); 80.489 + result += "\n"; 80.490 + result += "Test_Class_4.var_48 = "; result += Test.Printer.print(var_48); 80.491 + result += "\n"; 80.492 + result += "Test_Class_4.var_51 = "; result += Test.Printer.print(var_51); 80.493 + result += "\n"; 80.494 + result += "Test_Class_4.var_54 = "; result += Test.Printer.print(var_54); 80.495 + result += ""; 80.496 + result += "\n]"; 80.497 + return result; 80.498 + } 80.499 +} 80.500 + 80.501 + 80.502 +class Test_Class_5 extends Test_Class_4 { 80.503 + char var_60 = '_'; 80.504 + final byte var_61 = 101; 80.505 + 80.506 + 80.507 + public Test_Class_5() 80.508 + { 80.509 + 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'); 80.510 + } 80.511 + 80.512 + 80.513 + 80.514 + 80.515 + final char func_0(Test_Class_1 arg_0, final Test_Class_1 arg_1) 80.516 + { 80.517 + long var_62 = 0L; 80.518 + "aoal".toLowerCase(); 80.519 + 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) 80.520 + { 80.521 + ((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; 80.522 + var_62++; 80.523 + (!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)); 80.524 + float var_64; 80.525 + } 80.526 + Test_Class_1.var_29 = "xyenjknu"; 80.527 + Test_Class_3.var_40 ^= (Test_Class_3.var_40 = !false & true) ? Test_Class_3.var_40 : Test_Class_3.var_40; 80.528 + ((new Test_Class_2[var_48][arg_1.var_25])[arg_0.var_25][var_48]).var_33 = var_61; 80.529 + 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; 80.530 + var_51.compareToIgnoreCase("hgcaybk"); 80.531 + 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]; 80.532 + return 'U'; 80.533 + } 80.534 + 80.535 + protected static Test_Class_1 func_1(final short arg_0, long arg_1) 80.536 + { 80.537 + --new Test_Class_0().var_2; 80.538 + "xb".length(); 80.539 + 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) 80.540 + { 80.541 + --Test_Class_1.var_26; 80.542 + } 80.543 + else 80.544 + { 80.545 + "ybbe".substring(209378562, var_52 = (Test_Class_1.var_21 |= (Test_Class_2.var_31 = (byte)'a'))); 80.546 + } 80.547 + 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); 80.548 + (false ? new Test_Class_0() : new Test_Class_0()).var_2 >>= new Test_Class_1().var_25; 80.549 + 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(); 80.550 + } 80.551 + 80.552 + public String toString() 80.553 + { 80.554 + String result = "[\n"; 80.555 + result += "Test_Class_5.var_50 = "; result += Test.Printer.print(var_50); 80.556 + result += "\n"; 80.557 + result += "Test_Class_5.var_60 = "; result += Test.Printer.print(var_60); 80.558 + result += "\n"; 80.559 + result += "Test_Class_5.var_52 = "; result += Test.Printer.print(var_52); 80.560 + result += "\n"; 80.561 + result += "Test_Class_5.var_53 = "; result += Test.Printer.print(var_53); 80.562 + result += "\n"; 80.563 + result += "Test_Class_5.var_47 = "; result += Test.Printer.print(var_47); 80.564 + result += "\n"; 80.565 + result += "Test_Class_5.var_49 = "; result += Test.Printer.print(var_49); 80.566 + result += "\n"; 80.567 + result += "Test_Class_5.var_48 = "; result += Test.Printer.print(var_48); 80.568 + result += "\n"; 80.569 + result += "Test_Class_5.var_61 = "; result += Test.Printer.print(var_61); 80.570 + result += "\n"; 80.571 + result += "Test_Class_5.var_51 = "; result += Test.Printer.print(var_51); 80.572 + result += "\n"; 80.573 + result += "Test_Class_5.var_54 = "; result += Test.Printer.print(var_54); 80.574 + result += ""; 80.575 + result += "\n]"; 80.576 + return result; 80.577 + } 80.578 +} 80.579 + 80.580 +public class Test { 80.581 + Test_Class_4 var_66; 80.582 + Test_Class_3 var_67; 80.583 + Test_Class_5 var_68; 80.584 + Test_Class_2[] var_69; 80.585 + long var_70 = ++Test_Class_1.var_26 & Test_Class_1.var_21++; 80.586 + final static double var_71 = 3.566207721984698E307; 80.587 + static boolean var_72; 80.588 + final static String var_73 = "nmxx"; 80.589 + 80.590 + 80.591 + private final char func_0(Test_Class_3 arg_0, final boolean[] arg_1) 80.592 + { 80.593 + ((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(); 80.594 + new Test_Class_0(); 80.595 + (((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]); 80.596 + ((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)] << ']'; 80.597 + 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); 80.598 + Test_Class_1.var_26--; 80.599 + Test_Class_4 var_74 = var_66 = (Test_Class_5)(new Test_Class_4[arg_0.var_39])[arg_0.var_39]; 80.600 + 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)); 80.601 + 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; 80.602 + 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); 80.603 + arg_0.var_39 -= --var_70; 80.604 + int var_75; 80.605 + double var_76; 80.606 + { 80.607 + boolean var_77; 80.608 + var_70 ^= new Test_Class_0().var_2++; 80.609 + } 80.610 + Test_Class_1.var_26 /= Test_Class_0.var_3.lastIndexOf(~new Test_Class_1().var_25, Test_Class_1.var_21); 80.611 + Test_Class_1.var_26 |= Test_Class_1.var_21; 80.612 + (((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; 80.613 + Test_Class_1.var_21 &= arg_0.var_39; 80.614 + var_68 = (var_68 = (Test_Class_5)var_74); 80.615 + var_72 = false; 80.616 + return new Test_Class_5().var_60 ^= 'v'; 80.617 + } 80.618 + 80.619 + 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) 80.620 + { 80.621 + ((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()))); 80.622 + { 80.623 + --Test_Class_1.var_26; 80.624 + } 80.625 + if (!Test_Class_3.var_40) 80.626 + { 80.627 + "jfqj".replaceAll("ac", Test_Class_0.var_3); 80.628 + } 80.629 + else 80.630 + { 80.631 + 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); 80.632 + new Test_Class_1(); 80.633 + } 80.634 + if (true) 80.635 + { 80.636 + Test_Class_0.func_0(); 80.637 + } 80.638 + else 80.639 + { 80.640 + Test_Class_1.var_23 /= Test_Class_1.var_26; 80.641 + } 80.642 + Test_Class_1.var_26--; 80.643 + Test_Class_1.var_23 ^= Test_Class_0.var_1; 80.644 + return new Test_Class_2(); 80.645 + } 80.646 + 80.647 + public static String execute() 80.648 + { 80.649 + try { 80.650 + Test t = new Test(); 80.651 + try { t.test(); } 80.652 + catch(Throwable e) { } 80.653 + try { return t.toString(); } 80.654 + catch (Throwable e) { return "Error during result conversion to String"; } 80.655 + } catch (Throwable e) { return "Error during test execution"; } 80.656 + } 80.657 + 80.658 + public static void main(String[] args) 80.659 + { 80.660 + try { 80.661 + Test t = new Test(); 80.662 + try { t.test(); } 80.663 + catch(Throwable e) { } 80.664 + try { System.out.println(t); } 80.665 + catch(Throwable e) { } 80.666 + } catch (Throwable e) { } 80.667 + } 80.668 + 80.669 + private void test() 80.670 + { 80.671 + double var_78 = 0; 80.672 + --Test_Class_1.var_26; 80.673 + long var_79; 80.674 + 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) 80.675 + { 80.676 + short var_80 = 10682; 80.677 + Test_Class_1.var_21--; 80.678 + var_78++; 80.679 + var_72 = (Test_Class_3.var_40 |= (Test_Class_3.var_40 ^= false)); 80.680 + ++Test_Class_1.var_26; 80.681 + } 80.682 + Test_Class_2 var_81; 80.683 + new Test_Class_4(); 80.684 + int var_82 = 0; 80.685 + ++Test_Class_1.var_23; 80.686 + do 80.687 + { 80.688 + --Test_Class_1.var_26; 80.689 + var_82++; 80.690 + ++Test_Class_1.var_21; 80.691 + } while ((Test_Class_3.var_40 ^= false & false) && var_82 < 256); 80.692 + 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); 80.693 + (true ? new Test_Class_5() : (var_68 = (var_68 = new Test_Class_5()))).var_60 *= Test_Class_0.var_1; 80.694 + } 80.695 + public String toString() 80.696 + { 80.697 + String result = "[\n"; 80.698 + result += "Test.var_69 = "; result += Printer.print(var_69); 80.699 + result += "\n"; 80.700 + result += "Test.var_70 = "; result += Printer.print(var_70); 80.701 + result += "\n"; 80.702 + result += "Test.var_71 = "; result += Printer.print(var_71); 80.703 + result += "\n"; 80.704 + result += "Test.var_73 = "; result += Printer.print(var_73); 80.705 + result += "\n"; 80.706 + result += "Test.var_68 = "; result += Printer.print(var_68); 80.707 + result += "\n"; 80.708 + result += "Test.var_66 = "; result += Printer.print(var_66); 80.709 + result += "\n"; 80.710 + result += "Test.var_72 = "; result += Printer.print(var_72); 80.711 + result += "\n"; 80.712 + result += "Test.var_67 = "; result += Printer.print(var_67); 80.713 + result += ""; 80.714 + result += "\n]"; 80.715 + return result; 80.716 + } 80.717 + static class Printer 80.718 + { 80.719 + public static String print(boolean arg) { return String.valueOf(arg); } 80.720 + public static String print(byte arg) { return String.valueOf(arg); } 80.721 + public static String print(short arg) { return String.valueOf(arg); } 80.722 + public static String print(char arg) { return String.valueOf((int)arg); } 80.723 + public static String print(int arg) { return String.valueOf(arg); } 80.724 + public static String print(long arg) { return String.valueOf(arg); } 80.725 + public static String print(float arg) { return String.valueOf(arg); } 80.726 + public static String print(double arg) { return String.valueOf(arg); } 80.727 + 80.728 + 80.729 + public static String print(Object arg) 80.730 + { 80.731 + return print_r(new java.util.Stack(), arg); 80.732 + } 80.733 + 80.734 + private static String print_r(java.util.Stack visitedObjects, Object arg) 80.735 + { 80.736 + String result = ""; 80.737 + if (arg == null) 80.738 + result += "null"; 80.739 + else 80.740 + if (arg.getClass().isArray()) 80.741 + { 80.742 + for (int i = 0; i < visitedObjects.size(); i++) 80.743 + if (visitedObjects.elementAt(i) == arg) return "<recursive>"; 80.744 + 80.745 + visitedObjects.push(arg); 80.746 + 80.747 + final String delimiter = ", "; 80.748 + result += "["; 80.749 + 80.750 + if (arg instanceof Object[]) 80.751 + { 80.752 + Object[] array = (Object[]) arg; 80.753 + for (int i = 0; i < array.length; i++) 80.754 + { 80.755 + result += print_r(visitedObjects, array[i]); 80.756 + if (i < array.length - 1) result += delimiter; 80.757 + } 80.758 + } 80.759 + else 80.760 + if (arg instanceof boolean[]) 80.761 + { 80.762 + boolean[] array = (boolean[]) arg; 80.763 + for (int i = 0; i < array.length; i++) 80.764 + { 80.765 + result += print(array[i]); 80.766 + if (i < array.length - 1) result += delimiter; 80.767 + } 80.768 + } 80.769 + else 80.770 + if (arg instanceof byte[]) 80.771 + { 80.772 + byte[] array = (byte[]) arg; 80.773 + for (int i = 0; i < array.length; i++) 80.774 + { 80.775 + result += print(array[i]); 80.776 + if (i < array.length - 1) result += delimiter; 80.777 + } 80.778 + } 80.779 + else 80.780 + if (arg instanceof short[]) 80.781 + { 80.782 + short[] array = (short[]) arg; 80.783 + for (int i = 0; i < array.length; i++) 80.784 + { 80.785 + result += print(array[i]); 80.786 + if (i < array.length - 1) result += delimiter; 80.787 + } 80.788 + } 80.789 + else 80.790 + if (arg instanceof char[]) 80.791 + { 80.792 + char[] array = (char[]) arg; 80.793 + for (int i = 0; i < array.length; i++) 80.794 + { 80.795 + result += print(array[i]); 80.796 + if (i < array.length - 1) result += delimiter; 80.797 + } 80.798 + } 80.799 + else 80.800 + if (arg instanceof int[]) 80.801 + { 80.802 + int[] array = (int[]) arg; 80.803 + for (int i = 0; i < array.length; i++) 80.804 + { 80.805 + result += print(array[i]); 80.806 + if (i < array.length - 1) result += delimiter; 80.807 + } 80.808 + } 80.809 + else 80.810 + if (arg instanceof long[]) 80.811 + { 80.812 + long[] array = (long[]) arg; 80.813 + for (int i = 0; i < array.length; i++) 80.814 + { 80.815 + result += print(array[i]); 80.816 + if (i < array.length - 1) result += delimiter; 80.817 + } 80.818 + } 80.819 + else 80.820 + if (arg instanceof float[]) 80.821 + { 80.822 + float[] array = (float[]) arg; 80.823 + for (int i = 0; i < array.length; i++) 80.824 + { 80.825 + result += print(array[i]); 80.826 + if (i < array.length - 1) result += delimiter; 80.827 + } 80.828 + } 80.829 + else 80.830 + if (arg instanceof double[]) 80.831 + { 80.832 + double[] array = (double[]) arg; 80.833 + for (int i = 0; i < array.length; i++) 80.834 + { 80.835 + result += print(array[i]); 80.836 + if (i < array.length - 1) result += delimiter; 80.837 + } 80.838 + } 80.839 + 80.840 + result += "]"; 80.841 + visitedObjects.pop(); 80.842 + 80.843 + } else 80.844 + { 80.845 + result += arg.toString(); 80.846 + } 80.847 + 80.848 + return result; 80.849 + } 80.850 + } 80.851 +} 80.852 +
81.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 81.2 +++ b/test/compiler/6823453/Test.java Tue Apr 14 12:25:54 2009 -0700 81.3 @@ -0,0 +1,96 @@ 81.4 +/* 81.5 + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. 81.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 81.7 + * 81.8 + * This code is free software; you can redistribute it and/or modify it 81.9 + * under the terms of the GNU General Public License version 2 only, as 81.10 + * published by the Free Software Foundation. 81.11 + * 81.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 81.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 81.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 81.15 + * version 2 for more details (a copy is included in the LICENSE file that 81.16 + * accompanied this code). 81.17 + * 81.18 + * You should have received a copy of the GNU General Public License version 81.19 + * 2 along with this work; if not, write to the Free Software Foundation, 81.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 81.21 + * 81.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 81.23 + * CA 95054 USA or visit www.sun.com if you need additional information or 81.24 + * have any questions. 81.25 + * 81.26 + */ 81.27 + 81.28 +/* 81.29 + * @test 81.30 + * @bug 6823453 81.31 + * @summary DeoptimizeALot causes fastdebug server jvm to fail with assert(false,"unscheduable graph") 81.32 + * @run main/othervm -Xcomp -XX:CompileOnly=Test -XX:+DeoptimizeALot Test 81.33 + */ 81.34 + 81.35 +public class Test { 81.36 + 81.37 + static long vara_1 = 1L; 81.38 + 81.39 + static void testa() { 81.40 + short var_2 = (byte) 1.0E10; 81.41 + 81.42 + for ( Object temp = new byte[(byte)1.0E10]; true ; 81.43 + var_2 = "1".equals("0") ? ((byte) vara_1) : 1 ) {} 81.44 + } 81.45 + 81.46 + static void testb() { 81.47 + long var_1 = -1L; 81.48 + 81.49 + short var_2 = (byte) 1.0E10; 81.50 + 81.51 + for ( Object temp = new byte[(byte)1.0E10]; true ; 81.52 + var_2 = "1".equals("0") ? ((byte) var_1) : 1 ) {} 81.53 + } 81.54 + 81.55 + static void testc() { 81.56 + long var_1 = -1L; 81.57 + if (vara_1 > 0) var_1 = 1L; 81.58 + 81.59 + int var_2 = (byte)var_1 - 128; 81.60 + 81.61 + for ( Object temp = new byte[var_2]; true ; 81.62 + var_2 = "1".equals("0") ? 2 : 1 ) {} 81.63 + } 81.64 + 81.65 + static void testd() { 81.66 + long var_1 = 0L; 81.67 + 81.68 + int var_2 = (byte)var_1 + 1; 81.69 + for (int i=0; i<2 ; i++) var_2 = var_2 - 1; 81.70 + 81.71 + for ( Object temp = new byte[var_2]; true ; 81.72 + var_2 = "1".equals("0") ? 2 : 1 ) {} 81.73 + } 81.74 + 81.75 + public static void main(String[] args) throws Exception { 81.76 + int nex = 0; 81.77 + 81.78 + try { 81.79 + testa(); 81.80 + } 81.81 + catch (java.lang.NegativeArraySizeException ex) { nex++; } 81.82 + try { 81.83 + testb(); 81.84 + } 81.85 + catch (java.lang.NegativeArraySizeException ex) { nex++; } 81.86 + try { 81.87 + testc(); 81.88 + } 81.89 + catch (java.lang.NegativeArraySizeException ex) { nex++; } 81.90 + try { 81.91 + testd(); 81.92 + } 81.93 + catch (java.lang.NegativeArraySizeException ex) { nex++; } 81.94 + 81.95 + if (nex != 4) 81.96 + System.exit(97); 81.97 + } 81.98 +} 81.99 +