Merge

Tue, 14 Apr 2009 12:25:54 -0700

author
never
date
Tue, 14 Apr 2009 12:25:54 -0700
changeset 1147
6e33bfd4139b
parent 1138
68cd0d7ee9bb
parent 1146
9610b2a8ab4e
child 1148
4961a8a726a4
child 1155
67a2f5ba5582

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 +

mercurial