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

src/cpu/x86/vm/methodHandles_x86.cpp

Print this page




 192   assert(is_signature_polymorphic(iid), "expected invoke iid");
 193   if (iid == vmIntrinsics::_invokeGeneric ||
 194       iid == vmIntrinsics::_compiledLambdaForm) {
 195     // Perhaps surprisingly, the symbolic references visible to Java are not directly used.
 196     // They are linked to Java-generated adapters via MethodHandleNatives.linkMethod.
 197     // They all allow an appendix argument.
 198     __ hlt();           // empty stubs make SG sick
 199     return NULL;
 200   }
 201 
 202   // rsi/r13: sender SP (must preserve; see prepare_to_jump_from_interpreted)
 203   // rbx: Method*
 204   // rdx: argument locator (parameter slot count, added to rsp)
 205   // rcx: used as temp to hold mh or receiver
 206   // rax, rdi: garbage temps, blown away
 207   Register rdx_argp   = rdx;   // argument list ptr, live on error paths
 208   Register rax_temp   = rax;
 209   Register rcx_mh     = rcx;   // MH receiver; dies quickly and is recycled
 210   Register rbx_method = rbx;   // eventual target of this invocation
 211 
 212   address code_start = __ pc();
 213 
 214   // here's where control starts out:
 215   __ align(CodeEntryAlignment);
 216   address entry_point = __ pc();
 217 
 218   if (VerifyMethodHandles) {
 219     Label L;
 220     BLOCK_COMMENT("verify_intrinsic_id {");
 221     __ cmpb(Address(rbx_method, Method::intrinsic_id_offset_in_bytes()), (int) iid);
 222     __ jcc(Assembler::equal, L);
 223     if (iid == vmIntrinsics::_linkToVirtual ||
 224         iid == vmIntrinsics::_linkToSpecial) {
 225       // could do this for all kinds, but would explode assembly code size
 226       trace_method_handle(_masm, "bad Method*::intrinsic_id");
 227     }
 228     __ STOP("bad Method*::intrinsic_id");
 229     __ bind(L);
 230     BLOCK_COMMENT("} verify_intrinsic_id");
 231   }
 232 
 233   // First task:  Find out how big the argument list is.
 234   Address rdx_first_arg_addr;
 235   int ref_kind = signature_polymorphic_intrinsic_ref_kind(iid);
 236   assert(ref_kind != 0 || iid == vmIntrinsics::_invokeBasic, "must be _invokeBasic or a linkTo intrinsic");
 237   if (ref_kind == 0 || MethodHandles::ref_kind_has_receiver(ref_kind)) {
 238     __ load_sized_value(rdx_argp,
 239                         Address(rbx_method, Method::size_of_parameters_offset()),
 240                         sizeof(u2), /*is_signed*/ false);
 241     // assert(sizeof(u2) == sizeof(Method::_size_of_parameters), "");
 242     rdx_first_arg_addr = __ argument_address(rdx_argp, -1);
 243   } else {
 244     DEBUG_ONLY(rdx_argp = noreg);
 245   }
 246 
 247   if (!is_signature_polymorphic_static(iid)) {
 248     __ movptr(rcx_mh, rdx_first_arg_addr);
 249     DEBUG_ONLY(rdx_argp = noreg);
 250   }
 251 
 252   // rdx_first_arg_addr is live!
 253 
 254   if (TraceMethodHandles) {
 255     const char* name = vmIntrinsics::name_at(iid);
 256     if (*name == '_')  name += 1;
 257     const size_t len = strlen(name) + 50;
 258     char* qname = NEW_C_HEAP_ARRAY(char, len, mtInternal);
 259     const char* suffix = "";
 260     if (vmIntrinsics::method_for(iid) == NULL ||
 261         !vmIntrinsics::method_for(iid)->access_flags().is_public()) {
 262       if (is_signature_polymorphic_static(iid))
 263         suffix = "/static";
 264       else
 265         suffix = "/private";
 266     }
 267     jio_snprintf(qname, len, "MethodHandle::interpreter_entry::%s%s", name, suffix);
 268     // note: stub look for mh in rcx
 269     trace_method_handle(_masm, qname);
 270   }
 271 
 272   if (iid == vmIntrinsics::_invokeBasic) {
 273     generate_method_handle_dispatch(_masm, iid, rcx_mh, noreg, not_for_compiler_entry);
 274 
 275   } else {
 276     // Adjust argument list by popping the trailing MemberName argument.
 277     Register rcx_recv = noreg;
 278     if (MethodHandles::ref_kind_has_receiver(ref_kind)) {
 279       // Load the receiver (not the MH; the actual MemberName's receiver) up from the interpreter stack.
 280       __ movptr(rcx_recv = rcx, rdx_first_arg_addr);
 281     }
 282     DEBUG_ONLY(rdx_argp = noreg);
 283     Register rbx_member = rbx_method;  // MemberName ptr; incoming method ptr is dead now
 284     __ pop(rax_temp);           // return address
 285     __ pop(rbx_member);         // extract last argument
 286     __ push(rax_temp);          // re-push return address
 287     generate_method_handle_dispatch(_masm, iid, rcx_recv, rbx_member, not_for_compiler_entry);
 288   }
 289 
 290   if (PrintMethodHandleStubs) {
 291     address code_end = __ pc();
 292     tty->print_cr("--------");
 293     tty->print_cr("method handle interpreter entry for %s", vmIntrinsics::name_at(iid));
 294     Disassembler::decode(code_start, code_end);
 295     tty->cr();
 296   }
 297 
 298   return entry_point;
 299 }
 300 
 301 void MethodHandles::generate_method_handle_dispatch(MacroAssembler* _masm,
 302                                                     vmIntrinsics::ID iid,
 303                                                     Register receiver_reg,
 304                                                     Register member_reg,
 305                                                     bool for_compiler_entry) {
 306   assert(is_signature_polymorphic(iid), "expected invoke iid");
 307   Register rbx_method = rbx;   // eventual target of this invocation
 308   // temps used in this code are not used in *either* compiled or interpreted calling sequences
 309 #ifdef _LP64
 310   Register temp1 = rscratch1;
 311   Register temp2 = rscratch2;
 312   Register temp3 = rax;
 313   if (for_compiler_entry) {
 314     assert(receiver_reg == (iid == vmIntrinsics::_linkToStatic ? noreg : j_rarg0), "only valid assignment");
 315     assert_different_registers(temp1,        j_rarg0, j_rarg1, j_rarg2, j_rarg3, j_rarg4, j_rarg5);
 316     assert_different_registers(temp2,        j_rarg0, j_rarg1, j_rarg2, j_rarg3, j_rarg4, j_rarg5);
 317     assert_different_registers(temp3,        j_rarg0, j_rarg1, j_rarg2, j_rarg3, j_rarg4, j_rarg5);




 192   assert(is_signature_polymorphic(iid), "expected invoke iid");
 193   if (iid == vmIntrinsics::_invokeGeneric ||
 194       iid == vmIntrinsics::_compiledLambdaForm) {
 195     // Perhaps surprisingly, the symbolic references visible to Java are not directly used.
 196     // They are linked to Java-generated adapters via MethodHandleNatives.linkMethod.
 197     // They all allow an appendix argument.
 198     __ hlt();           // empty stubs make SG sick
 199     return NULL;
 200   }
 201 
 202   // rsi/r13: sender SP (must preserve; see prepare_to_jump_from_interpreted)
 203   // rbx: Method*
 204   // rdx: argument locator (parameter slot count, added to rsp)
 205   // rcx: used as temp to hold mh or receiver
 206   // rax, rdi: garbage temps, blown away
 207   Register rdx_argp   = rdx;   // argument list ptr, live on error paths
 208   Register rax_temp   = rax;
 209   Register rcx_mh     = rcx;   // MH receiver; dies quickly and is recycled
 210   Register rbx_method = rbx;   // eventual target of this invocation
 211 


 212   // here's where control starts out:
 213   __ align(CodeEntryAlignment);
 214   address entry_point = __ pc();
 215 
 216   if (VerifyMethodHandles) {
 217     Label L;
 218     BLOCK_COMMENT("verify_intrinsic_id {");
 219     __ cmpb(Address(rbx_method, Method::intrinsic_id_offset_in_bytes()), (int) iid);
 220     __ jcc(Assembler::equal, L);
 221     if (iid == vmIntrinsics::_linkToVirtual ||
 222         iid == vmIntrinsics::_linkToSpecial) {
 223       // could do this for all kinds, but would explode assembly code size
 224       trace_method_handle(_masm, "bad Method*::intrinsic_id");
 225     }
 226     __ STOP("bad Method*::intrinsic_id");
 227     __ bind(L);
 228     BLOCK_COMMENT("} verify_intrinsic_id");
 229   }
 230 
 231   // First task:  Find out how big the argument list is.
 232   Address rdx_first_arg_addr;
 233   int ref_kind = signature_polymorphic_intrinsic_ref_kind(iid);
 234   assert(ref_kind != 0 || iid == vmIntrinsics::_invokeBasic, "must be _invokeBasic or a linkTo intrinsic");
 235   if (ref_kind == 0 || MethodHandles::ref_kind_has_receiver(ref_kind)) {
 236     __ load_sized_value(rdx_argp,
 237                         Address(rbx_method, Method::size_of_parameters_offset()),
 238                         sizeof(u2), /*is_signed*/ false);
 239     // assert(sizeof(u2) == sizeof(Method::_size_of_parameters), "");
 240     rdx_first_arg_addr = __ argument_address(rdx_argp, -1);
 241   } else {
 242     DEBUG_ONLY(rdx_argp = noreg);
 243   }
 244 
 245   if (!is_signature_polymorphic_static(iid)) {
 246     __ movptr(rcx_mh, rdx_first_arg_addr);
 247     DEBUG_ONLY(rdx_argp = noreg);
 248   }
 249 
 250   // rdx_first_arg_addr is live!
 251 
 252   trace_method_handle_interpreter_entry(_masm, iid);
















 253 
 254   if (iid == vmIntrinsics::_invokeBasic) {
 255     generate_method_handle_dispatch(_masm, iid, rcx_mh, noreg, not_for_compiler_entry);
 256 
 257   } else {
 258     // Adjust argument list by popping the trailing MemberName argument.
 259     Register rcx_recv = noreg;
 260     if (MethodHandles::ref_kind_has_receiver(ref_kind)) {
 261       // Load the receiver (not the MH; the actual MemberName's receiver) up from the interpreter stack.
 262       __ movptr(rcx_recv = rcx, rdx_first_arg_addr);
 263     }
 264     DEBUG_ONLY(rdx_argp = noreg);
 265     Register rbx_member = rbx_method;  // MemberName ptr; incoming method ptr is dead now
 266     __ pop(rax_temp);           // return address
 267     __ pop(rbx_member);         // extract last argument
 268     __ push(rax_temp);          // re-push return address
 269     generate_method_handle_dispatch(_masm, iid, rcx_recv, rbx_member, not_for_compiler_entry);
 270   }
 271 








 272   return entry_point;
 273 }
 274 
 275 void MethodHandles::generate_method_handle_dispatch(MacroAssembler* _masm,
 276                                                     vmIntrinsics::ID iid,
 277                                                     Register receiver_reg,
 278                                                     Register member_reg,
 279                                                     bool for_compiler_entry) {
 280   assert(is_signature_polymorphic(iid), "expected invoke iid");
 281   Register rbx_method = rbx;   // eventual target of this invocation
 282   // temps used in this code are not used in *either* compiled or interpreted calling sequences
 283 #ifdef _LP64
 284   Register temp1 = rscratch1;
 285   Register temp2 = rscratch2;
 286   Register temp3 = rax;
 287   if (for_compiler_entry) {
 288     assert(receiver_reg == (iid == vmIntrinsics::_linkToStatic ? noreg : j_rarg0), "only valid assignment");
 289     assert_different_registers(temp1,        j_rarg0, j_rarg1, j_rarg2, j_rarg3, j_rarg4, j_rarg5);
 290     assert_different_registers(temp2,        j_rarg0, j_rarg1, j_rarg2, j_rarg3, j_rarg4, j_rarg5);
 291     assert_different_registers(temp3,        j_rarg0, j_rarg1, j_rarg2, j_rarg3, j_rarg4, j_rarg5);


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