changeset 2535:0e9653efc6ea

Merge
author asaha
date Mon, 06 Jun 2011 10:55:41 -0700
parents a983caeb2b3e 7bf54248da9f
children a884a8b0ec6d
files
diffstat 17 files changed, 732 insertions(+), 231 deletions(-) [+]
line wrap: on
line diff
--- a/.hgtags	Fri Jun 03 07:53:33 2011 -0700
+++ b/.hgtags	Mon Jun 06 10:55:41 2011 -0700
@@ -175,3 +175,4 @@
 c149193c768b8b7233da4c3a3fdc0756b975848e hs21-b13
 c149193c768b8b7233da4c3a3fdc0756b975848e jdk7-b143
 fe189d4a44e9e8f0c7d78fcbd1c63701745752ca jdk7-b144
+62f39d40ebf176306a916812729df586f9d10f43 hs21-b14
--- a/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp	Fri Jun 03 07:53:33 2011 -0700
+++ b/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp	Mon Jun 06 10:55:41 2011 -0700
@@ -3113,7 +3113,6 @@
     // reload the register args properly if we go slow path. Yuck
 
     // These are proper for the calling convention
-
     store_parameter(length, 2);
     store_parameter(dst_pos, 1);
     store_parameter(dst, 0);
@@ -3351,12 +3350,15 @@
           __ jcc(Assembler::notEqual, *stub->entry());
         }
 
+       // Spill because stubs can use any register they like and it's
+       // easier to restore just those that we care about.
+       store_parameter(dst, 0);
+       store_parameter(dst_pos, 1);
+       store_parameter(length, 2);
+       store_parameter(src_pos, 3);
+       store_parameter(src, 4);
+
 #ifndef _LP64
-        // save caller save registers
-        store_parameter(rax, 2);
-        store_parameter(rcx, 1);
-        store_parameter(rdx, 0);
-
         __ movptr(tmp, dst_klass_addr);
         __ movptr(tmp, Address(tmp, objArrayKlass::element_klass_offset_in_bytes() + sizeof(oopDesc)));
         __ push(tmp);
@@ -3372,17 +3374,6 @@
 #else
         __ movl2ptr(length, length); //higher 32bits must be null
 
-        // save caller save registers: copy them to callee save registers
-        __ mov(rbx, rdx);
-        __ mov(r13, r8);
-        __ mov(r14, r9);
-#ifndef _WIN64
-        store_parameter(rsi, 1);
-        store_parameter(rcx, 0);
-        // on WIN64 other incoming parameters are in rdi and rsi saved
-        // across the call
-#endif
-
         __ lea(c_rarg0, Address(src, src_pos, scale, arrayOopDesc::base_offset_in_bytes(basic_type)));
         assert_different_registers(c_rarg0, dst, dst_pos, length);
         __ lea(c_rarg1, Address(dst, dst_pos, scale, arrayOopDesc::base_offset_in_bytes(basic_type)));
@@ -3432,25 +3423,13 @@
 
         __ xorl(tmp, -1);
 
-#ifndef _LP64
-        // restore caller save registers
-        assert_different_registers(tmp, rdx, rcx, rax); // result of stub will be lost
-        __ movptr(rdx, Address(rsp, 0*BytesPerWord));
-        __ movptr(rcx, Address(rsp, 1*BytesPerWord));
-        __ movptr(rax, Address(rsp, 2*BytesPerWord));
-#else
-        // restore caller save registers
-        __ mov(rdx, rbx);
-        __ mov(r8, r13);
-        __ mov(r9, r14);
-#ifndef _WIN64
-        assert_different_registers(tmp, rdx, r8, r9, rcx, rsi); // result of stub will be lost
-        __ movptr(rcx, Address(rsp, 0*BytesPerWord));
-        __ movptr(rsi, Address(rsp, 1*BytesPerWord));
-#else
-        assert_different_registers(tmp, rdx, r8, r9); // result of stub will be lost
-#endif
-#endif
+        // Restore previously spilled arguments
+        __ movptr   (dst,     Address(rsp, 0*BytesPerWord));
+        __ movptr   (dst_pos, Address(rsp, 1*BytesPerWord));
+        __ movptr   (length,  Address(rsp, 2*BytesPerWord));
+        __ movptr   (src_pos, Address(rsp, 3*BytesPerWord));
+        __ movptr   (src,     Address(rsp, 4*BytesPerWord));
+
 
         __ subl(length, tmp);
         __ addl(src_pos, tmp);
--- a/src/cpu/x86/vm/x86_64.ad	Fri Jun 03 07:53:33 2011 -0700
+++ b/src/cpu/x86/vm/x86_64.ad	Mon Jun 06 10:55:41 2011 -0700
@@ -3179,50 +3179,6 @@
     emit_rm(cbuf, 0x3, 0x0, dstenc);
   %}
 
-  enc_class enc_cmpLTP(no_rcx_RegI p, no_rcx_RegI q, no_rcx_RegI y,
-                       rcx_RegI tmp)
-  %{
-    // cadd_cmpLT
-
-    int tmpReg = $tmp$$reg;
-
-    int penc = $p$$reg;
-    int qenc = $q$$reg;
-    int yenc = $y$$reg;
-
-    // subl $p,$q
-    if (penc < 8) {
-      if (qenc >= 8) {
-        emit_opcode(cbuf, Assembler::REX_B);
-      }
-    } else {
-      if (qenc < 8) {
-        emit_opcode(cbuf, Assembler::REX_R);
-      } else {
-        emit_opcode(cbuf, Assembler::REX_RB);
-      }
-    }
-    emit_opcode(cbuf, 0x2B);
-    emit_rm(cbuf, 0x3, penc & 7, qenc & 7);
-
-    // sbbl $tmp, $tmp
-    emit_opcode(cbuf, 0x1B);
-    emit_rm(cbuf, 0x3, tmpReg, tmpReg);
-
-    // andl $tmp, $y
-    if (yenc >= 8) {
-      emit_opcode(cbuf, Assembler::REX_B);
-    }
-    emit_opcode(cbuf, 0x23);
-    emit_rm(cbuf, 0x3, tmpReg, yenc & 7);
-
-    // addl $p,$tmp
-    if (penc >= 8) {
-        emit_opcode(cbuf, Assembler::REX_R);
-    }
-    emit_opcode(cbuf, 0x03);
-    emit_rm(cbuf, 0x3, penc & 7, tmpReg);
-  %}
 
   // Compare the lonogs and set -1, 0, or 1 into dst
   enc_class cmpl3_flag(rRegL src1, rRegL src2, rRegI dst)
@@ -10206,9 +10162,7 @@
 %}
 
 
-instruct cadd_cmpLTMask(rRegI p, rRegI q, rRegI y,
-                         rRegI tmp,
-                         rFlagsReg cr)
+instruct cadd_cmpLTMask(rRegI p, rRegI q, rRegI y, rRegI tmp, rFlagsReg cr)
 %{
   match(Set p (AddI (AndI (CmpLTMask p q) y) (SubI p q)));
   effect(TEMP tmp, KILL cr);
@@ -10218,25 +10172,19 @@
             "sbbl    $tmp, $tmp\n\t"
             "andl    $tmp, $y\n\t"
             "addl    $p, $tmp" %}
-  ins_encode(enc_cmpLTP(p, q, y, tmp));
+  ins_encode %{
+    Register Rp = $p$$Register;
+    Register Rq = $q$$Register;
+    Register Ry = $y$$Register;
+    Register Rt = $tmp$$Register;
+    __ subl(Rp, Rq);
+    __ sbbl(Rt, Rt);
+    __ andl(Rt, Ry);
+    __ addl(Rp, Rt);
+  %}
   ins_pipe(pipe_cmplt);
 %}
 
-/* If I enable this, I encourage spilling in the inner loop of compress.
-instruct cadd_cmpLTMask_mem( rRegI p, rRegI q, memory y, rRegI tmp, rFlagsReg cr )
-%{
-  match(Set p (AddI (AndI (CmpLTMask p q) (LoadI y)) (SubI p q)));
-  effect( TEMP tmp, KILL cr );
-  ins_cost(400);
-
-  format %{ "SUB    $p,$q\n\t"
-            "SBB    RCX,RCX\n\t"
-            "AND    RCX,$y\n\t"
-            "ADD    $p,RCX" %}
-  ins_encode( enc_cmpLTP_mem(p,q,y,tmp) );
-%}
-*/
-
 //---------- FP Instructions------------------------------------------------
 
 instruct cmpF_cc_reg(rFlagsRegU cr, regF src1, regF src2)
