Mercurial > hg > truffle
comparison src/cpu/x86/vm/templateTable_x86_64.cpp @ 628:7bb995fbd3c0
Merge
author | trims |
---|---|
date | Thu, 12 Mar 2009 18:16:36 -0700 |
parents | 9adddb8c0fc8 |
children | be93aad57795 |
comparison
equal
deleted
inserted
replaced
580:ce2272390558 | 628:7bb995fbd3c0 |
---|---|
305 __ load_signed_byte(rax, at_bcp(1)); | 305 __ load_signed_byte(rax, at_bcp(1)); |
306 } | 306 } |
307 | 307 |
308 void TemplateTable::sipush() { | 308 void TemplateTable::sipush() { |
309 transition(vtos, itos); | 309 transition(vtos, itos); |
310 __ load_unsigned_word(rax, at_bcp(1)); | 310 __ load_unsigned_short(rax, at_bcp(1)); |
311 __ bswapl(rax); | 311 __ bswapl(rax); |
312 __ sarl(rax, 16); | 312 __ sarl(rax, 16); |
313 } | 313 } |
314 | 314 |
315 void TemplateTable::ldc(bool wide) { | 315 void TemplateTable::ldc(bool wide) { |
643 transition(itos, itos); | 643 transition(itos, itos); |
644 __ pop_ptr(rdx); | 644 __ pop_ptr(rdx); |
645 // eax: index | 645 // eax: index |
646 // rdx: array | 646 // rdx: array |
647 index_check(rdx, rax); // kills rbx | 647 index_check(rdx, rax); // kills rbx |
648 __ load_unsigned_word(rax, | 648 __ load_unsigned_short(rax, |
649 Address(rdx, rax, | 649 Address(rdx, rax, |
650 Address::times_2, | 650 Address::times_2, |
651 arrayOopDesc::base_offset_in_bytes(T_CHAR))); | 651 arrayOopDesc::base_offset_in_bytes(T_CHAR))); |
652 } | 652 } |
653 | 653 |
654 // iload followed by caload frequent pair | 654 // iload followed by caload frequent pair |
655 void TemplateTable::fast_icaload() { | 655 void TemplateTable::fast_icaload() { |
656 transition(vtos, itos); | 656 transition(vtos, itos); |
661 | 661 |
662 // eax: index | 662 // eax: index |
663 // rdx: array | 663 // rdx: array |
664 __ pop_ptr(rdx); | 664 __ pop_ptr(rdx); |
665 index_check(rdx, rax); // kills rbx | 665 index_check(rdx, rax); // kills rbx |
666 __ load_unsigned_word(rax, | 666 __ load_unsigned_short(rax, |
667 Address(rdx, rax, | 667 Address(rdx, rax, |
668 Address::times_2, | 668 Address::times_2, |
669 arrayOopDesc::base_offset_in_bytes(T_CHAR))); | 669 arrayOopDesc::base_offset_in_bytes(T_CHAR))); |
670 } | 670 } |
671 | 671 |
672 void TemplateTable::saload() { | 672 void TemplateTable::saload() { |
673 transition(itos, itos); | 673 transition(itos, itos); |
674 __ pop_ptr(rdx); | 674 __ pop_ptr(rdx); |
675 // eax: index | 675 // eax: index |
676 // rdx: array | 676 // rdx: array |
677 index_check(rdx, rax); // kills rbx | 677 index_check(rdx, rax); // kills rbx |
678 __ load_signed_word(rax, | 678 __ load_signed_short(rax, |
679 Address(rdx, rax, | 679 Address(rdx, rax, |
680 Address::times_2, | 680 Address::times_2, |
681 arrayOopDesc::base_offset_in_bytes(T_SHORT))); | 681 arrayOopDesc::base_offset_in_bytes(T_SHORT))); |
682 } | 682 } |
683 | 683 |
684 void TemplateTable::iload(int n) { | 684 void TemplateTable::iload(int n) { |
685 transition(vtos, itos); | 685 transition(vtos, itos); |
686 __ movl(rax, iaddress(n)); | 686 __ movl(rax, iaddress(n)); |
1557 } | 1557 } |
1558 __ movl2ptr(rdx, rdx); | 1558 __ movl2ptr(rdx, rdx); |
1559 | 1559 |
1560 // Handle all the JSR stuff here, then exit. | 1560 // Handle all the JSR stuff here, then exit. |
1561 // It's much shorter and cleaner than intermingling with the non-JSR | 1561 // It's much shorter and cleaner than intermingling with the non-JSR |
1562 // normal-branch stuff occuring below. | 1562 // normal-branch stuff occurring below. |
1563 if (is_jsr) { | 1563 if (is_jsr) { |
1564 // Pre-load the next target bytecode into rbx | 1564 // Pre-load the next target bytecode into rbx |
1565 __ load_unsigned_byte(rbx, Address(r13, rdx, Address::times_1, 0)); | 1565 __ load_unsigned_byte(rbx, Address(r13, rdx, Address::times_1, 0)); |
1566 | 1566 |
1567 // compute return address as bci in rax | 1567 // compute return address as bci in rax |
2274 | 2274 |
2275 __ bind(notInt); | 2275 __ bind(notInt); |
2276 __ cmpl(flags, ctos); | 2276 __ cmpl(flags, ctos); |
2277 __ jcc(Assembler::notEqual, notChar); | 2277 __ jcc(Assembler::notEqual, notChar); |
2278 // ctos | 2278 // ctos |
2279 __ load_unsigned_word(rax, field); | 2279 __ load_unsigned_short(rax, field); |
2280 __ push(ctos); | 2280 __ push(ctos); |
2281 // Rewrite bytecode to be faster | 2281 // Rewrite bytecode to be faster |
2282 if (!is_static) { | 2282 if (!is_static) { |
2283 patch_bytecode(Bytecodes::_fast_cgetfield, bc, rbx); | 2283 patch_bytecode(Bytecodes::_fast_cgetfield, bc, rbx); |
2284 } | 2284 } |
2286 | 2286 |
2287 __ bind(notChar); | 2287 __ bind(notChar); |
2288 __ cmpl(flags, stos); | 2288 __ cmpl(flags, stos); |
2289 __ jcc(Assembler::notEqual, notShort); | 2289 __ jcc(Assembler::notEqual, notShort); |
2290 // stos | 2290 // stos |
2291 __ load_signed_word(rax, field); | 2291 __ load_signed_short(rax, field); |
2292 __ push(stos); | 2292 __ push(stos); |
2293 // Rewrite bytecode to be faster | 2293 // Rewrite bytecode to be faster |
2294 if (!is_static) { | 2294 if (!is_static) { |
2295 patch_bytecode(Bytecodes::_fast_sgetfield, bc, rbx); | 2295 patch_bytecode(Bytecodes::_fast_sgetfield, bc, rbx); |
2296 } | 2296 } |
2749 break; | 2749 break; |
2750 case Bytecodes::_fast_bgetfield: | 2750 case Bytecodes::_fast_bgetfield: |
2751 __ movsbl(rax, field); | 2751 __ movsbl(rax, field); |
2752 break; | 2752 break; |
2753 case Bytecodes::_fast_sgetfield: | 2753 case Bytecodes::_fast_sgetfield: |
2754 __ load_signed_word(rax, field); | 2754 __ load_signed_short(rax, field); |
2755 break; | 2755 break; |
2756 case Bytecodes::_fast_cgetfield: | 2756 case Bytecodes::_fast_cgetfield: |
2757 __ load_unsigned_word(rax, field); | 2757 __ load_unsigned_short(rax, field); |
2758 break; | 2758 break; |
2759 case Bytecodes::_fast_fgetfield: | 2759 case Bytecodes::_fast_fgetfield: |
2760 __ movflt(xmm0, field); | 2760 __ movflt(xmm0, field); |
2761 break; | 2761 break; |
2762 case Bytecodes::_fast_dgetfield: | 2762 case Bytecodes::_fast_dgetfield: |
3008 __ verify_oop(rdx); | 3008 __ verify_oop(rdx); |
3009 | 3009 |
3010 // profile this call | 3010 // profile this call |
3011 __ profile_virtual_call(rdx, r13, r14); | 3011 __ profile_virtual_call(rdx, r13, r14); |
3012 | 3012 |
3013 __ mov(r14, rdx); // Save klassOop in r14 | 3013 Label no_such_interface, no_such_method; |
3014 | 3014 |
3015 // Compute start of first itableOffsetEntry (which is at the end of | 3015 __ lookup_interface_method(// inputs: rec. class, interface, itable index |
3016 // the vtable) | 3016 rdx, rax, rbx, |
3017 const int base = instanceKlass::vtable_start_offset() * wordSize; | 3017 // outputs: method, scan temp. reg |
3018 // Get length of vtable | 3018 rbx, r13, |
3019 assert(vtableEntry::size() * wordSize == 8, | 3019 no_such_interface); |
3020 "adjust the scaling in the code below"); | 3020 |
3021 __ movl(r13, Address(rdx, | 3021 // rbx,: methodOop to call |
3022 instanceKlass::vtable_length_offset() * wordSize)); | 3022 // rcx: receiver |
3023 __ lea(rdx, Address(rdx, r13, Address::times_8, base)); | 3023 // Check for abstract method error |
3024 | 3024 // Note: This should be done more efficiently via a throw_abstract_method_error |
3025 if (HeapWordsPerLong > 1) { | 3025 // interpreter entry point and a conditional jump to it in case of a null |
3026 // Round up to align_object_offset boundary | 3026 // method. |
3027 __ round_to(rdx, BytesPerLong); | 3027 __ testptr(rbx, rbx); |
3028 } | 3028 __ jcc(Assembler::zero, no_such_method); |
3029 | 3029 |
3030 Label entry, search, interface_ok; | 3030 // do the call |
3031 | 3031 // rcx: receiver |
3032 __ jmpb(entry); | 3032 // rbx,: methodOop |
3033 __ bind(search); | 3033 __ jump_from_interpreted(rbx, rdx); |
3034 __ addptr(rdx, itableOffsetEntry::size() * wordSize); | 3034 __ should_not_reach_here(); |
3035 | 3035 |
3036 __ bind(entry); | 3036 // exception handling code follows... |
3037 | 3037 // note: must restore interpreter registers to canonical |
3038 // Check that the entry is non-null. A null entry means that the | 3038 // state for exception handling to work correctly! |
3039 // receiver class doesn't implement the interface, and wasn't the | 3039 |
3040 // same as the receiver class checked when the interface was | 3040 __ bind(no_such_method); |
3041 // resolved. | |
3042 __ push(rdx); | |
3043 __ movptr(rdx, Address(rdx, itableOffsetEntry::interface_offset_in_bytes())); | |
3044 __ testptr(rdx, rdx); | |
3045 __ jcc(Assembler::notZero, interface_ok); | |
3046 // throw exception | 3041 // throw exception |
3047 __ pop(rdx); // pop saved register first. | 3042 __ pop(rbx); // pop return address (pushed by prepare_invoke) |
3048 __ pop(rbx); // pop return address (pushed by prepare_invoke) | 3043 __ restore_bcp(); // r13 must be correct for exception handler (was destroyed) |
3049 __ restore_bcp(); // r13 must be correct for exception handler (was | 3044 __ restore_locals(); // make sure locals pointer is correct as well (was destroyed) |
3050 // destroyed) | 3045 __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_AbstractMethodError)); |
3051 __ restore_locals(); // make sure locals pointer is correct as well | 3046 // the call_VM checks for exception, so we should never return here. |
3052 // (was destroyed) | 3047 __ should_not_reach_here(); |
3048 | |
3049 __ bind(no_such_interface); | |
3050 // throw exception | |
3051 __ pop(rbx); // pop return address (pushed by prepare_invoke) | |
3052 __ restore_bcp(); // r13 must be correct for exception handler (was destroyed) | |
3053 __ restore_locals(); // make sure locals pointer is correct as well (was destroyed) | |
3053 __ call_VM(noreg, CAST_FROM_FN_PTR(address, | 3054 __ call_VM(noreg, CAST_FROM_FN_PTR(address, |
3054 InterpreterRuntime::throw_IncompatibleClassChangeError)); | 3055 InterpreterRuntime::throw_IncompatibleClassChangeError)); |
3055 // the call_VM checks for exception, so we should never return here. | 3056 // the call_VM checks for exception, so we should never return here. |
3056 __ should_not_reach_here(); | 3057 __ should_not_reach_here(); |
3057 __ bind(interface_ok); | 3058 return; |
3058 | 3059 } |
3059 __ pop(rdx); | 3060 |
3060 | |
3061 __ cmpptr(rax, Address(rdx, itableOffsetEntry::interface_offset_in_bytes())); | |
3062 __ jcc(Assembler::notEqual, search); | |
3063 | |
3064 __ movl(rdx, Address(rdx, itableOffsetEntry::offset_offset_in_bytes())); | |
3065 | |
3066 __ addptr(rdx, r14); // Add offset to klassOop | |
3067 assert(itableMethodEntry::size() * wordSize == 8, | |
3068 "adjust the scaling in the code below"); | |
3069 __ movptr(rbx, Address(rdx, rbx, Address::times_8)); | |
3070 // rbx: methodOop to call | |
3071 // rcx: receiver | |
3072 // Check for abstract method error | |
3073 // Note: This should be done more efficiently via a | |
3074 // throw_abstract_method_error interpreter entry point and a | |
3075 // conditional jump to it in case of a null method. | |
3076 { | |
3077 Label L; | |
3078 __ testptr(rbx, rbx); | |
3079 __ jcc(Assembler::notZero, L); | |
3080 // throw exception | |
3081 // note: must restore interpreter registers to canonical | |
3082 // state for exception handling to work correctly! | |
3083 __ pop(rbx); // pop return address (pushed by prepare_invoke) | |
3084 __ restore_bcp(); // r13 must be correct for exception handler | |
3085 // (was destroyed) | |
3086 __ restore_locals(); // make sure locals pointer is correct as | |
3087 // well (was destroyed) | |
3088 __ call_VM(noreg, | |
3089 CAST_FROM_FN_PTR(address, | |
3090 InterpreterRuntime::throw_AbstractMethodError)); | |
3091 // the call_VM checks for exception, so we should never return here. | |
3092 __ should_not_reach_here(); | |
3093 __ bind(L); | |
3094 } | |
3095 | |
3096 __ movptr(rcx, Address(rbx, methodOopDesc::interpreter_entry_offset())); | |
3097 | |
3098 // do the call | |
3099 // rcx: receiver | |
3100 // rbx: methodOop | |
3101 __ jump_from_interpreted(rbx, rdx); | |
3102 } | |
3103 | 3061 |
3104 //----------------------------------------------------------------------------- | 3062 //----------------------------------------------------------------------------- |
3105 // Allocation | 3063 // Allocation |
3106 | 3064 |
3107 void TemplateTable::_new() { | 3065 void TemplateTable::_new() { |