< prev index next >

src/hotspot/cpu/x86/methodHandles_x86.cpp

Print this page
rev 50390 : 8200623: Primitive heap access for interpreter BarrierSetAssembler/x86


 158                                         Register recv, Register method_temp,
 159                                         Register temp2,
 160                                         bool for_compiler_entry) {
 161   BLOCK_COMMENT("jump_to_lambda_form {");
 162   // This is the initial entry point of a lazy method handle.
 163   // After type checking, it picks up the invoker from the LambdaForm.
 164   assert_different_registers(recv, method_temp, temp2);
 165   assert(recv != noreg, "required register");
 166   assert(method_temp == rbx, "required register for loading method");
 167 
 168   //NOT_PRODUCT({ FlagSetting fs(TraceMethodHandles, true); trace_method_handle(_masm, "LZMH"); });
 169 
 170   // Load the invoker, as MH -> MH.form -> LF.vmentry
 171   __ verify_oop(recv);
 172   __ load_heap_oop(method_temp, Address(recv, NONZERO(java_lang_invoke_MethodHandle::form_offset_in_bytes())), temp2);
 173   __ verify_oop(method_temp);
 174   __ load_heap_oop(method_temp, Address(method_temp, NONZERO(java_lang_invoke_LambdaForm::vmentry_offset_in_bytes())), temp2);
 175   __ verify_oop(method_temp);
 176   __ load_heap_oop(method_temp, Address(method_temp, NONZERO(java_lang_invoke_MemberName::method_offset_in_bytes())), temp2);
 177   __ verify_oop(method_temp);
 178   __ movptr(method_temp, Address(method_temp, NONZERO(java_lang_invoke_ResolvedMethodName::vmtarget_offset_in_bytes())));


 179 
 180   if (VerifyMethodHandles && !for_compiler_entry) {
 181     // make sure recv is already on stack
 182     __ movptr(temp2, Address(method_temp, Method::const_offset()));
 183     __ load_sized_value(temp2,
 184                         Address(temp2, ConstMethod::size_of_parameters_offset()),
 185                         sizeof(u2), /*is_signed*/ false);
 186     // assert(sizeof(u2) == sizeof(Method::_size_of_parameters), "");
 187     Label L;
 188     __ cmpoop(recv, __ argument_address(temp2, -1));
 189     __ jcc(Assembler::equal, L);
 190     __ movptr(rax, __ argument_address(temp2, -1));
 191     __ STOP("receiver not on stack");
 192     __ BIND(L);
 193   }
 194 
 195   jump_from_method_handle(_masm, method_temp, temp2, for_compiler_entry);
 196   BLOCK_COMMENT("} jump_to_lambda_form");
 197 }
 198 


 373       BLOCK_COMMENT("} check_receiver");
 374     }
 375     if (iid == vmIntrinsics::_linkToSpecial ||
 376         iid == vmIntrinsics::_linkToStatic) {
 377       DEBUG_ONLY(temp1_recv_klass = noreg);  // these guys didn't load the recv_klass
 378     }
 379 
 380     // Live registers at this point:
 381     //  member_reg - MemberName that was the trailing argument
 382     //  temp1_recv_klass - klass of stacked receiver, if needed
 383     //  rsi/r13 - interpreter linkage (if interpreted)
 384     //  rcx, rdx, rsi, rdi, r8 - compiler arguments (if compiled)
 385 
 386     Label L_incompatible_class_change_error;
 387     switch (iid) {
 388     case vmIntrinsics::_linkToSpecial:
 389       if (VerifyMethodHandles) {
 390         verify_ref_kind(_masm, JVM_REF_invokeSpecial, member_reg, temp3);
 391       }
 392       __ load_heap_oop(rbx_method, member_vmtarget);
 393       __ movptr(rbx_method, vmtarget_method);
 394       break;
 395 
 396     case vmIntrinsics::_linkToStatic:
 397       if (VerifyMethodHandles) {
 398         verify_ref_kind(_masm, JVM_REF_invokeStatic, member_reg, temp3);
 399       }
 400       __ load_heap_oop(rbx_method, member_vmtarget);
 401       __ movptr(rbx_method, vmtarget_method);
 402       break;
 403 
 404     case vmIntrinsics::_linkToVirtual:
 405     {
 406       // same as TemplateTable::invokevirtual,
 407       // minus the CP setup and profiling:
 408 
 409       if (VerifyMethodHandles) {
 410         verify_ref_kind(_masm, JVM_REF_invokeVirtual, member_reg, temp3);
 411       }
 412 
 413       // pick out the vtable index from the MemberName, and then we can discard it:
 414       Register temp2_index = temp2;
 415       __ movptr(temp2_index, member_vmindex);
 416 
 417       if (VerifyMethodHandles) {
 418         Label L_index_ok;
 419         __ cmpl(temp2_index, 0);
 420         __ jcc(Assembler::greaterEqual, L_index_ok);
 421         __ STOP("no virtual index");
 422         __ BIND(L_index_ok);
 423       }
 424 
 425       // Note:  The verifier invariants allow us to ignore MemberName.clazz and vmtarget
 426       // at this point.  And VerifyMethodHandles has already checked clazz, if needed.
 427 
 428       // get target Method* & entry point
 429       __ lookup_virtual_method(temp1_recv_klass, temp2_index, rbx_method);
 430       break;
 431     }
 432 
 433     case vmIntrinsics::_linkToInterface:
 434     {
 435       // same as TemplateTable::invokeinterface
 436       // (minus the CP setup and profiling, with different argument motion)
 437       if (VerifyMethodHandles) {
 438         verify_ref_kind(_masm, JVM_REF_invokeInterface, member_reg, temp3);
 439       }
 440 
 441       BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler();
 442 
 443       Register temp3_intf = temp3;
 444       __ load_heap_oop(temp3_intf, member_clazz);
 445       load_klass_from_Class(_masm, temp3_intf);
 446       __ verify_klass_ptr(temp3_intf);
 447 
 448       Register rbx_index = rbx_method;
 449       __ movptr(rbx_index, member_vmindex);
 450       if (VerifyMethodHandles) {
 451         Label L;
 452         __ cmpl(rbx_index, 0);
 453         __ jcc(Assembler::greaterEqual, L);
 454         __ STOP("invalid vtable index for MH.invokeInterface");
 455         __ bind(L);
 456       }
 457 
 458       // given intf, index, and recv klass, dispatch to the implementation method
 459       __ lookup_interface_method(temp1_recv_klass, temp3_intf,
 460                                  // note: next two args must be the same:
 461                                  rbx_index, rbx_method,
 462                                  temp2,
 463                                  L_incompatible_class_change_error);
 464       break;
 465     }
 466 
 467     default:
 468       fatal("unexpected intrinsic %d: %s", iid, vmIntrinsics::name_at(iid));
 469       break;




 158                                         Register recv, Register method_temp,
 159                                         Register temp2,
 160                                         bool for_compiler_entry) {
 161   BLOCK_COMMENT("jump_to_lambda_form {");
 162   // This is the initial entry point of a lazy method handle.
 163   // After type checking, it picks up the invoker from the LambdaForm.
 164   assert_different_registers(recv, method_temp, temp2);
 165   assert(recv != noreg, "required register");
 166   assert(method_temp == rbx, "required register for loading method");
 167 
 168   //NOT_PRODUCT({ FlagSetting fs(TraceMethodHandles, true); trace_method_handle(_masm, "LZMH"); });
 169 
 170   // Load the invoker, as MH -> MH.form -> LF.vmentry
 171   __ verify_oop(recv);
 172   __ load_heap_oop(method_temp, Address(recv, NONZERO(java_lang_invoke_MethodHandle::form_offset_in_bytes())), temp2);
 173   __ verify_oop(method_temp);
 174   __ load_heap_oop(method_temp, Address(method_temp, NONZERO(java_lang_invoke_LambdaForm::vmentry_offset_in_bytes())), temp2);
 175   __ verify_oop(method_temp);
 176   __ load_heap_oop(method_temp, Address(method_temp, NONZERO(java_lang_invoke_MemberName::method_offset_in_bytes())), temp2);
 177   __ verify_oop(method_temp);
 178   __ access_load_at(T_ADDRESS, IN_HEAP, method_temp,
 179                     Address(method_temp, NONZERO(java_lang_invoke_ResolvedMethodName::vmtarget_offset_in_bytes())),
 180                     noreg, noreg);
 181 
 182   if (VerifyMethodHandles && !for_compiler_entry) {
 183     // make sure recv is already on stack
 184     __ movptr(temp2, Address(method_temp, Method::const_offset()));
 185     __ load_sized_value(temp2,
 186                         Address(temp2, ConstMethod::size_of_parameters_offset()),
 187                         sizeof(u2), /*is_signed*/ false);
 188     // assert(sizeof(u2) == sizeof(Method::_size_of_parameters), "");
 189     Label L;
 190     __ cmpoop(recv, __ argument_address(temp2, -1));
 191     __ jcc(Assembler::equal, L);
 192     __ movptr(rax, __ argument_address(temp2, -1));
 193     __ STOP("receiver not on stack");
 194     __ BIND(L);
 195   }
 196 
 197   jump_from_method_handle(_masm, method_temp, temp2, for_compiler_entry);
 198   BLOCK_COMMENT("} jump_to_lambda_form");
 199 }
 200 


 375       BLOCK_COMMENT("} check_receiver");
 376     }
 377     if (iid == vmIntrinsics::_linkToSpecial ||
 378         iid == vmIntrinsics::_linkToStatic) {
 379       DEBUG_ONLY(temp1_recv_klass = noreg);  // these guys didn't load the recv_klass
 380     }
 381 
 382     // Live registers at this point:
 383     //  member_reg - MemberName that was the trailing argument
 384     //  temp1_recv_klass - klass of stacked receiver, if needed
 385     //  rsi/r13 - interpreter linkage (if interpreted)
 386     //  rcx, rdx, rsi, rdi, r8 - compiler arguments (if compiled)
 387 
 388     Label L_incompatible_class_change_error;
 389     switch (iid) {
 390     case vmIntrinsics::_linkToSpecial:
 391       if (VerifyMethodHandles) {
 392         verify_ref_kind(_masm, JVM_REF_invokeSpecial, member_reg, temp3);
 393       }
 394       __ load_heap_oop(rbx_method, member_vmtarget);
 395       __ access_load_at(T_ADDRESS, IN_HEAP, rbx_method, vmtarget_method, noreg, noreg);
 396       break;
 397 
 398     case vmIntrinsics::_linkToStatic:
 399       if (VerifyMethodHandles) {
 400         verify_ref_kind(_masm, JVM_REF_invokeStatic, member_reg, temp3);
 401       }
 402       __ load_heap_oop(rbx_method, member_vmtarget);
 403       __ access_load_at(T_ADDRESS, IN_HEAP, rbx_method, vmtarget_method, noreg, noreg);
 404       break;
 405 
 406     case vmIntrinsics::_linkToVirtual:
 407     {
 408       // same as TemplateTable::invokevirtual,
 409       // minus the CP setup and profiling:
 410 
 411       if (VerifyMethodHandles) {
 412         verify_ref_kind(_masm, JVM_REF_invokeVirtual, member_reg, temp3);
 413       }
 414 
 415       // pick out the vtable index from the MemberName, and then we can discard it:
 416       Register temp2_index = temp2;
 417       __ access_load_at(T_ADDRESS, IN_HEAP, temp2_index, member_vmindex, noreg, noreg);
 418 
 419       if (VerifyMethodHandles) {
 420         Label L_index_ok;
 421         __ cmpl(temp2_index, 0);
 422         __ jcc(Assembler::greaterEqual, L_index_ok);
 423         __ STOP("no virtual index");
 424         __ BIND(L_index_ok);
 425       }
 426 
 427       // Note:  The verifier invariants allow us to ignore MemberName.clazz and vmtarget
 428       // at this point.  And VerifyMethodHandles has already checked clazz, if needed.
 429 
 430       // get target Method* & entry point
 431       __ lookup_virtual_method(temp1_recv_klass, temp2_index, rbx_method);
 432       break;
 433     }
 434 
 435     case vmIntrinsics::_linkToInterface:
 436     {
 437       // same as TemplateTable::invokeinterface
 438       // (minus the CP setup and profiling, with different argument motion)
 439       if (VerifyMethodHandles) {
 440         verify_ref_kind(_masm, JVM_REF_invokeInterface, member_reg, temp3);
 441       }
 442 
 443       BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler();
 444 
 445       Register temp3_intf = temp3;
 446       __ load_heap_oop(temp3_intf, member_clazz);
 447       load_klass_from_Class(_masm, temp3_intf);
 448       __ verify_klass_ptr(temp3_intf);
 449 
 450       Register rbx_index = rbx_method;
 451       __ access_load_at(T_ADDRESS, IN_HEAP, rbx_index, member_vmindex, noreg, noreg);
 452       if (VerifyMethodHandles) {
 453         Label L;
 454         __ cmpl(rbx_index, 0);
 455         __ jcc(Assembler::greaterEqual, L);
 456         __ STOP("invalid vtable index for MH.invokeInterface");
 457         __ bind(L);
 458       }
 459 
 460       // given intf, index, and recv klass, dispatch to the implementation method
 461       __ lookup_interface_method(temp1_recv_klass, temp3_intf,
 462                                  // note: next two args must be the same:
 463                                  rbx_index, rbx_method,
 464                                  temp2,
 465                                  L_incompatible_class_change_error);
 466       break;
 467     }
 468 
 469     default:
 470       fatal("unexpected intrinsic %d: %s", iid, vmIntrinsics::name_at(iid));
 471       break;


< prev index next >