Mercurial > hg > truffle
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 |