27 #include "asm/macroAssembler.hpp" |
27 #include "asm/macroAssembler.hpp" |
28 #include "assembler_aarch64.inline.hpp" |
28 #include "assembler_aarch64.inline.hpp" |
29 #include "code/vtableStubs.hpp" |
29 #include "code/vtableStubs.hpp" |
30 #include "interp_masm_aarch64.hpp" |
30 #include "interp_masm_aarch64.hpp" |
31 #include "memory/resourceArea.hpp" |
31 #include "memory/resourceArea.hpp" |
|
32 #include "oops/compiledICHolder.hpp" |
32 #include "oops/instanceKlass.hpp" |
33 #include "oops/instanceKlass.hpp" |
33 #include "oops/klassVtable.hpp" |
34 #include "oops/klassVtable.hpp" |
34 #include "runtime/sharedRuntime.hpp" |
35 #include "runtime/sharedRuntime.hpp" |
35 #include "vmreg_aarch64.inline.hpp" |
36 #include "vmreg_aarch64.inline.hpp" |
36 #ifdef COMPILER2 |
37 #ifdef COMPILER2 |
138 __ incrementw(Address(r10)); |
139 __ incrementw(Address(r10)); |
139 } |
140 } |
140 #endif |
141 #endif |
141 |
142 |
142 // Entry arguments: |
143 // Entry arguments: |
143 // rscratch2: Interface |
144 // rscratch2: CompiledICHolder |
144 // j_rarg0: Receiver |
145 // j_rarg0: Receiver |
145 |
146 |
146 // Free registers (non-args) are r0 (interface), rmethod |
147 |
|
148 // Most registers are in use; we'll use r0, rmethod, r10, r11 |
|
149 const Register recv_klass_reg = r10; |
|
150 const Register holder_klass_reg = r0; // declaring interface klass (DECC) |
|
151 const Register resolved_klass_reg = rmethod; // resolved interface klass (REFC) |
|
152 const Register temp_reg = r11; |
|
153 const Register icholder_reg = rscratch2; |
|
154 |
|
155 Label L_no_such_interface; |
|
156 |
|
157 __ ldr(resolved_klass_reg, Address(icholder_reg, CompiledICHolder::holder_klass_offset())); |
|
158 __ ldr(holder_klass_reg, Address(icholder_reg, CompiledICHolder::holder_metadata_offset())); |
147 |
159 |
148 // get receiver (need to skip return address on top of stack) |
160 // get receiver (need to skip return address on top of stack) |
149 |
|
150 assert(VtableStub::receiver_location() == j_rarg0->as_VMReg(), "receiver expected in j_rarg0"); |
161 assert(VtableStub::receiver_location() == j_rarg0->as_VMReg(), "receiver expected in j_rarg0"); |
151 // get receiver klass (also an implicit null-check) |
162 // get receiver klass (also an implicit null-check) |
152 address npe_addr = __ pc(); |
163 address npe_addr = __ pc(); |
153 |
164 __ load_klass(recv_klass_reg, j_rarg0); |
154 // Most registers are in use; we'll use r0, rmethod, r10, r11 |
165 |
155 __ load_klass(r10, j_rarg0); |
166 // Receiver subtype check against REFC. |
156 |
167 // Destroys recv_klass_reg value. |
157 Label throw_icce; |
168 __ lookup_interface_method(// inputs: rec. class, interface |
158 |
169 recv_klass_reg, resolved_klass_reg, noreg, |
159 // Get Method* and entrypoint for compiler |
170 // outputs: scan temp. reg1, scan temp. reg2 |
|
171 recv_klass_reg, temp_reg, |
|
172 L_no_such_interface, |
|
173 /*return_method=*/false); |
|
174 |
|
175 // Get selected method from declaring class and itable index |
|
176 __ load_klass(recv_klass_reg, j_rarg0); // restore recv_klass_reg |
160 __ lookup_interface_method(// inputs: rec. class, interface, itable index |
177 __ lookup_interface_method(// inputs: rec. class, interface, itable index |
161 r10, rscratch2, itable_index, |
178 recv_klass_reg, holder_klass_reg, itable_index, |
162 // outputs: method, scan temp. reg |
179 // outputs: method, scan temp. reg |
163 rmethod, r11, |
180 rmethod, temp_reg, |
164 throw_icce); |
181 L_no_such_interface); |
165 |
182 |
166 // method (rmethod): Method* |
183 // method (rmethod): Method* |
167 // j_rarg0: receiver |
184 // j_rarg0: receiver |
168 |
185 |
169 #ifdef ASSERT |
186 #ifdef ASSERT |
203 |
220 |
204 int VtableStub::pd_code_size_limit(bool is_vtable_stub) { |
221 int VtableStub::pd_code_size_limit(bool is_vtable_stub) { |
205 int size = DebugVtables ? 216 : 0; |
222 int size = DebugVtables ? 216 : 0; |
206 if (CountCompiledCalls) |
223 if (CountCompiledCalls) |
207 size += 6 * 4; |
224 size += 6 * 4; |
208 // FIXME |
225 // FIXME: vtable stubs only need 36 bytes |
209 if (is_vtable_stub) |
226 if (is_vtable_stub) |
210 size += 52; |
227 size += 52; |
211 else |
228 else |
212 size += 104; |
229 size += 176; |
213 return size; |
230 return size; |
214 |
231 |
215 // In order to tune these parameters, run the JVM with VM options |
232 // In order to tune these parameters, run the JVM with VM options |
216 // +PrintMiscellaneous and +WizardMode to see information about |
233 // +PrintMiscellaneous and +WizardMode to see information about |
217 // actual itable stubs. Run it with -Xmx31G -XX:+UseCompressedOops. |
234 // actual itable stubs. Run it with -Xmx31G -XX:+UseCompressedOops. |
218 // |
235 // |
219 // If Universe::narrow_klass_base is nonzero, decoding a compressed |
236 // If Universe::narrow_klass_base is nonzero, decoding a compressed |
220 // class can take zeveral instructions. Run it with -Xmx31G |
237 // class can take zeveral instructions. |
221 // -XX:+UseCompressedOops. |
|
222 // |
238 // |
223 // The JVM98 app. _202_jess has a megamorphic interface call. |
239 // The JVM98 app. _202_jess has a megamorphic interface call. |
224 // The itable code looks like this: |
240 // The itable code looks like this: |
225 // Decoding VtableStub itbl[1]@12 |
241 |
226 // ldr w10, [x1,#8] |
242 // ldr xmethod, [xscratch2,#CompiledICHolder::holder_klass_offset] |
227 // lsl x10, x10, #3 |
243 // ldr x0, [xscratch2] |
228 // ldr w11, [x10,#280] |
244 // ldr w10, [x1,#oopDesc::klass_offset_in_bytes] |
229 // add x11, x10, x11, uxtx #3 |
245 // mov xheapbase, #0x3c000000 // #narrow_klass_base |
230 // add x11, x11, #0x1b8 |
246 // movk xheapbase, #0x3f7, lsl #32 |
231 // ldr x12, [x11] |
247 // add x10, xheapbase, x10 |
232 // cmp x9, x12 |
248 // mov xheapbase, #0xe7ff0000 // #heapbase |
233 // b.eq success |
249 // movk xheapbase, #0x3f7, lsl #32 |
234 // loop: |
250 // ldr w11, [x10,#vtable_length_offset] |
235 // cbz x12, throw_icce |
251 // add x11, x10, x11, uxtx #3 |
236 // add x11, x11, #0x10 |
252 // add x11, x11, #itableMethodEntry::method_offset_in_bytes |
237 // ldr x12, [x11] |
253 // ldr x10, [x11] |
238 // cmp x9, x12 |
254 // cmp xmethod, x10 |
239 // b.ne loop |
255 // b.eq found_method |
240 // success: |
256 // search: |
241 // ldr x11, [x11,#8] |
257 // cbz x10, no_such_interface |
242 // ldr x12, [x10,x11] |
258 // add x11, x11, #0x10 |
243 // ldr x8, [x12,#72] |
259 // ldr x10, [x11] |
244 // br x8 |
260 // cmp xmethod, x10 |
245 // throw_icce: |
261 // b.ne search |
246 // b throw_ICCE_entry |
262 // found_method: |
|
263 // ldr w10, [x1,#oopDesc::klass_offset_in_bytes] |
|
264 // mov xheapbase, #0x3c000000 // #narrow_klass_base |
|
265 // movk xheapbase, #0x3f7, lsl #32 |
|
266 // add x10, xheapbase, x10 |
|
267 // mov xheapbase, #0xe7ff0000 // #heapbase |
|
268 // movk xheapbase, #0x3f7, lsl #32 |
|
269 // ldr w11, [x10,#vtable_length_offset] |
|
270 // add x11, x10, x11, uxtx #3 |
|
271 // add x11, x11, #itableMethodEntry::method_offset_in_bytes |
|
272 // add x10, x10, #itentry_off |
|
273 // ldr xmethod, [x11] |
|
274 // cmp x0, xmethod |
|
275 // b.eq found_method2 |
|
276 // search2: |
|
277 // cbz xmethod, 0x000003ffa872e6cc |
|
278 // add x11, x11, #0x10 |
|
279 // ldr xmethod, [x11] |
|
280 // cmp x0, xmethod |
|
281 // b.ne search2 |
|
282 // found_method2: |
|
283 // ldr w11, [x11,#itableOffsetEntry::offset_offset_in_bytes] |
|
284 // ldr xmethod, [x10,w11,uxtw] |
|
285 // ldr xscratch1, [xmethod,#Method::from_compiled_offset] |
|
286 // br xscratch1 |
|
287 // no_such_interface: |
|
288 // b throw_ICCE_entry |
247 |
289 |
248 } |
290 } |
249 |
291 |
250 int VtableStub::pd_code_alignment() { return 4; } |
292 int VtableStub::pd_code_alignment() { return 4; } |