comparison src/cpu/x86/vm/templateTable_x86_32.cpp @ 628:7bb995fbd3c0

Merge
author trims
date Thu, 12 Mar 2009 18:16:36 -0700
parents 0fbdb4381b99 9adddb8c0fc8
children be93aad57795
comparison
equal deleted inserted replaced
580:ce2272390558 628:7bb995fbd3c0
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) {
1584 LP64_ONLY(__ movslq(rdx, rdx)); 1584 LP64_ONLY(__ movslq(rdx, rdx));
1585 1585
1586 1586
1587 // Handle all the JSR stuff here, then exit. 1587 // Handle all the JSR stuff here, then exit.
1588 // It's much shorter and cleaner than intermingling with the 1588 // It's much shorter and cleaner than intermingling with the
1589 // non-JSR normal-branch stuff occuring below. 1589 // non-JSR normal-branch stuff occurring below.
1590 if (is_jsr) { 1590 if (is_jsr) {
1591 // Pre-load the next target bytecode into EBX 1591 // Pre-load the next target bytecode into EBX
1592 __ load_unsigned_byte(rbx, Address(rsi, rdx, Address::times_1, 0)); 1592 __ load_unsigned_byte(rbx, Address(rsi, rdx, Address::times_1, 0));
1593 1593
1594 // compute return address as bci in rax, 1594 // compute return address as bci in rax,
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