src/cpu/x86/vm/methodHandles_x86.cpp
Index Unified diffs Context diffs Sdiffs Wdiffs Patch New Old Previous File Next File 6893081 Sdiff src/cpu/x86/vm

src/cpu/x86/vm/methodHandles_x86.cpp

Print this page
rev 1079 : 6829192: JSR 292 needs to support 64-bit x86
Summary: changes for method handles and invokedynamic
Reviewed-by: ?, ?
rev 1080 : [mq]: meth.walker.patch
rev 1081 : imported patch indy-cleanup-6893081.patch


  48 }
  49 
  50 MethodHandleEntry* MethodHandleEntry::finish_compiled_entry(MacroAssembler* _masm,
  51                                                 address start_addr) {
  52   MethodHandleEntry* me = (MethodHandleEntry*) start_addr;
  53   assert(me->end_address() == start_addr, "valid ME");
  54 
  55   // Fill in the real end_address:
  56   __ align(wordSize);
  57   me->set_end_address(__ pc());
  58 
  59   return me;
  60 }
  61 
  62 #ifdef ASSERT
  63 static void verify_argslot(MacroAssembler* _masm, Register rax_argslot,
  64                            const char* error_message) {
  65   // Verify that argslot lies within (rsp, rbp].
  66   Label L_ok, L_bad;
  67   __ cmpptr(rax_argslot, rbp);
  68   __ jcc(Assembler::above, L_bad);
  69   __ cmpptr(rsp, rax_argslot);
  70   __ jcc(Assembler::below, L_ok);
  71   __ bind(L_bad);
  72   __ stop(error_message);
  73   __ bind(L_ok);
  74 }
  75 #endif
  76 
  77 
  78 // Code generation
  79 address MethodHandles::generate_method_handle_interpreter_entry(MacroAssembler* _masm) {
  80   // rbx: methodOop
  81   // rcx: receiver method handle (must load from sp[MethodTypeForm.vmslots])
  82   // rsi/r13: sender SP (must preserve; see prepare_to_jump_from_interpreted)
  83   // rdx: garbage temp, blown away
  84 
  85   Register rbx_method = rbx;
  86   Register rcx_recv   = rcx;
  87   Register rax_mtype  = rax;
  88   Register rdx_temp   = rdx;
  89 
  90   // emit WrongMethodType path first, to enable jccb back-branch from main path


 119   __ jump_to_method_handle_entry(rcx_recv, rdx_temp);
 120 
 121   return entry_point;
 122 }
 123 
 124 // Helper to insert argument slots into the stack.
 125 // arg_slots must be a multiple of stack_move_unit() and <= 0
 126 void MethodHandles::insert_arg_slots(MacroAssembler* _masm,
 127                                      RegisterOrConstant arg_slots,
 128                                      int arg_mask,
 129                                      Register rax_argslot,
 130                                      Register rbx_temp, Register rdx_temp) {
 131   assert_different_registers(rax_argslot, rbx_temp, rdx_temp,
 132                              (!arg_slots.is_register() ? rsp : arg_slots.as_register()));
 133 
 134 #ifdef ASSERT
 135   verify_argslot(_masm, rax_argslot, "insertion point must fall within current frame");
 136   if (arg_slots.is_register()) {
 137     Label L_ok, L_bad;
 138     __ cmpptr(arg_slots.as_register(), (int32_t) NULL_WORD);
 139     __ jcc(Assembler::greater, L_bad);
 140     __ testl(arg_slots.as_register(), -stack_move_unit() - 1);
 141     __ jcc(Assembler::zero, L_ok);
 142     __ bind(L_bad);
 143     __ stop("assert arg_slots <= 0 and clear low bits");
 144     __ bind(L_ok);
 145   } else {
 146     assert(arg_slots.as_constant() <= 0, "");
 147     assert(arg_slots.as_constant() % -stack_move_unit() == 0, "");
 148   }
 149 #endif //ASSERT
 150 
 151 #ifdef _LP64
 152   if (arg_slots.is_register()) {
 153     // clean high bits of stack motion register (was loaded as an int)
 154     __ movslq(arg_slots.as_register(), arg_slots.as_register());
 155   }
 156 #endif
 157 
 158   // Make space on the stack for the inserted argument(s).
 159   // Then pull down everything shallower than rax_argslot.
 160   // The stacked return address gets pulled down with everything else.
 161   // That is, copy [rsp, argslot) downward by -size words.  In pseudo-code:
 162   //   rsp -= size;
 163   //   for (rdx = rsp + size; rdx < argslot; rdx++)
 164   //     rdx[-size] = rdx[0]
 165   //   argslot -= size;
 166   __ mov(rdx_temp, rsp);                        // source pointer for copy
 167   __ lea(rsp, Address(rsp, arg_slots, Address::times_ptr));
 168   {
 169     Label loop;
 170     __ bind(loop);
 171     // pull one word down each time through the loop
 172     __ movptr(rbx_temp, Address(rdx_temp, 0));
 173     __ movptr(Address(rdx_temp, arg_slots, Address::times_ptr), rbx_temp);
 174     __ addptr(rdx_temp, wordSize);
 175     __ cmpptr(rdx_temp, rax_argslot);
 176     __ jcc(Assembler::less, loop);
 177   }
 178 
 179   // Now move the argslot down, to point to the opened-up space.
 180   __ lea(rax_argslot, Address(rax_argslot, arg_slots, Address::times_ptr));
 181 
 182   if (TaggedStackInterpreter && arg_mask != _INSERT_NO_MASK) {
 183     // The caller has specified a bitmask of tags to put into the opened space.
 184     // This only works when the arg_slots value is an assembly-time constant.
 185     int constant_arg_slots = arg_slots.as_constant() / stack_move_unit();
 186     int tag_offset = Interpreter::tag_offset_in_bytes() - Interpreter::value_offset_in_bytes();
 187     for (int slot = 0; slot < constant_arg_slots; slot++) {
 188       BasicType slot_type   = ((arg_mask & (1 << slot)) == 0 ? T_OBJECT : T_INT);
 189       int       slot_offset = Interpreter::stackElementSize() * slot;
 190       Address   tag_addr(rax_argslot, slot_offset + tag_offset);
 191       __ movptr(tag_addr, frame::tag_for_basic_type(slot_type));
 192     }
 193     // Note that the new argument slots are tagged properly but contain
 194     // garbage at this point.  The value portions must be initialized
 195     // by the caller.  (Especially references!)
 196   }
 197 }
 198 
 199 // Helper to remove argument slots from the stack.
 200 // arg_slots must be a multiple of stack_move_unit() and >= 0
 201 void MethodHandles::remove_arg_slots(MacroAssembler* _masm,
 202                                     RegisterOrConstant arg_slots,
 203                                     Register rax_argslot,
 204                                     Register rbx_temp, Register rdx_temp) {
 205   assert_different_registers(rax_argslot, rbx_temp, rdx_temp,
 206                              (!arg_slots.is_register() ? rsp : arg_slots.as_register()));
 207 
 208 #ifdef ASSERT
 209   {
 210     // Verify that [argslot..argslot+size) lies within (rsp, rbp).
 211     Label L_ok, L_bad;
 212     __ lea(rbx_temp, Address(rax_argslot, arg_slots, Address::times_ptr));
 213     __ cmpptr(rbx_temp, rbp);
 214     __ jcc(Assembler::above, L_bad);
 215     __ cmpptr(rsp, rax_argslot);
 216     __ jcc(Assembler::below, L_ok);
 217     __ bind(L_bad);
 218     __ stop("deleted argument(s) must fall within current frame");
 219     __ bind(L_ok);
 220   }
 221   if (arg_slots.is_register()) {
 222     Label L_ok, L_bad;
 223     __ cmpptr(arg_slots.as_register(), (int32_t) NULL_WORD);
 224     __ jcc(Assembler::less, L_bad);
 225     __ testl(arg_slots.as_register(), -stack_move_unit() - 1);
 226     __ jcc(Assembler::zero, L_ok);
 227     __ bind(L_bad);
 228     __ stop("assert arg_slots >= 0 and clear low bits");
 229     __ bind(L_ok);
 230   } else {
 231     assert(arg_slots.as_constant() >= 0, "");
 232     assert(arg_slots.as_constant() % -stack_move_unit() == 0, "");
 233   }
 234 #endif //ASSERT
 235 
 236 #ifdef _LP64
 237   if (false) {                  // not needed, since register is positive
 238     // clean high bits of stack motion register (was loaded as an int)
 239     if (arg_slots.is_register())
 240       __ movslq(arg_slots.as_register(), arg_slots.as_register());
 241   }
 242 #endif
 243 
 244   // Pull up everything shallower than rax_argslot.
 245   // Then remove the excess space on the stack.
 246   // The stacked return address gets pulled up with everything else.
 247   // That is, copy [rsp, argslot) upward by size words.  In pseudo-code:
 248   //   for (rdx = argslot-1; rdx >= rsp; --rdx)
 249   //     rdx[size] = rdx[0]
 250   //   argslot += size;
 251   //   rsp += size;
 252   __ lea(rdx_temp, Address(rax_argslot, -wordSize)); // source pointer for copy
 253   {
 254     Label loop;
 255     __ bind(loop);
 256     // pull one word up each time through the loop
 257     __ movptr(rbx_temp, Address(rdx_temp, 0));
 258     __ movptr(Address(rdx_temp, arg_slots, Address::times_ptr), rbx_temp);
 259     __ addptr(rdx_temp, -wordSize);
 260     __ cmpptr(rdx_temp, rsp);
 261     __ jcc(Assembler::greaterEqual, loop);
 262   }
 263 
 264   // Now move the argslot up, to point to the just-copied block.
 265   __ lea(rsp, Address(rsp, arg_slots, Address::times_ptr));
 266   // And adjust the argslot address to point at the deletion point.
 267   __ lea(rax_argslot, Address(rax_argslot, arg_slots, Address::times_ptr));
 268 }
 269 
 270 #ifndef PRODUCT
 271 extern "C" void print_method_handle(oopDesc* mh);
 272 void trace_method_handle_stub(const char* adaptername,
 273                               oopDesc* mh,
 274                               intptr_t* entry_sp,
 275                               intptr_t* saved_sp,
 276                               intptr_t* saved_bp) {
 277   // called as a leaf from native code: do not block the JVM!
 278   intptr_t* last_sp = (intptr_t*) saved_bp[frame::interpreter_frame_last_sp_offset];
 279   intptr_t* base_sp = (intptr_t*) saved_bp[frame::interpreter_frame_monitor_block_top_offset];
 280   printf("MH %s mh="INTPTR_FORMAT" sp=("INTPTR_FORMAT"+"INTX_FORMAT") stack_size="INTX_FORMAT" bp="INTPTR_FORMAT"\n",
 281          adaptername, (intptr_t)mh, (intptr_t)entry_sp, (intptr_t)(saved_sp - entry_sp), (intptr_t)(base_sp - last_sp), (intptr_t)saved_bp);


 367       __ pop(rdx_code);  // TOS+0
 368       __ pop(rcx_fail);  // TOS+4
 369       __ pop(rax_want);  // TOS+8
 370       __ pop(rdi_pc);    // caller PC
 371 
 372       __ mov(rsp, rsi);   // cut the stack back to where the caller started
 373 
 374       // Repush the arguments as if coming from the interpreter.
 375       if (TaggedStackInterpreter)  __ push(frame::tag_for_basic_type(T_INT));
 376       __ push(rdx_code);
 377       if (TaggedStackInterpreter)  __ push(frame::tag_for_basic_type(T_OBJECT));
 378       __ push(rcx_fail);
 379       if (TaggedStackInterpreter)  __ push(frame::tag_for_basic_type(T_OBJECT));
 380       __ push(rax_want);
 381 
 382       Register rbx_method = rbx_temp;
 383       Label no_method;
 384       // FIXME: fill in _raise_exception_method with a suitable sun.dyn method
 385       __ movptr(rbx_method, ExternalAddress((address) &_raise_exception_method));
 386       __ testptr(rbx_method, rbx_method);
 387       __ jcc(Assembler::zero, no_method);
 388       int jobject_oop_offset = 0;
 389       __ movptr(rbx_method, Address(rbx_method, jobject_oop_offset));  // dereference the jobject
 390       __ testptr(rbx_method, rbx_method);
 391       __ jcc(Assembler::zero, no_method);
 392       __ verify_oop(rbx_method);
 393       __ push(rdi_pc);          // and restore caller PC
 394       __ jmp(rbx_method_fie);
 395 
 396       // If we get here, the Java runtime did not do its job of creating the exception.
 397       // Do something that is at least causes a valid throw from the interpreter.
 398       __ bind(no_method);
 399       __ pop(rax_want);
 400       if (TaggedStackInterpreter)  __ pop(rcx_fail);
 401       __ pop(rcx_fail);
 402       __ push(rax_want);
 403       __ push(rcx_fail);
 404       __ jump(ExternalAddress(Interpreter::throw_WrongMethodType_entry()));
 405     }
 406     break;
 407 
 408   case _invokestatic_mh:
 409   case _invokespecial_mh:
 410     {
 411       Register rbx_method = rbx_temp;


 518       } else {
 519         assert(ek == _bound_ref_mh || ek == _bound_ref_direct_mh, "must be ref");
 520         arg_type = T_OBJECT;
 521       }
 522       int arg_slots = type2size[arg_type];
 523       int arg_mask  = (arg_type == T_OBJECT ? _INSERT_REF_MASK :
 524                        arg_slots == 1       ? _INSERT_INT_MASK :  _INSERT_LONG_MASK);
 525 
 526       // make room for the new argument:
 527       __ movl(rax_argslot, rcx_bmh_vmargslot);
 528       __ lea(rax_argslot, __ argument_address(rax_argslot));
 529       insert_arg_slots(_masm, arg_slots * stack_move_unit(), arg_mask,
 530                        rax_argslot, rbx_temp, rdx_temp);
 531 
 532       // store bound argument into the new stack slot:
 533       __ movptr(rbx_temp, rcx_bmh_argument);
 534       Address prim_value_addr(rbx_temp, java_lang_boxing_object::value_offset_in_bytes(arg_type));
 535       if (arg_type == T_OBJECT) {
 536         __ movptr(Address(rax_argslot, 0), rbx_temp);
 537       } else {
 538         __ load_sized_value(rbx_temp, prim_value_addr,
 539                             type2aelembytes(arg_type), is_signed_subword_type(arg_type));
 540         __ movptr(Address(rax_argslot, 0), rbx_temp);
 541 #ifndef _LP64
 542         if (arg_slots == 2) {
 543           __ movl(rbx_temp, prim_value_addr.plus_disp(wordSize));
 544           __ movl(Address(rax_argslot, Interpreter::stackElementSize()), rbx_temp);
 545         }
 546 #endif //_LP64
 547         break;
 548       }
 549 
 550       if (direct_to_method) {
 551         Register rbx_method = rbx_temp;
 552         __ movptr(rbx_method, rcx_mh_vmtarget);
 553         __ verify_oop(rbx_method);
 554         __ jmp(rbx_method_fie);
 555       } else {
 556         __ movptr(rcx_recv, rcx_mh_vmtarget);
 557         __ verify_oop(rcx_recv);
 558         __ jump_to_method_handle_entry(rcx_recv, rdx_temp);
 559       }
 560     }
 561     break;
 562 
 563   case _adapter_retype_only:
 564   case _adapter_retype_raw:
 565     // immediately jump to the next MH layer:
 566     __ movptr(rcx_recv, rcx_mh_vmtarget);
 567     __ verify_oop(rcx_recv);


 569     // This is OK when all parameter types widen.
 570     // It is also OK when a return type narrows.
 571     break;
 572 
 573   case _adapter_check_cast:
 574     {
 575       // temps:
 576       Register rbx_klass = rbx_temp; // interesting AMH data
 577 
 578       // check a reference argument before jumping to the next layer of MH:
 579       __ movl(rax_argslot, rcx_amh_vmargslot);
 580       vmarg = __ argument_address(rax_argslot);
 581 
 582       // What class are we casting to?
 583       __ movptr(rbx_klass, rcx_amh_argument); // this is a Class object!
 584       __ movptr(rbx_klass, Address(rbx_klass, java_lang_Class::klass_offset_in_bytes()));
 585 
 586       Label done;
 587       __ movptr(rdx_temp, vmarg);
 588       __ testl(rdx_temp, rdx_temp);
 589       __ jcc(Assembler::zero, done);          // no cast if null
 590       __ load_klass(rdx_temp, rdx_temp);
 591 
 592       // live at this point:
 593       // - rbx_klass:  klass required by the target method
 594       // - rdx_temp:   argument klass to test
 595       // - rcx_recv:   adapter method handle
 596       __ check_klass_subtype(rdx_temp, rbx_klass, rax_argslot, done);
 597 
 598       // If we get here, the type check failed!
 599       // Call the wrong_method_type stub, passing the failing argument type in rax.
 600       Register rax_mtype = rax_argslot;
 601       __ movl(rax_argslot, rcx_amh_vmargslot);  // reload argslot field
 602       __ movptr(rdx_temp, vmarg);
 603 
 604       __ pushptr(rcx_amh_argument); // required class
 605       __ push(rdx_temp);            // bad object
 606       __ push((int)Bytecodes::_checkcast);  // who is complaining?
 607       __ jump(ExternalAddress(from_interpreted_entry(_raise_exception)));
 608 
 609       __ bind(done);


 660           // The vminfo will guide us to clean those bits.
 661         }
 662         break;
 663       default:
 664         assert(false, "");
 665       }
 666       goto finish_int_conversion;
 667     }
 668 
 669   finish_int_conversion:
 670     {
 671       Register rbx_vminfo = rbx_temp;
 672       __ movl(rbx_vminfo, rcx_amh_conversion);
 673       assert(CONV_VMINFO_SHIFT == 0, "preshifted");
 674 
 675       // get the new MH:
 676       __ movptr(rcx_recv, rcx_mh_vmtarget);
 677       // (now we are done with the old MH)
 678 
 679       // original 32-bit vmdata word must be of this form:
 680       //    | MBZ:16 | signBitCount:8 | srcDstTypes:8 | conversionOp:8 |
 681       __ xchgl(rcx, rbx_vminfo);                // free rcx for shifts
 682       __ shll(rdx_temp /*, rcx*/);
 683       Label zero_extend, done;
 684       __ testl(rcx, CONV_VMINFO_SIGN_FLAG);
 685       __ jcc(Assembler::zero, zero_extend);
 686 
 687       // this path is taken for int->byte, int->short
 688       __ sarl(rdx_temp /*, rcx*/);
 689       __ jmp(done);
 690 
 691       __ bind(zero_extend);
 692       // this is taken for int->char
 693       __ shrl(rdx_temp /*, rcx*/);
 694 
 695       __ bind(done);
 696       __ movptr(vmarg, rdx_temp);
 697       __ xchgl(rcx, rbx_vminfo);                // restore rcx_recv
 698 
 699       __ jump_to_method_handle_entry(rcx_recv, rdx_temp);
 700     }
 701     break;
 702 
 703   case _adapter_opt_i2l:        // optimized subcase of adapt_prim_to_prim
 704   case _adapter_opt_unboxl:     // optimized subcase of adapt_ref_to_prim
 705     {
 706       // perform an in-place int-to-long or ref-to-long conversion
 707       __ movl(rax_argslot, rcx_amh_vmargslot);
 708 
 709       // on a little-endian machine we keep the first slot and add another after
 710       __ lea(rax_argslot, __ argument_address(rax_argslot, 1));
 711       insert_arg_slots(_masm, stack_move_unit(), _INSERT_INT_MASK,
 712                        rax_argslot, rbx_temp, rdx_temp);
 713       Address vmarg1(rax_argslot, -Interpreter::stackElementSize());
 714       Address vmarg2 = vmarg1.plus_disp(Interpreter::stackElementSize());
 715 
 716       switch (ek) {
 717       case _adapter_opt_i2l:


 846           __ movptr(rdx_temp, Address(rbx_destslot, i));
 847           __ movptr(Address(rax_argslot, i), rdx_temp);
 848           __ pop(rdx_temp);
 849           __ movptr(Address(rbx_destslot, i), rdx_temp);
 850         }
 851       } else {
 852         // push the first chunk, which is going to get overwritten
 853         for (int i = swap_bytes; (i -= wordSize) >= 0; ) {
 854           __ movptr(rdx_temp, Address(rax_argslot, i));
 855           __ push(rdx_temp);
 856         }
 857 
 858         if (rotate > 0) {
 859           // rotate upward
 860           __ subptr(rax_argslot, swap_bytes);
 861 #ifdef ASSERT
 862           {
 863             // Verify that argslot > destslot, by at least swap_bytes.
 864             Label L_ok;
 865             __ cmpptr(rax_argslot, rbx_destslot);
 866             __ jcc(Assembler::aboveEqual, L_ok);
 867             __ stop("source must be above destination (upward rotation)");
 868             __ bind(L_ok);
 869           }
 870 #endif
 871           // work argslot down to destslot, copying contiguous data upwards
 872           // pseudo-code:
 873           //   rax = src_addr - swap_bytes
 874           //   rbx = dest_addr
 875           //   while (rax >= rbx) *(rax + swap_bytes) = *(rax + 0), rax--;
 876           Label loop;
 877           __ bind(loop);
 878           __ movptr(rdx_temp, Address(rax_argslot, 0));
 879           __ movptr(Address(rax_argslot, swap_bytes), rdx_temp);
 880           __ addptr(rax_argslot, -wordSize);
 881           __ cmpptr(rax_argslot, rbx_destslot);
 882           __ jcc(Assembler::aboveEqual, loop);
 883         } else {
 884           __ addptr(rax_argslot, swap_bytes);
 885 #ifdef ASSERT
 886           {
 887             // Verify that argslot < destslot, by at least swap_bytes.
 888             Label L_ok;
 889             __ cmpptr(rax_argslot, rbx_destslot);
 890             __ jcc(Assembler::belowEqual, L_ok);
 891             __ stop("source must be below destination (downward rotation)");
 892             __ bind(L_ok);
 893           }
 894 #endif
 895           // work argslot up to destslot, copying contiguous data downwards
 896           // pseudo-code:
 897           //   rax = src_addr + swap_bytes
 898           //   rbx = dest_addr
 899           //   while (rax <= rbx) *(rax - swap_bytes) = *(rax + 0), rax++;
 900           Label loop;
 901           __ bind(loop);
 902           __ movptr(rdx_temp, Address(rax_argslot, 0));
 903           __ movptr(Address(rax_argslot, -swap_bytes), rdx_temp);
 904           __ addptr(rax_argslot, wordSize);
 905           __ cmpptr(rax_argslot, rbx_destslot);
 906           __ jcc(Assembler::belowEqual, loop);
 907         }
 908 
 909         // pop the original first chunk into the destination slot, now free
 910         for (int i = 0; i < swap_bytes; i += wordSize) {
 911           __ pop(rdx_temp);
 912           __ movptr(Address(rbx_destslot, i), rdx_temp);
 913         }
 914       }
 915 
 916       __ movptr(rcx_recv, rcx_mh_vmtarget);
 917       __ jump_to_method_handle_entry(rcx_recv, rdx_temp);
 918     }
 919     break;
 920 
 921   case _adapter_dup_args:
 922     {
 923       // 'argslot' is the position of the first argument to duplicate
 924       __ movl(rax_argslot, rcx_amh_vmargslot);
 925       __ lea(rax_argslot, __ argument_address(rax_argslot));
 926 


 952 
 953       // pull down the pre_arg_size data (PC)
 954       for (int i = -pre_arg_size; i < 0; i += wordSize) {
 955         __ movptr(rdi, Address(rbx_oldarg, i));
 956         __ movptr(Address(rdx_newarg, i), rdi);
 957       }
 958 
 959       // copy from rax_argslot[0...] down to new_rsp[1...]
 960       // pseudo-code:
 961       //   rbx = old_rsp+1
 962       //   rdx = new_rsp+1
 963       //   rax = argslot
 964       //   while (rdx < rbx) *rdx++ = *rax++
 965       Label loop;
 966       __ bind(loop);
 967       __ movptr(rdi, Address(rax_argslot, 0));
 968       __ movptr(Address(rdx_newarg, 0), rdi);
 969       __ addptr(rax_argslot, wordSize);
 970       __ addptr(rdx_newarg, wordSize);
 971       __ cmpptr(rdx_newarg, rbx_oldarg);
 972       __ jcc(Assembler::less, loop);
 973 
 974       __ pop(rdi);              // restore temp
 975 
 976       __ movptr(rcx_recv, rcx_mh_vmtarget);
 977       __ jump_to_method_handle_entry(rcx_recv, rdx_temp);
 978     }
 979     break;
 980 
 981   case _adapter_drop_args:
 982     {
 983       // 'argslot' is the position of the first argument to nuke
 984       __ movl(rax_argslot, rcx_amh_vmargslot);
 985       __ lea(rax_argslot, __ argument_address(rax_argslot));
 986 
 987       __ push(rdi);             // need a temp
 988       // (must do previous push after argslot address is taken)
 989 
 990       // 'stack_move' is number of words to drop
 991       Register rdi_stack_move = rdi;
 992       __ movl(rdi_stack_move, rcx_amh_conversion);


1104       }
1105 
1106       // Copy from the array to the new slots.
1107       // Note: Stack change code preserves integrity of rax_argslot pointer.
1108       // So even after slot insertions, rax_argslot still points to first argument.
1109       if (length_constant == -1) {
1110         // [rax_argslot, rdx_argslot_limit) is the area we are inserting into.
1111         Register rsi_source = rsi_array;
1112         __ lea(rsi_source, Address(rsi_array, elem0_offset));
1113         Label loop;
1114         __ bind(loop);
1115         __ movptr(rbx_temp, Address(rsi_source, 0));
1116         __ movptr(Address(rax_argslot, 0), rbx_temp);
1117         __ addptr(rsi_source, type2aelembytes(elem_type));
1118         if (TaggedStackInterpreter) {
1119           __ movptr(Address(rax_argslot, tag_offset),
1120                     frame::tag_for_basic_type(elem_type));
1121         }
1122         __ addptr(rax_argslot, Interpreter::stackElementSize());
1123         __ cmpptr(rax_argslot, rdx_argslot_limit);
1124         __ jcc(Assembler::less, loop);
1125       } else if (length_constant == 0) {
1126         __ bind(skip_array_check);
1127         // nothing to copy
1128       } else {
1129         int elem_offset = elem0_offset;
1130         int slot_offset = 0;
1131         for (int index = 0; index < length_constant; index++) {
1132           __ movptr(rbx_temp, Address(rsi_array, elem_offset));
1133           __ movptr(Address(rax_argslot, slot_offset), rbx_temp);
1134           elem_offset += type2aelembytes(elem_type);
1135           if (TaggedStackInterpreter) {
1136             __ movptr(Address(rax_argslot, slot_offset + tag_offset),
1137                       frame::tag_for_basic_type(elem_type));
1138           }
1139           slot_offset += Interpreter::stackElementSize();
1140         }
1141       }
1142 
1143       // Arguments are spread.  Move to next method handle.
1144       UNPUSH_RSI_RDI;




  48 }
  49 
  50 MethodHandleEntry* MethodHandleEntry::finish_compiled_entry(MacroAssembler* _masm,
  51                                                 address start_addr) {
  52   MethodHandleEntry* me = (MethodHandleEntry*) start_addr;
  53   assert(me->end_address() == start_addr, "valid ME");
  54 
  55   // Fill in the real end_address:
  56   __ align(wordSize);
  57   me->set_end_address(__ pc());
  58 
  59   return me;
  60 }
  61 
  62 #ifdef ASSERT
  63 static void verify_argslot(MacroAssembler* _masm, Register rax_argslot,
  64                            const char* error_message) {
  65   // Verify that argslot lies within (rsp, rbp].
  66   Label L_ok, L_bad;
  67   __ cmpptr(rax_argslot, rbp);
  68   __ jccb(Assembler::above, L_bad);
  69   __ cmpptr(rsp, rax_argslot);
  70   __ jccb(Assembler::below, L_ok);
  71   __ bind(L_bad);
  72   __ stop(error_message);
  73   __ bind(L_ok);
  74 }
  75 #endif
  76 
  77 
  78 // Code generation
  79 address MethodHandles::generate_method_handle_interpreter_entry(MacroAssembler* _masm) {
  80   // rbx: methodOop
  81   // rcx: receiver method handle (must load from sp[MethodTypeForm.vmslots])
  82   // rsi/r13: sender SP (must preserve; see prepare_to_jump_from_interpreted)
  83   // rdx: garbage temp, blown away
  84 
  85   Register rbx_method = rbx;
  86   Register rcx_recv   = rcx;
  87   Register rax_mtype  = rax;
  88   Register rdx_temp   = rdx;
  89 
  90   // emit WrongMethodType path first, to enable jccb back-branch from main path


 119   __ jump_to_method_handle_entry(rcx_recv, rdx_temp);
 120 
 121   return entry_point;
 122 }
 123 
 124 // Helper to insert argument slots into the stack.
 125 // arg_slots must be a multiple of stack_move_unit() and <= 0
 126 void MethodHandles::insert_arg_slots(MacroAssembler* _masm,
 127                                      RegisterOrConstant arg_slots,
 128                                      int arg_mask,
 129                                      Register rax_argslot,
 130                                      Register rbx_temp, Register rdx_temp) {
 131   assert_different_registers(rax_argslot, rbx_temp, rdx_temp,
 132                              (!arg_slots.is_register() ? rsp : arg_slots.as_register()));
 133 
 134 #ifdef ASSERT
 135   verify_argslot(_masm, rax_argslot, "insertion point must fall within current frame");
 136   if (arg_slots.is_register()) {
 137     Label L_ok, L_bad;
 138     __ cmpptr(arg_slots.as_register(), (int32_t) NULL_WORD);
 139     __ jccb(Assembler::greater, L_bad);
 140     __ testl(arg_slots.as_register(), -stack_move_unit() - 1);
 141     __ jccb(Assembler::zero, L_ok);
 142     __ bind(L_bad);
 143     __ stop("assert arg_slots <= 0 and clear low bits");
 144     __ bind(L_ok);
 145   } else {
 146     assert(arg_slots.as_constant() <= 0, "");
 147     assert(arg_slots.as_constant() % -stack_move_unit() == 0, "");
 148   }
 149 #endif //ASSERT
 150 
 151 #ifdef _LP64
 152   if (arg_slots.is_register()) {
 153     // clean high bits of stack motion register (was loaded as an int)
 154     __ movslq(arg_slots.as_register(), arg_slots.as_register());
 155   }
 156 #endif
 157 
 158   // Make space on the stack for the inserted argument(s).
 159   // Then pull down everything shallower than rax_argslot.
 160   // The stacked return address gets pulled down with everything else.
 161   // That is, copy [rsp, argslot) downward by -size words.  In pseudo-code:
 162   //   rsp -= size;
 163   //   for (rdx = rsp + size; rdx < argslot; rdx++)
 164   //     rdx[-size] = rdx[0]
 165   //   argslot -= size;
 166   __ mov(rdx_temp, rsp);                        // source pointer for copy
 167   __ lea(rsp, Address(rsp, arg_slots, Address::times_ptr));
 168   {
 169     Label loop;
 170     __ bind(loop);
 171     // pull one word down each time through the loop
 172     __ movptr(rbx_temp, Address(rdx_temp, 0));
 173     __ movptr(Address(rdx_temp, arg_slots, Address::times_ptr), rbx_temp);
 174     __ addptr(rdx_temp, wordSize);
 175     __ cmpptr(rdx_temp, rax_argslot);
 176     __ jccb(Assembler::less, loop);
 177   }
 178 
 179   // Now move the argslot down, to point to the opened-up space.
 180   __ lea(rax_argslot, Address(rax_argslot, arg_slots, Address::times_ptr));
 181 
 182   if (TaggedStackInterpreter && arg_mask != _INSERT_NO_MASK) {
 183     // The caller has specified a bitmask of tags to put into the opened space.
 184     // This only works when the arg_slots value is an assembly-time constant.
 185     int constant_arg_slots = arg_slots.as_constant() / stack_move_unit();
 186     int tag_offset = Interpreter::tag_offset_in_bytes() - Interpreter::value_offset_in_bytes();
 187     for (int slot = 0; slot < constant_arg_slots; slot++) {
 188       BasicType slot_type   = ((arg_mask & (1 << slot)) == 0 ? T_OBJECT : T_INT);
 189       int       slot_offset = Interpreter::stackElementSize() * slot;
 190       Address   tag_addr(rax_argslot, slot_offset + tag_offset);
 191       __ movptr(tag_addr, frame::tag_for_basic_type(slot_type));
 192     }
 193     // Note that the new argument slots are tagged properly but contain
 194     // garbage at this point.  The value portions must be initialized
 195     // by the caller.  (Especially references!)
 196   }
 197 }
 198 
 199 // Helper to remove argument slots from the stack.
 200 // arg_slots must be a multiple of stack_move_unit() and >= 0
 201 void MethodHandles::remove_arg_slots(MacroAssembler* _masm,
 202                                     RegisterOrConstant arg_slots,
 203                                     Register rax_argslot,
 204                                     Register rbx_temp, Register rdx_temp) {
 205   assert_different_registers(rax_argslot, rbx_temp, rdx_temp,
 206                              (!arg_slots.is_register() ? rsp : arg_slots.as_register()));
 207 
 208 #ifdef ASSERT
 209   {
 210     // Verify that [argslot..argslot+size) lies within (rsp, rbp).
 211     Label L_ok, L_bad;
 212     __ lea(rbx_temp, Address(rax_argslot, arg_slots, Address::times_ptr));
 213     __ cmpptr(rbx_temp, rbp);
 214     __ jccb(Assembler::above, L_bad);
 215     __ cmpptr(rsp, rax_argslot);
 216     __ jccb(Assembler::below, L_ok);
 217     __ bind(L_bad);
 218     __ stop("deleted argument(s) must fall within current frame");
 219     __ bind(L_ok);
 220   }
 221   if (arg_slots.is_register()) {
 222     Label L_ok, L_bad;
 223     __ cmpptr(arg_slots.as_register(), (int32_t) NULL_WORD);
 224     __ jccb(Assembler::less, L_bad);
 225     __ testl(arg_slots.as_register(), -stack_move_unit() - 1);
 226     __ jccb(Assembler::zero, L_ok);
 227     __ bind(L_bad);
 228     __ stop("assert arg_slots >= 0 and clear low bits");
 229     __ bind(L_ok);
 230   } else {
 231     assert(arg_slots.as_constant() >= 0, "");
 232     assert(arg_slots.as_constant() % -stack_move_unit() == 0, "");
 233   }
 234 #endif //ASSERT
 235 
 236 #ifdef _LP64
 237   if (false) {                  // not needed, since register is positive
 238     // clean high bits of stack motion register (was loaded as an int)
 239     if (arg_slots.is_register())
 240       __ movslq(arg_slots.as_register(), arg_slots.as_register());
 241   }
 242 #endif
 243 
 244   // Pull up everything shallower than rax_argslot.
 245   // Then remove the excess space on the stack.
 246   // The stacked return address gets pulled up with everything else.
 247   // That is, copy [rsp, argslot) upward by size words.  In pseudo-code:
 248   //   for (rdx = argslot-1; rdx >= rsp; --rdx)
 249   //     rdx[size] = rdx[0]
 250   //   argslot += size;
 251   //   rsp += size;
 252   __ lea(rdx_temp, Address(rax_argslot, -wordSize)); // source pointer for copy
 253   {
 254     Label loop;
 255     __ bind(loop);
 256     // pull one word up each time through the loop
 257     __ movptr(rbx_temp, Address(rdx_temp, 0));
 258     __ movptr(Address(rdx_temp, arg_slots, Address::times_ptr), rbx_temp);
 259     __ addptr(rdx_temp, -wordSize);
 260     __ cmpptr(rdx_temp, rsp);
 261     __ jccb(Assembler::greaterEqual, loop);
 262   }
 263 
 264   // Now move the argslot up, to point to the just-copied block.
 265   __ lea(rsp, Address(rsp, arg_slots, Address::times_ptr));
 266   // And adjust the argslot address to point at the deletion point.
 267   __ lea(rax_argslot, Address(rax_argslot, arg_slots, Address::times_ptr));
 268 }
 269 
 270 #ifndef PRODUCT
 271 extern "C" void print_method_handle(oopDesc* mh);
 272 void trace_method_handle_stub(const char* adaptername,
 273                               oopDesc* mh,
 274                               intptr_t* entry_sp,
 275                               intptr_t* saved_sp,
 276                               intptr_t* saved_bp) {
 277   // called as a leaf from native code: do not block the JVM!
 278   intptr_t* last_sp = (intptr_t*) saved_bp[frame::interpreter_frame_last_sp_offset];
 279   intptr_t* base_sp = (intptr_t*) saved_bp[frame::interpreter_frame_monitor_block_top_offset];
 280   printf("MH %s mh="INTPTR_FORMAT" sp=("INTPTR_FORMAT"+"INTX_FORMAT") stack_size="INTX_FORMAT" bp="INTPTR_FORMAT"\n",
 281          adaptername, (intptr_t)mh, (intptr_t)entry_sp, (intptr_t)(saved_sp - entry_sp), (intptr_t)(base_sp - last_sp), (intptr_t)saved_bp);


 367       __ pop(rdx_code);  // TOS+0
 368       __ pop(rcx_fail);  // TOS+4
 369       __ pop(rax_want);  // TOS+8
 370       __ pop(rdi_pc);    // caller PC
 371 
 372       __ mov(rsp, rsi);   // cut the stack back to where the caller started
 373 
 374       // Repush the arguments as if coming from the interpreter.
 375       if (TaggedStackInterpreter)  __ push(frame::tag_for_basic_type(T_INT));
 376       __ push(rdx_code);
 377       if (TaggedStackInterpreter)  __ push(frame::tag_for_basic_type(T_OBJECT));
 378       __ push(rcx_fail);
 379       if (TaggedStackInterpreter)  __ push(frame::tag_for_basic_type(T_OBJECT));
 380       __ push(rax_want);
 381 
 382       Register rbx_method = rbx_temp;
 383       Label no_method;
 384       // FIXME: fill in _raise_exception_method with a suitable sun.dyn method
 385       __ movptr(rbx_method, ExternalAddress((address) &_raise_exception_method));
 386       __ testptr(rbx_method, rbx_method);
 387       __ jccb(Assembler::zero, no_method);
 388       int jobject_oop_offset = 0;
 389       __ movptr(rbx_method, Address(rbx_method, jobject_oop_offset));  // dereference the jobject
 390       __ testptr(rbx_method, rbx_method);
 391       __ jccb(Assembler::zero, no_method);
 392       __ verify_oop(rbx_method);
 393       __ push(rdi_pc);          // and restore caller PC
 394       __ jmp(rbx_method_fie);
 395 
 396       // If we get here, the Java runtime did not do its job of creating the exception.
 397       // Do something that is at least causes a valid throw from the interpreter.
 398       __ bind(no_method);
 399       __ pop(rax_want);
 400       if (TaggedStackInterpreter)  __ pop(rcx_fail);
 401       __ pop(rcx_fail);
 402       __ push(rax_want);
 403       __ push(rcx_fail);
 404       __ jump(ExternalAddress(Interpreter::throw_WrongMethodType_entry()));
 405     }
 406     break;
 407 
 408   case _invokestatic_mh:
 409   case _invokespecial_mh:
 410     {
 411       Register rbx_method = rbx_temp;


 518       } else {
 519         assert(ek == _bound_ref_mh || ek == _bound_ref_direct_mh, "must be ref");
 520         arg_type = T_OBJECT;
 521       }
 522       int arg_slots = type2size[arg_type];
 523       int arg_mask  = (arg_type == T_OBJECT ? _INSERT_REF_MASK :
 524                        arg_slots == 1       ? _INSERT_INT_MASK :  _INSERT_LONG_MASK);
 525 
 526       // make room for the new argument:
 527       __ movl(rax_argslot, rcx_bmh_vmargslot);
 528       __ lea(rax_argslot, __ argument_address(rax_argslot));
 529       insert_arg_slots(_masm, arg_slots * stack_move_unit(), arg_mask,
 530                        rax_argslot, rbx_temp, rdx_temp);
 531 
 532       // store bound argument into the new stack slot:
 533       __ movptr(rbx_temp, rcx_bmh_argument);
 534       Address prim_value_addr(rbx_temp, java_lang_boxing_object::value_offset_in_bytes(arg_type));
 535       if (arg_type == T_OBJECT) {
 536         __ movptr(Address(rax_argslot, 0), rbx_temp);
 537       } else {
 538         __ load_sized_value(rdx_temp, prim_value_addr,
 539                             type2aelembytes(arg_type), is_signed_subword_type(arg_type));
 540         __ movptr(Address(rax_argslot, 0), rdx_temp);
 541 #ifndef _LP64
 542         if (arg_slots == 2) {
 543           __ movl(rdx_temp, prim_value_addr.plus_disp(wordSize));
 544           __ movl(Address(rax_argslot, Interpreter::stackElementSize()), rdx_temp);
 545         }
 546 #endif //_LP64

 547       }
 548 
 549       if (direct_to_method) {
 550         Register rbx_method = rbx_temp;
 551         __ movptr(rbx_method, rcx_mh_vmtarget);
 552         __ verify_oop(rbx_method);
 553         __ jmp(rbx_method_fie);
 554       } else {
 555         __ movptr(rcx_recv, rcx_mh_vmtarget);
 556         __ verify_oop(rcx_recv);
 557         __ jump_to_method_handle_entry(rcx_recv, rdx_temp);
 558       }
 559     }
 560     break;
 561 
 562   case _adapter_retype_only:
 563   case _adapter_retype_raw:
 564     // immediately jump to the next MH layer:
 565     __ movptr(rcx_recv, rcx_mh_vmtarget);
 566     __ verify_oop(rcx_recv);


 568     // This is OK when all parameter types widen.
 569     // It is also OK when a return type narrows.
 570     break;
 571 
 572   case _adapter_check_cast:
 573     {
 574       // temps:
 575       Register rbx_klass = rbx_temp; // interesting AMH data
 576 
 577       // check a reference argument before jumping to the next layer of MH:
 578       __ movl(rax_argslot, rcx_amh_vmargslot);
 579       vmarg = __ argument_address(rax_argslot);
 580 
 581       // What class are we casting to?
 582       __ movptr(rbx_klass, rcx_amh_argument); // this is a Class object!
 583       __ movptr(rbx_klass, Address(rbx_klass, java_lang_Class::klass_offset_in_bytes()));
 584 
 585       Label done;
 586       __ movptr(rdx_temp, vmarg);
 587       __ testl(rdx_temp, rdx_temp);
 588       __ jccb(Assembler::zero, done);         // no cast if null
 589       __ load_klass(rdx_temp, rdx_temp);
 590 
 591       // live at this point:
 592       // - rbx_klass:  klass required by the target method
 593       // - rdx_temp:   argument klass to test
 594       // - rcx_recv:   adapter method handle
 595       __ check_klass_subtype(rdx_temp, rbx_klass, rax_argslot, done);
 596 
 597       // If we get here, the type check failed!
 598       // Call the wrong_method_type stub, passing the failing argument type in rax.
 599       Register rax_mtype = rax_argslot;
 600       __ movl(rax_argslot, rcx_amh_vmargslot);  // reload argslot field
 601       __ movptr(rdx_temp, vmarg);
 602 
 603       __ pushptr(rcx_amh_argument); // required class
 604       __ push(rdx_temp);            // bad object
 605       __ push((int)Bytecodes::_checkcast);  // who is complaining?
 606       __ jump(ExternalAddress(from_interpreted_entry(_raise_exception)));
 607 
 608       __ bind(done);


 659           // The vminfo will guide us to clean those bits.
 660         }
 661         break;
 662       default:
 663         assert(false, "");
 664       }
 665       goto finish_int_conversion;
 666     }
 667 
 668   finish_int_conversion:
 669     {
 670       Register rbx_vminfo = rbx_temp;
 671       __ movl(rbx_vminfo, rcx_amh_conversion);
 672       assert(CONV_VMINFO_SHIFT == 0, "preshifted");
 673 
 674       // get the new MH:
 675       __ movptr(rcx_recv, rcx_mh_vmtarget);
 676       // (now we are done with the old MH)
 677 
 678       // original 32-bit vmdata word must be of this form:
 679       //    | MBZ:6 | signBitCount:8 | srcDstTypes:8 | conversionOp:8 |
 680       __ xchgptr(rcx, rbx_vminfo);                // free rcx for shifts
 681       __ shll(rdx_temp /*, rcx*/);
 682       Label zero_extend, done;
 683       __ testl(rcx, CONV_VMINFO_SIGN_FLAG);
 684       __ jccb(Assembler::zero, zero_extend);
 685 
 686       // this path is taken for int->byte, int->short
 687       __ sarl(rdx_temp /*, rcx*/);
 688       __ jmpb(done);
 689 
 690       __ bind(zero_extend);
 691       // this is taken for int->char
 692       __ shrl(rdx_temp /*, rcx*/);
 693 
 694       __ bind(done);
 695       __ movl(vmarg, rdx_temp);
 696       __ xchgptr(rcx, rbx_vminfo);                // restore rcx_recv
 697 
 698       __ jump_to_method_handle_entry(rcx_recv, rdx_temp);
 699     }
 700     break;
 701 
 702   case _adapter_opt_i2l:        // optimized subcase of adapt_prim_to_prim
 703   case _adapter_opt_unboxl:     // optimized subcase of adapt_ref_to_prim
 704     {
 705       // perform an in-place int-to-long or ref-to-long conversion
 706       __ movl(rax_argslot, rcx_amh_vmargslot);
 707 
 708       // on a little-endian machine we keep the first slot and add another after
 709       __ lea(rax_argslot, __ argument_address(rax_argslot, 1));
 710       insert_arg_slots(_masm, stack_move_unit(), _INSERT_INT_MASK,
 711                        rax_argslot, rbx_temp, rdx_temp);
 712       Address vmarg1(rax_argslot, -Interpreter::stackElementSize());
 713       Address vmarg2 = vmarg1.plus_disp(Interpreter::stackElementSize());
 714 
 715       switch (ek) {
 716       case _adapter_opt_i2l:


 845           __ movptr(rdx_temp, Address(rbx_destslot, i));
 846           __ movptr(Address(rax_argslot, i), rdx_temp);
 847           __ pop(rdx_temp);
 848           __ movptr(Address(rbx_destslot, i), rdx_temp);
 849         }
 850       } else {
 851         // push the first chunk, which is going to get overwritten
 852         for (int i = swap_bytes; (i -= wordSize) >= 0; ) {
 853           __ movptr(rdx_temp, Address(rax_argslot, i));
 854           __ push(rdx_temp);
 855         }
 856 
 857         if (rotate > 0) {
 858           // rotate upward
 859           __ subptr(rax_argslot, swap_bytes);
 860 #ifdef ASSERT
 861           {
 862             // Verify that argslot > destslot, by at least swap_bytes.
 863             Label L_ok;
 864             __ cmpptr(rax_argslot, rbx_destslot);
 865             __ jccb(Assembler::aboveEqual, L_ok);
 866             __ stop("source must be above destination (upward rotation)");
 867             __ bind(L_ok);
 868           }
 869 #endif
 870           // work argslot down to destslot, copying contiguous data upwards
 871           // pseudo-code:
 872           //   rax = src_addr - swap_bytes
 873           //   rbx = dest_addr
 874           //   while (rax >= rbx) *(rax + swap_bytes) = *(rax + 0), rax--;
 875           Label loop;
 876           __ bind(loop);
 877           __ movptr(rdx_temp, Address(rax_argslot, 0));
 878           __ movptr(Address(rax_argslot, swap_bytes), rdx_temp);
 879           __ addptr(rax_argslot, -wordSize);
 880           __ cmpptr(rax_argslot, rbx_destslot);
 881           __ jccb(Assembler::aboveEqual, loop);
 882         } else {
 883           __ addptr(rax_argslot, swap_bytes);
 884 #ifdef ASSERT
 885           {
 886             // Verify that argslot < destslot, by at least swap_bytes.
 887             Label L_ok;
 888             __ cmpptr(rax_argslot, rbx_destslot);
 889             __ jccb(Assembler::belowEqual, L_ok);
 890             __ stop("source must be below destination (downward rotation)");
 891             __ bind(L_ok);
 892           }
 893 #endif
 894           // work argslot up to destslot, copying contiguous data downwards
 895           // pseudo-code:
 896           //   rax = src_addr + swap_bytes
 897           //   rbx = dest_addr
 898           //   while (rax <= rbx) *(rax - swap_bytes) = *(rax + 0), rax++;
 899           Label loop;
 900           __ bind(loop);
 901           __ movptr(rdx_temp, Address(rax_argslot, 0));
 902           __ movptr(Address(rax_argslot, -swap_bytes), rdx_temp);
 903           __ addptr(rax_argslot, wordSize);
 904           __ cmpptr(rax_argslot, rbx_destslot);
 905           __ jccb(Assembler::belowEqual, loop);
 906         }
 907 
 908         // pop the original first chunk into the destination slot, now free
 909         for (int i = 0; i < swap_bytes; i += wordSize) {
 910           __ pop(rdx_temp);
 911           __ movptr(Address(rbx_destslot, i), rdx_temp);
 912         }
 913       }
 914 
 915       __ movptr(rcx_recv, rcx_mh_vmtarget);
 916       __ jump_to_method_handle_entry(rcx_recv, rdx_temp);
 917     }
 918     break;
 919 
 920   case _adapter_dup_args:
 921     {
 922       // 'argslot' is the position of the first argument to duplicate
 923       __ movl(rax_argslot, rcx_amh_vmargslot);
 924       __ lea(rax_argslot, __ argument_address(rax_argslot));
 925 


 951 
 952       // pull down the pre_arg_size data (PC)
 953       for (int i = -pre_arg_size; i < 0; i += wordSize) {
 954         __ movptr(rdi, Address(rbx_oldarg, i));
 955         __ movptr(Address(rdx_newarg, i), rdi);
 956       }
 957 
 958       // copy from rax_argslot[0...] down to new_rsp[1...]
 959       // pseudo-code:
 960       //   rbx = old_rsp+1
 961       //   rdx = new_rsp+1
 962       //   rax = argslot
 963       //   while (rdx < rbx) *rdx++ = *rax++
 964       Label loop;
 965       __ bind(loop);
 966       __ movptr(rdi, Address(rax_argslot, 0));
 967       __ movptr(Address(rdx_newarg, 0), rdi);
 968       __ addptr(rax_argslot, wordSize);
 969       __ addptr(rdx_newarg, wordSize);
 970       __ cmpptr(rdx_newarg, rbx_oldarg);
 971       __ jccb(Assembler::less, loop);
 972 
 973       __ pop(rdi);              // restore temp
 974 
 975       __ movptr(rcx_recv, rcx_mh_vmtarget);
 976       __ jump_to_method_handle_entry(rcx_recv, rdx_temp);
 977     }
 978     break;
 979 
 980   case _adapter_drop_args:
 981     {
 982       // 'argslot' is the position of the first argument to nuke
 983       __ movl(rax_argslot, rcx_amh_vmargslot);
 984       __ lea(rax_argslot, __ argument_address(rax_argslot));
 985 
 986       __ push(rdi);             // need a temp
 987       // (must do previous push after argslot address is taken)
 988 
 989       // 'stack_move' is number of words to drop
 990       Register rdi_stack_move = rdi;
 991       __ movl(rdi_stack_move, rcx_amh_conversion);


1103       }
1104 
1105       // Copy from the array to the new slots.
1106       // Note: Stack change code preserves integrity of rax_argslot pointer.
1107       // So even after slot insertions, rax_argslot still points to first argument.
1108       if (length_constant == -1) {
1109         // [rax_argslot, rdx_argslot_limit) is the area we are inserting into.
1110         Register rsi_source = rsi_array;
1111         __ lea(rsi_source, Address(rsi_array, elem0_offset));
1112         Label loop;
1113         __ bind(loop);
1114         __ movptr(rbx_temp, Address(rsi_source, 0));
1115         __ movptr(Address(rax_argslot, 0), rbx_temp);
1116         __ addptr(rsi_source, type2aelembytes(elem_type));
1117         if (TaggedStackInterpreter) {
1118           __ movptr(Address(rax_argslot, tag_offset),
1119                     frame::tag_for_basic_type(elem_type));
1120         }
1121         __ addptr(rax_argslot, Interpreter::stackElementSize());
1122         __ cmpptr(rax_argslot, rdx_argslot_limit);
1123         __ jccb(Assembler::less, loop);
1124       } else if (length_constant == 0) {
1125         __ bind(skip_array_check);
1126         // nothing to copy
1127       } else {
1128         int elem_offset = elem0_offset;
1129         int slot_offset = 0;
1130         for (int index = 0; index < length_constant; index++) {
1131           __ movptr(rbx_temp, Address(rsi_array, elem_offset));
1132           __ movptr(Address(rax_argslot, slot_offset), rbx_temp);
1133           elem_offset += type2aelembytes(elem_type);
1134           if (TaggedStackInterpreter) {
1135             __ movptr(Address(rax_argslot, slot_offset + tag_offset),
1136                       frame::tag_for_basic_type(elem_type));
1137           }
1138           slot_offset += Interpreter::stackElementSize();
1139         }
1140       }
1141 
1142       // Arguments are spread.  Move to next method handle.
1143       UNPUSH_RSI_RDI;


src/cpu/x86/vm/methodHandles_x86.cpp
Index Unified diffs Context diffs Sdiffs Wdiffs Patch New Old Previous File Next File