src/cpu/x86/vm/methodHandles_x86.cpp

changeset 1145
e5b0439ef4ae
child 1280
df6caf649ff7
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/src/cpu/x86/vm/methodHandles_x86.cpp	Wed Apr 08 10:56:49 2009 -0700
     1.3 @@ -0,0 +1,1133 @@
     1.4 +/*
     1.5 + * Copyright 1997-2009 Sun Microsystems, Inc.  All Rights Reserved.
     1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     1.7 + *
     1.8 + * This code is free software; you can redistribute it and/or modify it
     1.9 + * under the terms of the GNU General Public License version 2 only, as
    1.10 + * published by the Free Software Foundation.
    1.11 + *
    1.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
    1.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    1.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    1.15 + * version 2 for more details (a copy is included in the LICENSE file that
    1.16 + * accompanied this code).
    1.17 + *
    1.18 + * You should have received a copy of the GNU General Public License version
    1.19 + * 2 along with this work; if not, write to the Free Software Foundation,
    1.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    1.21 + *
    1.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
    1.23 + * CA 95054 USA or visit www.sun.com if you need additional information or
    1.24 + * have any questions.
    1.25 + *
    1.26 + */
    1.27 +
    1.28 +#include "incls/_precompiled.incl"
    1.29 +#include "incls/_methodHandles_x86.cpp.incl"
    1.30 +
    1.31 +#define __ _masm->
    1.32 +
    1.33 +address MethodHandleEntry::start_compiled_entry(MacroAssembler* _masm,
    1.34 +                                                address interpreted_entry) {
    1.35 +  // Just before the actual machine code entry point, allocate space
    1.36 +  // for a MethodHandleEntry::Data record, so that we can manage everything
    1.37 +  // from one base pointer.
    1.38 +  __ align(wordSize);
    1.39 +  address target = __ pc() + sizeof(Data);
    1.40 +  while (__ pc() < target) {
    1.41 +    __ nop();
    1.42 +    __ align(wordSize);
    1.43 +  }
    1.44 +
    1.45 +  MethodHandleEntry* me = (MethodHandleEntry*) __ pc();
    1.46 +  me->set_end_address(__ pc());         // set a temporary end_address
    1.47 +  me->set_from_interpreted_entry(interpreted_entry);
    1.48 +  me->set_type_checking_entry(NULL);
    1.49 +
    1.50 +  return (address) me;
    1.51 +}
    1.52 +
    1.53 +MethodHandleEntry* MethodHandleEntry::finish_compiled_entry(MacroAssembler* _masm,
    1.54 +                                                address start_addr) {
    1.55 +  MethodHandleEntry* me = (MethodHandleEntry*) start_addr;
    1.56 +  assert(me->end_address() == start_addr, "valid ME");
    1.57 +
    1.58 +  // Fill in the real end_address:
    1.59 +  __ align(wordSize);
    1.60 +  me->set_end_address(__ pc());
    1.61 +
    1.62 +  return me;
    1.63 +}
    1.64 +
    1.65 +#ifdef ASSERT
    1.66 +static void verify_argslot(MacroAssembler* _masm, Register rax_argslot,
    1.67 +                           const char* error_message) {
    1.68 +  // Verify that argslot lies within (rsp, rbp].
    1.69 +  Label L_ok, L_bad;
    1.70 +  __ cmpptr(rax_argslot, rbp);
    1.71 +  __ jcc(Assembler::above, L_bad);
    1.72 +  __ cmpptr(rsp, rax_argslot);
    1.73 +  __ jcc(Assembler::below, L_ok);
    1.74 +  __ bind(L_bad);
    1.75 +  __ stop(error_message);
    1.76 +  __ bind(L_ok);
    1.77 +}
    1.78 +#endif
    1.79 +
    1.80 +
    1.81 +// Code generation
    1.82 +address MethodHandles::generate_method_handle_interpreter_entry(MacroAssembler* _masm) {
    1.83 +  // rbx: methodOop
    1.84 +  // rcx: receiver method handle (must load from sp[MethodTypeForm.vmslots])
    1.85 +  // rsi/r13: sender SP (must preserve; see prepare_to_jump_from_interpreted)
    1.86 +  // rdx: garbage temp, blown away
    1.87 +
    1.88 +  Register rbx_method = rbx;
    1.89 +  Register rcx_recv   = rcx;
    1.90 +  Register rax_mtype  = rax;
    1.91 +  Register rdx_temp   = rdx;
    1.92 +
    1.93 +  // emit WrongMethodType path first, to enable jccb back-branch from main path
    1.94 +  Label wrong_method_type;
    1.95 +  __ bind(wrong_method_type);
    1.96 +  __ push(rax_mtype);       // required mtype
    1.97 +  __ push(rcx_recv);        // bad mh (1st stacked argument)
    1.98 +  __ jump(ExternalAddress(Interpreter::throw_WrongMethodType_entry()));
    1.99 +
   1.100 +  // here's where control starts out:
   1.101 +  __ align(CodeEntryAlignment);
   1.102 +  address entry_point = __ pc();
   1.103 +
   1.104 +  // fetch the MethodType from the method handle into rax (the 'check' register)
   1.105 +  {
   1.106 +    Register tem = rbx_method;
   1.107 +    for (jint* pchase = methodOopDesc::method_type_offsets_chain(); (*pchase) != -1; pchase++) {
   1.108 +      __ movptr(rax_mtype, Address(tem, *pchase));
   1.109 +      tem = rax_mtype;          // in case there is another indirection
   1.110 +    }
   1.111 +  }
   1.112 +  Register rbx_temp = rbx_method; // done with incoming methodOop
   1.113 +
   1.114 +  // given the MethodType, find out where the MH argument is buried
   1.115 +  __ movptr(rdx_temp, Address(rax_mtype,
   1.116 +                              __ delayed_value(java_dyn_MethodType::form_offset_in_bytes, rbx_temp)));
   1.117 +  __ movl(rdx_temp, Address(rdx_temp,
   1.118 +                            __ delayed_value(java_dyn_MethodTypeForm::vmslots_offset_in_bytes, rbx_temp)));
   1.119 +  __ movptr(rcx_recv, __ argument_address(rdx_temp));
   1.120 +
   1.121 +  __ check_method_handle_type(rax_mtype, rcx_recv, rdx_temp, wrong_method_type);
   1.122 +  __ jump_to_method_handle_entry(rcx_recv, rdx_temp);
   1.123 +
   1.124 +  return entry_point;
   1.125 +}
   1.126 +
   1.127 +// Helper to insert argument slots into the stack.
   1.128 +// arg_slots must be a multiple of stack_move_unit() and <= 0
   1.129 +void MethodHandles::insert_arg_slots(MacroAssembler* _masm,
   1.130 +                                     RegisterOrConstant arg_slots,
   1.131 +                                     int arg_mask,
   1.132 +                                     Register rax_argslot,
   1.133 +                                     Register rbx_temp, Register rdx_temp) {
   1.134 +  assert_different_registers(rax_argslot, rbx_temp, rdx_temp,
   1.135 +                             (!arg_slots.is_register() ? rsp : arg_slots.as_register()));
   1.136 +
   1.137 +#ifdef ASSERT
   1.138 +  verify_argslot(_masm, rax_argslot, "insertion point must fall within current frame");
   1.139 +  if (arg_slots.is_register()) {
   1.140 +    Label L_ok, L_bad;
   1.141 +    __ cmpptr(arg_slots.as_register(), (int32_t) NULL_WORD);
   1.142 +    __ jcc(Assembler::greater, L_bad);
   1.143 +    __ testl(arg_slots.as_register(), -stack_move_unit() - 1);
   1.144 +    __ jcc(Assembler::zero, L_ok);
   1.145 +    __ bind(L_bad);
   1.146 +    __ stop("assert arg_slots <= 0 and clear low bits");
   1.147 +    __ bind(L_ok);
   1.148 +  } else {
   1.149 +    assert(arg_slots.as_constant() <= 0, "");
   1.150 +    assert(arg_slots.as_constant() % -stack_move_unit() == 0, "");
   1.151 +  }
   1.152 +#endif //ASSERT
   1.153 +
   1.154 +#ifdef _LP64
   1.155 +  if (arg_slots.is_register()) {
   1.156 +    // clean high bits of stack motion register (was loaded as an int)
   1.157 +    __ movslq(arg_slots.as_register(), arg_slots.as_register());
   1.158 +  }
   1.159 +#endif
   1.160 +
   1.161 +  // Make space on the stack for the inserted argument(s).
   1.162 +  // Then pull down everything shallower than rax_argslot.
   1.163 +  // The stacked return address gets pulled down with everything else.
   1.164 +  // That is, copy [rsp, argslot) downward by -size words.  In pseudo-code:
   1.165 +  //   rsp -= size;
   1.166 +  //   for (rdx = rsp + size; rdx < argslot; rdx++)
   1.167 +  //     rdx[-size] = rdx[0]
   1.168 +  //   argslot -= size;
   1.169 +  __ mov(rdx_temp, rsp);                        // source pointer for copy
   1.170 +  __ lea(rsp, Address(rsp, arg_slots, Address::times_ptr));
   1.171 +  {
   1.172 +    Label loop;
   1.173 +    __ bind(loop);
   1.174 +    // pull one word down each time through the loop
   1.175 +    __ movptr(rbx_temp, Address(rdx_temp, 0));
   1.176 +    __ movptr(Address(rdx_temp, arg_slots, Address::times_ptr), rbx_temp);
   1.177 +    __ addptr(rdx_temp, wordSize);
   1.178 +    __ cmpptr(rdx_temp, rax_argslot);
   1.179 +    __ jcc(Assembler::less, loop);
   1.180 +  }
   1.181 +
   1.182 +  // Now move the argslot down, to point to the opened-up space.
   1.183 +  __ lea(rax_argslot, Address(rax_argslot, arg_slots, Address::times_ptr));
   1.184 +
   1.185 +  if (TaggedStackInterpreter && arg_mask != _INSERT_NO_MASK) {
   1.186 +    // The caller has specified a bitmask of tags to put into the opened space.
   1.187 +    // This only works when the arg_slots value is an assembly-time constant.
   1.188 +    int constant_arg_slots = arg_slots.as_constant() / stack_move_unit();
   1.189 +    int tag_offset = Interpreter::tag_offset_in_bytes() - Interpreter::value_offset_in_bytes();
   1.190 +    for (int slot = 0; slot < constant_arg_slots; slot++) {
   1.191 +      BasicType slot_type   = ((arg_mask & (1 << slot)) == 0 ? T_OBJECT : T_INT);
   1.192 +      int       slot_offset = Interpreter::stackElementSize() * slot;
   1.193 +      Address   tag_addr(rax_argslot, slot_offset + tag_offset);
   1.194 +      __ movptr(tag_addr, frame::tag_for_basic_type(slot_type));
   1.195 +    }
   1.196 +    // Note that the new argument slots are tagged properly but contain
   1.197 +    // garbage at this point.  The value portions must be initialized
   1.198 +    // by the caller.  (Especially references!)
   1.199 +  }
   1.200 +}
   1.201 +
   1.202 +// Helper to remove argument slots from the stack.
   1.203 +// arg_slots must be a multiple of stack_move_unit() and >= 0
   1.204 +void MethodHandles::remove_arg_slots(MacroAssembler* _masm,
   1.205 +                                    RegisterOrConstant arg_slots,
   1.206 +                                    Register rax_argslot,
   1.207 +                                    Register rbx_temp, Register rdx_temp) {
   1.208 +  assert_different_registers(rax_argslot, rbx_temp, rdx_temp,
   1.209 +                             (!arg_slots.is_register() ? rsp : arg_slots.as_register()));
   1.210 +
   1.211 +#ifdef ASSERT
   1.212 +  {
   1.213 +    // Verify that [argslot..argslot+size) lies within (rsp, rbp).
   1.214 +    Label L_ok, L_bad;
   1.215 +    __ lea(rbx_temp, Address(rax_argslot, arg_slots, Address::times_ptr));
   1.216 +    __ cmpptr(rbx_temp, rbp);
   1.217 +    __ jcc(Assembler::above, L_bad);
   1.218 +    __ cmpptr(rsp, rax_argslot);
   1.219 +    __ jcc(Assembler::below, L_ok);
   1.220 +    __ bind(L_bad);
   1.221 +    __ stop("deleted argument(s) must fall within current frame");
   1.222 +    __ bind(L_ok);
   1.223 +  }
   1.224 +  if (arg_slots.is_register()) {
   1.225 +    Label L_ok, L_bad;
   1.226 +    __ cmpptr(arg_slots.as_register(), (int32_t) NULL_WORD);
   1.227 +    __ jcc(Assembler::less, L_bad);
   1.228 +    __ testl(arg_slots.as_register(), -stack_move_unit() - 1);
   1.229 +    __ jcc(Assembler::zero, L_ok);
   1.230 +    __ bind(L_bad);
   1.231 +    __ stop("assert arg_slots >= 0 and clear low bits");
   1.232 +    __ bind(L_ok);
   1.233 +  } else {
   1.234 +    assert(arg_slots.as_constant() >= 0, "");
   1.235 +    assert(arg_slots.as_constant() % -stack_move_unit() == 0, "");
   1.236 +  }
   1.237 +#endif //ASSERT
   1.238 +
   1.239 +#ifdef _LP64
   1.240 +  if (false) {                  // not needed, since register is positive
   1.241 +    // clean high bits of stack motion register (was loaded as an int)
   1.242 +    if (arg_slots.is_register())
   1.243 +      __ movslq(arg_slots.as_register(), arg_slots.as_register());
   1.244 +  }
   1.245 +#endif
   1.246 +
   1.247 +  // Pull up everything shallower than rax_argslot.
   1.248 +  // Then remove the excess space on the stack.
   1.249 +  // The stacked return address gets pulled up with everything else.
   1.250 +  // That is, copy [rsp, argslot) upward by size words.  In pseudo-code:
   1.251 +  //   for (rdx = argslot-1; rdx >= rsp; --rdx)
   1.252 +  //     rdx[size] = rdx[0]
   1.253 +  //   argslot += size;
   1.254 +  //   rsp += size;
   1.255 +  __ lea(rdx_temp, Address(rax_argslot, -wordSize)); // source pointer for copy
   1.256 +  {
   1.257 +    Label loop;
   1.258 +    __ bind(loop);
   1.259 +    // pull one word up each time through the loop
   1.260 +    __ movptr(rbx_temp, Address(rdx_temp, 0));
   1.261 +    __ movptr(Address(rdx_temp, arg_slots, Address::times_ptr), rbx_temp);
   1.262 +    __ addptr(rdx_temp, -wordSize);
   1.263 +    __ cmpptr(rdx_temp, rsp);
   1.264 +    __ jcc(Assembler::greaterEqual, loop);
   1.265 +  }
   1.266 +
   1.267 +  // Now move the argslot up, to point to the just-copied block.
   1.268 +  __ lea(rsp, Address(rsp, arg_slots, Address::times_ptr));
   1.269 +  // And adjust the argslot address to point at the deletion point.
   1.270 +  __ lea(rax_argslot, Address(rax_argslot, arg_slots, Address::times_ptr));
   1.271 +}
   1.272 +
   1.273 +#ifndef PRODUCT
   1.274 +void trace_method_handle_stub(const char* adaptername,
   1.275 +                              oop mh,
   1.276 +                              intptr_t* entry_sp,
   1.277 +                              intptr_t* saved_sp) {
   1.278 +  // called as a leaf from native code: do not block the JVM!
   1.279 +  printf("MH %s "PTR_FORMAT" "PTR_FORMAT" "INTX_FORMAT"\n", adaptername, mh, entry_sp, entry_sp - saved_sp);
   1.280 +}
   1.281 +#endif //PRODUCT
   1.282 +
   1.283 +// Generate an "entry" field for a method handle.
   1.284 +// This determines how the method handle will respond to calls.
   1.285 +void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHandles::EntryKind ek) {
   1.286 +  // Here is the register state during an interpreted call,
   1.287 +  // as set up by generate_method_handle_interpreter_entry():
   1.288 +  // - rbx: garbage temp (was MethodHandle.invoke methodOop, unused)
   1.289 +  // - rcx: receiver method handle
   1.290 +  // - rax: method handle type (only used by the check_mtype entry point)
   1.291 +  // - rsi/r13: sender SP (must preserve; see prepare_to_jump_from_interpreted)
   1.292 +  // - rdx: garbage temp, can blow away
   1.293 +
   1.294 +  Register rcx_recv    = rcx;
   1.295 +  Register rax_argslot = rax;
   1.296 +  Register rbx_temp    = rbx;
   1.297 +  Register rdx_temp    = rdx;
   1.298 +
   1.299 +  guarantee(java_dyn_MethodHandle::vmentry_offset_in_bytes() != 0, "must have offsets");
   1.300 +
   1.301 +  // some handy addresses
   1.302 +  Address rbx_method_fie(     rbx,      methodOopDesc::from_interpreted_offset() );
   1.303 +
   1.304 +  Address rcx_mh_vmtarget(    rcx_recv, java_dyn_MethodHandle::vmtarget_offset_in_bytes() );
   1.305 +  Address rcx_dmh_vmindex(    rcx_recv, sun_dyn_DirectMethodHandle::vmindex_offset_in_bytes() );
   1.306 +
   1.307 +  Address rcx_bmh_vmargslot(  rcx_recv, sun_dyn_BoundMethodHandle::vmargslot_offset_in_bytes() );
   1.308 +  Address rcx_bmh_argument(   rcx_recv, sun_dyn_BoundMethodHandle::argument_offset_in_bytes() );
   1.309 +
   1.310 +  Address rcx_amh_vmargslot(  rcx_recv, sun_dyn_AdapterMethodHandle::vmargslot_offset_in_bytes() );
   1.311 +  Address rcx_amh_argument(   rcx_recv, sun_dyn_AdapterMethodHandle::argument_offset_in_bytes() );
   1.312 +  Address rcx_amh_conversion( rcx_recv, sun_dyn_AdapterMethodHandle::conversion_offset_in_bytes() );
   1.313 +  Address vmarg;                // __ argument_address(vmargslot)
   1.314 +
   1.315 +  int tag_offset = -1;
   1.316 +  if (TaggedStackInterpreter) {
   1.317 +    tag_offset = Interpreter::tag_offset_in_bytes() - Interpreter::value_offset_in_bytes();
   1.318 +    assert(tag_offset = wordSize, "stack grows as expected");
   1.319 +  }
   1.320 +
   1.321 +  if (have_entry(ek)) {
   1.322 +    __ nop();                   // empty stubs make SG sick
   1.323 +    return;
   1.324 +  }
   1.325 +
   1.326 +  address interp_entry = __ pc();
   1.327 +  if (UseCompressedOops)  __ unimplemented("UseCompressedOops");
   1.328 +
   1.329 +#ifndef PRODUCT
   1.330 +  if (TraceMethodHandles) {
   1.331 +    __ push(rax); __ push(rbx); __ push(rcx); __ push(rdx); __ push(rsi); __ push(rdi);
   1.332 +    __ lea(rax, Address(rsp, wordSize*6)); // entry_sp
   1.333 +    // arguments:
   1.334 +    __ push(rsi);               // saved_sp
   1.335 +    __ push(rax);               // entry_sp
   1.336 +    __ push(rcx);               // mh
   1.337 +    __ push(rcx);
   1.338 +    __ movptr(Address(rsp, 0), (intptr_t)entry_name(ek));
   1.339 +    __ call_VM_leaf(CAST_FROM_FN_PTR(address, trace_method_handle_stub), 4);
   1.340 +    __ pop(rdi); __ pop(rsi); __ pop(rdx); __ pop(rcx); __ pop(rbx); __ pop(rax);
   1.341 +  }
   1.342 +#endif //PRODUCT
   1.343 +
   1.344 +  switch ((int) ek) {
   1.345 +  case _check_mtype:
   1.346 +    {
   1.347 +      // this stub is special, because it requires a live mtype argument
   1.348 +      Register rax_mtype = rax;
   1.349 +
   1.350 +      // emit WrongMethodType path first, to enable jccb back-branch
   1.351 +      Label wrong_method_type;
   1.352 +      __ bind(wrong_method_type);
   1.353 +      __ movptr(rdx_temp, ExternalAddress((address) &_entries[_wrong_method_type]));
   1.354 +      __ jmp(Address(rdx_temp, MethodHandleEntry::from_interpreted_entry_offset_in_bytes()));
   1.355 +      __ hlt();
   1.356 +
   1.357 +      interp_entry = __ pc();
   1.358 +      __ check_method_handle_type(rax_mtype, rcx_recv, rdx_temp, wrong_method_type);
   1.359 +      // now rax_mtype is dead; subsequent stubs will use it as a temp
   1.360 +
   1.361 +      __ jump_to_method_handle_entry(rcx_recv, rdx_temp);
   1.362 +    }
   1.363 +    break;
   1.364 +
   1.365 +  case _wrong_method_type:
   1.366 +    {
   1.367 +      // this stub is special, because it requires a live mtype argument
   1.368 +      Register rax_mtype = rax;
   1.369 +
   1.370 +      interp_entry = __ pc();
   1.371 +      __ push(rax_mtype);       // required mtype
   1.372 +      __ push(rcx_recv);        // random mh (1st stacked argument)
   1.373 +      __ jump(ExternalAddress(Interpreter::throw_WrongMethodType_entry()));
   1.374 +    }
   1.375 +    break;
   1.376 +
   1.377 +  case _invokestatic_mh:
   1.378 +  case _invokespecial_mh:
   1.379 +    {
   1.380 +      Register rbx_method = rbx_temp;
   1.381 +      __ movptr(rbx_method, rcx_mh_vmtarget); // target is a methodOop
   1.382 +      __ verify_oop(rbx_method);
   1.383 +      // same as TemplateTable::invokestatic or invokespecial,
   1.384 +      // minus the CP setup and profiling:
   1.385 +      if (ek == _invokespecial_mh) {
   1.386 +        // Must load & check the first argument before entering the target method.
   1.387 +        __ load_method_handle_vmslots(rax_argslot, rcx_recv, rdx_temp);
   1.388 +        __ movptr(rcx_recv, __ argument_address(rax_argslot, -1));
   1.389 +        __ null_check(rcx_recv);
   1.390 +        __ verify_oop(rcx_recv);
   1.391 +      }
   1.392 +      __ jmp(rbx_method_fie);
   1.393 +    }
   1.394 +    break;
   1.395 +
   1.396 +  case _invokevirtual_mh:
   1.397 +    {
   1.398 +      // same as TemplateTable::invokevirtual,
   1.399 +      // minus the CP setup and profiling:
   1.400 +
   1.401 +      // pick out the vtable index and receiver offset from the MH,
   1.402 +      // and then we can discard it:
   1.403 +      __ load_method_handle_vmslots(rax_argslot, rcx_recv, rdx_temp);
   1.404 +      Register rbx_index = rbx_temp;
   1.405 +      __ movl(rbx_index, rcx_dmh_vmindex);
   1.406 +      // Note:  The verifier allows us to ignore rcx_mh_vmtarget.
   1.407 +      __ movptr(rcx_recv, __ argument_address(rax_argslot, -1));
   1.408 +      __ null_check(rcx_recv, oopDesc::klass_offset_in_bytes());
   1.409 +
   1.410 +      // get receiver klass
   1.411 +      Register rax_klass = rax_argslot;
   1.412 +      __ load_klass(rax_klass, rcx_recv);
   1.413 +      __ verify_oop(rax_klass);
   1.414 +
   1.415 +      // get target methodOop & entry point
   1.416 +      const int base = instanceKlass::vtable_start_offset() * wordSize;
   1.417 +      assert(vtableEntry::size() * wordSize == wordSize, "adjust the scaling in the code below");
   1.418 +      Address vtable_entry_addr(rax_klass,
   1.419 +                                rbx_index, Address::times_ptr,
   1.420 +                                base + vtableEntry::method_offset_in_bytes());
   1.421 +      Register rbx_method = rbx_temp;
   1.422 +      __ movl(rbx_method, vtable_entry_addr);
   1.423 +
   1.424 +      __ verify_oop(rbx_method);
   1.425 +      __ jmp(rbx_method_fie);
   1.426 +    }
   1.427 +    break;
   1.428 +
   1.429 +  case _invokeinterface_mh:
   1.430 +    {
   1.431 +      // same as TemplateTable::invokeinterface,
   1.432 +      // minus the CP setup and profiling:
   1.433 +
   1.434 +      // pick out the interface and itable index from the MH.
   1.435 +      __ load_method_handle_vmslots(rax_argslot, rcx_recv, rdx_temp);
   1.436 +      Register rdx_intf  = rdx_temp;
   1.437 +      Register rbx_index = rbx_temp;
   1.438 +      __ movptr(rdx_intf,  rcx_mh_vmtarget);
   1.439 +      __ movl(rbx_index,   rcx_dmh_vmindex);
   1.440 +      __ movptr(rcx_recv, __ argument_address(rax_argslot, -1));
   1.441 +      __ null_check(rcx_recv, oopDesc::klass_offset_in_bytes());
   1.442 +
   1.443 +      // get receiver klass
   1.444 +      Register rax_klass = rax_argslot;
   1.445 +      __ load_klass(rax_klass, rcx_recv);
   1.446 +      __ verify_oop(rax_klass);
   1.447 +
   1.448 +      Register rcx_temp   = rcx_recv;
   1.449 +      Register rbx_method = rbx_index;
   1.450 +
   1.451 +      // get interface klass
   1.452 +      Label no_such_interface;
   1.453 +      __ verify_oop(rdx_intf);
   1.454 +      __ lookup_interface_method(rax_klass, rdx_intf,
   1.455 +                                 // note: next two args must be the same:
   1.456 +                                 rbx_index, rbx_method,
   1.457 +                                 rcx_temp,
   1.458 +                                 no_such_interface);
   1.459 +
   1.460 +      __ verify_oop(rbx_method);
   1.461 +      __ jmp(rbx_method_fie);
   1.462 +      __ hlt();
   1.463 +
   1.464 +      __ bind(no_such_interface);
   1.465 +      // Throw an exception.
   1.466 +      // For historical reasons, it will be IncompatibleClassChangeError.
   1.467 +      __ should_not_reach_here(); // %%% FIXME NYI
   1.468 +    }
   1.469 +    break;
   1.470 +
   1.471 +  case _bound_ref_mh:
   1.472 +  case _bound_int_mh:
   1.473 +  case _bound_long_mh:
   1.474 +  case _bound_ref_direct_mh:
   1.475 +  case _bound_int_direct_mh:
   1.476 +  case _bound_long_direct_mh:
   1.477 +    {
   1.478 +      bool direct_to_method = (ek >= _bound_ref_direct_mh);
   1.479 +      BasicType arg_type = T_ILLEGAL;
   1.480 +      if (ek == _bound_long_mh || ek == _bound_long_direct_mh) {
   1.481 +        arg_type = T_LONG;
   1.482 +      } else if (ek == _bound_int_mh || ek == _bound_int_direct_mh) {
   1.483 +        arg_type = T_INT;
   1.484 +      } else {
   1.485 +        assert(ek == _bound_ref_mh || ek == _bound_ref_direct_mh, "must be ref");
   1.486 +        arg_type = T_OBJECT;
   1.487 +      }
   1.488 +      int arg_slots = type2size[arg_type];
   1.489 +      int arg_mask  = (arg_type == T_OBJECT ? _INSERT_REF_MASK :
   1.490 +                       arg_slots == 1       ? _INSERT_INT_MASK :  _INSERT_LONG_MASK);
   1.491 +
   1.492 +      // make room for the new argument:
   1.493 +      __ movl(rax_argslot, rcx_bmh_vmargslot);
   1.494 +      __ lea(rax_argslot, __ argument_address(rax_argslot));
   1.495 +      insert_arg_slots(_masm, arg_slots * stack_move_unit(), arg_mask,
   1.496 +                       rax_argslot, rbx_temp, rdx_temp);
   1.497 +
   1.498 +      // store bound argument into the new stack slot:
   1.499 +      __ movptr(rbx_temp, rcx_bmh_argument);
   1.500 +      Address prim_value_addr(rbx_temp, java_lang_boxing_object::value_offset_in_bytes(arg_type));
   1.501 +      if (arg_type == T_OBJECT) {
   1.502 +        __ movptr(Address(rax_argslot, 0), rbx_temp);
   1.503 +      } else {
   1.504 +        __ load_sized_value(rbx_temp, prim_value_addr,
   1.505 +                            type2aelembytes(arg_type), is_signed_subword_type(arg_type));
   1.506 +        __ movptr(Address(rax_argslot, 0), rbx_temp);
   1.507 +#ifndef _LP64
   1.508 +        if (arg_slots == 2) {
   1.509 +          __ movl(rbx_temp, prim_value_addr.plus_disp(wordSize));
   1.510 +          __ movl(Address(rax_argslot, Interpreter::stackElementSize()), rbx_temp);
   1.511 +        }
   1.512 +#endif //_LP64
   1.513 +        break;
   1.514 +      }
   1.515 +
   1.516 +      if (direct_to_method) {
   1.517 +        Register rbx_method = rbx_temp;
   1.518 +        __ movptr(rbx_method, rcx_mh_vmtarget);
   1.519 +        __ verify_oop(rbx_method);
   1.520 +        __ jmp(rbx_method_fie);
   1.521 +      } else {
   1.522 +        __ movptr(rcx_recv, rcx_mh_vmtarget);
   1.523 +        __ verify_oop(rcx_recv);
   1.524 +        __ jump_to_method_handle_entry(rcx_recv, rdx_temp);
   1.525 +      }
   1.526 +    }
   1.527 +    break;
   1.528 +
   1.529 +  case _adapter_retype_only:
   1.530 +    // immediately jump to the next MH layer:
   1.531 +    __ movptr(rcx_recv, rcx_mh_vmtarget);
   1.532 +    __ verify_oop(rcx_recv);
   1.533 +    __ jump_to_method_handle_entry(rcx_recv, rdx_temp);
   1.534 +    // This is OK when all parameter types widen.
   1.535 +    // It is also OK when a return type narrows.
   1.536 +    break;
   1.537 +
   1.538 +  case _adapter_check_cast:
   1.539 +    {
   1.540 +      // temps:
   1.541 +      Register rbx_klass = rbx_temp; // interesting AMH data
   1.542 +
   1.543 +      // check a reference argument before jumping to the next layer of MH:
   1.544 +      __ movl(rax_argslot, rcx_amh_vmargslot);
   1.545 +      vmarg = __ argument_address(rax_argslot);
   1.546 +
   1.547 +      // What class are we casting to?
   1.548 +      __ movptr(rbx_klass, rcx_amh_argument); // this is a Class object!
   1.549 +      __ movptr(rbx_klass, Address(rbx_klass, java_lang_Class::klass_offset_in_bytes()));
   1.550 +
   1.551 +      // get the new MH:
   1.552 +      __ movptr(rcx_recv, rcx_mh_vmtarget);
   1.553 +      // (now we are done with the old MH)
   1.554 +
   1.555 +      Label done;
   1.556 +      __ movptr(rdx_temp, vmarg);
   1.557 +      __ testl(rdx_temp, rdx_temp);
   1.558 +      __ jcc(Assembler::zero, done);          // no cast if null
   1.559 +      __ load_klass(rdx_temp, rdx_temp);
   1.560 +
   1.561 +      // live at this point:
   1.562 +      // - rbx_klass:  klass required by the target method
   1.563 +      // - rdx_temp:   argument klass to test
   1.564 +      // - rcx_recv:   method handle to invoke (after cast succeeds)
   1.565 +      __ check_klass_subtype(rdx_temp, rbx_klass, rax_argslot, done);
   1.566 +
   1.567 +      // If we get here, the type check failed!
   1.568 +      // Call the wrong_method_type stub, passing the failing argument type in rax.
   1.569 +      Register rax_mtype = rax_argslot;
   1.570 +      __ push(rbx_klass);       // missed klass (required type)
   1.571 +      __ push(rdx_temp);        // bad actual type (1st stacked argument)
   1.572 +      __ jump(ExternalAddress(Interpreter::throw_WrongMethodType_entry()));
   1.573 +
   1.574 +      __ bind(done);
   1.575 +      __ jump_to_method_handle_entry(rcx_recv, rdx_temp);
   1.576 +    }
   1.577 +    break;
   1.578 +
   1.579 +  case _adapter_prim_to_prim:
   1.580 +  case _adapter_ref_to_prim:
   1.581 +    // handled completely by optimized cases
   1.582 +    __ stop("init_AdapterMethodHandle should not issue this");
   1.583 +    break;
   1.584 +
   1.585 +  case _adapter_opt_i2i:        // optimized subcase of adapt_prim_to_prim
   1.586 +//case _adapter_opt_f2i:        // optimized subcase of adapt_prim_to_prim
   1.587 +  case _adapter_opt_l2i:        // optimized subcase of adapt_prim_to_prim
   1.588 +  case _adapter_opt_unboxi:     // optimized subcase of adapt_ref_to_prim
   1.589 +    {
   1.590 +      // perform an in-place conversion to int or an int subword
   1.591 +      __ movl(rax_argslot, rcx_amh_vmargslot);
   1.592 +      vmarg = __ argument_address(rax_argslot);
   1.593 +
   1.594 +      switch (ek) {
   1.595 +      case _adapter_opt_i2i:
   1.596 +        __ movl(rdx_temp, vmarg);
   1.597 +        break;
   1.598 +      case _adapter_opt_l2i:
   1.599 +        {
   1.600 +          // just delete the extra slot; on a little-endian machine we keep the first
   1.601 +          __ lea(rax_argslot, __ argument_address(rax_argslot, 1));
   1.602 +          remove_arg_slots(_masm, -stack_move_unit(),
   1.603 +                           rax_argslot, rbx_temp, rdx_temp);
   1.604 +          vmarg = Address(rax_argslot, -Interpreter::stackElementSize());
   1.605 +          __ movl(rdx_temp, vmarg);
   1.606 +        }
   1.607 +        break;
   1.608 +      case _adapter_opt_unboxi:
   1.609 +        {
   1.610 +          // Load the value up from the heap.
   1.611 +          __ movptr(rdx_temp, vmarg);
   1.612 +          int value_offset = java_lang_boxing_object::value_offset_in_bytes(T_INT);
   1.613 +#ifdef ASSERT
   1.614 +          for (int bt = T_BOOLEAN; bt < T_INT; bt++) {
   1.615 +            if (is_subword_type(BasicType(bt)))
   1.616 +              assert(value_offset == java_lang_boxing_object::value_offset_in_bytes(BasicType(bt)), "");
   1.617 +          }
   1.618 +#endif
   1.619 +          __ null_check(rdx_temp, value_offset);
   1.620 +          __ movl(rdx_temp, Address(rdx_temp, value_offset));
   1.621 +          // We load this as a word.  Because we are little-endian,
   1.622 +          // the low bits will be correct, but the high bits may need cleaning.
   1.623 +          // The vminfo will guide us to clean those bits.
   1.624 +        }
   1.625 +        break;
   1.626 +      default:
   1.627 +        assert(false, "");
   1.628 +      }
   1.629 +      goto finish_int_conversion;
   1.630 +    }
   1.631 +
   1.632 +  finish_int_conversion:
   1.633 +    {
   1.634 +      Register rbx_vminfo = rbx_temp;
   1.635 +      __ movl(rbx_vminfo, rcx_amh_conversion);
   1.636 +      assert(CONV_VMINFO_SHIFT == 0, "preshifted");
   1.637 +
   1.638 +      // get the new MH:
   1.639 +      __ movptr(rcx_recv, rcx_mh_vmtarget);
   1.640 +      // (now we are done with the old MH)
   1.641 +
   1.642 +      // original 32-bit vmdata word must be of this form:
   1.643 +      //    | MBZ:16 | signBitCount:8 | srcDstTypes:8 | conversionOp:8 |
   1.644 +      __ xchgl(rcx, rbx_vminfo);                // free rcx for shifts
   1.645 +      __ shll(rdx_temp /*, rcx*/);
   1.646 +      Label zero_extend, done;
   1.647 +      __ testl(rcx, CONV_VMINFO_SIGN_FLAG);
   1.648 +      __ jcc(Assembler::zero, zero_extend);
   1.649 +
   1.650 +      // this path is taken for int->byte, int->short
   1.651 +      __ sarl(rdx_temp /*, rcx*/);
   1.652 +      __ jmp(done);
   1.653 +
   1.654 +      __ bind(zero_extend);
   1.655 +      // this is taken for int->char
   1.656 +      __ shrl(rdx_temp /*, rcx*/);
   1.657 +
   1.658 +      __ bind(done);
   1.659 +      __ movptr(vmarg, rdx_temp);
   1.660 +      __ xchgl(rcx, rbx_vminfo);                // restore rcx_recv
   1.661 +
   1.662 +      __ jump_to_method_handle_entry(rcx_recv, rdx_temp);
   1.663 +    }
   1.664 +    break;
   1.665 +
   1.666 +  case _adapter_opt_i2l:        // optimized subcase of adapt_prim_to_prim
   1.667 +  case _adapter_opt_unboxl:     // optimized subcase of adapt_ref_to_prim
   1.668 +    {
   1.669 +      // perform an in-place int-to-long or ref-to-long conversion
   1.670 +      __ movl(rax_argslot, rcx_amh_vmargslot);
   1.671 +
   1.672 +      // on a little-endian machine we keep the first slot and add another after
   1.673 +      __ lea(rax_argslot, __ argument_address(rax_argslot, 1));
   1.674 +      insert_arg_slots(_masm, stack_move_unit(), _INSERT_INT_MASK,
   1.675 +                       rax_argslot, rbx_temp, rdx_temp);
   1.676 +      Address vmarg1(rax_argslot, -Interpreter::stackElementSize());
   1.677 +      Address vmarg2 = vmarg1.plus_disp(Interpreter::stackElementSize());
   1.678 +
   1.679 +      switch (ek) {
   1.680 +      case _adapter_opt_i2l:
   1.681 +        {
   1.682 +          __ movl(rdx_temp, vmarg1);
   1.683 +          __ sarl(rdx_temp, 31);  // __ extend_sign()
   1.684 +          __ movl(vmarg2, rdx_temp); // store second word
   1.685 +        }
   1.686 +        break;
   1.687 +      case _adapter_opt_unboxl:
   1.688 +        {
   1.689 +          // Load the value up from the heap.
   1.690 +          __ movptr(rdx_temp, vmarg1);
   1.691 +          int value_offset = java_lang_boxing_object::value_offset_in_bytes(T_LONG);
   1.692 +          assert(value_offset == java_lang_boxing_object::value_offset_in_bytes(T_DOUBLE), "");
   1.693 +          __ null_check(rdx_temp, value_offset);
   1.694 +          __ movl(rbx_temp, Address(rdx_temp, value_offset + 0*BytesPerInt));
   1.695 +          __ movl(rdx_temp, Address(rdx_temp, value_offset + 1*BytesPerInt));
   1.696 +          __ movl(vmarg1, rbx_temp);
   1.697 +          __ movl(vmarg2, rdx_temp);
   1.698 +        }
   1.699 +        break;
   1.700 +      default:
   1.701 +        assert(false, "");
   1.702 +      }
   1.703 +
   1.704 +      __ movptr(rcx_recv, rcx_mh_vmtarget);
   1.705 +      __ jump_to_method_handle_entry(rcx_recv, rdx_temp);
   1.706 +    }
   1.707 +    break;
   1.708 +
   1.709 +  case _adapter_opt_f2d:        // optimized subcase of adapt_prim_to_prim
   1.710 +  case _adapter_opt_d2f:        // optimized subcase of adapt_prim_to_prim
   1.711 +    {
   1.712 +      // perform an in-place floating primitive conversion
   1.713 +      __ movl(rax_argslot, rcx_amh_vmargslot);
   1.714 +      __ lea(rax_argslot, __ argument_address(rax_argslot, 1));
   1.715 +      if (ek == _adapter_opt_f2d) {
   1.716 +        insert_arg_slots(_masm, stack_move_unit(), _INSERT_INT_MASK,
   1.717 +                         rax_argslot, rbx_temp, rdx_temp);
   1.718 +      }
   1.719 +      Address vmarg(rax_argslot, -Interpreter::stackElementSize());
   1.720 +
   1.721 +#ifdef _LP64
   1.722 +      if (ek == _adapter_opt_f2d) {
   1.723 +        __ movflt(xmm0, vmarg);
   1.724 +        __ cvtss2sd(xmm0, xmm0);
   1.725 +        __ movdbl(vmarg, xmm0);
   1.726 +      } else {
   1.727 +        __ movdbl(xmm0, vmarg);
   1.728 +        __ cvtsd2ss(xmm0, xmm0);
   1.729 +        __ movflt(vmarg, xmm0);
   1.730 +      }
   1.731 +#else //_LP64
   1.732 +      if (ek == _adapter_opt_f2d) {
   1.733 +        __ fld_s(vmarg);        // load float to ST0
   1.734 +        __ fstp_s(vmarg);       // store single
   1.735 +      } else if (!TaggedStackInterpreter) {
   1.736 +        __ fld_d(vmarg);        // load double to ST0
   1.737 +        __ fstp_s(vmarg);       // store single
   1.738 +      } else {
   1.739 +        Address vmarg_tag = vmarg.plus_disp(tag_offset);
   1.740 +        Address vmarg2    = vmarg.plus_disp(Interpreter::stackElementSize());
   1.741 +        // vmarg2_tag does not participate in this code
   1.742 +        Register rbx_tag = rbx_temp;
   1.743 +        __ movl(rbx_tag, vmarg_tag); // preserve tag
   1.744 +        __ movl(rdx_temp, vmarg2); // get second word of double
   1.745 +        __ movl(vmarg_tag, rdx_temp); // align with first word
   1.746 +        __ fld_d(vmarg);        // load double to ST0
   1.747 +        __ movl(vmarg_tag, rbx_tag); // restore tag
   1.748 +        __ fstp_s(vmarg);       // store single
   1.749 +      }
   1.750 +#endif //_LP64
   1.751 +
   1.752 +      if (ek == _adapter_opt_d2f) {
   1.753 +        remove_arg_slots(_masm, -stack_move_unit(),
   1.754 +                         rax_argslot, rbx_temp, rdx_temp);
   1.755 +      }
   1.756 +
   1.757 +      __ movptr(rcx_recv, rcx_mh_vmtarget);
   1.758 +      __ jump_to_method_handle_entry(rcx_recv, rdx_temp);
   1.759 +    }
   1.760 +    break;
   1.761 +
   1.762 +  case _adapter_prim_to_ref:
   1.763 +    __ unimplemented(entry_name(ek)); // %%% FIXME: NYI
   1.764 +    break;
   1.765 +
   1.766 +  case _adapter_swap_args:
   1.767 +  case _adapter_rot_args:
   1.768 +    // handled completely by optimized cases
   1.769 +    __ stop("init_AdapterMethodHandle should not issue this");
   1.770 +    break;
   1.771 +
   1.772 +  case _adapter_opt_swap_1:
   1.773 +  case _adapter_opt_swap_2:
   1.774 +  case _adapter_opt_rot_1_up:
   1.775 +  case _adapter_opt_rot_1_down:
   1.776 +  case _adapter_opt_rot_2_up:
   1.777 +  case _adapter_opt_rot_2_down:
   1.778 +    {
   1.779 +      int rotate = 0, swap_slots = 0;
   1.780 +      switch ((int)ek) {
   1.781 +      case _adapter_opt_swap_1:     swap_slots = 1; break;
   1.782 +      case _adapter_opt_swap_2:     swap_slots = 2; break;
   1.783 +      case _adapter_opt_rot_1_up:   swap_slots = 1; rotate++; break;
   1.784 +      case _adapter_opt_rot_1_down: swap_slots = 1; rotate--; break;
   1.785 +      case _adapter_opt_rot_2_up:   swap_slots = 2; rotate++; break;
   1.786 +      case _adapter_opt_rot_2_down: swap_slots = 2; rotate--; break;
   1.787 +      default: assert(false, "");
   1.788 +      }
   1.789 +
   1.790 +      // the real size of the move must be doubled if TaggedStackInterpreter:
   1.791 +      int swap_bytes = (int)( swap_slots * Interpreter::stackElementWords() * wordSize );
   1.792 +
   1.793 +      // 'argslot' is the position of the first argument to swap
   1.794 +      __ movl(rax_argslot, rcx_amh_vmargslot);
   1.795 +      __ lea(rax_argslot, __ argument_address(rax_argslot));
   1.796 +
   1.797 +      // 'vminfo' is the second
   1.798 +      Register rbx_destslot = rbx_temp;
   1.799 +      __ movl(rbx_destslot, rcx_amh_conversion);
   1.800 +      assert(CONV_VMINFO_SHIFT == 0, "preshifted");
   1.801 +      __ andl(rbx_destslot, CONV_VMINFO_MASK);
   1.802 +      __ lea(rbx_destslot, __ argument_address(rbx_destslot));
   1.803 +      DEBUG_ONLY(verify_argslot(_masm, rbx_destslot, "swap point must fall within current frame"));
   1.804 +
   1.805 +      if (!rotate) {
   1.806 +        for (int i = 0; i < swap_bytes; i += wordSize) {
   1.807 +          __ movptr(rdx_temp, Address(rax_argslot , i));
   1.808 +          __ push(rdx_temp);
   1.809 +          __ movptr(rdx_temp, Address(rbx_destslot, i));
   1.810 +          __ movptr(Address(rax_argslot, i), rdx_temp);
   1.811 +          __ pop(rdx_temp);
   1.812 +          __ movptr(Address(rbx_destslot, i), rdx_temp);
   1.813 +        }
   1.814 +      } else {
   1.815 +        // push the first chunk, which is going to get overwritten
   1.816 +        for (int i = swap_bytes; (i -= wordSize) >= 0; ) {
   1.817 +          __ movptr(rdx_temp, Address(rax_argslot, i));
   1.818 +          __ push(rdx_temp);
   1.819 +        }
   1.820 +
   1.821 +        if (rotate > 0) {
   1.822 +          // rotate upward
   1.823 +          __ subptr(rax_argslot, swap_bytes);
   1.824 +#ifdef ASSERT
   1.825 +          {
   1.826 +            // Verify that argslot > destslot, by at least swap_bytes.
   1.827 +            Label L_ok;
   1.828 +            __ cmpptr(rax_argslot, rbx_destslot);
   1.829 +            __ jcc(Assembler::aboveEqual, L_ok);
   1.830 +            __ stop("source must be above destination (upward rotation)");
   1.831 +            __ bind(L_ok);
   1.832 +          }
   1.833 +#endif
   1.834 +          // work argslot down to destslot, copying contiguous data upwards
   1.835 +          // pseudo-code:
   1.836 +          //   rax = src_addr - swap_bytes
   1.837 +          //   rbx = dest_addr
   1.838 +          //   while (rax >= rbx) *(rax + swap_bytes) = *(rax + 0), rax--;
   1.839 +          Label loop;
   1.840 +          __ bind(loop);
   1.841 +          __ movptr(rdx_temp, Address(rax_argslot, 0));
   1.842 +          __ movptr(Address(rax_argslot, swap_bytes), rdx_temp);
   1.843 +          __ addptr(rax_argslot, -wordSize);
   1.844 +          __ cmpptr(rax_argslot, rbx_destslot);
   1.845 +          __ jcc(Assembler::aboveEqual, loop);
   1.846 +        } else {
   1.847 +          __ addptr(rax_argslot, swap_bytes);
   1.848 +#ifdef ASSERT
   1.849 +          {
   1.850 +            // Verify that argslot < destslot, by at least swap_bytes.
   1.851 +            Label L_ok;
   1.852 +            __ cmpptr(rax_argslot, rbx_destslot);
   1.853 +            __ jcc(Assembler::belowEqual, L_ok);
   1.854 +            __ stop("source must be below destination (downward rotation)");
   1.855 +            __ bind(L_ok);
   1.856 +          }
   1.857 +#endif
   1.858 +          // work argslot up to destslot, copying contiguous data downwards
   1.859 +          // pseudo-code:
   1.860 +          //   rax = src_addr + swap_bytes
   1.861 +          //   rbx = dest_addr
   1.862 +          //   while (rax <= rbx) *(rax - swap_bytes) = *(rax + 0), rax++;
   1.863 +          Label loop;
   1.864 +          __ bind(loop);
   1.865 +          __ movptr(rdx_temp, Address(rax_argslot, 0));
   1.866 +          __ movptr(Address(rax_argslot, -swap_bytes), rdx_temp);
   1.867 +          __ addptr(rax_argslot, wordSize);
   1.868 +          __ cmpptr(rax_argslot, rbx_destslot);
   1.869 +          __ jcc(Assembler::belowEqual, loop);
   1.870 +        }
   1.871 +
   1.872 +        // pop the original first chunk into the destination slot, now free
   1.873 +        for (int i = 0; i < swap_bytes; i += wordSize) {
   1.874 +          __ pop(rdx_temp);
   1.875 +          __ movptr(Address(rbx_destslot, i), rdx_temp);
   1.876 +        }
   1.877 +      }
   1.878 +
   1.879 +      __ movptr(rcx_recv, rcx_mh_vmtarget);
   1.880 +      __ jump_to_method_handle_entry(rcx_recv, rdx_temp);
   1.881 +    }
   1.882 +    break;
   1.883 +
   1.884 +  case _adapter_dup_args:
   1.885 +    {
   1.886 +      // 'argslot' is the position of the first argument to duplicate
   1.887 +      __ movl(rax_argslot, rcx_amh_vmargslot);
   1.888 +      __ lea(rax_argslot, __ argument_address(rax_argslot));
   1.889 +
   1.890 +      // 'stack_move' is negative number of words to duplicate
   1.891 +      Register rdx_stack_move = rdx_temp;
   1.892 +      __ movl(rdx_stack_move, rcx_amh_conversion);
   1.893 +      __ sarl(rdx_stack_move, CONV_STACK_MOVE_SHIFT);
   1.894 +
   1.895 +      int argslot0_num = 0;
   1.896 +      Address argslot0 = __ argument_address(RegisterOrConstant(argslot0_num));
   1.897 +      assert(argslot0.base() == rsp, "");
   1.898 +      int pre_arg_size = argslot0.disp();
   1.899 +      assert(pre_arg_size % wordSize == 0, "");
   1.900 +      assert(pre_arg_size > 0, "must include PC");
   1.901 +
   1.902 +      // remember the old rsp+1 (argslot[0])
   1.903 +      Register rbx_oldarg = rbx_temp;
   1.904 +      __ lea(rbx_oldarg, argslot0);
   1.905 +
   1.906 +      // move rsp down to make room for dups
   1.907 +      __ lea(rsp, Address(rsp, rdx_stack_move, Address::times_ptr));
   1.908 +
   1.909 +      // compute the new rsp+1 (argslot[0])
   1.910 +      Register rdx_newarg = rdx_temp;
   1.911 +      __ lea(rdx_newarg, argslot0);
   1.912 +
   1.913 +      __ push(rdi);             // need a temp
   1.914 +      // (preceding push must be done after arg addresses are taken!)
   1.915 +
   1.916 +      // pull down the pre_arg_size data (PC)
   1.917 +      for (int i = -pre_arg_size; i < 0; i += wordSize) {
   1.918 +        __ movptr(rdi, Address(rbx_oldarg, i));
   1.919 +        __ movptr(Address(rdx_newarg, i), rdi);
   1.920 +      }
   1.921 +
   1.922 +      // copy from rax_argslot[0...] down to new_rsp[1...]
   1.923 +      // pseudo-code:
   1.924 +      //   rbx = old_rsp+1
   1.925 +      //   rdx = new_rsp+1
   1.926 +      //   rax = argslot
   1.927 +      //   while (rdx < rbx) *rdx++ = *rax++
   1.928 +      Label loop;
   1.929 +      __ bind(loop);
   1.930 +      __ movptr(rdi, Address(rax_argslot, 0));
   1.931 +      __ movptr(Address(rdx_newarg, 0), rdi);
   1.932 +      __ addptr(rax_argslot, wordSize);
   1.933 +      __ addptr(rdx_newarg, wordSize);
   1.934 +      __ cmpptr(rdx_newarg, rbx_oldarg);
   1.935 +      __ jcc(Assembler::less, loop);
   1.936 +
   1.937 +      __ pop(rdi);              // restore temp
   1.938 +
   1.939 +      __ movptr(rcx_recv, rcx_mh_vmtarget);
   1.940 +      __ jump_to_method_handle_entry(rcx_recv, rdx_temp);
   1.941 +    }
   1.942 +    break;
   1.943 +
   1.944 +  case _adapter_drop_args:
   1.945 +    {
   1.946 +      // 'argslot' is the position of the first argument to nuke
   1.947 +      __ movl(rax_argslot, rcx_amh_vmargslot);
   1.948 +      __ lea(rax_argslot, __ argument_address(rax_argslot));
   1.949 +
   1.950 +      __ push(rdi);             // need a temp
   1.951 +      // (must do previous push after argslot address is taken)
   1.952 +
   1.953 +      // 'stack_move' is number of words to drop
   1.954 +      Register rdi_stack_move = rdi;
   1.955 +      __ movl(rdi_stack_move, rcx_amh_conversion);
   1.956 +      __ sarl(rdi_stack_move, CONV_STACK_MOVE_SHIFT);
   1.957 +      remove_arg_slots(_masm, rdi_stack_move,
   1.958 +                       rax_argslot, rbx_temp, rdx_temp);
   1.959 +
   1.960 +      __ pop(rdi);              // restore temp
   1.961 +
   1.962 +      __ movptr(rcx_recv, rcx_mh_vmtarget);
   1.963 +      __ jump_to_method_handle_entry(rcx_recv, rdx_temp);
   1.964 +    }
   1.965 +    break;
   1.966 +
   1.967 +  case _adapter_collect_args:
   1.968 +    __ unimplemented(entry_name(ek)); // %%% FIXME: NYI
   1.969 +    break;
   1.970 +
   1.971 +  case _adapter_spread_args:
   1.972 +    // handled completely by optimized cases
   1.973 +    __ stop("init_AdapterMethodHandle should not issue this");
   1.974 +    break;
   1.975 +
   1.976 +  case _adapter_opt_spread_0:
   1.977 +  case _adapter_opt_spread_1:
   1.978 +  case _adapter_opt_spread_more:
   1.979 +    {
   1.980 +      // spread an array out into a group of arguments
   1.981 +      int length_constant = -1;
   1.982 +      switch (ek) {
   1.983 +      case _adapter_opt_spread_0: length_constant = 0; break;
   1.984 +      case _adapter_opt_spread_1: length_constant = 1; break;
   1.985 +      }
   1.986 +
   1.987 +      // find the address of the array argument
   1.988 +      __ movl(rax_argslot, rcx_amh_vmargslot);
   1.989 +      __ lea(rax_argslot, __ argument_address(rax_argslot));
   1.990 +
   1.991 +      // grab some temps
   1.992 +      { __ push(rsi); __ push(rdi); }
   1.993 +      // (preceding pushes must be done after argslot address is taken!)
   1.994 +#define UNPUSH_RSI_RDI \
   1.995 +      { __ pop(rdi); __ pop(rsi); }
   1.996 +
   1.997 +      // arx_argslot points both to the array and to the first output arg
   1.998 +      vmarg = Address(rax_argslot, 0);
   1.999 +
  1.1000 +      // Get the array value.
  1.1001 +      Register  rsi_array       = rsi;
  1.1002 +      Register  rdx_array_klass = rdx_temp;
  1.1003 +      BasicType elem_type       = T_OBJECT;
  1.1004 +      int       length_offset   = arrayOopDesc::length_offset_in_bytes();
  1.1005 +      int       elem0_offset    = arrayOopDesc::base_offset_in_bytes(elem_type);
  1.1006 +      __ movptr(rsi_array, vmarg);
  1.1007 +      Label skip_array_check;
  1.1008 +      if (length_constant == 0) {
  1.1009 +        __ testptr(rsi_array, rsi_array);
  1.1010 +        __ jcc(Assembler::zero, skip_array_check);
  1.1011 +      }
  1.1012 +      __ null_check(rsi_array, oopDesc::klass_offset_in_bytes());
  1.1013 +      __ load_klass(rdx_array_klass, rsi_array);
  1.1014 +
  1.1015 +      // Check the array type.
  1.1016 +      Register rbx_klass = rbx_temp;
  1.1017 +      __ movptr(rbx_klass, rcx_amh_argument); // this is a Class object!
  1.1018 +      __ movptr(rbx_klass, Address(rbx_klass, java_lang_Class::klass_offset_in_bytes()));
  1.1019 +
  1.1020 +      Label ok_array_klass, bad_array_klass, bad_array_length;
  1.1021 +      __ check_klass_subtype(rdx_array_klass, rbx_klass, rdi, ok_array_klass);
  1.1022 +      // If we get here, the type check failed!
  1.1023 +      __ jmp(bad_array_klass);
  1.1024 +      __ bind(ok_array_klass);
  1.1025 +
  1.1026 +      // Check length.
  1.1027 +      if (length_constant >= 0) {
  1.1028 +        __ cmpl(Address(rsi_array, length_offset), length_constant);
  1.1029 +      } else {
  1.1030 +        Register rbx_vminfo = rbx_temp;
  1.1031 +        __ movl(rbx_vminfo, rcx_amh_conversion);
  1.1032 +        assert(CONV_VMINFO_SHIFT == 0, "preshifted");
  1.1033 +        __ andl(rbx_vminfo, CONV_VMINFO_MASK);
  1.1034 +        __ cmpl(rbx_vminfo, Address(rsi_array, length_offset));
  1.1035 +      }
  1.1036 +      __ jcc(Assembler::notEqual, bad_array_length);
  1.1037 +
  1.1038 +      Register rdx_argslot_limit = rdx_temp;
  1.1039 +
  1.1040 +      // Array length checks out.  Now insert any required stack slots.
  1.1041 +      if (length_constant == -1) {
  1.1042 +        // Form a pointer to the end of the affected region.
  1.1043 +        __ lea(rdx_argslot_limit, Address(rax_argslot, Interpreter::stackElementSize()));
  1.1044 +        // 'stack_move' is negative number of words to insert
  1.1045 +        Register rdi_stack_move = rdi;
  1.1046 +        __ movl(rdi_stack_move, rcx_amh_conversion);
  1.1047 +        __ sarl(rdi_stack_move, CONV_STACK_MOVE_SHIFT);
  1.1048 +        Register rsi_temp = rsi_array;  // spill this
  1.1049 +        insert_arg_slots(_masm, rdi_stack_move, -1,
  1.1050 +                         rax_argslot, rbx_temp, rsi_temp);
  1.1051 +        // reload the array (since rsi was killed)
  1.1052 +        __ movptr(rsi_array, vmarg);
  1.1053 +      } else if (length_constant > 1) {
  1.1054 +        int arg_mask = 0;
  1.1055 +        int new_slots = (length_constant - 1);
  1.1056 +        for (int i = 0; i < new_slots; i++) {
  1.1057 +          arg_mask <<= 1;
  1.1058 +          arg_mask |= _INSERT_REF_MASK;
  1.1059 +        }
  1.1060 +        insert_arg_slots(_masm, new_slots * stack_move_unit(), arg_mask,
  1.1061 +                         rax_argslot, rbx_temp, rdx_temp);
  1.1062 +      } else if (length_constant == 1) {
  1.1063 +        // no stack resizing required
  1.1064 +      } else if (length_constant == 0) {
  1.1065 +        remove_arg_slots(_masm, -stack_move_unit(),
  1.1066 +                         rax_argslot, rbx_temp, rdx_temp);
  1.1067 +      }
  1.1068 +
  1.1069 +      // Copy from the array to the new slots.
  1.1070 +      // Note: Stack change code preserves integrity of rax_argslot pointer.
  1.1071 +      // So even after slot insertions, rax_argslot still points to first argument.
  1.1072 +      if (length_constant == -1) {
  1.1073 +        // [rax_argslot, rdx_argslot_limit) is the area we are inserting into.
  1.1074 +        Register rsi_source = rsi_array;
  1.1075 +        __ lea(rsi_source, Address(rsi_array, elem0_offset));
  1.1076 +        Label loop;
  1.1077 +        __ bind(loop);
  1.1078 +        __ movptr(rbx_temp, Address(rsi_source, 0));
  1.1079 +        __ movptr(Address(rax_argslot, 0), rbx_temp);
  1.1080 +        __ addptr(rsi_source, type2aelembytes(elem_type));
  1.1081 +        if (TaggedStackInterpreter) {
  1.1082 +          __ movptr(Address(rax_argslot, tag_offset),
  1.1083 +                    frame::tag_for_basic_type(elem_type));
  1.1084 +        }
  1.1085 +        __ addptr(rax_argslot, Interpreter::stackElementSize());
  1.1086 +        __ cmpptr(rax_argslot, rdx_argslot_limit);
  1.1087 +        __ jcc(Assembler::less, loop);
  1.1088 +      } else if (length_constant == 0) {
  1.1089 +        __ bind(skip_array_check);
  1.1090 +        // nothing to copy
  1.1091 +      } else {
  1.1092 +        int elem_offset = elem0_offset;
  1.1093 +        int slot_offset = 0;
  1.1094 +        for (int index = 0; index < length_constant; index++) {
  1.1095 +          __ movptr(rbx_temp, Address(rsi_array, elem_offset));
  1.1096 +          __ movptr(Address(rax_argslot, slot_offset), rbx_temp);
  1.1097 +          elem_offset += type2aelembytes(elem_type);
  1.1098 +          if (TaggedStackInterpreter) {
  1.1099 +            __ movptr(Address(rax_argslot, slot_offset + tag_offset),
  1.1100 +                      frame::tag_for_basic_type(elem_type));
  1.1101 +          }
  1.1102 +          slot_offset += Interpreter::stackElementSize();
  1.1103 +        }
  1.1104 +      }
  1.1105 +
  1.1106 +      // Arguments are spread.  Move to next method handle.
  1.1107 +      UNPUSH_RSI_RDI;
  1.1108 +      __ movptr(rcx_recv, rcx_mh_vmtarget);
  1.1109 +      __ jump_to_method_handle_entry(rcx_recv, rdx_temp);
  1.1110 +
  1.1111 +      __ bind(bad_array_klass);
  1.1112 +      UNPUSH_RSI_RDI;
  1.1113 +      __ stop("bad array klass NYI");
  1.1114 +
  1.1115 +      __ bind(bad_array_length);
  1.1116 +      UNPUSH_RSI_RDI;
  1.1117 +      __ stop("bad array length NYI");
  1.1118 +
  1.1119 +#undef UNPUSH_RSI_RDI
  1.1120 +    }
  1.1121 +    break;
  1.1122 +
  1.1123 +  case _adapter_flyby:
  1.1124 +  case _adapter_ricochet:
  1.1125 +    __ unimplemented(entry_name(ek)); // %%% FIXME: NYI
  1.1126 +    break;
  1.1127 +
  1.1128 +  default:  ShouldNotReachHere();
  1.1129 +  }
  1.1130 +  __ hlt();
  1.1131 +
  1.1132 +  address me_cookie = MethodHandleEntry::start_compiled_entry(_masm, interp_entry);
  1.1133 +  __ unimplemented(entry_name(ek)); // %%% FIXME: NYI
  1.1134 +
  1.1135 +  init_entry(ek, MethodHandleEntry::finish_compiled_entry(_masm, me_cookie));
  1.1136 +}

mercurial