src/cpu/sparc/vm/methodHandles_sparc.cpp

changeset 4101
2cb2f30450c7
parent 4052
75f33eecc1b3
child 4158
65d07d9ee446
equal deleted inserted replaced
4060:a6fe94b9759f 4101:2cb2f30450c7
119 #endif // ASSERT 119 #endif // ASSERT
120 120
121 void MethodHandles::jump_from_method_handle(MacroAssembler* _masm, Register method, Register target, Register temp, 121 void MethodHandles::jump_from_method_handle(MacroAssembler* _masm, Register method, Register target, Register temp,
122 bool for_compiler_entry) { 122 bool for_compiler_entry) {
123 assert(method == G5_method, "interpreter calling convention"); 123 assert(method == G5_method, "interpreter calling convention");
124 assert_different_registers(method, target, temp);
124 125
125 if (!for_compiler_entry && JvmtiExport::can_post_interpreter_events()) { 126 if (!for_compiler_entry && JvmtiExport::can_post_interpreter_events()) {
126 Label run_compiled_code; 127 Label run_compiled_code;
127 // JVMTI events, such as single-stepping, are implemented partly by avoiding running 128 // JVMTI events, such as single-stepping, are implemented partly by avoiding running
128 // compiled code in threads for which the event is enabled. Check here for 129 // compiled code in threads for which the event is enabled. Check here for
151 Register temp2, Register temp3, 152 Register temp2, Register temp3,
152 bool for_compiler_entry) { 153 bool for_compiler_entry) {
153 BLOCK_COMMENT("jump_to_lambda_form {"); 154 BLOCK_COMMENT("jump_to_lambda_form {");
154 // This is the initial entry point of a lazy method handle. 155 // This is the initial entry point of a lazy method handle.
155 // After type checking, it picks up the invoker from the LambdaForm. 156 // After type checking, it picks up the invoker from the LambdaForm.
156 assert_different_registers(recv, method_temp, temp2, temp3); 157 assert_different_registers(recv, method_temp, temp2); // temp3 is only passed on
157 assert(method_temp == G5_method, "required register for loading method"); 158 assert(method_temp == G5_method, "required register for loading method");
158 159
159 //NOT_PRODUCT({ FlagSetting fs(TraceMethodHandles, true); trace_method_handle(_masm, "LZMH"); }); 160 //NOT_PRODUCT({ FlagSetting fs(TraceMethodHandles, true); trace_method_handle(_masm, "LZMH"); });
160 161
161 // Load the invoker, as MH -> MH.form -> LF.vmentry 162 // Load the invoker, as MH -> MH.form -> LF.vmentry
162 __ verify_oop(recv); 163 __ verify_oop(recv);
163 __ load_heap_oop(Address(recv, NONZERO(java_lang_invoke_MethodHandle::form_offset_in_bytes())), method_temp); 164 __ load_heap_oop(Address(recv, NONZERO(java_lang_invoke_MethodHandle::form_offset_in_bytes())), method_temp);
164 __ verify_oop(method_temp); 165 __ verify_oop(method_temp);
165 __ load_heap_oop(Address(method_temp, NONZERO(java_lang_invoke_LambdaForm::vmentry_offset_in_bytes())), method_temp); 166 __ load_heap_oop(Address(method_temp, NONZERO(java_lang_invoke_LambdaForm::vmentry_offset_in_bytes())), method_temp);
166 __ verify_oop(method_temp); 167 __ verify_oop(method_temp);
167 // the following assumes that a Method* is normally compressed in the vmtarget field: 168 // the following assumes that a Method* is normally compressed in the vmtarget field:
168 __ ld_ptr(Address(method_temp, NONZERO(java_lang_invoke_MemberName::vmtarget_offset_in_bytes())), method_temp); 169 __ ld_ptr( Address(method_temp, NONZERO(java_lang_invoke_MemberName::vmtarget_offset_in_bytes())), method_temp);
169 170
170 if (VerifyMethodHandles && !for_compiler_entry) { 171 if (VerifyMethodHandles && !for_compiler_entry) {
171 // make sure recv is already on stack 172 // make sure recv is already on stack
172 __ load_sized_value(Address(method_temp, Method::size_of_parameters_offset()), 173 __ load_sized_value(Address(method_temp, Method::size_of_parameters_offset()),
173 temp2, 174 temp2,
301 vmIntrinsics::ID iid, 302 vmIntrinsics::ID iid,
302 Register receiver_reg, 303 Register receiver_reg,
303 Register member_reg, 304 Register member_reg,
304 bool for_compiler_entry) { 305 bool for_compiler_entry) {
305 assert(is_signature_polymorphic(iid), "expected invoke iid"); 306 assert(is_signature_polymorphic(iid), "expected invoke iid");
306 // temps used in this code are not used in *either* compiled or interpreted calling sequences
307 Register temp1 = (for_compiler_entry ? G1_scratch : O1); 307 Register temp1 = (for_compiler_entry ? G1_scratch : O1);
308 Register temp2 = (for_compiler_entry ? G4_scratch : O4); 308 Register temp2 = (for_compiler_entry ? G3_scratch : O2);
309 Register temp3 = G3_scratch; 309 Register temp3 = (for_compiler_entry ? G4_scratch : O3);
310 Register temp4 = (for_compiler_entry ? noreg : O2); 310 Register temp4 = (for_compiler_entry ? noreg : O4);
311 if (for_compiler_entry) { 311 if (for_compiler_entry) {
312 assert(receiver_reg == (iid == vmIntrinsics::_linkToStatic ? noreg : O0), "only valid assignment"); 312 assert(receiver_reg == (iid == vmIntrinsics::_linkToStatic ? noreg : O0), "only valid assignment");
313 assert_different_registers(temp1, O0, O1, O2, O3, O4, O5); 313 assert_different_registers(temp1, O0, O1, O2, O3, O4, O5);
314 assert_different_registers(temp2, O0, O1, O2, O3, O4, O5); 314 assert_different_registers(temp2, O0, O1, O2, O3, O4, O5);
315 assert_different_registers(temp3, O0, O1, O2, O3, O4, O5); 315 assert_different_registers(temp3, O0, O1, O2, O3, O4, O5);
316 assert_different_registers(temp4, O0, O1, O2, O3, O4, O5); 316 assert_different_registers(temp4, O0, O1, O2, O3, O4, O5);
317 } else {
318 assert_different_registers(temp1, temp2, temp3, temp4, O5_savedSP); // don't trash lastSP
317 } 319 }
318 if (receiver_reg != noreg) assert_different_registers(temp1, temp2, temp3, temp4, receiver_reg); 320 if (receiver_reg != noreg) assert_different_registers(temp1, temp2, temp3, temp4, receiver_reg);
319 if (member_reg != noreg) assert_different_registers(temp1, temp2, temp3, temp4, member_reg); 321 if (member_reg != noreg) assert_different_registers(temp1, temp2, temp3, temp4, member_reg);
320 if (!for_compiler_entry) assert_different_registers(temp1, temp2, temp3, temp4, O5_savedSP); // don't trash lastSP
321 322
322 if (iid == vmIntrinsics::_invokeBasic) { 323 if (iid == vmIntrinsics::_invokeBasic) {
323 // indirect through MH.form.vmentry.vmtarget 324 // indirect through MH.form.vmentry.vmtarget
324 jump_to_lambda_form(_masm, receiver_reg, G5_method, temp2, temp3, for_compiler_entry); 325 jump_to_lambda_form(_masm, receiver_reg, G5_method, temp1, temp2, for_compiler_entry);
325 326
326 } else { 327 } else {
327 // The method is a member invoker used by direct method handles. 328 // The method is a member invoker used by direct method handles.
328 if (VerifyMethodHandles) { 329 if (VerifyMethodHandles) {
329 // make sure the trailing argument really is a MemberName (caller responsibility) 330 // make sure the trailing argument really is a MemberName (caller responsibility)
376 377
377 // Live registers at this point: 378 // Live registers at this point:
378 // member_reg - MemberName that was the trailing argument 379 // member_reg - MemberName that was the trailing argument
379 // temp1_recv_klass - klass of stacked receiver, if needed 380 // temp1_recv_klass - klass of stacked receiver, if needed
380 // O5_savedSP - interpreter linkage (if interpreted) 381 // O5_savedSP - interpreter linkage (if interpreted)
381 // O0..O7,G1,G4 - compiler arguments (if compiled) 382 // O0..O5 - compiler arguments (if compiled)
382 383
383 bool method_is_live = false; 384 Label L_incompatible_class_change_error;
384 switch (iid) { 385 switch (iid) {
385 case vmIntrinsics::_linkToSpecial: 386 case vmIntrinsics::_linkToSpecial:
386 if (VerifyMethodHandles) { 387 if (VerifyMethodHandles) {
387 verify_ref_kind(_masm, JVM_REF_invokeSpecial, member_reg, temp3); 388 verify_ref_kind(_masm, JVM_REF_invokeSpecial, member_reg, temp2);
388 } 389 }
389 __ ld_ptr(member_vmtarget, G5_method); 390 __ ld_ptr(member_vmtarget, G5_method);
390 method_is_live = true;
391 break; 391 break;
392 392
393 case vmIntrinsics::_linkToStatic: 393 case vmIntrinsics::_linkToStatic:
394 if (VerifyMethodHandles) { 394 if (VerifyMethodHandles) {
395 verify_ref_kind(_masm, JVM_REF_invokeStatic, member_reg, temp3); 395 verify_ref_kind(_masm, JVM_REF_invokeStatic, member_reg, temp2);
396 } 396 }
397 __ ld_ptr(member_vmtarget, G5_method); 397 __ ld_ptr(member_vmtarget, G5_method);
398 method_is_live = true;
399 break; 398 break;
400 399
401 case vmIntrinsics::_linkToVirtual: 400 case vmIntrinsics::_linkToVirtual:
402 { 401 {
403 // same as TemplateTable::invokevirtual, 402 // same as TemplateTable::invokevirtual,
404 // minus the CP setup and profiling: 403 // minus the CP setup and profiling:
405 404
406 if (VerifyMethodHandles) { 405 if (VerifyMethodHandles) {
407 verify_ref_kind(_masm, JVM_REF_invokeVirtual, member_reg, temp3); 406 verify_ref_kind(_masm, JVM_REF_invokeVirtual, member_reg, temp2);
408 } 407 }
409 408
410 // pick out the vtable index from the MemberName, and then we can discard it: 409 // pick out the vtable index from the MemberName, and then we can discard it:
411 Register temp2_index = temp2; 410 Register temp2_index = temp2;
412 __ ld_ptr(member_vmindex, temp2_index); 411 __ ld_ptr(member_vmindex, temp2_index);
421 // Note: The verifier invariants allow us to ignore MemberName.clazz and vmtarget 420 // Note: The verifier invariants allow us to ignore MemberName.clazz and vmtarget
422 // at this point. And VerifyMethodHandles has already checked clazz, if needed. 421 // at this point. And VerifyMethodHandles has already checked clazz, if needed.
423 422
424 // get target Method* & entry point 423 // get target Method* & entry point
425 __ lookup_virtual_method(temp1_recv_klass, temp2_index, G5_method); 424 __ lookup_virtual_method(temp1_recv_klass, temp2_index, G5_method);
426 method_is_live = true;
427 break; 425 break;
428 } 426 }
429 427
430 case vmIntrinsics::_linkToInterface: 428 case vmIntrinsics::_linkToInterface:
431 { 429 {
432 // same as TemplateTable::invokeinterface 430 // same as TemplateTable::invokeinterface
433 // (minus the CP setup and profiling, with different argument motion) 431 // (minus the CP setup and profiling, with different argument motion)
434 if (VerifyMethodHandles) { 432 if (VerifyMethodHandles) {
435 verify_ref_kind(_masm, JVM_REF_invokeInterface, member_reg, temp3); 433 verify_ref_kind(_masm, JVM_REF_invokeInterface, member_reg, temp2);
436 } 434 }
437 435
438 Register temp3_intf = temp3; 436 Register temp2_intf = temp2;
439 __ load_heap_oop(member_clazz, temp3_intf); 437 __ load_heap_oop(member_clazz, temp2_intf);
440 load_klass_from_Class(_masm, temp3_intf, temp2, temp4); 438 load_klass_from_Class(_masm, temp2_intf, temp3, temp4);
441 __ verify_klass_ptr(temp3_intf); 439 __ verify_klass_ptr(temp2_intf);
442 440
443 Register G5_index = G5_method; 441 Register G5_index = G5_method;
444 __ ld_ptr(member_vmindex, G5_index); 442 __ ld_ptr(member_vmindex, G5_index);
445 if (VerifyMethodHandles) { 443 if (VerifyMethodHandles) {
446 Label L; 444 Label L;
448 __ STOP("invalid vtable index for MH.invokeInterface"); 446 __ STOP("invalid vtable index for MH.invokeInterface");
449 __ bind(L); 447 __ bind(L);
450 } 448 }
451 449
452 // given intf, index, and recv klass, dispatch to the implementation method 450 // given intf, index, and recv klass, dispatch to the implementation method
453 Label L_no_such_interface; 451 __ lookup_interface_method(temp1_recv_klass, temp2_intf,
454 Register no_sethi_temp = noreg;
455 __ lookup_interface_method(temp1_recv_klass, temp3_intf,
456 // note: next two args must be the same: 452 // note: next two args must be the same:
457 G5_index, G5_method, 453 G5_index, G5_method,
458 temp2, no_sethi_temp, 454 temp3, temp4,
459 L_no_such_interface); 455 L_incompatible_class_change_error);
460 456 break;
461 __ verify_method_ptr(G5_method); 457 }
462 jump_from_method_handle(_masm, G5_method, temp2, temp3, for_compiler_entry); 458
463 459 default:
464 __ bind(L_no_such_interface); 460 fatal(err_msg_res("unexpected intrinsic %d: %s", iid, vmIntrinsics::name_at(iid)));
461 break;
462 }
463
464 // Live at this point:
465 // G5_method
466 // O5_savedSP (if interpreted)
467
468 // After figuring out which concrete method to call, jump into it.
469 // Note that this works in the interpreter with no data motion.
470 // But the compiled version will require that rcx_recv be shifted out.
471 __ verify_method_ptr(G5_method);
472 jump_from_method_handle(_masm, G5_method, temp1, temp2, for_compiler_entry);
473
474 if (iid == vmIntrinsics::_linkToInterface) {
475 __ BIND(L_incompatible_class_change_error);
465 AddressLiteral icce(StubRoutines::throw_IncompatibleClassChangeError_entry()); 476 AddressLiteral icce(StubRoutines::throw_IncompatibleClassChangeError_entry());
466 __ jump_to(icce, temp3); 477 __ jump_to(icce, temp1);
467 __ delayed()->nop(); 478 __ delayed()->nop();
468 break;
469 }
470
471 default:
472 fatal(err_msg("unexpected intrinsic %d: %s", iid, vmIntrinsics::name_at(iid)));
473 break;
474 }
475
476 if (method_is_live) {
477 // live at this point: G5_method, O5_savedSP (if interpreted)
478
479 // After figuring out which concrete method to call, jump into it.
480 // Note that this works in the interpreter with no data motion.
481 // But the compiled version will require that rcx_recv be shifted out.
482 __ verify_method_ptr(G5_method);
483 jump_from_method_handle(_masm, G5_method, temp1, temp3, for_compiler_entry);
484 } 479 }
485 } 480 }
486 } 481 }
487 482
488 #ifndef PRODUCT 483 #ifndef PRODUCT

mercurial