Mercurial > hg > truffle
comparison src/cpu/x86/vm/templateTable_x86_32.cpp @ 625:2f2f54ed12ce
Merge
author | kvn |
---|---|
date | Tue, 10 Mar 2009 08:52:16 -0700 |
parents | 9adddb8c0fc8 |
children | 7bb995fbd3c0 |
comparison
equal
deleted
inserted
replaced
620:bcedf688d882 | 625:2f2f54ed12ce |
---|---|
294 } | 294 } |
295 | 295 |
296 | 296 |
297 void TemplateTable::sipush() { | 297 void TemplateTable::sipush() { |
298 transition(vtos, itos); | 298 transition(vtos, itos); |
299 __ load_unsigned_word(rax, at_bcp(1)); | 299 __ load_unsigned_short(rax, at_bcp(1)); |
300 __ bswapl(rax); | 300 __ bswapl(rax); |
301 __ sarl(rax, 16); | 301 __ sarl(rax, 16); |
302 } | 302 } |
303 | 303 |
304 void TemplateTable::ldc(bool wide) { | 304 void TemplateTable::ldc(bool wide) { |
660 transition(itos, itos); | 660 transition(itos, itos); |
661 // rdx: array | 661 // rdx: array |
662 index_check(rdx, rax); // kills rbx, | 662 index_check(rdx, rax); // kills rbx, |
663 // rax,: index | 663 // rax,: index |
664 // can do better code for P5 - may want to improve this at some point | 664 // can do better code for P5 - may want to improve this at some point |
665 __ load_unsigned_word(rbx, Address(rdx, rax, Address::times_2, arrayOopDesc::base_offset_in_bytes(T_CHAR))); | 665 __ load_unsigned_short(rbx, Address(rdx, rax, Address::times_2, arrayOopDesc::base_offset_in_bytes(T_CHAR))); |
666 __ mov(rax, rbx); | 666 __ mov(rax, rbx); |
667 } | 667 } |
668 | 668 |
669 // iload followed by caload frequent pair | 669 // iload followed by caload frequent pair |
670 void TemplateTable::fast_icaload() { | 670 void TemplateTable::fast_icaload() { |
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) { |
2308 __ bind(notObj); | 2308 __ bind(notObj); |
2309 // ctos | 2309 // ctos |
2310 __ cmpl(flags, ctos ); | 2310 __ cmpl(flags, ctos ); |
2311 __ jcc(Assembler::notEqual, notChar); | 2311 __ jcc(Assembler::notEqual, notChar); |
2312 | 2312 |
2313 __ load_unsigned_word(rax, lo ); | 2313 __ load_unsigned_short(rax, lo ); |
2314 __ push(ctos); | 2314 __ push(ctos); |
2315 if (!is_static) { | 2315 if (!is_static) { |
2316 patch_bytecode(Bytecodes::_fast_cgetfield, rcx, rbx); | 2316 patch_bytecode(Bytecodes::_fast_cgetfield, rcx, rbx); |
2317 } | 2317 } |
2318 __ jmp(Done); | 2318 __ jmp(Done); |
2320 __ bind(notChar); | 2320 __ bind(notChar); |
2321 // stos | 2321 // stos |
2322 __ cmpl(flags, stos ); | 2322 __ cmpl(flags, stos ); |
2323 __ jcc(Assembler::notEqual, notShort); | 2323 __ jcc(Assembler::notEqual, notShort); |
2324 | 2324 |
2325 __ load_signed_word(rax, lo ); | 2325 __ load_signed_short(rax, lo ); |
2326 __ push(stos); | 2326 __ push(stos); |
2327 if (!is_static) { | 2327 if (!is_static) { |
2328 patch_bytecode(Bytecodes::_fast_sgetfield, rcx, rbx); | 2328 patch_bytecode(Bytecodes::_fast_sgetfield, rcx, rbx); |
2329 } | 2329 } |
2330 __ jmp(Done); | 2330 __ jmp(Done); |
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 |