--- a/src/share/vm/classfile/systemDictionary.hpp	Fri Jun 03 07:53:33 2011 -0700
+++ b/src/share/vm/classfile/systemDictionary.hpp	Mon Jun 06 10:55:41 2011 -0700
@@ -152,6 +152,7 @@
   template(DirectMethodHandle_klass,     java_lang_invoke_DirectMethodHandle, Pre_JSR292) \
   template(MethodType_klass,             java_lang_invoke_MethodType,       Pre_JSR292) \
   template(MethodTypeForm_klass,         java_lang_invoke_MethodTypeForm,   Pre_JSR292) \
+  template(BootstrapMethodError_klass,   java_lang_BootstrapMethodError, Pre_JSR292) \
   template(WrongMethodTypeException_klass, java_lang_invoke_WrongMethodTypeException, Pre_JSR292) \
   template(CallSite_klass,               java_lang_invoke_CallSite,         Pre_JSR292) \
   /* Note: MethodHandle must be first, and CallSite last in group */          \
--- a/src/share/vm/classfile/vmSymbols.hpp	Fri Jun 03 07:53:33 2011 -0700
+++ b/src/share/vm/classfile/vmSymbols.hpp	Mon Jun 06 10:55:41 2011 -0700
@@ -148,6 +148,7 @@
   template(java_lang_InstantiationException,          "java/lang/InstantiationException")         \
   template(java_lang_InstantiationError,              "java/lang/InstantiationError")             \
   template(java_lang_InterruptedException,            "java/lang/InterruptedException")           \
+  template(java_lang_BootstrapMethodError,            "java/lang/BootstrapMethodError")           \
   template(java_lang_LinkageError,                    "java/lang/LinkageError")                   \
   template(java_lang_NegativeArraySizeException,      "java/lang/NegativeArraySizeException")     \
   template(java_lang_NoSuchFieldException,            "java/lang/NoSuchFieldException")           \
--- a/src/share/vm/interpreter/linkResolver.cpp	Fri Jun 03 07:53:33 2011 -0700
+++ b/src/share/vm/interpreter/linkResolver.cpp	Mon Jun 06 10:55:41 2011 -0700
@@ -1117,7 +1117,24 @@
   // The extra MH receiver will be inserted into the stack on every call.
   methodHandle resolved_method;
   KlassHandle current_klass(THREAD, pool->pool_holder());
-  lookup_implicit_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, CHECK);
+  lookup_implicit_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, THREAD);
+  if (HAS_PENDING_EXCEPTION) {
+    if (PENDING_EXCEPTION->is_a(SystemDictionary::BootstrapMethodError_klass())) {
+      // throw these guys, since they are already wrapped
+      return;
+    }
+    if (!PENDING_EXCEPTION->is_a(SystemDictionary::LinkageError_klass())) {
+      // intercept only LinkageErrors which might have failed to wrap
+      return;
+    }
+    // See the "Linking Exceptions" section for the invokedynamic instruction in the JVMS.
+    Handle ex(THREAD, PENDING_EXCEPTION);
+    CLEAR_PENDING_EXCEPTION;
+    oop bsme = Klass::cast(SystemDictionary::BootstrapMethodError_klass())->java_mirror();
+    MethodHandles::raise_exception(Bytecodes::_athrow, ex(), bsme, CHECK);
+    // java code should not return, but if it does throw out anyway
+    THROW(vmSymbols::java_lang_InternalError());
+  }
   if (resolved_method.is_null()) {
     THROW(vmSymbols::java_lang_InternalError());
   }
--- a/src/share/vm/oops/methodOop.cpp	Fri Jun 03 07:53:33 2011 -0700
+++ b/src/share/vm/oops/methodOop.cpp	Mon Jun 06 10:55:41 2011 -0700
@@ -720,7 +720,7 @@
   // called from the vtable.  We need adapters on such methods that get loaded
   // later.  Ditto for mega-morphic itable calls.  If this proves to be a
   // problem we'll make these lazily later.
-  if (UseCompiler) (void) make_adapters(h_method, CHECK);
+  (void) make_adapters(h_method, CHECK);
 
   // ONLY USE the h_method now as make_adapter may have blocked
 
--- a/src/share/vm/opto/library_call.cpp	Fri Jun 03 07:53:33 2011 -0700
+++ b/src/share/vm/opto/library_call.cpp	Mon Jun 06 10:55:41 2011 -0700
@@ -5225,15 +5225,16 @@
 
   // Look at the alignment of the starting offsets.
   int abase = arrayOopDesc::base_offset_in_bytes(basic_elem_type);
-  const intptr_t BIG_NEG = -128;
-  assert(BIG_NEG + 2*abase < 0, "neg enough");
-
-  intptr_t src_off  = abase + ((intptr_t) find_int_con(src_offset, -1)  << scale);
-  intptr_t dest_off = abase + ((intptr_t) find_int_con(dest_offset, -1) << scale);
-  if (src_off < 0 || dest_off < 0)
+
+  intptr_t src_off_con  = (intptr_t) find_int_con(src_offset, -1);
+  intptr_t dest_off_con = (intptr_t) find_int_con(dest_offset, -1);
+  if (src_off_con < 0 || dest_off_con < 0)
     // At present, we can only understand constants.
     return false;
 
