675 debug_only(__ verify_local_tag(frame::TagValue, rbx)); |
675 debug_only(__ verify_local_tag(frame::TagValue, rbx)); |
676 |
676 |
677 // rdx: array |
677 // rdx: array |
678 index_check(rdx, rax); |
678 index_check(rdx, rax); |
679 // rax,: index |
679 // rax,: index |
680 __ load_unsigned_word(rbx, Address(rdx, rax, Address::times_2, arrayOopDesc::base_offset_in_bytes(T_CHAR))); |
680 __ load_unsigned_short(rbx, Address(rdx, rax, Address::times_2, arrayOopDesc::base_offset_in_bytes(T_CHAR))); |
681 __ mov(rax, rbx); |
681 __ mov(rax, rbx); |
682 } |
682 } |
683 |
683 |
684 void TemplateTable::saload() { |
684 void TemplateTable::saload() { |
685 transition(itos, itos); |
685 transition(itos, itos); |
686 // rdx: array |
686 // rdx: array |
687 index_check(rdx, rax); // kills rbx, |
687 index_check(rdx, rax); // kills rbx, |
688 // rax,: index |
688 // rax,: index |
689 // can do better code for P5 - may want to improve this at some point |
689 // can do better code for P5 - may want to improve this at some point |
690 __ load_signed_word(rbx, Address(rdx, rax, Address::times_2, arrayOopDesc::base_offset_in_bytes(T_SHORT))); |
690 __ load_signed_short(rbx, Address(rdx, rax, Address::times_2, arrayOopDesc::base_offset_in_bytes(T_SHORT))); |
691 __ mov(rax, rbx); |
691 __ mov(rax, rbx); |
692 } |
692 } |
693 |
693 |
694 |
694 |
695 void TemplateTable::iload(int n) { |
695 void TemplateTable::iload(int n) { |
2828 const Address hi = Address(rax, rbx, Address::times_1, 1*wordSize); |
2828 const Address hi = Address(rax, rbx, Address::times_1, 1*wordSize); |
2829 |
2829 |
2830 // access field |
2830 // access field |
2831 switch (bytecode()) { |
2831 switch (bytecode()) { |
2832 case Bytecodes::_fast_bgetfield: __ movsbl(rax, lo ); break; |
2832 case Bytecodes::_fast_bgetfield: __ movsbl(rax, lo ); break; |
2833 case Bytecodes::_fast_sgetfield: __ load_signed_word(rax, lo ); break; |
2833 case Bytecodes::_fast_sgetfield: __ load_signed_short(rax, lo ); break; |
2834 case Bytecodes::_fast_cgetfield: __ load_unsigned_word(rax, lo ); break; |
2834 case Bytecodes::_fast_cgetfield: __ load_unsigned_short(rax, lo ); break; |
2835 case Bytecodes::_fast_igetfield: __ movl(rax, lo); break; |
2835 case Bytecodes::_fast_igetfield: __ movl(rax, lo); break; |
2836 case Bytecodes::_fast_lgetfield: __ stop("should not be rewritten"); break; |
2836 case Bytecodes::_fast_lgetfield: __ stop("should not be rewritten"); break; |
2837 case Bytecodes::_fast_fgetfield: __ fld_s(lo); break; |
2837 case Bytecodes::_fast_fgetfield: __ fld_s(lo); break; |
2838 case Bytecodes::_fast_dgetfield: __ fld_d(lo); break; |
2838 case Bytecodes::_fast_dgetfield: __ fld_d(lo); break; |
2839 case Bytecodes::_fast_agetfield: __ movptr(rax, lo); __ verify_oop(rax); break; |
2839 case Bytecodes::_fast_agetfield: __ movptr(rax, lo); __ verify_oop(rax); break; |
3053 __ verify_oop(rdx); |
3053 __ verify_oop(rdx); |
3054 |
3054 |
3055 // profile this call |
3055 // profile this call |
3056 __ profile_virtual_call(rdx, rsi, rdi); |
3056 __ profile_virtual_call(rdx, rsi, rdi); |
3057 |
3057 |
3058 __ mov(rdi, rdx); // Save klassOop in rdi |
3058 Label no_such_interface, no_such_method; |
3059 |
3059 |
3060 // Compute start of first itableOffsetEntry (which is at the end of the vtable) |
3060 __ lookup_interface_method(// inputs: rec. class, interface, itable index |
3061 const int base = instanceKlass::vtable_start_offset() * wordSize; |
3061 rdx, rax, rbx, |
3062 assert(vtableEntry::size() * wordSize == (1 << (int)Address::times_ptr), "adjust the scaling in the code below"); |
3062 // outputs: method, scan temp. reg |
3063 __ movl(rsi, Address(rdx, instanceKlass::vtable_length_offset() * wordSize)); // Get length of vtable |
3063 rbx, rsi, |
3064 __ lea(rdx, Address(rdx, rsi, Address::times_4, base)); |
3064 no_such_interface); |
3065 if (HeapWordsPerLong > 1) { |
3065 |
3066 // Round up to align_object_offset boundary |
3066 // rbx,: methodOop to call |
3067 __ round_to(rdx, BytesPerLong); |
3067 // rcx: receiver |
3068 } |
3068 // Check for abstract method error |
3069 |
3069 // Note: This should be done more efficiently via a throw_abstract_method_error |
3070 Label entry, search, interface_ok; |
3070 // interpreter entry point and a conditional jump to it in case of a null |
3071 |
3071 // method. |
3072 __ jmpb(entry); |
3072 __ testptr(rbx, rbx); |
3073 __ bind(search); |
3073 __ jcc(Assembler::zero, no_such_method); |
3074 __ addptr(rdx, itableOffsetEntry::size() * wordSize); |
3074 |
3075 |
3075 // do the call |
3076 __ bind(entry); |
3076 // rcx: receiver |
3077 |
3077 // rbx,: methodOop |
3078 // Check that the entry is non-null. A null entry means that the receiver |
3078 __ jump_from_interpreted(rbx, rdx); |
3079 // class doesn't implement the interface, and wasn't the same as the |
3079 __ should_not_reach_here(); |
3080 // receiver class checked when the interface was resolved. |
3080 |
3081 __ push(rdx); |
3081 // exception handling code follows... |
3082 __ movptr(rdx, Address(rdx, itableOffsetEntry::interface_offset_in_bytes())); |
3082 // note: must restore interpreter registers to canonical |
3083 __ testptr(rdx, rdx); |
3083 // state for exception handling to work correctly! |
3084 __ jcc(Assembler::notZero, interface_ok); |
3084 |
|
3085 __ bind(no_such_method); |
3085 // throw exception |
3086 // throw exception |
3086 __ pop(rdx); // pop saved register first. |
3087 __ pop(rbx); // pop return address (pushed by prepare_invoke) |
|
3088 __ restore_bcp(); // rsi must be correct for exception handler (was destroyed) |
|
3089 __ restore_locals(); // make sure locals pointer is correct as well (was destroyed) |
|
3090 __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_AbstractMethodError)); |
|
3091 // the call_VM checks for exception, so we should never return here. |
|
3092 __ should_not_reach_here(); |
|
3093 |
|
3094 __ bind(no_such_interface); |
|
3095 // throw exception |
3087 __ pop(rbx); // pop return address (pushed by prepare_invoke) |
3096 __ pop(rbx); // pop return address (pushed by prepare_invoke) |
3088 __ restore_bcp(); // rsi must be correct for exception handler (was destroyed) |
3097 __ restore_bcp(); // rsi must be correct for exception handler (was destroyed) |
3089 __ restore_locals(); // make sure locals pointer is correct as well (was destroyed) |
3098 __ restore_locals(); // make sure locals pointer is correct as well (was destroyed) |
3090 __ call_VM(noreg, CAST_FROM_FN_PTR(address, |
3099 __ call_VM(noreg, CAST_FROM_FN_PTR(address, |
3091 InterpreterRuntime::throw_IncompatibleClassChangeError)); |
3100 InterpreterRuntime::throw_IncompatibleClassChangeError)); |
3092 // the call_VM checks for exception, so we should never return here. |
3101 // the call_VM checks for exception, so we should never return here. |
3093 __ should_not_reach_here(); |
3102 __ should_not_reach_here(); |
3094 __ bind(interface_ok); |
|
3095 |
|
3096 __ pop(rdx); |
|
3097 |
|
3098 __ cmpptr(rax, Address(rdx, itableOffsetEntry::interface_offset_in_bytes())); |
|
3099 __ jcc(Assembler::notEqual, search); |
|
3100 |
|
3101 __ movl(rdx, Address(rdx, itableOffsetEntry::offset_offset_in_bytes())); |
|
3102 __ addptr(rdx, rdi); // Add offset to klassOop |
|
3103 assert(itableMethodEntry::size() * wordSize == (1 << (int)Address::times_ptr), "adjust the scaling in the code below"); |
|
3104 __ movptr(rbx, Address(rdx, rbx, Address::times_ptr)); |
|
3105 // rbx,: methodOop to call |
|
3106 // rcx: receiver |
|
3107 // Check for abstract method error |
|
3108 // Note: This should be done more efficiently via a throw_abstract_method_error |
|
3109 // interpreter entry point and a conditional jump to it in case of a null |
|
3110 // method. |
|
3111 { Label L; |
|
3112 __ testptr(rbx, rbx); |
|
3113 __ jcc(Assembler::notZero, L); |
|
3114 // throw exception |
|
3115 // note: must restore interpreter registers to canonical |
|
3116 // state for exception handling to work correctly! |
|
3117 __ pop(rbx); // pop return address (pushed by prepare_invoke) |
|
3118 __ restore_bcp(); // rsi must be correct for exception handler (was destroyed) |
|
3119 __ restore_locals(); // make sure locals pointer is correct as well (was destroyed) |
|
3120 __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_AbstractMethodError)); |
|
3121 // the call_VM checks for exception, so we should never return here. |
|
3122 __ should_not_reach_here(); |
|
3123 __ bind(L); |
|
3124 } |
|
3125 |
|
3126 // do the call |
|
3127 // rcx: receiver |
|
3128 // rbx,: methodOop |
|
3129 __ jump_from_interpreted(rbx, rdx); |
|
3130 } |
3103 } |
3131 |
3104 |
3132 //---------------------------------------------------------------------------------------------------- |
3105 //---------------------------------------------------------------------------------------------------- |
3133 // Allocation |
3106 // Allocation |
3134 |
3107 |