comparison src/cpu/sparc/vm/vtableStubs_sparc.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 d1605aabd0a1
children 660978a2a31a
comparison
equal deleted inserted replaced
622:56aae7be60d4 623:9adddb8c0fc8
104 __ JMP(G3_scratch, 0); 104 __ JMP(G3_scratch, 0);
105 // load methodOop (in case we call c2iadapter) 105 // load methodOop (in case we call c2iadapter)
106 __ delayed()->nop(); 106 __ delayed()->nop();
107 107
108 masm->flush(); 108 masm->flush();
109
110 if (PrintMiscellaneous && (WizardMode || Verbose)) {
111 tty->print_cr("vtable #%d at "PTR_FORMAT"[%d] left over: %d",
112 vtable_index, s->entry_point(),
113 (int)(s->code_end() - s->entry_point()),
114 (int)(s->code_end() - __ pc()));
115 }
116 guarantee(__ pc() <= s->code_end(), "overflowed buffer");
117
109 s->set_exception_points(npe_addr, ame_addr); 118 s->set_exception_points(npe_addr, ame_addr);
110 return s; 119 return s;
111 } 120 }
112 121
113 122
114 // NOTE: %%%% if any change is made to this stub make sure that the function 123 // NOTE: %%%% if any change is made to this stub make sure that the function
115 // pd_code_size_limit is changed to ensure the correct size for VtableStub 124 // pd_code_size_limit is changed to ensure the correct size for VtableStub
116 VtableStub* VtableStubs::create_itable_stub(int vtable_index) { 125 VtableStub* VtableStubs::create_itable_stub(int itable_index) {
117 const int sparc_code_length = VtableStub::pd_code_size_limit(false); 126 const int sparc_code_length = VtableStub::pd_code_size_limit(false);
118 VtableStub* s = new(sparc_code_length) VtableStub(false, vtable_index); 127 VtableStub* s = new(sparc_code_length) VtableStub(false, itable_index);
119 ResourceMark rm; 128 ResourceMark rm;
120 CodeBuffer cb(s->entry_point(), sparc_code_length); 129 CodeBuffer cb(s->entry_point(), sparc_code_length);
121 MacroAssembler* masm = new MacroAssembler(&cb); 130 MacroAssembler* masm = new MacroAssembler(&cb);
122 131
123 Register G3_klassOop = G3_scratch; 132 Register G3_klassOop = G3_scratch;
137 // Push a new window to get some temp registers. This chops the head of all 146 // Push a new window to get some temp registers. This chops the head of all
138 // my 64-bit %o registers in the LION build, but this is OK because no longs 147 // my 64-bit %o registers in the LION build, but this is OK because no longs
139 // are passed in the %o registers. Instead, longs are passed in G1 and G4 148 // are passed in the %o registers. Instead, longs are passed in G1 and G4
140 // and so those registers are not available here. 149 // and so those registers are not available here.
141 __ save(SP,-frame::register_save_words*wordSize,SP); 150 __ save(SP,-frame::register_save_words*wordSize,SP);
142 Register I0_receiver = I0; // Location of receiver after save
143 151
144 #ifndef PRODUCT 152 #ifndef PRODUCT
145 if (CountCompiledCalls) { 153 if (CountCompiledCalls) {
146 Address ctr(L0, SharedRuntime::nof_megamorphic_calls_addr()); 154 Address ctr(L0, SharedRuntime::nof_megamorphic_calls_addr());
147 __ sethi(ctr); 155 __ sethi(ctr);
149 __ inc(L1); 157 __ inc(L1);
150 __ st(L1, ctr); 158 __ st(L1, ctr);
151 } 159 }
152 #endif /* PRODUCT */ 160 #endif /* PRODUCT */
153 161
154 // load start of itable entries into L0 register
155 const int base = instanceKlass::vtable_start_offset() * wordSize;
156 __ ld(Address(G3_klassOop, 0, instanceKlass::vtable_length_offset() * wordSize), L0);
157
158 // %%% Could store the aligned, prescaled offset in the klassoop.
159 __ sll(L0, exact_log2(vtableEntry::size() * wordSize), L0);
160 // see code for instanceKlass::start_of_itable!
161 const int vtable_alignment = align_object_offset(1);
162 assert(vtable_alignment == 1 || vtable_alignment == 2, "");
163 const int odd_bit = vtableEntry::size() * wordSize;
164 if (vtable_alignment == 2) {
165 __ and3(L0, odd_bit, L1); // isolate the odd bit
166 }
167 __ add(G3_klassOop, L0, L0);
168 if (vtable_alignment == 2) {
169 __ add(L0, L1, L0); // double the odd bit, to align up
170 }
171
172 // Loop over all itable entries until desired interfaceOop (G5_interface) found
173 __ bind(search);
174
175 // %%%% Could load both offset and interface in one ldx, if they were
176 // in the opposite order. This would save a load.
177 __ ld_ptr(L0, base + itableOffsetEntry::interface_offset_in_bytes(), L1);
178
179 // If the entry is NULL then we've reached the end of the table
180 // without finding the expected interface, so throw an exception
181 Label throw_icce; 162 Label throw_icce;
182 __ bpr(Assembler::rc_z, false, Assembler::pn, L1, throw_icce); 163
183 __ delayed()->cmp(G5_interface, L1); 164 Register L5_method = L5;
184 __ brx(Assembler::notEqual, true, Assembler::pn, search); 165 __ lookup_interface_method(// inputs: rec. class, interface, itable index
185 __ delayed()->add(L0, itableOffsetEntry::size() * wordSize, L0); 166 G3_klassOop, G5_interface, itable_index,
186 167 // outputs: method, scan temp. reg
187 // entry found and L0 points to it, move offset of vtable for interface into L0 168 L5_method, L2, L3,
188 __ ld(L0, base + itableOffsetEntry::offset_offset_in_bytes(), L0); 169 throw_icce);
189
190 // Compute itableMethodEntry and get methodOop(G5_method) and entrypoint(L0) for compiler
191 const int method_offset = (itableMethodEntry::size() * wordSize * vtable_index) + itableMethodEntry::method_offset_in_bytes();
192 __ add(G3_klassOop, L0, L1);
193 __ ld_ptr(L1, method_offset, G5_method);
194 170
195 #ifndef PRODUCT 171 #ifndef PRODUCT
196 if (DebugVtables) { 172 if (DebugVtables) {
197 Label L01; 173 Label L01;
198 __ ld_ptr(L1, method_offset, G5_method); 174 __ bpr(Assembler::rc_nz, false, Assembler::pt, L5_method, L01);
199 __ bpr(Assembler::rc_nz, false, Assembler::pt, G5_method, L01);
200 __ delayed()->nop(); 175 __ delayed()->nop();
201 __ stop("methodOop is null"); 176 __ stop("methodOop is null");
202 __ bind(L01); 177 __ bind(L01);
203 __ verify_oop(G5_method); 178 __ verify_oop(L5_method);
204 } 179 }
205 #endif 180 #endif
206 181
207 // If the following load is through a NULL pointer, we'll take an OS 182 // If the following load is through a NULL pointer, we'll take an OS
208 // exception that should translate into an AbstractMethodError. We need the 183 // exception that should translate into an AbstractMethodError. We need the
209 // window count to be correct at that time. 184 // window count to be correct at that time.
210 __ restore(); // Restore registers BEFORE the AME point 185 __ restore(L5_method, 0, G5_method);
186 // Restore registers *before* the AME point.
211 187
212 address ame_addr = __ pc(); // if the vtable entry is null, the method is abstract 188 address ame_addr = __ pc(); // if the vtable entry is null, the method is abstract
213 __ ld_ptr(G5_method, in_bytes(methodOopDesc::from_compiled_offset()), G3_scratch); 189 __ ld_ptr(G5_method, in_bytes(methodOopDesc::from_compiled_offset()), G3_scratch);
214 190
215 // G5_method: methodOop 191 // G5_method: methodOop
223 __ jump_to(icce, 0); 199 __ jump_to(icce, 0);
224 __ delayed()->restore(); 200 __ delayed()->restore();
225 201
226 masm->flush(); 202 masm->flush();
227 203
204 if (PrintMiscellaneous && (WizardMode || Verbose)) {
205 tty->print_cr("itable #%d at "PTR_FORMAT"[%d] left over: %d",
206 itable_index, s->entry_point(),
207 (int)(s->code_end() - s->entry_point()),
208 (int)(s->code_end() - __ pc()));
209 }
228 guarantee(__ pc() <= s->code_end(), "overflowed buffer"); 210 guarantee(__ pc() <= s->code_end(), "overflowed buffer");
229 211
230 s->set_exception_points(npe_addr, ame_addr); 212 s->set_exception_points(npe_addr, ame_addr);
231 return s; 213 return s;
232 } 214 }
241 const int basic = 5*BytesPerInstWord + 223 const int basic = 5*BytesPerInstWord +
242 // shift;add for load_klass 224 // shift;add for load_klass
243 (UseCompressedOops ? 2*BytesPerInstWord : 0); 225 (UseCompressedOops ? 2*BytesPerInstWord : 0);
244 return basic + slop; 226 return basic + slop;
245 } else { 227 } else {
246 // save, ld, ld, sll, and, add, add, ld, cmp, br, add, ld, add, ld, ld, jmp, restore, sethi, jmpl, restore 228 const int basic = (28 LP64_ONLY(+ 6)) * BytesPerInstWord +
247 const int basic = (20 LP64_ONLY(+ 6)) * BytesPerInstWord +
248 // shift;add for load_klass 229 // shift;add for load_klass
249 (UseCompressedOops ? 2*BytesPerInstWord : 0); 230 (UseCompressedOops ? 2*BytesPerInstWord : 0);
250 return (basic + slop); 231 return (basic + slop);
251 } 232 }
252 } 233 }