Mercurial > hg > truffle
annotate src/cpu/x86/vm/interp_masm_x86_64.cpp @ 304:dc7f315e41f7
5108146: Merge i486 and amd64 cpu directories
6459804: Want client (c1) compiler for x86_64 (amd64) for faster start-up
Reviewed-by: kvn
author | never |
---|---|
date | Wed, 27 Aug 2008 00:21:55 -0700 |
parents | d1605aabd0a1 |
children | f8199438385b |
rev | line source |
---|---|
0 | 1 /* |
196 | 2 * Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved. |
0 | 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * | |
5 * This code is free software; you can redistribute it and/or modify it | |
6 * under the terms of the GNU General Public License version 2 only, as | |
7 * published by the Free Software Foundation. | |
8 * | |
9 * This code is distributed in the hope that it will be useful, but WITHOUT | |
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
12 * version 2 for more details (a copy is included in the LICENSE file that | |
13 * accompanied this code). | |
14 * | |
15 * You should have received a copy of the GNU General Public License version | |
16 * 2 along with this work; if not, write to the Free Software Foundation, | |
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
18 * | |
19 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, | |
20 * CA 95054 USA or visit www.sun.com if you need additional information or | |
21 * have any questions. | |
22 * | |
23 */ | |
24 | |
25 #include "incls/_precompiled.incl" | |
26 #include "incls/_interp_masm_x86_64.cpp.incl" | |
27 | |
28 | |
29 // Implementation of InterpreterMacroAssembler | |
30 | |
304 | 31 #ifdef CC_INTERP |
32 void InterpreterMacroAssembler::get_method(Register reg) { | |
33 movptr(reg, Address(rbp, -(sizeof(BytecodeInterpreter) + 2 * wordSize))); | |
34 movptr(reg, Address(reg, byte_offset_of(BytecodeInterpreter, _method))); | |
35 } | |
36 #endif // CC_INTERP | |
37 | |
38 #ifndef CC_INTERP | |
39 | |
0 | 40 void InterpreterMacroAssembler::call_VM_leaf_base(address entry_point, |
41 int number_of_arguments) { | |
42 // interpreter specific | |
43 // | |
44 // Note: No need to save/restore bcp & locals (r13 & r14) pointer | |
45 // since these are callee saved registers and no blocking/ | |
46 // GC can happen in leaf calls. | |
47 #ifdef ASSERT | |
48 save_bcp(); | |
49 { | |
50 Label L; | |
304 | 51 cmpptr(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), (int32_t)NULL_WORD); |
0 | 52 jcc(Assembler::equal, L); |
53 stop("InterpreterMacroAssembler::call_VM_leaf_base:" | |
54 " last_sp != NULL"); | |
55 bind(L); | |
56 } | |
57 #endif | |
58 // super call | |
59 MacroAssembler::call_VM_leaf_base(entry_point, number_of_arguments); | |
60 // interpreter specific | |
61 #ifdef ASSERT | |
62 { | |
63 Label L; | |
304 | 64 cmpptr(r13, Address(rbp, frame::interpreter_frame_bcx_offset * wordSize)); |
0 | 65 jcc(Assembler::equal, L); |
66 stop("InterpreterMacroAssembler::call_VM_leaf_base:" | |
67 " r13 not callee saved?"); | |
68 bind(L); | |
69 } | |
70 { | |
71 Label L; | |
304 | 72 cmpptr(r14, Address(rbp, frame::interpreter_frame_locals_offset * wordSize)); |
0 | 73 jcc(Assembler::equal, L); |
74 stop("InterpreterMacroAssembler::call_VM_leaf_base:" | |
75 " r14 not callee saved?"); | |
76 bind(L); | |
77 } | |
78 #endif | |
79 } | |
80 | |
81 void InterpreterMacroAssembler::call_VM_base(Register oop_result, | |
82 Register java_thread, | |
83 Register last_java_sp, | |
84 address entry_point, | |
85 int number_of_arguments, | |
86 bool check_exceptions) { | |
87 // interpreter specific | |
88 // | |
89 // Note: Could avoid restoring locals ptr (callee saved) - however doesn't | |
90 // really make a difference for these runtime calls, since they are | |
91 // slow anyway. Btw., bcp must be saved/restored since it may change | |
92 // due to GC. | |
93 // assert(java_thread == noreg , "not expecting a precomputed java thread"); | |
94 save_bcp(); | |
95 #ifdef ASSERT | |
96 { | |
97 Label L; | |
304 | 98 cmpptr(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), (int32_t)NULL_WORD); |
0 | 99 jcc(Assembler::equal, L); |
100 stop("InterpreterMacroAssembler::call_VM_leaf_base:" | |
101 " last_sp != NULL"); | |
102 bind(L); | |
103 } | |
104 #endif /* ASSERT */ | |
105 // super call | |
106 MacroAssembler::call_VM_base(oop_result, noreg, last_java_sp, | |
107 entry_point, number_of_arguments, | |
108 check_exceptions); | |
109 // interpreter specific | |
110 restore_bcp(); | |
111 restore_locals(); | |
112 } | |
113 | |
114 | |
115 void InterpreterMacroAssembler::check_and_handle_popframe(Register java_thread) { | |
116 if (JvmtiExport::can_pop_frame()) { | |
117 Label L; | |
118 // Initiate popframe handling only if it is not already being | |
119 // processed. If the flag has the popframe_processing bit set, it | |
120 // means that this code is called *during* popframe handling - we | |
121 // don't want to reenter. | |
122 // This method is only called just after the call into the vm in | |
123 // call_VM_base, so the arg registers are available. | |
124 movl(c_rarg0, Address(r15_thread, JavaThread::popframe_condition_offset())); | |
125 testl(c_rarg0, JavaThread::popframe_pending_bit); | |
126 jcc(Assembler::zero, L); | |
127 testl(c_rarg0, JavaThread::popframe_processing_bit); | |
128 jcc(Assembler::notZero, L); | |
129 // Call Interpreter::remove_activation_preserving_args_entry() to get the | |
130 // address of the same-named entrypoint in the generated interpreter code. | |
131 call_VM_leaf(CAST_FROM_FN_PTR(address, Interpreter::remove_activation_preserving_args_entry)); | |
132 jmp(rax); | |
133 bind(L); | |
134 } | |
135 } | |
136 | |
137 | |
138 void InterpreterMacroAssembler::load_earlyret_value(TosState state) { | |
304 | 139 movptr(rcx, Address(r15_thread, JavaThread::jvmti_thread_state_offset())); |
0 | 140 const Address tos_addr(rcx, JvmtiThreadState::earlyret_tos_offset()); |
141 const Address oop_addr(rcx, JvmtiThreadState::earlyret_oop_offset()); | |
142 const Address val_addr(rcx, JvmtiThreadState::earlyret_value_offset()); | |
143 switch (state) { | |
304 | 144 case atos: movptr(rax, oop_addr); |
145 movptr(oop_addr, (int32_t)NULL_WORD); | |
0 | 146 verify_oop(rax, state); break; |
304 | 147 case ltos: movptr(rax, val_addr); break; |
0 | 148 case btos: // fall through |
149 case ctos: // fall through | |
150 case stos: // fall through | |
151 case itos: movl(rax, val_addr); break; | |
152 case ftos: movflt(xmm0, val_addr); break; | |
153 case dtos: movdbl(xmm0, val_addr); break; | |
154 case vtos: /* nothing to do */ break; | |
155 default : ShouldNotReachHere(); | |
156 } | |
157 // Clean up tos value in the thread object | |
158 movl(tos_addr, (int) ilgl); | |
304 | 159 movl(val_addr, (int32_t) NULL_WORD); |
0 | 160 } |
161 | |
162 | |
163 void InterpreterMacroAssembler::check_and_handle_earlyret(Register java_thread) { | |
164 if (JvmtiExport::can_force_early_return()) { | |
165 Label L; | |
304 | 166 movptr(c_rarg0, Address(r15_thread, JavaThread::jvmti_thread_state_offset())); |
167 testptr(c_rarg0, c_rarg0); | |
0 | 168 jcc(Assembler::zero, L); // if (thread->jvmti_thread_state() == NULL) exit; |
169 | |
170 // Initiate earlyret handling only if it is not already being processed. | |
171 // If the flag has the earlyret_processing bit set, it means that this code | |
172 // is called *during* earlyret handling - we don't want to reenter. | |
173 movl(c_rarg0, Address(c_rarg0, JvmtiThreadState::earlyret_state_offset())); | |
174 cmpl(c_rarg0, JvmtiThreadState::earlyret_pending); | |
175 jcc(Assembler::notEqual, L); | |
176 | |
177 // Call Interpreter::remove_activation_early_entry() to get the address of the | |
178 // same-named entrypoint in the generated interpreter code. | |
304 | 179 movptr(c_rarg0, Address(r15_thread, JavaThread::jvmti_thread_state_offset())); |
0 | 180 movl(c_rarg0, Address(c_rarg0, JvmtiThreadState::earlyret_tos_offset())); |
181 call_VM_leaf(CAST_FROM_FN_PTR(address, Interpreter::remove_activation_early_entry), c_rarg0); | |
182 jmp(rax); | |
183 bind(L); | |
184 } | |
185 } | |
186 | |
187 | |
188 void InterpreterMacroAssembler::get_unsigned_2_byte_index_at_bcp( | |
189 Register reg, | |
190 int bcp_offset) { | |
191 assert(bcp_offset >= 0, "bcp is still pointing to start of bytecode"); | |
192 movl(reg, Address(r13, bcp_offset)); | |
193 bswapl(reg); | |
194 shrl(reg, 16); | |
195 } | |
196 | |
197 | |
198 void InterpreterMacroAssembler::get_cache_and_index_at_bcp(Register cache, | |
199 Register index, | |
200 int bcp_offset) { | |
201 assert(bcp_offset > 0, "bcp is still pointing to start of bytecode"); | |
202 assert(cache != index, "must use different registers"); | |
203 load_unsigned_word(index, Address(r13, bcp_offset)); | |
304 | 204 movptr(cache, Address(rbp, frame::interpreter_frame_cache_offset * wordSize)); |
0 | 205 assert(sizeof(ConstantPoolCacheEntry) == 4 * wordSize, "adjust code below"); |
206 // convert from field index to ConstantPoolCacheEntry index | |
207 shll(index, 2); | |
208 } | |
209 | |
210 | |
211 void InterpreterMacroAssembler::get_cache_entry_pointer_at_bcp(Register cache, | |
212 Register tmp, | |
213 int bcp_offset) { | |
214 assert(bcp_offset > 0, "bcp is still pointing to start of bytecode"); | |
215 assert(cache != tmp, "must use different register"); | |
216 load_unsigned_word(tmp, Address(r13, bcp_offset)); | |
217 assert(sizeof(ConstantPoolCacheEntry) == 4 * wordSize, "adjust code below"); | |
218 // convert from field index to ConstantPoolCacheEntry index | |
219 // and from word offset to byte offset | |
220 shll(tmp, 2 + LogBytesPerWord); | |
304 | 221 movptr(cache, Address(rbp, frame::interpreter_frame_cache_offset * wordSize)); |
0 | 222 // skip past the header |
304 | 223 addptr(cache, in_bytes(constantPoolCacheOopDesc::base_offset())); |
224 addptr(cache, tmp); // construct pointer to cache entry | |
0 | 225 } |
226 | |
227 | |
228 // Generate a subtype check: branch to ok_is_subtype if sub_klass is a | |
229 // subtype of super_klass. | |
230 // | |
231 // Args: | |
232 // rax: superklass | |
233 // Rsub_klass: subklass | |
234 // | |
235 // Kills: | |
236 // rcx, rdi | |
237 void InterpreterMacroAssembler::gen_subtype_check(Register Rsub_klass, | |
238 Label& ok_is_subtype) { | |
239 assert(Rsub_klass != rax, "rax holds superklass"); | |
240 assert(Rsub_klass != r14, "r14 holds locals"); | |
241 assert(Rsub_klass != r13, "r13 holds bcp"); | |
242 assert(Rsub_klass != rcx, "rcx holds 2ndary super array length"); | |
243 assert(Rsub_klass != rdi, "rdi holds 2ndary super array scan ptr"); | |
244 | |
178
6d172e3548cb
6695819: verify_oopx rax: broken oop in decode_heap_oop
coleenp
parents:
113
diff
changeset
|
245 Label not_subtype, not_subtype_pop, loop; |
0 | 246 |
247 // Profile the not-null value's klass. | |
248 profile_typecheck(rcx, Rsub_klass, rdi); // blows rcx, rdi | |
249 | |
250 // Load the super-klass's check offset into rcx | |
251 movl(rcx, Address(rax, sizeof(oopDesc) + | |
252 Klass::super_check_offset_offset_in_bytes())); | |
253 // Load from the sub-klass's super-class display list, or a 1-word | |
254 // cache of the secondary superclass list, or a failing value with a | |
255 // sentinel offset if the super-klass is an interface or | |
256 // exceptionally deep in the Java hierarchy and we have to scan the | |
257 // secondary superclass list the hard way. See if we get an | |
258 // immediate positive hit | |
304 | 259 cmpptr(rax, Address(Rsub_klass, rcx, Address::times_1)); |
0 | 260 jcc(Assembler::equal,ok_is_subtype); |
261 | |
262 // Check for immediate negative hit | |
263 cmpl(rcx, sizeof(oopDesc) + Klass::secondary_super_cache_offset_in_bytes()); | |
264 jcc( Assembler::notEqual, not_subtype ); | |
265 // Check for self | |
304 | 266 cmpptr(Rsub_klass, rax); |
0 | 267 jcc(Assembler::equal, ok_is_subtype); |
268 | |
269 // Now do a linear scan of the secondary super-klass chain. | |
304 | 270 movptr(rdi, Address(Rsub_klass, sizeof(oopDesc) + |
271 Klass::secondary_supers_offset_in_bytes())); | |
0 | 272 // rdi holds the objArrayOop of secondary supers. |
273 // Load the array length | |
274 movl(rcx, Address(rdi, arrayOopDesc::length_offset_in_bytes())); | |
275 // Skip to start of data; also clear Z flag incase rcx is zero | |
304 | 276 addptr(rdi, arrayOopDesc::base_offset_in_bytes(T_OBJECT)); |
0 | 277 // Scan rcx words at [rdi] for occurance of rax |
278 // Set NZ/Z based on last compare | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
279 |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
280 // this part is kind tricky, as values in supers array could be 32 or 64 bit wide |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
281 // and we store values in objArrays always encoded, thus we need to encode value |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
282 // before repne |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
283 if (UseCompressedOops) { |
304 | 284 push(rax); |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
285 encode_heap_oop(rax); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
286 repne_scanl(); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
287 // Not equal? |
178
6d172e3548cb
6695819: verify_oopx rax: broken oop in decode_heap_oop
coleenp
parents:
113
diff
changeset
|
288 jcc(Assembler::notEqual, not_subtype_pop); |
6d172e3548cb
6695819: verify_oopx rax: broken oop in decode_heap_oop
coleenp
parents:
113
diff
changeset
|
289 // restore heap oop here for movq |
304 | 290 pop(rax); |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
291 } else { |
304 | 292 repne_scan(); |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
293 jcc(Assembler::notEqual, not_subtype); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
294 } |
0 | 295 // Must be equal but missed in cache. Update cache. |
304 | 296 movptr(Address(Rsub_klass, sizeof(oopDesc) + |
0 | 297 Klass::secondary_super_cache_offset_in_bytes()), rax); |
298 jmp(ok_is_subtype); | |
299 | |
178
6d172e3548cb
6695819: verify_oopx rax: broken oop in decode_heap_oop
coleenp
parents:
113
diff
changeset
|
300 bind(not_subtype_pop); |
6d172e3548cb
6695819: verify_oopx rax: broken oop in decode_heap_oop
coleenp
parents:
113
diff
changeset
|
301 // restore heap oop here for miss |
304 | 302 if (UseCompressedOops) pop(rax); |
0 | 303 bind(not_subtype); |
304 profile_typecheck_failed(rcx); // blows rcx | |
305 } | |
306 | |
307 | |
304 | 308 |
0 | 309 // Java Expression Stack |
310 | |
311 #ifdef ASSERT | |
312 // Verifies that the stack tag matches. Must be called before the stack | |
313 // value is popped off the stack. | |
314 void InterpreterMacroAssembler::verify_stack_tag(frame::Tag t) { | |
315 if (TaggedStackInterpreter) { | |
316 frame::Tag tag = t; | |
317 if (t == frame::TagCategory2) { | |
318 tag = frame::TagValue; | |
319 Label hokay; | |
304 | 320 cmpptr(Address(rsp, 3*wordSize), (int32_t)tag); |
0 | 321 jcc(Assembler::equal, hokay); |
322 stop("Java Expression stack tag high value is bad"); | |
323 bind(hokay); | |
324 } | |
325 Label okay; | |
304 | 326 cmpptr(Address(rsp, wordSize), (int32_t)tag); |
0 | 327 jcc(Assembler::equal, okay); |
328 // Also compare if the stack value is zero, then the tag might | |
329 // not have been set coming from deopt. | |
304 | 330 cmpptr(Address(rsp, 0), 0); |
0 | 331 jcc(Assembler::equal, okay); |
332 stop("Java Expression stack tag value is bad"); | |
333 bind(okay); | |
334 } | |
335 } | |
336 #endif // ASSERT | |
337 | |
338 void InterpreterMacroAssembler::pop_ptr(Register r) { | |
339 debug_only(verify_stack_tag(frame::TagReference)); | |
304 | 340 pop(r); |
341 if (TaggedStackInterpreter) addptr(rsp, 1 * wordSize); | |
0 | 342 } |
343 | |
344 void InterpreterMacroAssembler::pop_ptr(Register r, Register tag) { | |
304 | 345 pop(r); |
346 if (TaggedStackInterpreter) pop(tag); | |
0 | 347 } |
348 | |
349 void InterpreterMacroAssembler::pop_i(Register r) { | |
304 | 350 // XXX can't use pop currently, upper half non clean |
0 | 351 debug_only(verify_stack_tag(frame::TagValue)); |
352 movl(r, Address(rsp, 0)); | |
304 | 353 addptr(rsp, wordSize); |
354 if (TaggedStackInterpreter) addptr(rsp, 1 * wordSize); | |
0 | 355 } |
356 | |
357 void InterpreterMacroAssembler::pop_l(Register r) { | |
358 debug_only(verify_stack_tag(frame::TagCategory2)); | |
359 movq(r, Address(rsp, 0)); | |
304 | 360 addptr(rsp, 2 * Interpreter::stackElementSize()); |
0 | 361 } |
362 | |
363 void InterpreterMacroAssembler::pop_f(XMMRegister r) { | |
364 debug_only(verify_stack_tag(frame::TagValue)); | |
365 movflt(r, Address(rsp, 0)); | |
304 | 366 addptr(rsp, wordSize); |
367 if (TaggedStackInterpreter) addptr(rsp, 1 * wordSize); | |
0 | 368 } |
369 | |
370 void InterpreterMacroAssembler::pop_d(XMMRegister r) { | |
371 debug_only(verify_stack_tag(frame::TagCategory2)); | |
372 movdbl(r, Address(rsp, 0)); | |
304 | 373 addptr(rsp, 2 * Interpreter::stackElementSize()); |
0 | 374 } |
375 | |
376 void InterpreterMacroAssembler::push_ptr(Register r) { | |
304 | 377 if (TaggedStackInterpreter) push(frame::TagReference); |
378 push(r); | |
0 | 379 } |
380 | |
381 void InterpreterMacroAssembler::push_ptr(Register r, Register tag) { | |
304 | 382 if (TaggedStackInterpreter) push(tag); |
383 push(r); | |
0 | 384 } |
385 | |
386 void InterpreterMacroAssembler::push_i(Register r) { | |
304 | 387 if (TaggedStackInterpreter) push(frame::TagValue); |
388 push(r); | |
0 | 389 } |
390 | |
391 void InterpreterMacroAssembler::push_l(Register r) { | |
392 if (TaggedStackInterpreter) { | |
304 | 393 push(frame::TagValue); |
394 subptr(rsp, 1 * wordSize); | |
395 push(frame::TagValue); | |
396 subptr(rsp, 1 * wordSize); | |
0 | 397 } else { |
304 | 398 subptr(rsp, 2 * wordSize); |
0 | 399 } |
400 movq(Address(rsp, 0), r); | |
401 } | |
402 | |
403 void InterpreterMacroAssembler::push_f(XMMRegister r) { | |
304 | 404 if (TaggedStackInterpreter) push(frame::TagValue); |
405 subptr(rsp, wordSize); | |
0 | 406 movflt(Address(rsp, 0), r); |
407 } | |
408 | |
409 void InterpreterMacroAssembler::push_d(XMMRegister r) { | |
410 if (TaggedStackInterpreter) { | |
304 | 411 push(frame::TagValue); |
412 subptr(rsp, 1 * wordSize); | |
413 push(frame::TagValue); | |
414 subptr(rsp, 1 * wordSize); | |
0 | 415 } else { |
304 | 416 subptr(rsp, 2 * wordSize); |
0 | 417 } |
418 movdbl(Address(rsp, 0), r); | |
419 } | |
420 | |
421 void InterpreterMacroAssembler::pop(TosState state) { | |
422 switch (state) { | |
423 case atos: pop_ptr(); break; | |
424 case btos: | |
425 case ctos: | |
426 case stos: | |
427 case itos: pop_i(); break; | |
428 case ltos: pop_l(); break; | |
429 case ftos: pop_f(); break; | |
430 case dtos: pop_d(); break; | |
431 case vtos: /* nothing to do */ break; | |
432 default: ShouldNotReachHere(); | |
433 } | |
434 verify_oop(rax, state); | |
435 } | |
436 | |
437 void InterpreterMacroAssembler::push(TosState state) { | |
438 verify_oop(rax, state); | |
439 switch (state) { | |
440 case atos: push_ptr(); break; | |
441 case btos: | |
442 case ctos: | |
443 case stos: | |
444 case itos: push_i(); break; | |
445 case ltos: push_l(); break; | |
446 case ftos: push_f(); break; | |
447 case dtos: push_d(); break; | |
448 case vtos: /* nothing to do */ break; | |
449 default : ShouldNotReachHere(); | |
450 } | |
451 } | |
452 | |
453 | |
304 | 454 |
455 | |
0 | 456 // Tagged stack helpers for swap and dup |
457 void InterpreterMacroAssembler::load_ptr_and_tag(int n, Register val, | |
458 Register tag) { | |
304 | 459 movptr(val, Address(rsp, Interpreter::expr_offset_in_bytes(n))); |
0 | 460 if (TaggedStackInterpreter) { |
304 | 461 movptr(tag, Address(rsp, Interpreter::expr_tag_offset_in_bytes(n))); |
0 | 462 } |
463 } | |
464 | |
465 void InterpreterMacroAssembler::store_ptr_and_tag(int n, Register val, | |
466 Register tag) { | |
304 | 467 movptr(Address(rsp, Interpreter::expr_offset_in_bytes(n)), val); |
0 | 468 if (TaggedStackInterpreter) { |
304 | 469 movptr(Address(rsp, Interpreter::expr_tag_offset_in_bytes(n)), tag); |
0 | 470 } |
471 } | |
472 | |
473 | |
474 // Tagged local support | |
475 void InterpreterMacroAssembler::tag_local(frame::Tag tag, int n) { | |
476 if (TaggedStackInterpreter) { | |
477 if (tag == frame::TagCategory2) { | |
304 | 478 movptr(Address(r14, Interpreter::local_tag_offset_in_bytes(n+1)), |
479 (int32_t)frame::TagValue); | |
480 movptr(Address(r14, Interpreter::local_tag_offset_in_bytes(n)), | |
481 (int32_t)frame::TagValue); | |
0 | 482 } else { |
304 | 483 movptr(Address(r14, Interpreter::local_tag_offset_in_bytes(n)), (int32_t)tag); |
0 | 484 } |
485 } | |
486 } | |
487 | |
488 void InterpreterMacroAssembler::tag_local(frame::Tag tag, Register idx) { | |
489 if (TaggedStackInterpreter) { | |
490 if (tag == frame::TagCategory2) { | |
304 | 491 movptr(Address(r14, idx, Address::times_8, |
492 Interpreter::local_tag_offset_in_bytes(1)), (int32_t)frame::TagValue); | |
493 movptr(Address(r14, idx, Address::times_8, | |
494 Interpreter::local_tag_offset_in_bytes(0)), (int32_t)frame::TagValue); | |
0 | 495 } else { |
304 | 496 movptr(Address(r14, idx, Address::times_8, Interpreter::local_tag_offset_in_bytes(0)), |
497 (int32_t)tag); | |
0 | 498 } |
499 } | |
500 } | |
501 | |
502 void InterpreterMacroAssembler::tag_local(Register tag, Register idx) { | |
503 if (TaggedStackInterpreter) { | |
504 // can only be TagValue or TagReference | |
304 | 505 movptr(Address(r14, idx, Address::times_8, Interpreter::local_tag_offset_in_bytes(0)), tag); |
0 | 506 } |
507 } | |
508 | |
509 | |
510 void InterpreterMacroAssembler::tag_local(Register tag, int n) { | |
511 if (TaggedStackInterpreter) { | |
512 // can only be TagValue or TagReference | |
304 | 513 movptr(Address(r14, Interpreter::local_tag_offset_in_bytes(n)), tag); |
0 | 514 } |
515 } | |
516 | |
517 #ifdef ASSERT | |
518 void InterpreterMacroAssembler::verify_local_tag(frame::Tag tag, int n) { | |
519 if (TaggedStackInterpreter) { | |
520 frame::Tag t = tag; | |
521 if (tag == frame::TagCategory2) { | |
522 Label nbl; | |
523 t = frame::TagValue; // change to what is stored in locals | |
304 | 524 cmpptr(Address(r14, Interpreter::local_tag_offset_in_bytes(n+1)), (int32_t)t); |
0 | 525 jcc(Assembler::equal, nbl); |
526 stop("Local tag is bad for long/double"); | |
527 bind(nbl); | |
528 } | |
529 Label notBad; | |
304 | 530 cmpq(Address(r14, Interpreter::local_tag_offset_in_bytes(n)), (int32_t)t); |
0 | 531 jcc(Assembler::equal, notBad); |
532 // Also compare if the local value is zero, then the tag might | |
533 // not have been set coming from deopt. | |
304 | 534 cmpptr(Address(r14, Interpreter::local_offset_in_bytes(n)), 0); |
0 | 535 jcc(Assembler::equal, notBad); |
536 stop("Local tag is bad"); | |
537 bind(notBad); | |
538 } | |
539 } | |
540 | |
541 void InterpreterMacroAssembler::verify_local_tag(frame::Tag tag, Register idx) { | |
542 if (TaggedStackInterpreter) { | |
543 frame::Tag t = tag; | |
544 if (tag == frame::TagCategory2) { | |
545 Label nbl; | |
546 t = frame::TagValue; // change to what is stored in locals | |
304 | 547 cmpptr(Address(r14, idx, Address::times_8, Interpreter::local_tag_offset_in_bytes(1)), (int32_t)t); |
0 | 548 jcc(Assembler::equal, nbl); |
549 stop("Local tag is bad for long/double"); | |
550 bind(nbl); | |
551 } | |
552 Label notBad; | |
304 | 553 cmpptr(Address(r14, idx, Address::times_8, Interpreter::local_tag_offset_in_bytes(0)), (int32_t)t); |
0 | 554 jcc(Assembler::equal, notBad); |
555 // Also compare if the local value is zero, then the tag might | |
556 // not have been set coming from deopt. | |
304 | 557 cmpptr(Address(r14, idx, Address::times_8, Interpreter::local_offset_in_bytes(0)), 0); |
0 | 558 jcc(Assembler::equal, notBad); |
559 stop("Local tag is bad"); | |
560 bind(notBad); | |
561 } | |
562 } | |
563 #endif // ASSERT | |
564 | |
565 | |
566 void InterpreterMacroAssembler::super_call_VM_leaf(address entry_point) { | |
567 MacroAssembler::call_VM_leaf_base(entry_point, 0); | |
568 } | |
569 | |
570 | |
571 void InterpreterMacroAssembler::super_call_VM_leaf(address entry_point, | |
572 Register arg_1) { | |
573 if (c_rarg0 != arg_1) { | |
304 | 574 mov(c_rarg0, arg_1); |
0 | 575 } |
576 MacroAssembler::call_VM_leaf_base(entry_point, 1); | |
577 } | |
578 | |
579 | |
580 void InterpreterMacroAssembler::super_call_VM_leaf(address entry_point, | |
581 Register arg_1, | |
582 Register arg_2) { | |
583 assert(c_rarg0 != arg_2, "smashed argument"); | |
584 assert(c_rarg1 != arg_1, "smashed argument"); | |
585 if (c_rarg0 != arg_1) { | |
304 | 586 mov(c_rarg0, arg_1); |
0 | 587 } |
588 if (c_rarg1 != arg_2) { | |
304 | 589 mov(c_rarg1, arg_2); |
0 | 590 } |
591 MacroAssembler::call_VM_leaf_base(entry_point, 2); | |
592 } | |
593 | |
594 void InterpreterMacroAssembler::super_call_VM_leaf(address entry_point, | |
595 Register arg_1, | |
596 Register arg_2, | |
597 Register arg_3) { | |
598 assert(c_rarg0 != arg_2, "smashed argument"); | |
599 assert(c_rarg0 != arg_3, "smashed argument"); | |
600 assert(c_rarg1 != arg_1, "smashed argument"); | |
601 assert(c_rarg1 != arg_3, "smashed argument"); | |
602 assert(c_rarg2 != arg_1, "smashed argument"); | |
603 assert(c_rarg2 != arg_2, "smashed argument"); | |
604 if (c_rarg0 != arg_1) { | |
304 | 605 mov(c_rarg0, arg_1); |
0 | 606 } |
607 if (c_rarg1 != arg_2) { | |
304 | 608 mov(c_rarg1, arg_2); |
0 | 609 } |
610 if (c_rarg2 != arg_3) { | |
304 | 611 mov(c_rarg2, arg_3); |
0 | 612 } |
613 MacroAssembler::call_VM_leaf_base(entry_point, 3); | |
614 } | |
615 | |
616 // Jump to from_interpreted entry of a call unless single stepping is possible | |
617 // in this thread in which case we must call the i2i entry | |
618 void InterpreterMacroAssembler::jump_from_interpreted(Register method, Register temp) { | |
619 // set sender sp | |
304 | 620 lea(r13, Address(rsp, wordSize)); |
0 | 621 // record last_sp |
304 | 622 movptr(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), r13); |
0 | 623 |
624 if (JvmtiExport::can_post_interpreter_events()) { | |
625 Label run_compiled_code; | |
626 // JVMTI events, such as single-stepping, are implemented partly by avoiding running | |
627 // compiled code in threads for which the event is enabled. Check here for | |
628 // interp_only_mode if these events CAN be enabled. | |
629 get_thread(temp); | |
630 // interp_only is an int, on little endian it is sufficient to test the byte only | |
631 // Is a cmpl faster (ce | |
632 cmpb(Address(temp, JavaThread::interp_only_mode_offset()), 0); | |
633 jcc(Assembler::zero, run_compiled_code); | |
634 jmp(Address(method, methodOopDesc::interpreter_entry_offset())); | |
635 bind(run_compiled_code); | |
636 } | |
637 | |
638 jmp(Address(method, methodOopDesc::from_interpreted_offset())); | |
639 | |
640 } | |
641 | |
642 | |
643 // The following two routines provide a hook so that an implementation | |
644 // can schedule the dispatch in two parts. amd64 does not do this. | |
645 void InterpreterMacroAssembler::dispatch_prolog(TosState state, int step) { | |
646 // Nothing amd64 specific to be done here | |
647 } | |
648 | |
649 void InterpreterMacroAssembler::dispatch_epilog(TosState state, int step) { | |
650 dispatch_next(state, step); | |
651 } | |
652 | |
653 void InterpreterMacroAssembler::dispatch_base(TosState state, | |
654 address* table, | |
655 bool verifyoop) { | |
656 verify_FPU(1, state); | |
657 if (VerifyActivationFrameSize) { | |
658 Label L; | |
304 | 659 mov(rcx, rbp); |
660 subptr(rcx, rsp); | |
661 int32_t min_frame_size = | |
0 | 662 (frame::link_offset - frame::interpreter_frame_initial_sp_offset) * |
663 wordSize; | |
304 | 664 cmpptr(rcx, (int32_t)min_frame_size); |
0 | 665 jcc(Assembler::greaterEqual, L); |
666 stop("broken stack frame"); | |
667 bind(L); | |
668 } | |
669 if (verifyoop) { | |
670 verify_oop(rax, state); | |
671 } | |
672 lea(rscratch1, ExternalAddress((address)table)); | |
673 jmp(Address(rscratch1, rbx, Address::times_8)); | |
674 } | |
675 | |
676 void InterpreterMacroAssembler::dispatch_only(TosState state) { | |
677 dispatch_base(state, Interpreter::dispatch_table(state)); | |
678 } | |
679 | |
680 void InterpreterMacroAssembler::dispatch_only_normal(TosState state) { | |
681 dispatch_base(state, Interpreter::normal_table(state)); | |
682 } | |
683 | |
684 void InterpreterMacroAssembler::dispatch_only_noverify(TosState state) { | |
685 dispatch_base(state, Interpreter::normal_table(state), false); | |
686 } | |
687 | |
688 | |
689 void InterpreterMacroAssembler::dispatch_next(TosState state, int step) { | |
690 // load next bytecode (load before advancing r13 to prevent AGI) | |
691 load_unsigned_byte(rbx, Address(r13, step)); | |
692 // advance r13 | |
304 | 693 increment(r13, step); |
0 | 694 dispatch_base(state, Interpreter::dispatch_table(state)); |
695 } | |
696 | |
697 void InterpreterMacroAssembler::dispatch_via(TosState state, address* table) { | |
698 // load current bytecode | |
699 load_unsigned_byte(rbx, Address(r13, 0)); | |
700 dispatch_base(state, table); | |
701 } | |
702 | |
703 // remove activation | |
704 // | |
705 // Unlock the receiver if this is a synchronized method. | |
706 // Unlock any Java monitors from syncronized blocks. | |
707 // Remove the activation from the stack. | |
708 // | |
709 // If there are locked Java monitors | |
710 // If throw_monitor_exception | |
711 // throws IllegalMonitorStateException | |
712 // Else if install_monitor_exception | |
713 // installs IllegalMonitorStateException | |
714 // Else | |
715 // no error processing | |
716 void InterpreterMacroAssembler::remove_activation( | |
717 TosState state, | |
718 Register ret_addr, | |
719 bool throw_monitor_exception, | |
720 bool install_monitor_exception, | |
721 bool notify_jvmdi) { | |
722 // Note: Registers rdx xmm0 may be in use for the | |
723 // result check if synchronized method | |
724 Label unlocked, unlock, no_unlock; | |
725 | |
726 // get the value of _do_not_unlock_if_synchronized into rdx | |
727 const Address do_not_unlock_if_synchronized(r15_thread, | |
728 in_bytes(JavaThread::do_not_unlock_if_synchronized_offset())); | |
729 movbool(rdx, do_not_unlock_if_synchronized); | |
730 movbool(do_not_unlock_if_synchronized, false); // reset the flag | |
731 | |
732 // get method access flags | |
304 | 733 movptr(rbx, Address(rbp, frame::interpreter_frame_method_offset * wordSize)); |
0 | 734 movl(rcx, Address(rbx, methodOopDesc::access_flags_offset())); |
735 testl(rcx, JVM_ACC_SYNCHRONIZED); | |
736 jcc(Assembler::zero, unlocked); | |
737 | |
738 // Don't unlock anything if the _do_not_unlock_if_synchronized flag | |
739 // is set. | |
740 testbool(rdx); | |
741 jcc(Assembler::notZero, no_unlock); | |
742 | |
743 // unlock monitor | |
744 push(state); // save result | |
745 | |
746 // BasicObjectLock will be first in list, since this is a | |
747 // synchronized method. However, need to check that the object has | |
748 // not been unlocked by an explicit monitorexit bytecode. | |
749 const Address monitor(rbp, frame::interpreter_frame_initial_sp_offset * | |
750 wordSize - (int) sizeof(BasicObjectLock)); | |
751 // We use c_rarg1 so that if we go slow path it will be the correct | |
752 // register for unlock_object to pass to VM directly | |
304 | 753 lea(c_rarg1, monitor); // address of first monitor |
0 | 754 |
304 | 755 movptr(rax, Address(c_rarg1, BasicObjectLock::obj_offset_in_bytes())); |
756 testptr(rax, rax); | |
0 | 757 jcc(Assembler::notZero, unlock); |
758 | |
759 pop(state); | |
760 if (throw_monitor_exception) { | |
761 // Entry already unlocked, need to throw exception | |
762 call_VM(noreg, CAST_FROM_FN_PTR(address, | |
763 InterpreterRuntime::throw_illegal_monitor_state_exception)); | |
764 should_not_reach_here(); | |
765 } else { | |
766 // Monitor already unlocked during a stack unroll. If requested, | |
767 // install an illegal_monitor_state_exception. Continue with | |
768 // stack unrolling. | |
769 if (install_monitor_exception) { | |
770 call_VM(noreg, CAST_FROM_FN_PTR(address, | |
771 InterpreterRuntime::new_illegal_monitor_state_exception)); | |
772 } | |
773 jmp(unlocked); | |
774 } | |
775 | |
776 bind(unlock); | |
777 unlock_object(c_rarg1); | |
778 pop(state); | |
779 | |
780 // Check that for block-structured locking (i.e., that all locked | |
781 // objects has been unlocked) | |
782 bind(unlocked); | |
783 | |
784 // rax: Might contain return value | |
785 | |
786 // Check that all monitors are unlocked | |
787 { | |
788 Label loop, exception, entry, restart; | |
789 const int entry_size = frame::interpreter_frame_monitor_size() * wordSize; | |
790 const Address monitor_block_top( | |
791 rbp, frame::interpreter_frame_monitor_block_top_offset * wordSize); | |
792 const Address monitor_block_bot( | |
793 rbp, frame::interpreter_frame_initial_sp_offset * wordSize); | |
794 | |
795 bind(restart); | |
796 // We use c_rarg1 so that if we go slow path it will be the correct | |
797 // register for unlock_object to pass to VM directly | |
304 | 798 movptr(c_rarg1, monitor_block_top); // points to current entry, starting |
0 | 799 // with top-most entry |
304 | 800 lea(rbx, monitor_block_bot); // points to word before bottom of |
0 | 801 // monitor block |
802 jmp(entry); | |
803 | |
804 // Entry already locked, need to throw exception | |
805 bind(exception); | |
806 | |
807 if (throw_monitor_exception) { | |
808 // Throw exception | |
809 MacroAssembler::call_VM(noreg, | |
810 CAST_FROM_FN_PTR(address, InterpreterRuntime:: | |
811 throw_illegal_monitor_state_exception)); | |
812 should_not_reach_here(); | |
813 } else { | |
814 // Stack unrolling. Unlock object and install illegal_monitor_exception. | |
815 // Unlock does not block, so don't have to worry about the frame. | |
816 // We don't have to preserve c_rarg1 since we are going to throw an exception. | |
817 | |
818 push(state); | |
819 unlock_object(c_rarg1); | |
820 pop(state); | |
821 | |
822 if (install_monitor_exception) { | |
823 call_VM(noreg, CAST_FROM_FN_PTR(address, | |
824 InterpreterRuntime:: | |
825 new_illegal_monitor_state_exception)); | |
826 } | |
827 | |
828 jmp(restart); | |
829 } | |
830 | |
831 bind(loop); | |
832 // check if current entry is used | |
304 | 833 cmpptr(Address(c_rarg1, BasicObjectLock::obj_offset_in_bytes()), (int32_t) NULL); |
0 | 834 jcc(Assembler::notEqual, exception); |
835 | |
304 | 836 addptr(c_rarg1, entry_size); // otherwise advance to next entry |
0 | 837 bind(entry); |
304 | 838 cmpptr(c_rarg1, rbx); // check if bottom reached |
0 | 839 jcc(Assembler::notEqual, loop); // if not at bottom then check this entry |
840 } | |
841 | |
842 bind(no_unlock); | |
843 | |
844 // jvmti support | |
845 if (notify_jvmdi) { | |
846 notify_method_exit(state, NotifyJVMTI); // preserve TOSCA | |
847 } else { | |
848 notify_method_exit(state, SkipNotifyJVMTI); // preserve TOSCA | |
849 } | |
850 | |
851 // remove activation | |
852 // get sender sp | |
304 | 853 movptr(rbx, |
854 Address(rbp, frame::interpreter_frame_sender_sp_offset * wordSize)); | |
0 | 855 leave(); // remove frame anchor |
304 | 856 pop(ret_addr); // get return address |
857 mov(rsp, rbx); // set sp to sender sp | |
0 | 858 } |
859 | |
304 | 860 #endif // C_INTERP |
861 | |
0 | 862 // Lock object |
863 // | |
864 // Args: | |
865 // c_rarg1: BasicObjectLock to be used for locking | |
866 // | |
867 // Kills: | |
868 // rax | |
869 // c_rarg0, c_rarg1, c_rarg2, c_rarg3, .. (param regs) | |
870 // rscratch1, rscratch2 (scratch regs) | |
871 void InterpreterMacroAssembler::lock_object(Register lock_reg) { | |
872 assert(lock_reg == c_rarg1, "The argument is only for looks. It must be c_rarg1"); | |
873 | |
874 if (UseHeavyMonitors) { | |
875 call_VM(noreg, | |
876 CAST_FROM_FN_PTR(address, InterpreterRuntime::monitorenter), | |
877 lock_reg); | |
878 } else { | |
879 Label done; | |
880 | |
881 const Register swap_reg = rax; // Must use rax for cmpxchg instruction | |
882 const Register obj_reg = c_rarg3; // Will contain the oop | |
883 | |
884 const int obj_offset = BasicObjectLock::obj_offset_in_bytes(); | |
885 const int lock_offset = BasicObjectLock::lock_offset_in_bytes (); | |
886 const int mark_offset = lock_offset + | |
887 BasicLock::displaced_header_offset_in_bytes(); | |
888 | |
889 Label slow_case; | |
890 | |
891 // Load object pointer into obj_reg %c_rarg3 | |
304 | 892 movptr(obj_reg, Address(lock_reg, obj_offset)); |
0 | 893 |
894 if (UseBiasedLocking) { | |
895 biased_locking_enter(lock_reg, obj_reg, swap_reg, rscratch1, false, done, &slow_case); | |
896 } | |
897 | |
898 // Load immediate 1 into swap_reg %rax | |
899 movl(swap_reg, 1); | |
900 | |
901 // Load (object->mark() | 1) into swap_reg %rax | |
304 | 902 orptr(swap_reg, Address(obj_reg, 0)); |
0 | 903 |
904 // Save (object->mark() | 1) into BasicLock's displaced header | |
304 | 905 movptr(Address(lock_reg, mark_offset), swap_reg); |
0 | 906 |
907 assert(lock_offset == 0, | |
908 "displached header must be first word in BasicObjectLock"); | |
909 | |
910 if (os::is_MP()) lock(); | |
304 | 911 cmpxchgptr(lock_reg, Address(obj_reg, 0)); |
0 | 912 if (PrintBiasedLockingStatistics) { |
913 cond_inc32(Assembler::zero, | |
914 ExternalAddress((address) BiasedLocking::fast_path_entry_count_addr())); | |
915 } | |
916 jcc(Assembler::zero, done); | |
917 | |
918 // Test if the oopMark is an obvious stack pointer, i.e., | |
919 // 1) (mark & 7) == 0, and | |
920 // 2) rsp <= mark < mark + os::pagesize() | |
921 // | |
922 // These 3 tests can be done by evaluating the following | |
923 // expression: ((mark - rsp) & (7 - os::vm_page_size())), | |
924 // assuming both stack pointer and pagesize have their | |
925 // least significant 3 bits clear. | |
926 // NOTE: the oopMark is in swap_reg %rax as the result of cmpxchg | |
304 | 927 subptr(swap_reg, rsp); |
928 andptr(swap_reg, 7 - os::vm_page_size()); | |
0 | 929 |
930 // Save the test result, for recursive case, the result is zero | |
304 | 931 movptr(Address(lock_reg, mark_offset), swap_reg); |
0 | 932 |
933 if (PrintBiasedLockingStatistics) { | |
934 cond_inc32(Assembler::zero, | |
935 ExternalAddress((address) BiasedLocking::fast_path_entry_count_addr())); | |
936 } | |
937 jcc(Assembler::zero, done); | |
938 | |
939 bind(slow_case); | |
940 | |
941 // Call the runtime routine for slow case | |
942 call_VM(noreg, | |
943 CAST_FROM_FN_PTR(address, InterpreterRuntime::monitorenter), | |
944 lock_reg); | |
945 | |
946 bind(done); | |
947 } | |
948 } | |
949 | |
950 | |
951 // Unlocks an object. Used in monitorexit bytecode and | |
952 // remove_activation. Throws an IllegalMonitorException if object is | |
953 // not locked by current thread. | |
954 // | |
955 // Args: | |
956 // c_rarg1: BasicObjectLock for lock | |
957 // | |
958 // Kills: | |
959 // rax | |
960 // c_rarg0, c_rarg1, c_rarg2, c_rarg3, ... (param regs) | |
961 // rscratch1, rscratch2 (scratch regs) | |
962 void InterpreterMacroAssembler::unlock_object(Register lock_reg) { | |
963 assert(lock_reg == c_rarg1, "The argument is only for looks. It must be rarg1"); | |
964 | |
965 if (UseHeavyMonitors) { | |
966 call_VM(noreg, | |
967 CAST_FROM_FN_PTR(address, InterpreterRuntime::monitorexit), | |
968 lock_reg); | |
969 } else { | |
970 Label done; | |
971 | |
972 const Register swap_reg = rax; // Must use rax for cmpxchg instruction | |
973 const Register header_reg = c_rarg2; // Will contain the old oopMark | |
974 const Register obj_reg = c_rarg3; // Will contain the oop | |
975 | |
976 save_bcp(); // Save in case of exception | |
977 | |
978 // Convert from BasicObjectLock structure to object and BasicLock | |
979 // structure Store the BasicLock address into %rax | |
304 | 980 lea(swap_reg, Address(lock_reg, BasicObjectLock::lock_offset_in_bytes())); |
0 | 981 |
982 // Load oop into obj_reg(%c_rarg3) | |
304 | 983 movptr(obj_reg, Address(lock_reg, BasicObjectLock::obj_offset_in_bytes())); |
0 | 984 |
985 // Free entry | |
304 | 986 movptr(Address(lock_reg, BasicObjectLock::obj_offset_in_bytes()), (int32_t)NULL_WORD); |
0 | 987 |
988 if (UseBiasedLocking) { | |
989 biased_locking_exit(obj_reg, header_reg, done); | |
990 } | |
991 | |
992 // Load the old header from BasicLock structure | |
304 | 993 movptr(header_reg, Address(swap_reg, |
994 BasicLock::displaced_header_offset_in_bytes())); | |
0 | 995 |
996 // Test for recursion | |
304 | 997 testptr(header_reg, header_reg); |
0 | 998 |
999 // zero for recursive case | |
1000 jcc(Assembler::zero, done); | |
1001 | |
1002 // Atomic swap back the old header | |
1003 if (os::is_MP()) lock(); | |
304 | 1004 cmpxchgptr(header_reg, Address(obj_reg, 0)); |
0 | 1005 |
1006 // zero for recursive case | |
1007 jcc(Assembler::zero, done); | |
1008 | |
1009 // Call the runtime routine for slow case. | |
304 | 1010 movptr(Address(lock_reg, BasicObjectLock::obj_offset_in_bytes()), |
0 | 1011 obj_reg); // restore obj |
1012 call_VM(noreg, | |
1013 CAST_FROM_FN_PTR(address, InterpreterRuntime::monitorexit), | |
1014 lock_reg); | |
1015 | |
1016 bind(done); | |
1017 | |
1018 restore_bcp(); | |
1019 } | |
1020 } | |
1021 | |
304 | 1022 #ifndef CC_INTERP |
0 | 1023 |
1024 void InterpreterMacroAssembler::test_method_data_pointer(Register mdp, | |
1025 Label& zero_continue) { | |
1026 assert(ProfileInterpreter, "must be profiling interpreter"); | |
304 | 1027 movptr(mdp, Address(rbp, frame::interpreter_frame_mdx_offset * wordSize)); |
1028 testptr(mdp, mdp); | |
0 | 1029 jcc(Assembler::zero, zero_continue); |
1030 } | |
1031 | |
1032 | |
1033 // Set the method data pointer for the current bcp. | |
1034 void InterpreterMacroAssembler::set_method_data_pointer_for_bcp() { | |
1035 assert(ProfileInterpreter, "must be profiling interpreter"); | |
1036 Label zero_continue; | |
304 | 1037 push(rax); |
1038 push(rbx); | |
0 | 1039 |
1040 get_method(rbx); | |
1041 // Test MDO to avoid the call if it is NULL. | |
304 | 1042 movptr(rax, Address(rbx, in_bytes(methodOopDesc::method_data_offset()))); |
1043 testptr(rax, rax); | |
0 | 1044 jcc(Assembler::zero, zero_continue); |
1045 | |
1046 // rbx: method | |
1047 // r13: bcp | |
1048 call_VM_leaf(CAST_FROM_FN_PTR(address, InterpreterRuntime::bcp_to_di), rbx, r13); | |
1049 // rax: mdi | |
1050 | |
304 | 1051 movptr(rbx, Address(rbx, in_bytes(methodOopDesc::method_data_offset()))); |
1052 testptr(rbx, rbx); | |
0 | 1053 jcc(Assembler::zero, zero_continue); |
304 | 1054 addptr(rbx, in_bytes(methodDataOopDesc::data_offset())); |
1055 addptr(rbx, rax); | |
1056 movptr(Address(rbp, frame::interpreter_frame_mdx_offset * wordSize), rbx); | |
0 | 1057 |
1058 bind(zero_continue); | |
304 | 1059 pop(rbx); |
1060 pop(rax); | |
0 | 1061 } |
1062 | |
1063 void InterpreterMacroAssembler::verify_method_data_pointer() { | |
1064 assert(ProfileInterpreter, "must be profiling interpreter"); | |
1065 #ifdef ASSERT | |
1066 Label verify_continue; | |
304 | 1067 push(rax); |
1068 push(rbx); | |
1069 push(c_rarg3); | |
1070 push(c_rarg2); | |
0 | 1071 test_method_data_pointer(c_rarg3, verify_continue); // If mdp is zero, continue |
1072 get_method(rbx); | |
1073 | |
1074 // If the mdp is valid, it will point to a DataLayout header which is | |
1075 // consistent with the bcp. The converse is highly probable also. | |
1076 load_unsigned_word(c_rarg2, | |
1077 Address(c_rarg3, in_bytes(DataLayout::bci_offset()))); | |
304 | 1078 addptr(c_rarg2, Address(rbx, methodOopDesc::const_offset())); |
1079 lea(c_rarg2, Address(c_rarg2, constMethodOopDesc::codes_offset())); | |
1080 cmpptr(c_rarg2, r13); | |
0 | 1081 jcc(Assembler::equal, verify_continue); |
1082 // rbx: method | |
1083 // r13: bcp | |
1084 // c_rarg3: mdp | |
1085 call_VM_leaf(CAST_FROM_FN_PTR(address, InterpreterRuntime::verify_mdp), | |
1086 rbx, r13, c_rarg3); | |
1087 bind(verify_continue); | |
304 | 1088 pop(c_rarg2); |
1089 pop(c_rarg3); | |
1090 pop(rbx); | |
1091 pop(rax); | |
0 | 1092 #endif // ASSERT |
1093 } | |
1094 | |
1095 | |
1096 void InterpreterMacroAssembler::set_mdp_data_at(Register mdp_in, | |
1097 int constant, | |
1098 Register value) { | |
1099 assert(ProfileInterpreter, "must be profiling interpreter"); | |
1100 Address data(mdp_in, constant); | |
304 | 1101 movptr(data, value); |
0 | 1102 } |
1103 | |
1104 | |
1105 void InterpreterMacroAssembler::increment_mdp_data_at(Register mdp_in, | |
1106 int constant, | |
1107 bool decrement) { | |
1108 // Counter address | |
1109 Address data(mdp_in, constant); | |
1110 | |
1111 increment_mdp_data_at(data, decrement); | |
1112 } | |
1113 | |
1114 void InterpreterMacroAssembler::increment_mdp_data_at(Address data, | |
1115 bool decrement) { | |
1116 assert(ProfileInterpreter, "must be profiling interpreter"); | |
304 | 1117 // %%% this does 64bit counters at best it is wasting space |
1118 // at worst it is a rare bug when counters overflow | |
0 | 1119 |
1120 if (decrement) { | |
1121 // Decrement the register. Set condition codes. | |
304 | 1122 addptr(data, (int32_t) -DataLayout::counter_increment); |
0 | 1123 // If the decrement causes the counter to overflow, stay negative |
1124 Label L; | |
1125 jcc(Assembler::negative, L); | |
304 | 1126 addptr(data, (int32_t) DataLayout::counter_increment); |
0 | 1127 bind(L); |
1128 } else { | |
1129 assert(DataLayout::counter_increment == 1, | |
1130 "flow-free idiom only works with 1"); | |
1131 // Increment the register. Set carry flag. | |
304 | 1132 addptr(data, DataLayout::counter_increment); |
0 | 1133 // If the increment causes the counter to overflow, pull back by 1. |
304 | 1134 sbbptr(data, (int32_t)0); |
0 | 1135 } |
1136 } | |
1137 | |
1138 | |
1139 void InterpreterMacroAssembler::increment_mdp_data_at(Register mdp_in, | |
1140 Register reg, | |
1141 int constant, | |
1142 bool decrement) { | |
1143 Address data(mdp_in, reg, Address::times_1, constant); | |
1144 | |
1145 increment_mdp_data_at(data, decrement); | |
1146 } | |
1147 | |
1148 void InterpreterMacroAssembler::set_mdp_flag_at(Register mdp_in, | |
1149 int flag_byte_constant) { | |
1150 assert(ProfileInterpreter, "must be profiling interpreter"); | |
1151 int header_offset = in_bytes(DataLayout::header_offset()); | |
1152 int header_bits = DataLayout::flag_mask_to_header_mask(flag_byte_constant); | |
1153 // Set the flag | |
1154 orl(Address(mdp_in, header_offset), header_bits); | |
1155 } | |
1156 | |
1157 | |
1158 | |
1159 void InterpreterMacroAssembler::test_mdp_data_at(Register mdp_in, | |
1160 int offset, | |
1161 Register value, | |
1162 Register test_value_out, | |
1163 Label& not_equal_continue) { | |
1164 assert(ProfileInterpreter, "must be profiling interpreter"); | |
1165 if (test_value_out == noreg) { | |
304 | 1166 cmpptr(value, Address(mdp_in, offset)); |
0 | 1167 } else { |
1168 // Put the test value into a register, so caller can use it: | |
304 | 1169 movptr(test_value_out, Address(mdp_in, offset)); |
1170 cmpptr(test_value_out, value); | |
0 | 1171 } |
1172 jcc(Assembler::notEqual, not_equal_continue); | |
1173 } | |
1174 | |
1175 | |
1176 void InterpreterMacroAssembler::update_mdp_by_offset(Register mdp_in, | |
1177 int offset_of_disp) { | |
1178 assert(ProfileInterpreter, "must be profiling interpreter"); | |
1179 Address disp_address(mdp_in, offset_of_disp); | |
304 | 1180 addptr(mdp_in, disp_address); |
1181 movptr(Address(rbp, frame::interpreter_frame_mdx_offset * wordSize), mdp_in); | |
0 | 1182 } |
1183 | |
1184 | |
1185 void InterpreterMacroAssembler::update_mdp_by_offset(Register mdp_in, | |
1186 Register reg, | |
1187 int offset_of_disp) { | |
1188 assert(ProfileInterpreter, "must be profiling interpreter"); | |
1189 Address disp_address(mdp_in, reg, Address::times_1, offset_of_disp); | |
304 | 1190 addptr(mdp_in, disp_address); |
1191 movptr(Address(rbp, frame::interpreter_frame_mdx_offset * wordSize), mdp_in); | |
0 | 1192 } |
1193 | |
1194 | |
1195 void InterpreterMacroAssembler::update_mdp_by_constant(Register mdp_in, | |
1196 int constant) { | |
1197 assert(ProfileInterpreter, "must be profiling interpreter"); | |
304 | 1198 addptr(mdp_in, constant); |
1199 movptr(Address(rbp, frame::interpreter_frame_mdx_offset * wordSize), mdp_in); | |
0 | 1200 } |
1201 | |
1202 | |
1203 void InterpreterMacroAssembler::update_mdp_for_ret(Register return_bci) { | |
1204 assert(ProfileInterpreter, "must be profiling interpreter"); | |
304 | 1205 push(return_bci); // save/restore across call_VM |
0 | 1206 call_VM(noreg, |
1207 CAST_FROM_FN_PTR(address, InterpreterRuntime::update_mdp_for_ret), | |
1208 return_bci); | |
304 | 1209 pop(return_bci); |
0 | 1210 } |
1211 | |
1212 | |
1213 void InterpreterMacroAssembler::profile_taken_branch(Register mdp, | |
1214 Register bumped_count) { | |
1215 if (ProfileInterpreter) { | |
1216 Label profile_continue; | |
1217 | |
1218 // If no method data exists, go to profile_continue. | |
1219 // Otherwise, assign to mdp | |
1220 test_method_data_pointer(mdp, profile_continue); | |
1221 | |
1222 // We are taking a branch. Increment the taken count. | |
1223 // We inline increment_mdp_data_at to return bumped_count in a register | |
1224 //increment_mdp_data_at(mdp, in_bytes(JumpData::taken_offset())); | |
1225 Address data(mdp, in_bytes(JumpData::taken_offset())); | |
304 | 1226 movptr(bumped_count, data); |
0 | 1227 assert(DataLayout::counter_increment == 1, |
1228 "flow-free idiom only works with 1"); | |
304 | 1229 addptr(bumped_count, DataLayout::counter_increment); |
1230 sbbptr(bumped_count, 0); | |
1231 movptr(data, bumped_count); // Store back out | |
0 | 1232 |
1233 // The method data pointer needs to be updated to reflect the new target. | |
1234 update_mdp_by_offset(mdp, in_bytes(JumpData::displacement_offset())); | |
1235 bind(profile_continue); | |
1236 } | |
1237 } | |
1238 | |
1239 | |
1240 void InterpreterMacroAssembler::profile_not_taken_branch(Register mdp) { | |
1241 if (ProfileInterpreter) { | |
1242 Label profile_continue; | |
1243 | |
1244 // If no method data exists, go to profile_continue. | |
1245 test_method_data_pointer(mdp, profile_continue); | |
1246 | |
1247 // We are taking a branch. Increment the not taken count. | |
1248 increment_mdp_data_at(mdp, in_bytes(BranchData::not_taken_offset())); | |
1249 | |
1250 // The method data pointer needs to be updated to correspond to | |
1251 // the next bytecode | |
1252 update_mdp_by_constant(mdp, in_bytes(BranchData::branch_data_size())); | |
1253 bind(profile_continue); | |
1254 } | |
1255 } | |
1256 | |
1257 | |
1258 void InterpreterMacroAssembler::profile_call(Register mdp) { | |
1259 if (ProfileInterpreter) { | |
1260 Label profile_continue; | |
1261 | |
1262 // If no method data exists, go to profile_continue. | |
1263 test_method_data_pointer(mdp, profile_continue); | |
1264 | |
1265 // We are making a call. Increment the count. | |
1266 increment_mdp_data_at(mdp, in_bytes(CounterData::count_offset())); | |
1267 | |
1268 // The method data pointer needs to be updated to reflect the new target. | |
1269 update_mdp_by_constant(mdp, in_bytes(CounterData::counter_data_size())); | |
1270 bind(profile_continue); | |
1271 } | |
1272 } | |
1273 | |
1274 | |
1275 void InterpreterMacroAssembler::profile_final_call(Register mdp) { | |
1276 if (ProfileInterpreter) { | |
1277 Label profile_continue; | |
1278 | |
1279 // If no method data exists, go to profile_continue. | |
1280 test_method_data_pointer(mdp, profile_continue); | |
1281 | |
1282 // We are making a call. Increment the count. | |
1283 increment_mdp_data_at(mdp, in_bytes(CounterData::count_offset())); | |
1284 | |
1285 // The method data pointer needs to be updated to reflect the new target. | |
1286 update_mdp_by_constant(mdp, | |
1287 in_bytes(VirtualCallData:: | |
1288 virtual_call_data_size())); | |
1289 bind(profile_continue); | |
1290 } | |
1291 } | |
1292 | |
1293 | |
1294 void InterpreterMacroAssembler::profile_virtual_call(Register receiver, | |
1295 Register mdp, | |
1296 Register reg2) { | |
1297 if (ProfileInterpreter) { | |
1298 Label profile_continue; | |
1299 | |
1300 // If no method data exists, go to profile_continue. | |
1301 test_method_data_pointer(mdp, profile_continue); | |
1302 | |
1303 // We are making a call. Increment the count. | |
1304 increment_mdp_data_at(mdp, in_bytes(CounterData::count_offset())); | |
1305 | |
1306 // Record the receiver type. | |
1307 record_klass_in_profile(receiver, mdp, reg2); | |
1308 | |
1309 // The method data pointer needs to be updated to reflect the new target. | |
1310 update_mdp_by_constant(mdp, | |
1311 in_bytes(VirtualCallData:: | |
1312 virtual_call_data_size())); | |
1313 bind(profile_continue); | |
1314 } | |
1315 } | |
1316 | |
1317 // This routine creates a state machine for updating the multi-row | |
1318 // type profile at a virtual call site (or other type-sensitive bytecode). | |
1319 // The machine visits each row (of receiver/count) until the receiver type | |
1320 // is found, or until it runs out of rows. At the same time, it remembers | |
1321 // the location of the first empty row. (An empty row records null for its | |
1322 // receiver, and can be allocated for a newly-observed receiver type.) | |
1323 // Because there are two degrees of freedom in the state, a simple linear | |
1324 // search will not work; it must be a decision tree. Hence this helper | |
1325 // function is recursive, to generate the required tree structured code. | |
1326 // It's the interpreter, so we are trading off code space for speed. | |
1327 // See below for example code. | |
1328 void InterpreterMacroAssembler::record_klass_in_profile_helper( | |
1329 Register receiver, Register mdp, | |
1330 Register reg2, | |
1331 int start_row, Label& done) { | |
1332 int last_row = VirtualCallData::row_limit() - 1; | |
1333 assert(start_row <= last_row, "must be work left to do"); | |
1334 // Test this row for both the receiver and for null. | |
1335 // Take any of three different outcomes: | |
1336 // 1. found receiver => increment count and goto done | |
1337 // 2. found null => keep looking for case 1, maybe allocate this cell | |
1338 // 3. found something else => keep looking for cases 1 and 2 | |
1339 // Case 3 is handled by a recursive call. | |
1340 for (int row = start_row; row <= last_row; row++) { | |
1341 Label next_test; | |
1342 bool test_for_null_also = (row == start_row); | |
1343 | |
1344 // See if the receiver is receiver[n]. | |
1345 int recvr_offset = in_bytes(VirtualCallData::receiver_offset(row)); | |
1346 test_mdp_data_at(mdp, recvr_offset, receiver, | |
1347 (test_for_null_also ? reg2 : noreg), | |
1348 next_test); | |
1349 // (Reg2 now contains the receiver from the CallData.) | |
1350 | |
1351 // The receiver is receiver[n]. Increment count[n]. | |
1352 int count_offset = in_bytes(VirtualCallData::receiver_count_offset(row)); | |
1353 increment_mdp_data_at(mdp, count_offset); | |
1354 jmp(done); | |
1355 bind(next_test); | |
1356 | |
1357 if (test_for_null_also) { | |
1358 // Failed the equality check on receiver[n]... Test for null. | |
304 | 1359 testptr(reg2, reg2); |
0 | 1360 if (start_row == last_row) { |
1361 // The only thing left to do is handle the null case. | |
1362 jcc(Assembler::notZero, done); | |
1363 break; | |
1364 } | |
1365 // Since null is rare, make it be the branch-taken case. | |
1366 Label found_null; | |
1367 jcc(Assembler::zero, found_null); | |
1368 | |
1369 // Put all the "Case 3" tests here. | |
1370 record_klass_in_profile_helper(receiver, mdp, reg2, start_row + 1, done); | |
1371 | |
1372 // Found a null. Keep searching for a matching receiver, | |
1373 // but remember that this is an empty (unused) slot. | |
1374 bind(found_null); | |
1375 } | |
1376 } | |
1377 | |
1378 // In the fall-through case, we found no matching receiver, but we | |
1379 // observed the receiver[start_row] is NULL. | |
1380 | |
1381 // Fill in the receiver field and increment the count. | |
1382 int recvr_offset = in_bytes(VirtualCallData::receiver_offset(start_row)); | |
1383 set_mdp_data_at(mdp, recvr_offset, receiver); | |
1384 int count_offset = in_bytes(VirtualCallData::receiver_count_offset(start_row)); | |
1385 movl(reg2, DataLayout::counter_increment); | |
1386 set_mdp_data_at(mdp, count_offset, reg2); | |
1387 jmp(done); | |
1388 } | |
1389 | |
1390 // Example state machine code for three profile rows: | |
1391 // // main copy of decision tree, rooted at row[1] | |
1392 // if (row[0].rec == rec) { row[0].incr(); goto done; } | |
1393 // if (row[0].rec != NULL) { | |
1394 // // inner copy of decision tree, rooted at row[1] | |
1395 // if (row[1].rec == rec) { row[1].incr(); goto done; } | |
1396 // if (row[1].rec != NULL) { | |
1397 // // degenerate decision tree, rooted at row[2] | |
1398 // if (row[2].rec == rec) { row[2].incr(); goto done; } | |
1399 // if (row[2].rec != NULL) { goto done; } // overflow | |
1400 // row[2].init(rec); goto done; | |
1401 // } else { | |
1402 // // remember row[1] is empty | |
1403 // if (row[2].rec == rec) { row[2].incr(); goto done; } | |
1404 // row[1].init(rec); goto done; | |
1405 // } | |
1406 // } else { | |
1407 // // remember row[0] is empty | |
1408 // if (row[1].rec == rec) { row[1].incr(); goto done; } | |
1409 // if (row[2].rec == rec) { row[2].incr(); goto done; } | |
1410 // row[0].init(rec); goto done; | |
1411 // } | |
1412 | |
1413 void InterpreterMacroAssembler::record_klass_in_profile(Register receiver, | |
1414 Register mdp, | |
1415 Register reg2) { | |
1416 assert(ProfileInterpreter, "must be profiling"); | |
1417 Label done; | |
1418 | |
1419 record_klass_in_profile_helper(receiver, mdp, reg2, 0, done); | |
1420 | |
1421 bind (done); | |
1422 } | |
1423 | |
1424 void InterpreterMacroAssembler::profile_ret(Register return_bci, | |
1425 Register mdp) { | |
1426 if (ProfileInterpreter) { | |
1427 Label profile_continue; | |
1428 uint row; | |
1429 | |
1430 // If no method data exists, go to profile_continue. | |
1431 test_method_data_pointer(mdp, profile_continue); | |
1432 | |
1433 // Update the total ret count. | |
1434 increment_mdp_data_at(mdp, in_bytes(CounterData::count_offset())); | |
1435 | |
1436 for (row = 0; row < RetData::row_limit(); row++) { | |
1437 Label next_test; | |
1438 | |
1439 // See if return_bci is equal to bci[n]: | |
1440 test_mdp_data_at(mdp, | |
1441 in_bytes(RetData::bci_offset(row)), | |
1442 return_bci, noreg, | |
1443 next_test); | |
1444 | |
1445 // return_bci is equal to bci[n]. Increment the count. | |
1446 increment_mdp_data_at(mdp, in_bytes(RetData::bci_count_offset(row))); | |
1447 | |
1448 // The method data pointer needs to be updated to reflect the new target. | |
1449 update_mdp_by_offset(mdp, | |
1450 in_bytes(RetData::bci_displacement_offset(row))); | |
1451 jmp(profile_continue); | |
1452 bind(next_test); | |
1453 } | |
1454 | |
1455 update_mdp_for_ret(return_bci); | |
1456 | |
1457 bind(profile_continue); | |
1458 } | |
1459 } | |
1460 | |
1461 | |
1462 void InterpreterMacroAssembler::profile_null_seen(Register mdp) { | |
1463 if (ProfileInterpreter) { | |
1464 Label profile_continue; | |
1465 | |
1466 // If no method data exists, go to profile_continue. | |
1467 test_method_data_pointer(mdp, profile_continue); | |
1468 | |
1469 // The method data pointer needs to be updated. | |
1470 int mdp_delta = in_bytes(BitData::bit_data_size()); | |
1471 if (TypeProfileCasts) { | |
1472 mdp_delta = in_bytes(VirtualCallData::virtual_call_data_size()); | |
1473 } | |
1474 update_mdp_by_constant(mdp, mdp_delta); | |
1475 | |
1476 bind(profile_continue); | |
1477 } | |
1478 } | |
1479 | |
1480 | |
1481 void InterpreterMacroAssembler::profile_typecheck_failed(Register mdp) { | |
1482 if (ProfileInterpreter && TypeProfileCasts) { | |
1483 Label profile_continue; | |
1484 | |
1485 // If no method data exists, go to profile_continue. | |
1486 test_method_data_pointer(mdp, profile_continue); | |
1487 | |
1488 int count_offset = in_bytes(CounterData::count_offset()); | |
1489 // Back up the address, since we have already bumped the mdp. | |
1490 count_offset -= in_bytes(VirtualCallData::virtual_call_data_size()); | |
1491 | |
1492 // *Decrement* the counter. We expect to see zero or small negatives. | |
1493 increment_mdp_data_at(mdp, count_offset, true); | |
1494 | |
1495 bind (profile_continue); | |
1496 } | |
1497 } | |
1498 | |
1499 | |
1500 void InterpreterMacroAssembler::profile_typecheck(Register mdp, Register klass, Register reg2) { | |
1501 if (ProfileInterpreter) { | |
1502 Label profile_continue; | |
1503 | |
1504 // If no method data exists, go to profile_continue. | |
1505 test_method_data_pointer(mdp, profile_continue); | |
1506 | |
1507 // The method data pointer needs to be updated. | |
1508 int mdp_delta = in_bytes(BitData::bit_data_size()); | |
1509 if (TypeProfileCasts) { | |
1510 mdp_delta = in_bytes(VirtualCallData::virtual_call_data_size()); | |
1511 | |
1512 // Record the object type. | |
1513 record_klass_in_profile(klass, mdp, reg2); | |
1514 } | |
1515 update_mdp_by_constant(mdp, mdp_delta); | |
1516 | |
1517 bind(profile_continue); | |
1518 } | |
1519 } | |
1520 | |
1521 | |
1522 void InterpreterMacroAssembler::profile_switch_default(Register mdp) { | |
1523 if (ProfileInterpreter) { | |
1524 Label profile_continue; | |
1525 | |
1526 // If no method data exists, go to profile_continue. | |
1527 test_method_data_pointer(mdp, profile_continue); | |
1528 | |
1529 // Update the default case count | |
1530 increment_mdp_data_at(mdp, | |
1531 in_bytes(MultiBranchData::default_count_offset())); | |
1532 | |
1533 // The method data pointer needs to be updated. | |
1534 update_mdp_by_offset(mdp, | |
1535 in_bytes(MultiBranchData:: | |
1536 default_displacement_offset())); | |
1537 | |
1538 bind(profile_continue); | |
1539 } | |
1540 } | |
1541 | |
1542 | |
1543 void InterpreterMacroAssembler::profile_switch_case(Register index, | |
1544 Register mdp, | |
1545 Register reg2) { | |
1546 if (ProfileInterpreter) { | |
1547 Label profile_continue; | |
1548 | |
1549 // If no method data exists, go to profile_continue. | |
1550 test_method_data_pointer(mdp, profile_continue); | |
1551 | |
1552 // Build the base (index * per_case_size_in_bytes()) + | |
1553 // case_array_offset_in_bytes() | |
1554 movl(reg2, in_bytes(MultiBranchData::per_case_size())); | |
304 | 1555 imulptr(index, reg2); // XXX l ? |
1556 addptr(index, in_bytes(MultiBranchData::case_array_offset())); // XXX l ? | |
0 | 1557 |
1558 // Update the case count | |
1559 increment_mdp_data_at(mdp, | |
1560 index, | |
1561 in_bytes(MultiBranchData::relative_count_offset())); | |
1562 | |
1563 // The method data pointer needs to be updated. | |
1564 update_mdp_by_offset(mdp, | |
1565 index, | |
1566 in_bytes(MultiBranchData:: | |
1567 relative_displacement_offset())); | |
1568 | |
1569 bind(profile_continue); | |
1570 } | |
1571 } | |
1572 | |
1573 | |
304 | 1574 |
0 | 1575 void InterpreterMacroAssembler::verify_oop(Register reg, TosState state) { |
1576 if (state == atos) { | |
1577 MacroAssembler::verify_oop(reg); | |
1578 } | |
1579 } | |
1580 | |
1581 void InterpreterMacroAssembler::verify_FPU(int stack_depth, TosState state) { | |
1582 } | |
304 | 1583 #endif // !CC_INTERP |
0 | 1584 |
1585 | |
1586 void InterpreterMacroAssembler::notify_method_entry() { | |
1587 // Whenever JVMTI is interp_only_mode, method entry/exit events are sent to | |
1588 // track stack depth. If it is possible to enter interp_only_mode we add | |
1589 // the code to check if the event should be sent. | |
1590 if (JvmtiExport::can_post_interpreter_events()) { | |
1591 Label L; | |
1592 movl(rdx, Address(r15_thread, JavaThread::interp_only_mode_offset())); | |
1593 testl(rdx, rdx); | |
1594 jcc(Assembler::zero, L); | |
1595 call_VM(noreg, CAST_FROM_FN_PTR(address, | |
1596 InterpreterRuntime::post_method_entry)); | |
1597 bind(L); | |
1598 } | |
1599 | |
1600 { | |
1601 SkipIfEqual skip(this, &DTraceMethodProbes, false); | |
1602 get_method(c_rarg1); | |
1603 call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::dtrace_method_entry), | |
1604 r15_thread, c_rarg1); | |
1605 } | |
1606 } | |
1607 | |
1608 | |
1609 void InterpreterMacroAssembler::notify_method_exit( | |
1610 TosState state, NotifyMethodExitMode mode) { | |
1611 // Whenever JVMTI is interp_only_mode, method entry/exit events are sent to | |
1612 // track stack depth. If it is possible to enter interp_only_mode we add | |
1613 // the code to check if the event should be sent. | |
1614 if (mode == NotifyJVMTI && JvmtiExport::can_post_interpreter_events()) { | |
1615 Label L; | |
1616 // Note: frame::interpreter_frame_result has a dependency on how the | |
1617 // method result is saved across the call to post_method_exit. If this | |
1618 // is changed then the interpreter_frame_result implementation will | |
1619 // need to be updated too. | |
304 | 1620 |
1621 // For c++ interpreter the result is always stored at a known location in the frame | |
1622 // template interpreter will leave it on the top of the stack. | |
1623 NOT_CC_INTERP(push(state);) | |
0 | 1624 movl(rdx, Address(r15_thread, JavaThread::interp_only_mode_offset())); |
1625 testl(rdx, rdx); | |
1626 jcc(Assembler::zero, L); | |
1627 call_VM(noreg, | |
1628 CAST_FROM_FN_PTR(address, InterpreterRuntime::post_method_exit)); | |
1629 bind(L); | |
304 | 1630 NOT_CC_INTERP(pop(state)); |
0 | 1631 } |
1632 | |
1633 { | |
1634 SkipIfEqual skip(this, &DTraceMethodProbes, false); | |
304 | 1635 NOT_CC_INTERP(push(state)); |
0 | 1636 get_method(c_rarg1); |
1637 call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::dtrace_method_exit), | |
1638 r15_thread, c_rarg1); | |
304 | 1639 NOT_CC_INTERP(pop(state)); |
0 | 1640 } |
1641 } |