Mercurial > hg > graal-compiler
comparison src/cpu/sparc/vm/methodHandles_sparc.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 | b856cd7f4e60 |
children | d810e9a3fc33 |
comparison
equal
deleted
inserted
replaced
2087:352765ed11a1 | 2088:8d0b933dda2d |
---|---|
393 //------------------------------------------------------------------------------ | 393 //------------------------------------------------------------------------------ |
394 // MethodHandles::generate_method_handle_stub | 394 // MethodHandles::generate_method_handle_stub |
395 // | 395 // |
396 // Generate an "entry" field for a method handle. | 396 // Generate an "entry" field for a method handle. |
397 // This determines how the method handle will respond to calls. | 397 // This determines how the method handle will respond to calls. |
398 void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHandles::EntryKind ek) { | 398 void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHandles::EntryKind ek, TRAPS) { |
399 // Here is the register state during an interpreted call, | 399 // Here is the register state during an interpreted call, |
400 // as set up by generate_method_handle_interpreter_entry(): | 400 // as set up by generate_method_handle_interpreter_entry(): |
401 // - G5: garbage temp (was MethodHandle.invoke methodOop, unused) | 401 // - G5: garbage temp (was MethodHandle.invoke methodOop, unused) |
402 // - G3: receiver method handle | 402 // - G3: receiver method handle |
403 // - O5_savedSP: sender SP (must preserve) | 403 // - O5_savedSP: sender SP (must preserve) |
404 | 404 |
405 Register O0_argslot = O0; | 405 const Register O0_argslot = O0; |
406 Register O1_scratch = O1; | 406 const Register O1_scratch = O1; |
407 Register O2_scratch = O2; | 407 const Register O2_scratch = O2; |
408 Register O3_scratch = O3; | 408 const Register O3_scratch = O3; |
409 Register G5_index = G5; | 409 const Register G5_index = G5; |
410 | |
411 // Argument registers for _raise_exception. | |
412 const Register O0_code = O0; | |
413 const Register O1_actual = O1; | |
414 const Register O2_required = O2; | |
410 | 415 |
411 guarantee(java_dyn_MethodHandle::vmentry_offset_in_bytes() != 0, "must have offsets"); | 416 guarantee(java_dyn_MethodHandle::vmentry_offset_in_bytes() != 0, "must have offsets"); |
412 | 417 |
413 // Some handy addresses: | 418 // Some handy addresses: |
414 Address G5_method_fie( G5_method, in_bytes(methodOopDesc::from_interpreted_offset())); | 419 Address G5_method_fie( G5_method, in_bytes(methodOopDesc::from_interpreted_offset())); |
437 | 442 |
438 switch ((int) ek) { | 443 switch ((int) ek) { |
439 case _raise_exception: | 444 case _raise_exception: |
440 { | 445 { |
441 // Not a real MH entry, but rather shared code for raising an | 446 // Not a real MH entry, but rather shared code for raising an |
442 // exception. Extra local arguments are passed in scratch | 447 // exception. Since we use a C2I adapter to set up the |
443 // registers, as required type in O3, failing object (or NULL) | 448 // interpreter state, arguments are expected in compiler |
444 // in O2, failing bytecode type in O1. | 449 // argument registers. |
450 methodHandle mh(raise_exception_method()); | |
451 address c2i_entry = methodOopDesc::make_adapters(mh, CATCH); | |
445 | 452 |
446 __ mov(O5_savedSP, SP); // Cut the stack back to where the caller started. | 453 __ mov(O5_savedSP, SP); // Cut the stack back to where the caller started. |
447 | 454 |
448 // Push arguments as if coming from the interpreter. | 455 Label L_no_method; |
449 Register O0_scratch = O0_argslot; | |
450 int stackElementSize = Interpreter::stackElementSize; | |
451 | |
452 // Make space on the stack for the arguments and set Gargs | |
453 // correctly. | |
454 __ sub(SP, 4*stackElementSize, SP); // Keep stack aligned. | |
455 __ add(SP, (frame::varargs_offset)*wordSize - 1*Interpreter::stackElementSize + STACK_BIAS + BytesPerWord, Gargs); | |
456 | |
457 // void raiseException(int code, Object actual, Object required) | |
458 __ st( O1_scratch, Address(Gargs, 2*stackElementSize)); // code | |
459 __ st_ptr(O2_scratch, Address(Gargs, 1*stackElementSize)); // actual | |
460 __ st_ptr(O3_scratch, Address(Gargs, 0*stackElementSize)); // required | |
461 | |
462 Label no_method; | |
463 // FIXME: fill in _raise_exception_method with a suitable sun.dyn method | 456 // FIXME: fill in _raise_exception_method with a suitable sun.dyn method |
464 __ set(AddressLiteral((address) &_raise_exception_method), G5_method); | 457 __ set(AddressLiteral((address) &_raise_exception_method), G5_method); |
465 __ ld_ptr(Address(G5_method, 0), G5_method); | 458 __ ld_ptr(Address(G5_method, 0), G5_method); |
466 __ tst(G5_method); | 459 __ tst(G5_method); |
467 __ brx(Assembler::zero, false, Assembler::pn, no_method); | 460 __ brx(Assembler::zero, false, Assembler::pn, L_no_method); |
468 __ delayed()->nop(); | 461 __ delayed()->nop(); |
469 | 462 |
470 int jobject_oop_offset = 0; | 463 const int jobject_oop_offset = 0; |
471 __ ld_ptr(Address(G5_method, jobject_oop_offset), G5_method); | 464 __ ld_ptr(Address(G5_method, jobject_oop_offset), G5_method); |
472 __ tst(G5_method); | 465 __ tst(G5_method); |
473 __ brx(Assembler::zero, false, Assembler::pn, no_method); | 466 __ brx(Assembler::zero, false, Assembler::pn, L_no_method); |
474 __ delayed()->nop(); | 467 __ delayed()->nop(); |
475 | 468 |
476 __ verify_oop(G5_method); | 469 __ verify_oop(G5_method); |
477 __ jump_indirect_to(G5_method_fie, O1_scratch); | 470 __ jump_to(AddressLiteral(c2i_entry), O3_scratch); |
478 __ delayed()->nop(); | 471 __ delayed()->nop(); |
479 | 472 |
480 // If we get here, the Java runtime did not do its job of creating the exception. | 473 // If we get here, the Java runtime did not do its job of creating the exception. |
481 // Do something that is at least causes a valid throw from the interpreter. | 474 // Do something that is at least causes a valid throw from the interpreter. |
482 __ bind(no_method); | 475 __ bind(L_no_method); |
483 __ unimplemented("_raise_exception no method"); | 476 __ unimplemented("call throw_WrongMethodType_entry"); |
484 } | 477 } |
485 break; | 478 break; |
486 | 479 |
487 case _invokestatic_mh: | 480 case _invokestatic_mh: |
488 case _invokespecial_mh: | 481 case _invokespecial_mh: |
568 | 561 |
569 __ bind(no_such_interface); | 562 __ bind(no_such_interface); |
570 // Throw an exception. | 563 // Throw an exception. |
571 // For historical reasons, it will be IncompatibleClassChangeError. | 564 // For historical reasons, it will be IncompatibleClassChangeError. |
572 __ unimplemented("not tested yet"); | 565 __ unimplemented("not tested yet"); |
573 __ ld_ptr(Address(O1_intf, java_mirror_offset), O3_scratch); // required interface | 566 __ ld_ptr(Address(O1_intf, java_mirror_offset), O2_required); // required interface |
574 __ mov(O0_klass, O2_scratch); // bad receiver | 567 __ mov( O0_klass, O1_actual); // bad receiver |
575 __ jump_to(AddressLiteral(from_interpreted_entry(_raise_exception)), O0_argslot); | 568 __ jump_to(AddressLiteral(from_interpreted_entry(_raise_exception)), O3_scratch); |
576 __ delayed()->mov(Bytecodes::_invokeinterface, O1_scratch); // who is complaining? | 569 __ delayed()->mov(Bytecodes::_invokeinterface, O0_code); // who is complaining? |
577 } | 570 } |
578 break; | 571 break; |
579 | 572 |
580 case _bound_ref_mh: | 573 case _bound_ref_mh: |
581 case _bound_int_mh: | 574 case _bound_int_mh: |
661 // - O1_scratch : argument klass to test | 654 // - O1_scratch : argument klass to test |
662 // - G3_method_handle: adapter method handle | 655 // - G3_method_handle: adapter method handle |
663 __ check_klass_subtype(O1_scratch, G5_klass, O0_argslot, O2_scratch, done); | 656 __ check_klass_subtype(O1_scratch, G5_klass, O0_argslot, O2_scratch, done); |
664 | 657 |
665 // If we get here, the type check failed! | 658 // If we get here, the type check failed! |
666 __ ldsw(G3_amh_vmargslot, O0_argslot); // reload argslot field | 659 __ load_heap_oop(G3_amh_argument, O2_required); // required class |
667 __ load_heap_oop(G3_amh_argument, O3_scratch); // required class | 660 __ ld_ptr( vmarg, O1_actual); // bad object |
668 __ ld_ptr(vmarg, O2_scratch); // bad object | 661 __ jump_to(AddressLiteral(from_interpreted_entry(_raise_exception)), O3_scratch); |
669 __ jump_to(AddressLiteral(from_interpreted_entry(_raise_exception)), O0_argslot); | 662 __ delayed()->mov(Bytecodes::_checkcast, O0_code); // who is complaining? |
670 __ delayed()->mov(Bytecodes::_checkcast, O1_scratch); // who is complaining? | |
671 | 663 |
672 __ bind(done); | 664 __ bind(done); |
673 // Get the new MH: | 665 // Get the new MH: |
674 __ load_heap_oop(G3_mh_vmtarget, G3_method_handle); | 666 __ load_heap_oop(G3_mh_vmtarget, G3_method_handle); |
675 __ jump_to_method_handle_entry(G3_method_handle, O1_scratch); | 667 __ jump_to_method_handle_entry(G3_method_handle, O1_scratch); |