+  intptr_t src_off  = abase + (src_off_con  << scale);
+  intptr_t dest_off = abase + (dest_off_con << scale);
+
   if (((src_off | dest_off) & (BytesPerLong-1)) != 0) {
     // Non-aligned; too bad.
     // One more chance:  Pick off an initial 32-bit word.
--- a/src/share/vm/opto/subnode.cpp	Fri Jun 03 07:53:33 2011 -0700
+++ b/src/share/vm/opto/subnode.cpp	Mon Jun 06 10:55:41 2011 -0700
@@ -1101,6 +1101,7 @@
   if( cmp2_type == TypeInt::ZERO &&
       cmp1_op == Op_XorI &&
       j_xor->in(1) != j_xor &&          // An xor of itself is dead
+      phase->type( j_xor->in(1) ) == TypeInt::BOOL &&
       phase->type( j_xor->in(2) ) == TypeInt::ONE &&
       (_test._test == BoolTest::eq ||
        _test._test == BoolTest::ne) ) {
--- a/src/share/vm/prims/methodHandleWalk.cpp	Fri Jun 03 07:53:33 2011 -0700
+++ b/src/share/vm/prims/methodHandleWalk.cpp	Mon Jun 06 10:55:41 2011 -0700
@@ -141,6 +141,12 @@
 
 void MethodHandleChain::lose(const char* msg, TRAPS) {
   _lose_message = msg;
+#ifdef ASSERT
+  if (Verbose) {
+    tty->print_cr(INTPTR_FORMAT " lose: %s", _method_handle(), msg);
+    print();
+  }
+#endif
   if (!THREAD->is_Java_thread() || ((JavaThread*)THREAD)->thread_state() != _thread_in_vm) {
     // throw a preallocated exception
     THROW_OOP(Universe::virtual_machine_error_instance());
@@ -149,6 +155,145 @@
 }
 
 
+#ifdef ASSERT
+static const char* adapter_ops[] = {
+  "retype_only"  ,
+  "retype_raw"   ,
+  "check_cast"   ,
+  "prim_to_prim" ,
+  "ref_to_prim"  ,
+  "prim_to_ref"  ,
+  "swap_args"    ,
+  "rot_args"     ,
+  "dup_args"     ,
+  "drop_args"    ,
+  "collect_args" ,
+  "spread_args"  ,
+  "fold_args"
+};
+
+static const char* adapter_op_to_string(int op) {
+  if (op >= 0 && op < (int)ARRAY_SIZE(adapter_ops))
+    return adapter_ops[op];
+  return "unknown_op";
+}
+
+
+void MethodHandleChain::print(Handle mh) {
+  EXCEPTION_MARK;
+  MethodHandleChain mhc(mh, THREAD);
+  if (HAS_PENDING_EXCEPTION) {
+    oop ex = THREAD->pending_exception();
+    CLEAR_PENDING_EXCEPTION;
+    ex->print();
+    return;
+  }
+  mhc.print();
+}
+
+
+void MethodHandleChain::print() {
+  EXCEPTION_MARK;
+  print_impl(THREAD);
+  if (HAS_PENDING_EXCEPTION) {
+    oop ex = THREAD->pending_exception();
+    CLEAR_PENDING_EXCEPTION;
+    ex->print();
+  }
+}
+
+void MethodHandleChain::print_impl(TRAPS) {
+  ResourceMark rm;
+
+  MethodHandleChain chain(_root, CHECK);
+  for (;;) {
+    tty->print(INTPTR_FORMAT ": ", chain.method_handle()());
+    if (chain.is_bound()) {
+      tty->print("bound: arg_type %s arg_slot %d",
+                 type2name(chain.bound_arg_type()),
+                 chain.bound_arg_slot());
+      oop o = chain.bound_arg_oop();
+      if (o != NULL) {
+        if (o->is_instance()) {
+          tty->print(" instance %s", o->klass()->klass_part()->internal_name());
+        } else {
+          o->print();
+        }
+      }
+    } else if (chain.is_adapter()) {
+      tty->print("adapter: arg_slot %d conversion op %s",
+                 chain.adapter_arg_slot(),
+                 adapter_op_to_string(chain.adapter_conversion_op()));
+      switch (chain.adapter_conversion_op()) {
+        case java_lang_invoke_AdapterMethodHandle::OP_RETYPE_ONLY:
+        case java_lang_invoke_AdapterMethodHandle::OP_RETYPE_RAW:
+        case java_lang_invoke_AdapterMethodHandle::OP_CHECK_CAST:
+        case java_lang_invoke_AdapterMethodHandle::OP_PRIM_TO_PRIM:
+        case java_lang_invoke_AdapterMethodHandle::OP_REF_TO_PRIM:
+        case java_lang_invoke_AdapterMethodHandle::OP_PRIM_TO_REF:
+          break;
+
+        case java_lang_invoke_AdapterMethodHandle::OP_SWAP_ARGS:
+        case java_lang_invoke_AdapterMethodHandle::OP_ROT_ARGS: {
+          int dest_arg_slot = chain.adapter_conversion_vminfo();
+          tty->print(" dest_arg_slot %d type %s", dest_arg_slot, type2name(chain.adapter_conversion_src_type()));
+          break;
+        }
+
+        case java_lang_invoke_AdapterMethodHandle::OP_DUP_ARGS:
+        case java_lang_invoke_AdapterMethodHandle::OP_DROP_ARGS: {
+          int dup_slots = chain.adapter_conversion_stack_pushes();
+          tty->print(" pushes %d", dup_slots);
+          break;
+        }
+
+        case java_lang_invoke_AdapterMethodHandle::OP_FOLD_ARGS:
+        case java_lang_invoke_AdapterMethodHandle::OP_COLLECT_ARGS: {
+          int coll_slots = chain.MethodHandle_vmslots();
+          tty->print(" coll_slots %d", coll_slots);
+          break;
+        }
+
+        case java_lang_invoke_AdapterMethodHandle::OP_SPREAD_ARGS: {
+          // Check the required length.
+          int spread_slots = 1 + chain.adapter_conversion_stack_pushes();
+          tty->print(" spread_slots %d", spread_slots);
+          break;
+        }
+
+        default:
+          tty->print_cr("bad adapter conversion");
+          break;
+      }
+    } else {
+      // DMH
+      tty->print("direct: ");
+      chain.last_method_oop()->print_short_name(tty);
+    }
+
+    tty->print(" (");
+    objArrayOop ptypes = java_lang_invoke_MethodType::ptypes(chain.method_type_oop());
+    for (int i = ptypes->length() - 1; i >= 0; i--) {
+      BasicType t = java_lang_Class::as_BasicType(ptypes->obj_at(i));
+      if (t == T_ARRAY) t = T_OBJECT;
+      tty->print("%c", type2char(t));
+      if (t == T_LONG || t == T_DOUBLE) tty->print("_");
+    }
+    tty->print(")");
+    BasicType rtype = java_lang_Class::as_BasicType(java_lang_invoke_MethodType::rtype(chain.method_type_oop()));
+    if (rtype == T_ARRAY) rtype = T_OBJECT;
+    tty->print("%c", type2char(rtype));
+    tty->cr();
+    if (!chain.is_last()) {
+      chain.next(CHECK);
+    } else {
+      break;
+    }
+  }
+}
+#endif
+
+
 // -----------------------------------------------------------------------------
 // MethodHandleWalker
 
@@ -205,10 +350,16 @@
     if (chain().is_adapter()) {
       int conv_op = chain().adapter_conversion_op();
       int arg_slot = chain().adapter_arg_slot();
-      SlotState* arg_state = slot_state(arg_slot);
-      if (arg_state == NULL
-          && conv_op > java_lang_invoke_AdapterMethodHandle::OP_RETYPE_RAW) {
-        lose("bad argument index", CHECK_(empty));
+
+      // Check that the arg_slot is valid.  In most cases it must be
+      // within range of the current arguments but there are some
+      // exceptions.  Those are sanity checked in their implemention
+      // below.
+      if ((arg_slot < 0 || arg_slot >= _outgoing.length()) &&
+          conv_op > java_lang_invoke_AdapterMethodHandle::OP_RETYPE_RAW &&
+          conv_op != java_lang_invoke_AdapterMethodHandle::OP_COLLECT_ARGS &&
+          conv_op != java_lang_invoke_AdapterMethodHandle::OP_FOLD_ARGS) {
+        lose(err_msg("bad argument index %d", arg_slot), CHECK_(empty));
       }
 
       bool retain_original_args = false;  // used by fold/collect logic
@@ -237,8 +388,7 @@
 
         // Argument types.
         for (int i = 0, slot = _outgoing.length() - 1; slot >= 0; slot--) {
-          SlotState* arg_state = slot_state(slot);
-          if (arg_state->_type == T_VOID)  continue;
+          if (arg_type(slot) == T_VOID)  continue;
 
           klassOop  src_klass = NULL;
           klassOop  dst_klass = NULL;
@@ -262,8 +412,8 @@
         klassOop dest_klass = NULL;
         BasicType dest = java_lang_Class::as_BasicType(chain().adapter_arg_oop(), &dest_klass);
         assert(dest == T_OBJECT, "");
-        assert(dest == arg_state->_type, "");
-        ArgToken arg = arg_state->_arg;
+        ArgToken arg = _outgoing.at(arg_slot);
+        assert(dest == arg.basic_type(), "");
         ArgToken new_arg = make_conversion(T_OBJECT, dest_klass, Bytecodes::_checkcast, arg, CHECK_(empty));
         assert(!arg.has_index() || arg.index() == new_arg.index(), "should be the same index");
         debug_only(dest_klass = (klassOop)badOop);
@@ -274,8 +424,8 @@
         // i2l, etc., on the Nth outgoing argument in place
         BasicType src = chain().adapter_conversion_src_type(),
                   dest = chain().adapter_conversion_dest_type();
+        ArgToken arg = _outgoing.at(arg_slot);
         Bytecodes::Code bc = conversion_code(src, dest);
-        ArgToken arg = arg_state->_arg;
         if (bc == Bytecodes::_nop) {
           break;
         } else if (bc != Bytecodes::_illegal) {
@@ -289,7 +439,7 @@
           }
         }
         if (bc == Bytecodes::_illegal) {
-          lose("bad primitive conversion", CHECK_(empty));
+          lose(err_msg("bad primitive conversion for %s -> %s", type2name(src), type2name(dest)), CHECK_(empty));
         }
         change_argument(src, arg_slot, dest, arg);
         break;
@@ -298,7 +448,7 @@
       case java_lang_invoke_AdapterMethodHandle::OP_REF_TO_PRIM: {
         // checkcast to wrapper type & call intValue, etc.
         BasicType dest = chain().adapter_conversion_dest_type();
-        ArgToken arg = arg_state->_arg;
+        ArgToken arg = _outgoing.at(arg_slot);
         arg = make_conversion(T_OBJECT, SystemDictionary::box_klass(dest),
                               Bytecodes::_checkcast, arg, CHECK_(empty));
         vmIntrinsics::ID unboxer = vmIntrinsics::for_unboxing(dest);
@@ -316,11 +466,11 @@
       case java_lang_invoke_AdapterMethodHandle::OP_PRIM_TO_REF: {
         // call wrapper type.valueOf
         BasicType src = chain().adapter_conversion_src_type();
-        ArgToken arg = arg_state->_arg;
         vmIntrinsics::ID boxer = vmIntrinsics::for_boxing(src);
         if (boxer == vmIntrinsics::_none) {
           lose("no boxing method", CHECK_(empty));
         }
+        ArgToken arg = _outgoing.at(arg_slot);
         ArgToken arglist[2];
         arglist[0] = arg;         // outgoing value
         arglist[1] = ArgToken();  // sentinel
@@ -331,40 +481,45 @@
 
       case java_lang_invoke_AdapterMethodHandle::OP_SWAP_ARGS: {
         int dest_arg_slot = chain().adapter_conversion_vminfo();
-        if (!slot_has_argument(dest_arg_slot)) {
+        if (!has_argument(dest_arg_slot)) {
           lose("bad swap index", CHECK_(empty));
         }
         // a simple swap between two arguments
-        SlotState* dest_arg_state = slot_state(dest_arg_slot);
-        SlotState temp = (*dest_arg_state);
-        (*dest_arg_state) = (*arg_state);
-        (*arg_state) = temp;
+        if (arg_slot > dest_arg_slot) {
+          int tmp = arg_slot;
+          arg_slot = dest_arg_slot;
+          dest_arg_slot = tmp;
+        }
+        ArgToken a1 = _outgoing.at(arg_slot);
+        ArgToken a2 = _outgoing.at(dest_arg_slot);
+        change_argument(a2.basic_type(), dest_arg_slot, a1);
+        change_argument(a1.basic_type(), arg_slot, a2);
         break;
       }
 
       case java_lang_invoke_AdapterMethodHandle::OP_ROT_ARGS: {
         int dest_arg_slot = chain().adapter_conversion_vminfo();
-        if (!slot_has_argument(dest_arg_slot) || arg_slot == dest_arg_slot) {
+        if (!has_argument(dest_arg_slot) || arg_slot == dest_arg_slot) {
           lose("bad rotate index", CHECK_(empty));
         }
-        SlotState* dest_arg_state = slot_state(dest_arg_slot);
         // Rotate the source argument (plus following N slots) into the
         // position occupied by the dest argument (plus following N slots).
-        int rotate_count = type2size[dest_arg_state->_type];
+        int rotate_count = type2size[chain().adapter_conversion_src_type()];
         // (no other rotate counts are currently supported)
         if (arg_slot < dest_arg_slot) {
           for (int i = 0; i < rotate_count; i++) {
-            SlotState temp = _outgoing.at(arg_slot);
+            ArgToken temp = _outgoing.at(arg_slot);
             _outgoing.remove_at(arg_slot);
             _outgoing.insert_before(dest_arg_slot + rotate_count - 1, temp);
           }
         } else { // arg_slot > dest_arg_slot
           for (int i = 0; i < rotate_count; i++) {
-            SlotState temp = _outgoing.at(arg_slot + rotate_count - 1);
+            ArgToken temp = _outgoing.at(arg_slot + rotate_count - 1);
             _outgoing.remove_at(arg_slot + rotate_count - 1);
             _outgoing.insert_before(dest_arg_slot, temp);
           }
         }
+        assert(_outgoing_argc == argument_count_slow(), "empty slots under control");
         break;
       }
 
@@ -374,11 +529,11 @@
           lose("bad dup count", CHECK_(empty));
         }
         for (int i = 0; i < dup_slots; i++) {
-          SlotState* dup = slot_state(arg_slot + 2*i);
-          if (dup == NULL)              break;  // safety net
-          if (dup->_type != T_VOID)     _outgoing_argc += 1;
-          _outgoing.insert_before(i, (*dup));
+          ArgToken dup = _outgoing.at(arg_slot + 2*i);
+          if (dup.basic_type() != T_VOID)     _outgoing_argc += 1;
+          _outgoing.insert_before(i, dup);
         }
+        assert(_outgoing_argc == argument_count_slow(), "empty slots under control");
         break;
       }
 
@@ -388,11 +543,11 @@
           lose("bad drop count", CHECK_(empty));
         }
         for (int i = 0; i < drop_slots; i++) {
-          SlotState* drop = slot_state(arg_slot);
-          if (drop == NULL)             break;  // safety net
-          if (drop->_type != T_VOID)    _outgoing_argc -= 1;
+          ArgToken drop = _outgoing.at(arg_slot);
+          if (drop.basic_type() != T_VOID)    _outgoing_argc -= 1;
           _outgoing.remove_at(arg_slot);
         }
+        assert(_outgoing_argc == argument_count_slow(), "empty slots under control");
         break;
       }
 
@@ -415,10 +570,10 @@
           lose("bad fold/collect arg slot", CHECK_(empty));
         }
         for (int i = 0, slot = arg_slot + coll_slots - 1; slot >= arg_slot; slot--) {
-          SlotState* arg_state = slot_state(slot);
-          BasicType  arg_type  = arg_state->_type;
+          ArgToken arg_state = _outgoing.at(slot);
+          BasicType  arg_type  = arg_state.basic_type();
           if (arg_type == T_VOID)  continue;
-          ArgToken arg = _outgoing.at(slot)._arg;
+          ArgToken arg = _outgoing.at(slot);
           if (i >= argc) { lose("bad fold/collect arg", CHECK_(empty)); }
           arglist[1+i] = arg;
           if (!retain_original_args)
@@ -466,8 +621,9 @@
         debug_only(element_klass_oop = (klassOop)badOop);
 
         // Fetch the argument, which we will cast to the required array type.
-        assert(arg_state->_type == T_OBJECT, "");
-        ArgToken array_arg = arg_state->_arg;
+        ArgToken arg = _outgoing.at(arg_slot);
+        assert(arg.basic_type() == T_OBJECT, "");
+        ArgToken array_arg = arg;
         array_arg = make_conversion(T_OBJECT, array_klass(), Bytecodes::_checkcast, array_arg, CHECK_(empty));
         change_argument(T_OBJECT, arg_slot, T_VOID, ArgToken(tt_void));
 
@@ -534,10 +690,10 @@
       } else {
         jvalue arg_value;
         BasicType bt = java_lang_boxing_object::get_value(arg_oop, &arg_value);
-        if (bt == arg_type) {
+        if (bt == arg_type || (bt == T_INT && is_subword_type(arg_type))) {
           arg = make_prim_constant(arg_type, &arg_value, CHECK_(empty));
         } else {
-          lose("bad bound value", CHECK_(empty));
+          lose(err_msg("bad bound value: arg_type %s boxing %s", type2name(arg_type), type2name(bt)), CHECK_(empty));
         }
       }
       DEBUG_ONLY(arg_oop = badOop);
@@ -557,9 +713,9 @@
   ArgToken* arglist = NEW_RESOURCE_ARRAY(ArgToken, _outgoing.length() + 1);
   int ap = 0;
   for (int i = _outgoing.length() - 1; i >= 0; i--) {
-    SlotState* arg_state = slot_state(i);
-    if (arg_state->_type == T_VOID)  continue;
-    arglist[ap++] = _outgoing.at(i)._arg;
+    ArgToken arg_state = _outgoing.at(i);
+    if (arg_state.basic_type() == T_VOID)  continue;
+    arglist[ap++] = _outgoing.at(i);
   }
   assert(ap == _outgoing_argc, "");
   arglist[ap] = ArgToken();  // add a sentinel, for the sake of asserts
@@ -579,7 +735,7 @@
   _outgoing_argc = nptypes;
   int argp = nptypes - 1;
   if (argp >= 0) {
-    _outgoing.at_grow(argp, make_state(T_VOID, ArgToken(tt_void))); // presize
+    _outgoing.at_grow(argp, ArgToken(tt_void)); // presize
   }
   for (int i = 0; i < nptypes; i++) {
     klassOop  arg_type_klass = NULL;
@@ -587,10 +743,10 @@
     int index = new_local_index(arg_type);
     ArgToken arg = make_parameter(arg_type, arg_type_klass, index, CHECK);
     DEBUG_ONLY(arg_type_klass = (klassOop) NULL);
-    _outgoing.at_put(argp, make_state(arg_type, arg));
+    _outgoing.at_put(argp, arg);
     if (type2size[arg_type] == 2) {
       // add the extra slot, so we can model the JVM stack
-      _outgoing.insert_before(argp+1, make_state(T_VOID, ArgToken(tt_void)));
+      _outgoing.insert_before(argp+1, ArgToken(tt_void));
     }
     --argp;
   }
@@ -599,38 +755,61 @@
   BasicType ret_type = java_lang_Class::as_BasicType(java_lang_invoke_MethodType::rtype(mtype()), &ret_type_klass);
   ArgToken  ret = make_parameter(ret_type, ret_type_klass, -1, CHECK);
   // ignore ret; client can catch it if needed
+
+  assert(_outgoing_argc == argument_count_slow(), "empty slots under control");
+
+  verify_args_and_signature(CHECK);
 }
 
 
+#ifdef ASSERT
+void MethodHandleWalker::verify_args_and_signature(TRAPS) {
+  int index = _outgoing.length() - 1;
+  objArrayOop ptypes = java_lang_invoke_MethodType::ptypes(chain().method_type_oop());
+  for (int i = 0, limit = ptypes->length(); i < limit; i++) {
+    BasicType t = java_lang_Class::as_BasicType(ptypes->obj_at(i));
+    if (t == T_ARRAY) t = T_OBJECT;
+    if (t == T_LONG || t == T_DOUBLE) {
+      assert(T_VOID == _outgoing.at(index).basic_type(), "types must match");
+      index--;
+    }
+    assert(t == _outgoing.at(index).basic_type(), "types must match");
+    index--;
+  }
+}
+#endif
+
+
 // -----------------------------------------------------------------------------
 // MethodHandleWalker::change_argument
 //
 // This is messy because some kinds of arguments are paired with
 // companion slots containing an empty value.
-void MethodHandleWalker::change_argument(BasicType old_type, int slot, BasicType new_type,
-                                         const ArgToken& new_arg) {
+void MethodHandleWalker::change_argument(BasicType old_type, int slot, const ArgToken& new_arg) {
+  BasicType new_type = new_arg.basic_type();
   int old_size = type2size[old_type];
   int new_size = type2size[new_type];
   if (old_size == new_size) {
     // simple case first
-    _outgoing.at_put(slot, make_state(new_type, new_arg));
+    _outgoing.at_put(slot, new_arg);
   } else if (old_size > new_size) {
     for (int i = old_size - 1; i >= new_size; i--) {
-      assert((i != 0) == (_outgoing.at(slot + i)._type == T_VOID), "");
+      assert((i != 0) == (_outgoing.at(slot + i).basic_type() == T_VOID), "");
       _outgoing.remove_at(slot + i);
     }
     if (new_size > 0)
-      _outgoing.at_put(slot, make_state(new_type, new_arg));
+      _outgoing.at_put(slot, new_arg);
     else
       _outgoing_argc -= 1;      // deleted a real argument
   } else {
     for (int i = old_size; i < new_size; i++) {
-      _outgoing.insert_before(slot + i, make_state(T_VOID, ArgToken(tt_void)));
+      _outgoing.insert_before(slot + i, ArgToken(tt_void));
     }
-    _outgoing.at_put(slot, make_state(new_type, new_arg));
+    _outgoing.at_put(slot, new_arg);
     if (old_size == 0)
       _outgoing_argc += 1;      // inserted a real argument
   }
+  assert(_outgoing_argc == argument_count_slow(), "empty slots under control");
 }
 
 
@@ -638,8 +817,15 @@
 int MethodHandleWalker::argument_count_slow() {
   int args_seen = 0;
   for (int i = _outgoing.length() - 1; i >= 0; i--) {
-    if (_outgoing.at(i)._type != T_VOID) {
+    if (_outgoing.at(i).basic_type() != T_VOID) {
       ++args_seen;
+      if (_outgoing.at(i).basic_type() == T_LONG ||
+          _outgoing.at(i).basic_type() == T_DOUBLE) {
+        assert(_outgoing.at(i + 1).basic_type() == T_VOID, "should only follow two word");
+      }
+    } else {
+      assert(_outgoing.at(i - 1).basic_type() == T_LONG ||
+             _outgoing.at(i - 1).basic_type() == T_DOUBLE, "should only follow two word");
     }
   }
   return args_seen;
@@ -663,7 +849,7 @@
         ArgToken arglist[2];
         if (!for_return) {
           // argument type conversion
-          ArgToken arg = _outgoing.at(slot)._arg;
+          ArgToken arg = _outgoing.at(slot);
           assert(arg.token_type() >= tt_symbolic || src == arg.basic_type(), "sanity");
           arglist[0] = arg;         // outgoing 'this'
           arglist[1] = ArgToken();  // sentinel
@@ -683,7 +869,7 @@
       // ref-to-prim: discard ref, push zero
       lose("requested ref-to-prim conversion not expected", CHECK);
     } else {
-      lose("requested raw conversion not allowed", CHECK);
+      lose(err_msg("requested raw conversion not allowed: %s -> %s", type2name(src), type2name(dst)), CHECK);
     }
   }
 }
@@ -963,6 +1149,7 @@
 
 void MethodHandleCompiler::emit_load_constant(ArgToken arg) {
   BasicType bt = arg.basic_type();
+  if (is_subword_type(bt)) bt = T_INT;
   switch (bt) {
   case T_INT: {
     jint value = arg.get_jint();
@@ -1066,11 +1253,15 @@
     emit_store(srctype, index);
     break;
 
+  case Bytecodes::_nop:
+    // nothing to do
+    return src;
+
   default:
     if (op == Bytecodes::_illegal)
-      lose("no such primitive conversion", THREAD);
+      lose(err_msg("no such primitive conversion: %s -> %s", type2name(src.basic_type()), type2name(type)), THREAD);
     else
-      lose("bad primitive conversion op", THREAD);
+      lose(err_msg("bad primitive conversion op: %s", Bytecodes::name(op)), THREAD);
     return make_prim_constant(type, &zero_jvalue, THREAD);
   }
 
@@ -1300,7 +1491,7 @@
 
 //   for (int i = 1, imax = _constants.length(); i < imax; i++) {
 //     ConstantValue* con = _constants.at(i);
-//     if (con != NULL && con->is_primitive() && con->_type == bt) {
+//     if (con != NULL && con->is_primitive() && con.basic_type() == bt) {
 //       bool match = false;
 //       switch (type2size[bt]) {
 //       case 1:  if (pcon->_value.i == con->i)  match = true;  break;
@@ -1452,8 +1643,8 @@
     _strbuf.reset();
     return s;
   }
-  ArgToken token(const char* str) {
-    return ArgToken(str);
+  ArgToken token(const char* str, BasicType type) {
+    return ArgToken(str, type);
   }
   const char* string(ArgToken token) {
     return token.str();
@@ -1475,12 +1666,12 @@
   }
   ArgToken maybe_make_temp(const char* statement_op, BasicType type, const char* temp_name) {
     const char* value = strbuf();
-    if (!_verbose)  return token(value);
+    if (!_verbose)  return token(value, type);
     // make an explicit binding for each separate value
     _strbuf.print("%s%d", temp_name, ++_temp_num);
     const char* temp = strbuf();
     _out->print("\n  %s %s %s = %s;", statement_op, type2name(type), temp, value);
-    return token(temp);
+    return token(temp, type);
   }
 
 public:
@@ -1496,7 +1687,7 @@
   virtual ArgToken make_parameter(BasicType type, klassOop tk, int argnum, TRAPS) {
     if (argnum < 0) {
       end_params();
-      return token("return");
+      return token("return", type);
     }
     if ((_param_state & 1) == 0) {
       _param_state |= 1;
@@ -1511,7 +1702,7 @@
     const char* arg = strbuf();
     put_type_name(type, tk, _out);
     _out->print(" %s", arg);
-    return token(arg);
+    return token(arg, type);
   }
   virtual ArgToken make_oop_constant(oop con, TRAPS) {
     if (con == NULL)
@@ -1598,7 +1789,7 @@
     out->print("\n");
   }
   static void print(Handle root, bool verbose = Verbose, outputStream* out = tty) {
-    EXCEPTION_MARK;
+    Thread* THREAD = Thread::current();
     ResourceMark rm;
     MethodHandlePrinter printer(root, verbose, out, THREAD);
     if (!HAS_PENDING_EXCEPTION)
--- a/src/share/vm/prims/methodHandleWalk.hpp	Fri Jun 03 07:53:33 2011 -0700
+++ b/src/share/vm/prims/methodHandleWalk.hpp	Mon Jun 06 10:55:41 2011 -0700
@@ -56,6 +56,10 @@
   int BoundMethodHandle_vmargslot()    { return java_lang_invoke_BoundMethodHandle::vmargslot(method_handle_oop()); }
   int AdapterMethodHandle_conversion() { return java_lang_invoke_AdapterMethodHandle::conversion(method_handle_oop()); }
 
+#ifdef ASSERT
+  void print_impl(TRAPS);
+#endif
+
 public:
   MethodHandleChain(Handle root, TRAPS)
     : _root(root)
@@ -99,6 +103,14 @@
 
   void lose(const char* msg, TRAPS);
   const char* lose_message()    { return _lose_message; }
+
+#ifdef ASSERT
+  // Print a symbolic description of a method handle chain, including
+  // the signature for each method.  The signatures are printed in
+  // slot order to make it easier to understand.
+  void print();
+  static void print(Handle mh);
+#endif
 };
 
 
@@ -126,7 +138,7 @@
     Handle    _handle;
 
   public:
-    ArgToken(TokenType tt = tt_illegal) : _tt(tt) {
+    ArgToken(TokenType tt = tt_illegal) : _tt(tt), _bt(tt == tt_void ? T_VOID : T_ILLEGAL) {
       assert(tt == tt_illegal || tt == tt_void, "invalid token type");
     }
 
@@ -135,11 +147,11 @@
       _value.i = index;
     }
 
-    ArgToken(BasicType bt, jvalue value) : _tt(tt_constant), _bt(bt), _value(value) {}
-    ArgToken(BasicType bt, Handle value) : _tt(tt_constant), _bt(bt), _handle(value) {}
+    ArgToken(BasicType bt, jvalue value) : _tt(tt_constant), _bt(bt), _value(value) { assert(_bt != T_OBJECT, "wrong constructor"); }
+    ArgToken(Handle handle) : _tt(tt_constant), _bt(T_OBJECT), _handle(handle) {}
 
 
-    ArgToken(const char* str) : _tt(tt_symbolic), _bt(T_LONG) {
+    ArgToken(const char* str, BasicType type) : _tt(tt_symbolic), _bt(type) {
       _value.j = (intptr_t)str;
     }
 
@@ -147,27 +159,15 @@
     BasicType basic_type()  const { return _bt; }
     bool      has_index()   const { return _tt == tt_parameter || _tt == tt_temporary; }
     int       index()       const { assert(has_index(), "must have index");; return _value.i; }
-    Handle    object()      const { assert(_tt == tt_constant, "value type"); return _handle; }
-    const char* str()       const { assert(_tt == tt_symbolic, "string type"); return (const char*)_value.j; }
+    Handle    object()      const { assert(_bt == T_OBJECT, "wrong accessor"); assert(_tt == tt_constant, "value type"); return _handle; }
+    const char* str()       const { assert(_tt == tt_symbolic, "string type"); return (const char*)(intptr_t)_value.j; }
 
-    jint      get_jint()    const { assert(_tt == tt_constant, "value types"); return _value.i; }
-    jlong     get_jlong()   const { assert(_tt == tt_constant, "value types"); return _value.j; }
-    jfloat    get_jfloat()  const { assert(_tt == tt_constant, "value types"); return _value.f; }
-    jdouble   get_jdouble() const { assert(_tt == tt_constant, "value types"); return _value.d; }
+    jint      get_jint()    const { assert(_bt == T_INT || is_subword_type(_bt), "wrong accessor"); assert(_tt == tt_constant, "value types"); return _value.i; }
+    jlong     get_jlong()   const { assert(_bt == T_LONG, "wrong accessor");   assert(_tt == tt_constant, "value types"); return _value.j; }
+    jfloat    get_jfloat()  const { assert(_bt == T_FLOAT, "wrong accessor");  assert(_tt == tt_constant, "value types"); return _value.f; }
+    jdouble   get_jdouble() const { assert(_bt == T_DOUBLE, "wrong accessor"); assert(_tt == tt_constant, "value types"); return _value.d; }
   };
 
-  // Abstract interpretation state:
-  struct SlotState {
-    BasicType _type;
-    ArgToken  _arg;
-    SlotState() : _type(), _arg() {}
-  };
-  static SlotState make_state(BasicType type, ArgToken arg) {
-    SlotState ss;
-    ss._type = type; ss._arg = arg;
-    return ss;
-  }
-
 private:
   MethodHandleChain _chain;
   bool              _for_invokedynamic;
@@ -177,33 +177,29 @@
   // TOS is always _outgoing.at(0), so simple pushes and pops shift the whole _outgoing array.
   // If there is a receiver in the current argument list, it is at _outgoing.at(_outgoing.length()-1).
   // If a value at _outgoing.at(n) is T_LONG or T_DOUBLE, the value at _outgoing.at(n+1) is T_VOID.
-  GrowableArray<SlotState> _outgoing;       // current outgoing parameter slots
+  GrowableArray<ArgToken>  _outgoing;       // current outgoing parameter slots
   int                      _outgoing_argc;  // # non-empty outgoing slots
 
   // Replace a value of type old_type at slot (and maybe slot+1) with the new value.
   // If old_type != T_VOID, remove the old argument at that point.
   // If new_type != T_VOID, insert the new argument at that point.
   // Insert or delete a second empty slot as needed.
-  void change_argument(BasicType old_type, int slot, BasicType new_type, const ArgToken& new_arg);
+  void change_argument(BasicType old_type, int slot, const ArgToken& new_arg);
+  void change_argument(BasicType old_type, int slot, BasicType type, const ArgToken& new_arg) {
+    assert(type == new_arg.basic_type(), "must agree");
+    change_argument(old_type, slot, new_arg);
+  }
 
   // Raw retype conversions for OP_RAW_RETYPE.
   void retype_raw_conversion(BasicType src, BasicType dst, bool for_return, int slot, TRAPS);
   void retype_raw_argument_type(BasicType src, BasicType dst, int slot, TRAPS) { retype_raw_conversion(src, dst, false, slot, CHECK); }
   void retype_raw_return_type(  BasicType src, BasicType dst,           TRAPS) { retype_raw_conversion(src, dst, true,  -1,   CHECK); }
 
-  SlotState* slot_state(int slot) {
-    if (slot < 0 || slot >= _outgoing.length())
-      return NULL;
-    return _outgoing.adr_at(slot);
+  BasicType arg_type(int slot) {
+    return _outgoing.at(slot).basic_type();
   }
-  BasicType slot_type(int slot) {
-    SlotState* ss = slot_state(slot);
-    if (ss == NULL)
-      return T_ILLEGAL;
-    return ss->_type;
-  }
-  bool slot_has_argument(int slot) {
-    return slot_type(slot) < T_VOID;
+  bool has_argument(int slot) {
+    return arg_type(slot) < T_VOID;
   }
 
 #ifdef ASSERT
@@ -215,6 +211,8 @@
 
   void walk_incoming_state(TRAPS);
 
+  void verify_args_and_signature(TRAPS) NOT_DEBUG_RETURN;
+
 public:
   MethodHandleWalker(Handle root, bool for_invokedynamic, TRAPS)
     : _chain(root, THREAD),
@@ -421,7 +419,7 @@
   }
   virtual ArgToken make_oop_constant(oop con, TRAPS) {
     Handle h(THREAD, con);
-    return ArgToken(T_OBJECT, h);
+    return ArgToken(h);
   }
   virtual ArgToken make_prim_constant(BasicType type, jvalue* con, TRAPS) {
     return ArgToken(type, *con);
--- a/src/share/vm/prims/methodHandles.cpp	Fri Jun 03 07:53:33 2011 -0700
+++ b/src/share/vm/prims/methodHandles.cpp	Mon Jun 06 10:55:41 2011 -0700
@@ -1305,6 +1305,7 @@
   // Verify that argslot points at the given argnum.
   int check_slot = argument_slot(java_lang_invoke_MethodHandle::type(mh()), argnum);
   if (argslot != check_slot || argslot < 0) {
+    ResourceMark rm;
     const char* fmt = "for argnum of %d, vmargslot is %d, should be %d";
     size_t msglen = strlen(fmt) + 3*11 + 1;
     char* msg = NEW_RESOURCE_ARRAY(char, msglen);
@@ -1829,6 +1830,7 @@
   bool direct_to_method = false;
   if (OptimizeMethodHandles &&
       target->klass() == SystemDictionary::DirectMethodHandle_klass() &&
+      (argnum != 0 || java_lang_invoke_BoundMethodHandle::argument(mh()) != NULL) &&
       (argnum == 0 || java_lang_invoke_DirectMethodHandle::vmindex(target()) < 0)) {
     KlassHandle receiver_limit; int decode_flags = 0;
     methodHandle m = decode_method(target(), receiver_limit, decode_flags);
@@ -1980,7 +1982,6 @@
           err = "adapter requires src/dest conversion subfields for swap"; break;
         }
         int swap_size = type2size[src];
-        int slot_limit = java_lang_invoke_MethodHandle::vmslots(target());
         int src_slot   = argslot;
         int dest_slot  = vminfo;
         bool rotate_up = (src_slot > dest_slot); // upward rotation
@@ -2333,7 +2334,6 @@
   case _adapter_rot_args:
     {
       int swap_slots = type2size[src];
-      int slot_limit = java_lang_invoke_AdapterMethodHandle::vmslots(mh());
       int src_slot   = argslot;
       int dest_slot  = vminfo;
       int rotate     = (ek_orig == _adapter_swap_args) ? 0 : (src_slot > dest_slot) ? 1 : -1;
@@ -2661,14 +2661,14 @@
   ResourceMark rm;              // for error messages
 
   // This is the guy we are initializing:
-  if (mh_jh == NULL) { THROW(vmSymbols::java_lang_InternalError()); }
+  if (mh_jh == NULL) { THROW_MSG(vmSymbols::java_lang_InternalError(), "self is null"); }
   Handle mh(THREAD, JNIHandles::resolve_non_null(mh_jh));
 
   // Early returns out of this method leave the DMH in an unfinished state.
   assert(java_lang_invoke_MethodHandle::vmentry(mh()) == NULL, "must be safely null");
 
   // which method are we really talking about?
-  if (target_jh == NULL) { THROW(vmSymbols::java_lang_InternalError()); }
+  if (target_jh == NULL) { THROW_MSG(vmSymbols::java_lang_InternalError(), "target is null"); }
   Handle target(THREAD, JNIHandles::resolve_non_null(target_jh));
   if (java_lang_invoke_MemberName::is_instance(target()) &&
       java_lang_invoke_MemberName::vmindex(target()) == VM_INDEX_UNINITIALIZED) {
@@ -2722,13 +2722,13 @@
   ResourceMark rm;              // for error messages
 
   // This is the guy we are initializing:
-  if (mh_jh == NULL) { THROW(vmSymbols::java_lang_InternalError()); }
+  if (mh_jh == NULL) { THROW_MSG(vmSymbols::java_lang_InternalError(), "self is null"); }
   Handle mh(THREAD, JNIHandles::resolve_non_null(mh_jh));
 
   // Early returns out of this method leave the BMH in an unfinished state.
   assert(java_lang_invoke_MethodHandle::vmentry(mh()) == NULL, "must be safely null");
 
-  if (target_jh == NULL) { THROW(vmSymbols::java_lang_InternalError()); }
+  if (target_jh == NULL) { THROW_MSG(vmSymbols::java_lang_InternalError(), "target is null"); }
   Handle target(THREAD, JNIHandles::resolve_non_null(target_jh));
 
   if (!java_lang_invoke_MethodHandle::is_instance(target())) {
@@ -2753,9 +2753,8 @@
 JVM_ENTRY(void, MHN_init_AMH(JNIEnv *env, jobject igcls, jobject mh_jh,
                              jobject target_jh, int argnum)) {
   // This is the guy we are initializing:
-  if (mh_jh == NULL || target_jh == NULL) {
-    THROW(vmSymbols::java_lang_InternalError());
-  }
+  if (mh_jh == NULL) { THROW_MSG(vmSymbols::java_lang_InternalError(), "self is null"); }
+  if (target_jh == NULL) { THROW_MSG(vmSymbols::java_lang_InternalError(), "target is null"); }
   Handle mh(THREAD, JNIHandles::resolve_non_null(mh_jh));
   Handle target(THREAD, JNIHandles::resolve_non_null(target_jh));
 
@@ -2890,7 +2889,8 @@
 
 // void init(MemberName self, AccessibleObject ref)
 JVM_ENTRY(void, MHN_init_Mem(JNIEnv *env, jobject igcls, jobject mname_jh, jobject target_jh)) {
-  if (mname_jh == NULL || target_jh == NULL) { THROW(vmSymbols::java_lang_InternalError()); }
+  if (mname_jh == NULL) { THROW_MSG(vmSymbols::java_lang_InternalError(), "mname is null"); }
+  if (target_jh == NULL) { THROW_MSG(vmSymbols::java_lang_InternalError(), "target is null"); }
   Handle mname(THREAD, JNIHandles::resolve_non_null(mname_jh));
   oop target_oop = JNIHandles::resolve_non_null(target_jh);
   MethodHandles::init_MemberName(mname(), target_oop);
@@ -2899,7 +2899,7 @@
 
 // void expand(MemberName self)
 JVM_ENTRY(void, MHN_expand_Mem(JNIEnv *env, jobject igcls, jobject mname_jh)) {
-  if (mname_jh == NULL) { THROW(vmSymbols::java_lang_InternalError()); }
+  if (mname_jh == NULL) { THROW_MSG(vmSymbols::java_lang_InternalError(), "mname is null"); }
   Handle mname(THREAD, JNIHandles::resolve_non_null(mname_jh));
   MethodHandles::expand_MemberName(mname, 0, CHECK);
 }
@@ -2907,7 +2907,7 @@
 
 // void resolve(MemberName self, Class<?> caller)
 JVM_ENTRY(void, MHN_resolve_Mem(JNIEnv *env, jobject igcls, jobject mname_jh, jclass caller_jh)) {
-  if (mname_jh == NULL) { THROW(vmSymbols::java_lang_InternalError()); }
+  if (mname_jh == NULL) { THROW_MSG(vmSymbols::java_lang_InternalError(), "mname is null"); }
   Handle mname(THREAD, JNIHandles::resolve_non_null(mname_jh));
 
   // The trusted Java code that calls this method should already have performed
@@ -2970,6 +2970,45 @@
 }
 JVM_END
 
+methodOop MethodHandles::resolve_raise_exception_method(TRAPS) {
+  if (_raise_exception_method != NULL) {
+    // no need to do it twice
+    return raise_exception_method();
+  }
+  // LinkResolver::resolve_invokedynamic can reach this point
+  // because an invokedynamic has failed very early (7049415)
+  KlassHandle MHN_klass = SystemDictionaryHandles::MethodHandleNatives_klass();
+  if (MHN_klass.not_null()) {
+    TempNewSymbol raiseException_name = SymbolTable::new_symbol("raiseException", CHECK_NULL);
+    TempNewSymbol raiseException_sig = SymbolTable::new_symbol("(ILjava/lang/Object;Ljava/lang/Object;)V", CHECK_NULL);
+    methodOop raiseException_method  = instanceKlass::cast(MHN_klass->as_klassOop())
+                  ->find_method(raiseException_name, raiseException_sig);
+    if (raiseException_method != NULL && raiseException_method->is_static()) {
+      return raiseException_method;
+    }
+  }
+  // not found; let the caller deal with it
+  return NULL;
+}
+void MethodHandles::raise_exception(int code, oop actual, oop required, TRAPS) {
+  methodOop raiseException_method = resolve_raise_exception_method(CHECK);
+  if (raiseException_method != NULL &&
+      instanceKlass::cast(raiseException_method->method_holder())->is_not_initialized()) {
+    instanceKlass::cast(raiseException_method->method_holder())->initialize(CHECK);
+    // it had better be resolved by now, or maybe JSR 292 failed to load
+    raiseException_method = raise_exception_method();
+  }
+  if (raiseException_method == NULL) {
+    THROW_MSG(vmSymbols::java_lang_InternalError(), "no raiseException method");
+  }
+  JavaCallArguments args;
+  args.push_int(code);
+  args.push_oop(actual);
+  args.push_oop(required);
+  JavaValue result(T_VOID);
+  JavaCalls::call(&result, raiseException_method, &args, CHECK);
+}
+
 JVM_ENTRY(jobject, MH_invoke_UOE(JNIEnv *env, jobject igmh, jobjectArray igargs)) {
     TempNewSymbol UOE_name = SymbolTable::new_symbol("java/lang/UnsupportedOperationException", CHECK_NULL);
     THROW_MSG_NULL(UOE_name, "MethodHandle.invoke cannot be invoked reflectively");
@@ -3059,19 +3098,11 @@
   }
 
   if (enable_MH) {
-    KlassHandle MHN_klass = SystemDictionaryHandles::MethodHandleNatives_klass();
-    if (MHN_klass.not_null()) {
-      TempNewSymbol raiseException_name = SymbolTable::new_symbol("raiseException", CHECK);
-      TempNewSymbol raiseException_sig = SymbolTable::new_symbol("(ILjava/lang/Object;Ljava/lang/Object;)V", CHECK);
-      methodOop raiseException_method  = instanceKlass::cast(MHN_klass->as_klassOop())
-                    ->find_method(raiseException_name, raiseException_sig);
-      if (raiseException_method != NULL && raiseException_method->is_static()) {
-        MethodHandles::set_raise_exception_method(raiseException_method);
-      } else {
-        warning("JSR 292 method handle code is mismatched to this JVM.  Disabling support.");
-        enable_MH = false;
-      }
+    methodOop raiseException_method = MethodHandles::resolve_raise_exception_method(CHECK);
+    if (raiseException_method != NULL) {
+      MethodHandles::set_raise_exception_method(raiseException_method);
     } else {
+      warning("JSR 292 method handle code is mismatched to this JVM.  Disabling support.");
       enable_MH = false;
     }
   }
--- a/src/share/vm/prims/methodHandles.hpp	Fri Jun 03 07:53:33 2011 -0700
+++ b/src/share/vm/prims/methodHandles.hpp	Mon Jun 06 10:55:41 2011 -0700
@@ -439,6 +439,9 @@
     assert(_raise_exception_method == NULL, "");
     _raise_exception_method = JNIHandles::make_global(Handle(rem));
   }
+  static methodOop resolve_raise_exception_method(TRAPS);
+  // call raise_exception_method from C code:
+  static void raise_exception(int code, oop actual, oop required, TRAPS);
 
   static jint adapter_conversion(int conv_op, BasicType src, BasicType dest,
                                  int stack_move = 0, int vminfo = 0) {
--- a/src/share/vm/runtime/globals.hpp	Fri Jun 03 07:53:33 2011 -0700
+++ b/src/share/vm/runtime/globals.hpp	Mon Jun 06 10:55:41 2011 -0700
@@ -3734,7 +3734,7 @@
   experimental(bool, TrustFinalNonStaticFields, false,                      \
           "trust final non-static declarations for constant folding")       \
                                                                             \
-  experimental(bool, AllowInvokeGeneric, true,                              \
+  experimental(bool, AllowInvokeGeneric, false,                             \
           "accept MethodHandle.invoke and MethodHandle.invokeGeneric "      \
           "as equivalent methods")                                          \
                                                                             \
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compiler/6956668/Test6956668.java	Mon Jun 06 10:55:41 2011 -0700
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+/**
+ * @test
+ * @bug 6956668
+ * @summary misbehavior of XOR operator (^) with int
+ *
+ * @run main/othervm -Xbatch Test6956668
+ */
+
+
+public class Test6956668 {
+
+   public static int bitTest() {
+      int result = 0;
+
+      int testValue = 73;
+      int bitCount = Integer.bitCount(testValue);
+
+      if (testValue != 0) {
+         int gap = Long.numberOfTrailingZeros(testValue);
+         testValue >>>= gap;
+
+         while (testValue != 0) {
+            result++;
+
+            if ((testValue ^= 0x1) != 0) {
+               gap = Long.numberOfTrailingZeros(testValue);
+               testValue >>>= gap;
+            }
+         }
+      }
+
+      if (bitCount != result) {
+         System.out.println("ERROR: " + bitCount + " != " + result);
+         System.exit(97);
+      }
+
+      return (result);
+   }
+
+   public static void main(String[] args) {
+      for (int i = 0; i < 100000; i++) {
+         int ct = bitTest();
+      }
+   }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compiler/7047069/Test7047069.java	Mon Jun 06 10:55:41 2011 -0700
@@ -0,0 +1,200 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+/**
+ * @test
+ * @bug 7047069
+ * @summary Array can dynamically change size when assigned to an object field
+ *
+ * @run main/othervm -Xbatch Test7047069
+ */
+
+import java.util.*;
+import java.awt.geom.*;
+
+public class Test7047069 {
+    static boolean verbose;
+
+    static final int GROW_SIZE = 24;    // Multiple of cubic & quad curve size
+
+    float squareflat;           // Square of the flatness parameter
+                    // for testing against squared lengths
+
+    int limit;              // Maximum number of recursion levels
+
+    float hold[] = new float[14];   // The cache of interpolated coords
+                    // Note that this must be long enough
+                    // to store a full cubic segment and
+                    // a relative cubic segment to avoid
+                    // aliasing when copying the coords
+                    // of a curve to the end of the array.
+                    // This is also serendipitously equal
+                    // to the size of a full quad segment
+                    // and 2 relative quad segments.
+
+    int holdEnd;            // The index of the last curve segment
+                    // being held for interpolation
+
+    int holdIndex;          // The index of the curve segment
+                    // that was last interpolated.  This
+                    // is the curve segment ready to be
+                    // returned in the next call to
+                    // currentSegment().
+
+    int levels[];           // The recursion level at which
+                    // each curve being held in storage
+                    // was generated.
+
+    int levelIndex;         // The index of the entry in the
+                    // levels array of the curve segment
+                    // at the holdIndex
+
+    public static void subdivide(float src[], int srcoff,
+                                 float left[], int leftoff,
+                                 float right[], int rightoff)
+    {
+        float x1 = src[srcoff + 0];
+        float y1 = src[srcoff + 1];
+        float ctrlx = src[srcoff + 2];
+        float ctrly = src[srcoff + 3];
+        float x2 = src[srcoff + 4];
+        float y2 = src[srcoff + 5];
+        if (left != null) {
+            left[leftoff + 0] = x1;
+            left[leftoff + 1] = y1;
+        }
+        if (right != null) {
+            right[rightoff + 4] = x2;
+            right[rightoff + 5] = y2;
+        }
+        x1 = (x1 + ctrlx) / 2f;
+        y1 = (y1 + ctrly) / 2f;
+        x2 = (x2 + ctrlx) / 2f;
+        y2 = (y2 + ctrly) / 2f;
+        ctrlx = (x1 + x2) / 2f;
+        ctrly = (y1 + y2) / 2f;
+        if (left != null) {
+            left[leftoff + 2] = x1;
+            left[leftoff + 3] = y1;
+            left[leftoff + 4] = ctrlx;
+            left[leftoff + 5] = ctrly;
+        }
+        if (right != null) {
+            right[rightoff + 0] = ctrlx;
+            right[rightoff + 1] = ctrly;
+            right[rightoff + 2] = x2;
+            right[rightoff + 3] = y2;
+        }
+    }
+
+    public static double getFlatnessSq(float coords[], int offset) {
+        return Line2D.ptSegDistSq(coords[offset + 0], coords[offset + 1],
+                                  coords[offset + 4], coords[offset + 5],
+                                  coords[offset + 2], coords[offset + 3]);
+    }
+
+    public Test7047069() {
+        this.squareflat = .0001f * .0001f;
+        holdIndex = hold.length - 6;
+        holdEnd = hold.length - 2;
+        hold[holdIndex + 0] = (float) (Math.random() * 100);
+        hold[holdIndex + 1] = (float) (Math.random() * 100);
+        hold[holdIndex + 2] = (float) (Math.random() * 100);
+        hold[holdIndex + 3] = (float) (Math.random() * 100);
+        hold[holdIndex + 4] = (float) (Math.random() * 100);
+        hold[holdIndex + 5] = (float) (Math.random() * 100);
+        levelIndex = 0;
+        this.limit = 10;
+        this.levels = new int[limit + 1];
+    }
+
+    /*
+     * Ensures that the hold array can hold up to (want) more values.
+     * It is currently holding (hold.length - holdIndex) values.
+     */
+    void ensureHoldCapacity(int want) {
+        if (holdIndex - want < 0) {
+            int have = hold.length - holdIndex;
+            int newsize = hold.length + GROW_SIZE;
+            float newhold[] = new float[newsize];
+            System.arraycopy(hold, holdIndex,
+                     newhold, holdIndex + GROW_SIZE,
+                     have);
+            if (verbose) System.err.println("old hold = "+hold+"["+hold.length+"]");
+            if (verbose) System.err.println("replacement hold = "+newhold+"["+newhold.length+"]");
+            hold = newhold;
+            if (verbose) System.err.println("new hold = "+hold+"["+hold.length+"]");
+            if (verbose) System.err.println("replacement hold still = "+newhold+"["+newhold.length+"]");
+            holdIndex += GROW_SIZE;
+            holdEnd += GROW_SIZE;
+        }
+    }
+
+    private boolean next() {
+        if (holdIndex >= holdEnd) {
+            return false;
+        }
+
+        int level = levels[levelIndex];
+        while (level < limit) {
+            if (getFlatnessSq(hold, holdIndex) < squareflat) {
+                break;
+            }
+
+            ensureHoldCapacity(4);
+            subdivide(hold, holdIndex,
+                      hold, holdIndex - 4,
+                      hold, holdIndex);
+            holdIndex -= 4;
+
+            // Now that we have subdivided, we have constructed
+            // two curves of one depth lower than the original
+            // curve.  One of those curves is in the place of
+            // the former curve and one of them is in the next
+            // set of held coordinate slots.  We now set both
+            // curves level values to the next higher level.
+            level++;
+            levels[levelIndex] = level;
+            levelIndex++;
+            levels[levelIndex] = level;
+        }
+
+        // This curve segment is flat enough, or it is too deep
+        // in recursion levels to try to flatten any more.  The
+        // two coordinates at holdIndex+4 and holdIndex+5 now
+        // contain the endpoint of the curve which can be the
+        // endpoint of an approximating line segment.
+        holdIndex += 4;
+        levelIndex--;
+        return true;
+    }
+
+    public static void main(String argv[]) {
+        verbose = (argv.length > 0);
+        for (int i = 0; i < 100000; i++) {
+            Test7047069 st = new Test7047069();
+            while (st.next()) {}
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compiler/7048332/Test7048332.java	Mon Jun 06 10:55:41 2011 -0700
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+/**
+ * @test
+ * @bug 7048332
+ * @summary Cadd_cmpLTMask doesn't handle 64-bit tmp register properly
+ *
+ * @run main/othervm -Xbatch Test7048332
+ */
+
+
+public class Test7048332 {
+
+  static int capacity = 2;
+  static int first = 1;
+  static int last = 2;
+
+  static int test(int i1, int i2, int i3, int i4, int i5, int i6) {
+    final int result;
+    if (last >= first) {
+      result = last - first;
+    } else {
+      result = last - first + capacity;
+    }
+    return result;
+  }
+
+  public static void main(String [] args) {
+    for (int i = 0; i < 11000; i++) {
+      last = (i & 1) << 1; // 0 or 2
+      int k = test(1, 2, 3, 4, 5, 6);
+      if (k != 1) {
+        System.out.println("FAILED: " + k + " != 1");
+        System.exit(97);
+      }
+    }
+  }
+}