Mercurial > hg > truffle
comparison src/cpu/x86/vm/methodHandles_x86.cpp @ 2088:8d0b933dda2d
7007377: JSR 292 MethodHandlesTest.testCastFailure fails on SPARC with -Xcomp +DeoptimizeALot
Reviewed-by: kvn, jrose
author | twisti |
---|---|
date | Wed, 22 Dec 2010 02:02:53 -0800 |
parents | f95d63e2154a |
children | d810e9a3fc33 |
comparison
equal
deleted
inserted
replaced
2087:352765ed11a1 | 2088:8d0b933dda2d |
---|---|
383 //|(1<<sun_dyn_AdapterMethodHandle::OP_SPREAD_ARGS) //BUG! | 383 //|(1<<sun_dyn_AdapterMethodHandle::OP_SPREAD_ARGS) //BUG! |
384 ); | 384 ); |
385 // FIXME: MethodHandlesTest gets a crash if we enable OP_SPREAD_ARGS. | 385 // FIXME: MethodHandlesTest gets a crash if we enable OP_SPREAD_ARGS. |
386 } | 386 } |
387 | 387 |
388 //------------------------------------------------------------------------------ | |
389 // MethodHandles::generate_method_handle_stub | |
390 // | |
388 // Generate an "entry" field for a method handle. | 391 // Generate an "entry" field for a method handle. |
389 // This determines how the method handle will respond to calls. | 392 // This determines how the method handle will respond to calls. |
390 void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHandles::EntryKind ek) { | 393 void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHandles::EntryKind ek, TRAPS) { |
391 // Here is the register state during an interpreted call, | 394 // Here is the register state during an interpreted call, |
392 // as set up by generate_method_handle_interpreter_entry(): | 395 // as set up by generate_method_handle_interpreter_entry(): |
393 // - rbx: garbage temp (was MethodHandle.invoke methodOop, unused) | 396 // - rbx: garbage temp (was MethodHandle.invoke methodOop, unused) |
394 // - rcx: receiver method handle | 397 // - rcx: receiver method handle |
395 // - rax: method handle type (only used by the check_mtype entry point) | 398 // - rax: method handle type (only used by the check_mtype entry point) |
396 // - rsi/r13: sender SP (must preserve; see prepare_to_jump_from_interpreted) | 399 // - rsi/r13: sender SP (must preserve; see prepare_to_jump_from_interpreted) |
397 // - rdx: garbage temp, can blow away | 400 // - rdx: garbage temp, can blow away |
398 | 401 |
399 Register rcx_recv = rcx; | 402 const Register rcx_recv = rcx; |
400 Register rax_argslot = rax; | 403 const Register rax_argslot = rax; |
401 Register rbx_temp = rbx; | 404 const Register rbx_temp = rbx; |
402 Register rdx_temp = rdx; | 405 const Register rdx_temp = rdx; |
403 | 406 |
404 // This guy is set up by prepare_to_jump_from_interpreted (from interpreted calls) | 407 // This guy is set up by prepare_to_jump_from_interpreted (from interpreted calls) |
405 // and gen_c2i_adapter (from compiled calls): | 408 // and gen_c2i_adapter (from compiled calls): |
406 Register saved_last_sp = LP64_ONLY(r13) NOT_LP64(rsi); | 409 const Register saved_last_sp = LP64_ONLY(r13) NOT_LP64(rsi); |
410 | |
411 // Argument registers for _raise_exception. | |
412 // 32-bit: Pass first two oop/int args in registers ECX and EDX. | |
413 const Register rarg0_code = LP64_ONLY(j_rarg0) NOT_LP64(rcx); | |
414 const Register rarg1_actual = LP64_ONLY(j_rarg1) NOT_LP64(rdx); | |
415 const Register rarg2_required = LP64_ONLY(j_rarg2) NOT_LP64(rdi); | |
416 assert_different_registers(rarg0_code, rarg1_actual, rarg2_required, saved_last_sp); | |
407 | 417 |
408 guarantee(java_dyn_MethodHandle::vmentry_offset_in_bytes() != 0, "must have offsets"); | 418 guarantee(java_dyn_MethodHandle::vmentry_offset_in_bytes() != 0, "must have offsets"); |
409 | 419 |
410 // some handy addresses | 420 // some handy addresses |
411 Address rbx_method_fie( rbx, methodOopDesc::from_interpreted_offset() ); | 421 Address rbx_method_fie( rbx, methodOopDesc::from_interpreted_offset() ); |
435 BLOCK_COMMENT(entry_name(ek)); | 445 BLOCK_COMMENT(entry_name(ek)); |
436 | 446 |
437 switch ((int) ek) { | 447 switch ((int) ek) { |
438 case _raise_exception: | 448 case _raise_exception: |
439 { | 449 { |
440 // Not a real MH entry, but rather shared code for raising an exception. | 450 // Not a real MH entry, but rather shared code for raising an |
441 // Extra local arguments are pushed on stack, as required type at TOS+8, | 451 // exception. Since we use a C2I adapter to set up the |
442 // failing object (or NULL) at TOS+4, failing bytecode type at TOS. | 452 // interpreter state, arguments are expected in compiler |
443 // Beyond those local arguments are the PC, of course. | 453 // argument registers. |
444 Register rdx_code = rdx_temp; | 454 methodHandle mh(raise_exception_method()); |
445 Register rcx_fail = rcx_recv; | 455 address c2i_entry = methodOopDesc::make_adapters(mh, CHECK); |
446 Register rax_want = rax_argslot; | 456 |
447 Register rdi_pc = rdi; | 457 const Register rdi_pc = rax; |
448 __ pop(rdx_code); // TOS+0 | 458 __ pop(rdi_pc); // caller PC |
449 __ pop(rcx_fail); // TOS+4 | 459 __ mov(rsp, saved_last_sp); // cut the stack back to where the caller started |
450 __ pop(rax_want); // TOS+8 | |
451 __ pop(rdi_pc); // caller PC | |
452 | |
453 __ mov(rsp, rsi); // cut the stack back to where the caller started | |
454 | |
455 // Repush the arguments as if coming from the interpreter. | |
456 __ push(rdx_code); | |
457 __ push(rcx_fail); | |
458 __ push(rax_want); | |
459 | 460 |
460 Register rbx_method = rbx_temp; | 461 Register rbx_method = rbx_temp; |
461 Label no_method; | 462 Label L_no_method; |
462 // FIXME: fill in _raise_exception_method with a suitable sun.dyn method | 463 // FIXME: fill in _raise_exception_method with a suitable sun.dyn method |
463 __ movptr(rbx_method, ExternalAddress((address) &_raise_exception_method)); | 464 __ movptr(rbx_method, ExternalAddress((address) &_raise_exception_method)); |
464 __ testptr(rbx_method, rbx_method); | 465 __ testptr(rbx_method, rbx_method); |
465 __ jccb(Assembler::zero, no_method); | 466 __ jccb(Assembler::zero, L_no_method); |
466 int jobject_oop_offset = 0; | 467 |
468 const int jobject_oop_offset = 0; | |
467 __ movptr(rbx_method, Address(rbx_method, jobject_oop_offset)); // dereference the jobject | 469 __ movptr(rbx_method, Address(rbx_method, jobject_oop_offset)); // dereference the jobject |
468 __ testptr(rbx_method, rbx_method); | 470 __ testptr(rbx_method, rbx_method); |
469 __ jccb(Assembler::zero, no_method); | 471 __ jccb(Assembler::zero, L_no_method); |
470 __ verify_oop(rbx_method); | 472 __ verify_oop(rbx_method); |
471 __ push(rdi_pc); // and restore caller PC | 473 |
472 __ jmp(rbx_method_fie); | 474 // 32-bit: push remaining arguments as if coming from the compiler. |
475 NOT_LP64(__ push(rarg2_required)); | |
476 | |
477 __ push(rdi_pc); // restore caller PC | |
478 __ jump(ExternalAddress(c2i_entry)); // do C2I transition | |
473 | 479 |
474 // If we get here, the Java runtime did not do its job of creating the exception. | 480 // If we get here, the Java runtime did not do its job of creating the exception. |
475 // Do something that is at least causes a valid throw from the interpreter. | 481 // Do something that is at least causes a valid throw from the interpreter. |
476 __ bind(no_method); | 482 __ bind(L_no_method); |
477 __ pop(rax_want); | 483 __ push(rarg2_required); |
478 __ pop(rcx_fail); | 484 __ push(rarg1_actual); |
479 __ push(rax_want); | |
480 __ push(rcx_fail); | |
481 __ jump(ExternalAddress(Interpreter::throw_WrongMethodType_entry())); | 485 __ jump(ExternalAddress(Interpreter::throw_WrongMethodType_entry())); |
482 } | 486 } |
483 break; | 487 break; |
484 | 488 |
485 case _invokestatic_mh: | 489 case _invokestatic_mh: |
570 __ hlt(); | 574 __ hlt(); |
571 | 575 |
572 __ bind(no_such_interface); | 576 __ bind(no_such_interface); |
573 // Throw an exception. | 577 // Throw an exception. |
574 // For historical reasons, it will be IncompatibleClassChangeError. | 578 // For historical reasons, it will be IncompatibleClassChangeError. |
575 __ pushptr(Address(rdx_intf, java_mirror_offset)); // required interface | 579 __ mov(rbx_temp, rcx_recv); // rarg2_required might be RCX |
576 __ push(rcx_recv); // bad receiver | 580 assert_different_registers(rarg2_required, rbx_temp); |
577 __ push((int)Bytecodes::_invokeinterface); // who is complaining? | 581 __ movptr(rarg2_required, Address(rdx_intf, java_mirror_offset)); // required interface |
582 __ mov( rarg1_actual, rbx_temp); // bad receiver | |
583 __ movl( rarg0_code, (int) Bytecodes::_invokeinterface); // who is complaining? | |
578 __ jump(ExternalAddress(from_interpreted_entry(_raise_exception))); | 584 __ jump(ExternalAddress(from_interpreted_entry(_raise_exception))); |
579 } | 585 } |
580 break; | 586 break; |
581 | 587 |
582 case _bound_ref_mh: | 588 case _bound_ref_mh: |
667 // Call the wrong_method_type stub, passing the failing argument type in rax. | 673 // Call the wrong_method_type stub, passing the failing argument type in rax. |
668 Register rax_mtype = rax_argslot; | 674 Register rax_mtype = rax_argslot; |
669 __ movl(rax_argslot, rcx_amh_vmargslot); // reload argslot field | 675 __ movl(rax_argslot, rcx_amh_vmargslot); // reload argslot field |
670 __ movptr(rdx_temp, vmarg); | 676 __ movptr(rdx_temp, vmarg); |
671 | 677 |
672 __ load_heap_oop(rbx_klass, rcx_amh_argument); // required class | 678 assert_different_registers(rarg2_required, rdx_temp); |
673 __ push(rbx_klass); | 679 __ load_heap_oop(rarg2_required, rcx_amh_argument); // required class |
674 __ push(rdx_temp); // bad object | 680 __ mov( rarg1_actual, rdx_temp); // bad object |
675 __ push((int)Bytecodes::_checkcast); // who is complaining? | 681 __ movl( rarg0_code, (int) Bytecodes::_checkcast); // who is complaining? |
676 __ jump(ExternalAddress(from_interpreted_entry(_raise_exception))); | 682 __ jump(ExternalAddress(from_interpreted_entry(_raise_exception))); |
677 | 683 |
678 __ bind(done); | 684 __ bind(done); |
679 // get the new MH: | 685 // get the new MH: |
680 __ load_heap_oop(rcx_recv, rcx_mh_vmtarget); | 686 __ load_heap_oop(rcx_recv, rcx_mh_vmtarget); |
1187 __ load_heap_oop(rcx_recv, rcx_mh_vmtarget); | 1193 __ load_heap_oop(rcx_recv, rcx_mh_vmtarget); |
1188 __ jump_to_method_handle_entry(rcx_recv, rdx_temp); | 1194 __ jump_to_method_handle_entry(rcx_recv, rdx_temp); |
1189 | 1195 |
1190 __ bind(bad_array_klass); | 1196 __ bind(bad_array_klass); |
1191 UNPUSH_RSI_RDI; | 1197 UNPUSH_RSI_RDI; |
1192 __ pushptr(Address(rdx_array_klass, java_mirror_offset)); // required type | 1198 assert(!vmarg.uses(rarg2_required), "must be different registers"); |
1193 __ pushptr(vmarg); // bad array | 1199 __ movptr(rarg2_required, Address(rdx_array_klass, java_mirror_offset)); // required type |
1194 __ push((int)Bytecodes::_aaload); // who is complaining? | 1200 __ movptr(rarg1_actual, vmarg); // bad array |
1201 __ movl( rarg0_code, (int) Bytecodes::_aaload); // who is complaining? | |
1195 __ jump(ExternalAddress(from_interpreted_entry(_raise_exception))); | 1202 __ jump(ExternalAddress(from_interpreted_entry(_raise_exception))); |
1196 | 1203 |
1197 __ bind(bad_array_length); | 1204 __ bind(bad_array_length); |
1198 UNPUSH_RSI_RDI; | 1205 UNPUSH_RSI_RDI; |
1199 __ push(rcx_recv); // AMH requiring a certain length | 1206 assert(!vmarg.uses(rarg2_required), "must be different registers"); |
1200 __ pushptr(vmarg); // bad array | 1207 __ mov (rarg2_required, rcx_recv); // AMH requiring a certain length |
1201 __ push((int)Bytecodes::_arraylength); // who is complaining? | 1208 __ movptr(rarg1_actual, vmarg); // bad array |
1209 __ movl( rarg0_code, (int) Bytecodes::_arraylength); // who is complaining? | |
1202 __ jump(ExternalAddress(from_interpreted_entry(_raise_exception))); | 1210 __ jump(ExternalAddress(from_interpreted_entry(_raise_exception))); |
1203 | 1211 |
1204 #undef UNPUSH_RSI_RDI | 1212 #undef UNPUSH_RSI_RDI |
1205 } | 1213 } |
1206 break; | 1214 break; |