comparison src/cpu/x86/vm/templateTable_x86_32.cpp @ 623:9adddb8c0fc8

6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638) Summary: Code in vtableStubs and templateTable moved into MacroAssembler. Reviewed-by: kvn
author jrose
date Fri, 06 Mar 2009 21:36:50 -0800
parents 56aae7be60d4
children 7bb995fbd3c0
comparison
equal deleted inserted replaced
622:56aae7be60d4 623:9adddb8c0fc8
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