Mercurial > hg > graal-compiler
annotate src/cpu/x86/vm/interp_masm_x86_32.cpp @ 1842:6e0aac35bfa9
6980838: G1: guarantee(false) failed: thread has an unexpected active value in its SATB queue
Summary: Under certain circumstances a safepoint could happen between a JavaThread object being created and that object being added to the Java threads list. This could cause the active field of that thread's SATB queue to get out-of-sync with respect to the other Java threads. The solution is to activate the SATB queue, when necessary, before adding the thread to the Java threads list, not when the JavaThread object is created. The changeset also includes a small fix to rename the surrogate locker thread from "Surrogate Locker Thread (CMS)" to "Surrogate Locker Thread (Concurrent GC)" since it's also used in G1.
Reviewed-by: iveresov, ysr, johnc, jcoomes
author | tonyp |
---|---|
date | Fri, 01 Oct 2010 16:43:05 -0400 |
parents | e9ff18c4ace7 |
children | d5d065957597 |
rev | line source |
---|---|
0 | 1 /* |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1506
diff
changeset
|
2 * Copyright (c) 1997, 2010, Oracle and/or its affiliates. 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 * | |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1506
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1506
diff
changeset
|
20 * or visit www.oracle.com if you need additional information or have any |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1506
diff
changeset
|
21 * questions. |
0 | 22 * |
23 */ | |
24 | |
25 #include "incls/_precompiled.incl" | |
26 #include "incls/_interp_masm_x86_32.cpp.incl" | |
27 | |
28 | |
29 // Implementation of InterpreterMacroAssembler | |
30 #ifdef CC_INTERP | |
31 void InterpreterMacroAssembler::get_method(Register reg) { | |
304 | 32 movptr(reg, Address(rbp, -(sizeof(BytecodeInterpreter) + 2 * wordSize))); |
33 movptr(reg, Address(reg, byte_offset_of(BytecodeInterpreter, _method))); | |
0 | 34 } |
35 #endif // CC_INTERP | |
36 | |
37 | |
38 #ifndef CC_INTERP | |
39 void InterpreterMacroAssembler::call_VM_leaf_base( | |
40 address entry_point, | |
41 int number_of_arguments | |
42 ) { | |
43 // interpreter specific | |
44 // | |
45 // Note: No need to save/restore bcp & locals (rsi & rdi) pointer | |
46 // since these are callee saved registers and no blocking/ | |
47 // GC can happen in leaf calls. | |
48 // Further Note: DO NOT save/restore bcp/locals. If a caller has | |
49 // already saved them so that it can use rsi/rdi as temporaries | |
50 // then a save/restore here will DESTROY the copy the caller | |
51 // saved! There used to be a save_bcp() that only happened in | |
52 // the ASSERT path (no restore_bcp). Which caused bizarre failures | |
53 // when jvm built with ASSERTs. | |
54 #ifdef ASSERT | |
55 { Label L; | |
304 | 56 cmpptr(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), (int32_t)NULL_WORD); |
0 | 57 jcc(Assembler::equal, L); |
58 stop("InterpreterMacroAssembler::call_VM_leaf_base: last_sp != NULL"); | |
59 bind(L); | |
60 } | |
61 #endif | |
62 // super call | |
63 MacroAssembler::call_VM_leaf_base(entry_point, number_of_arguments); | |
64 // interpreter specific | |
65 | |
66 // Used to ASSERT that rsi/rdi were equal to frame's bcp/locals | |
67 // but since they may not have been saved (and we don't want to | |
68 // save them here (see note above) the assert is invalid. | |
69 } | |
70 | |
71 | |
72 void InterpreterMacroAssembler::call_VM_base( | |
73 Register oop_result, | |
74 Register java_thread, | |
75 Register last_java_sp, | |
76 address entry_point, | |
77 int number_of_arguments, | |
78 bool check_exceptions | |
79 ) { | |
80 #ifdef ASSERT | |
81 { Label L; | |
304 | 82 cmpptr(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), (int32_t)NULL_WORD); |
0 | 83 jcc(Assembler::equal, L); |
84 stop("InterpreterMacroAssembler::call_VM_base: last_sp != NULL"); | |
85 bind(L); | |
86 } | |
87 #endif /* ASSERT */ | |
88 // interpreter specific | |
89 // | |
90 // Note: Could avoid restoring locals ptr (callee saved) - however doesn't | |
91 // really make a difference for these runtime calls, since they are | |
92 // slow anyway. Btw., bcp must be saved/restored since it may change | |
93 // due to GC. | |
94 assert(java_thread == noreg , "not expecting a precomputed java thread"); | |
95 save_bcp(); | |
96 // super call | |
97 MacroAssembler::call_VM_base(oop_result, java_thread, last_java_sp, entry_point, number_of_arguments, check_exceptions); | |
98 // interpreter specific | |
99 restore_bcp(); | |
100 restore_locals(); | |
101 } | |
102 | |
103 | |
104 void InterpreterMacroAssembler::check_and_handle_popframe(Register java_thread) { | |
105 if (JvmtiExport::can_pop_frame()) { | |
106 Label L; | |
107 // Initiate popframe handling only if it is not already being processed. If the flag | |
108 // has the popframe_processing bit set, it means that this code is called *during* popframe | |
109 // handling - we don't want to reenter. | |
110 Register pop_cond = java_thread; // Not clear if any other register is available... | |
111 movl(pop_cond, Address(java_thread, JavaThread::popframe_condition_offset())); | |
112 testl(pop_cond, JavaThread::popframe_pending_bit); | |
113 jcc(Assembler::zero, L); | |
114 testl(pop_cond, JavaThread::popframe_processing_bit); | |
115 jcc(Assembler::notZero, L); | |
116 // Call Interpreter::remove_activation_preserving_args_entry() to get the | |
117 // address of the same-named entrypoint in the generated interpreter code. | |
118 call_VM_leaf(CAST_FROM_FN_PTR(address, Interpreter::remove_activation_preserving_args_entry)); | |
119 jmp(rax); | |
120 bind(L); | |
121 get_thread(java_thread); | |
122 } | |
123 } | |
124 | |
125 | |
126 void InterpreterMacroAssembler::load_earlyret_value(TosState state) { | |
127 get_thread(rcx); | |
128 movl(rcx, Address(rcx, JavaThread::jvmti_thread_state_offset())); | |
129 const Address tos_addr (rcx, JvmtiThreadState::earlyret_tos_offset()); | |
130 const Address oop_addr (rcx, JvmtiThreadState::earlyret_oop_offset()); | |
131 const Address val_addr (rcx, JvmtiThreadState::earlyret_value_offset()); | |
132 const Address val_addr1(rcx, JvmtiThreadState::earlyret_value_offset() | |
133 + in_ByteSize(wordSize)); | |
134 switch (state) { | |
304 | 135 case atos: movptr(rax, oop_addr); |
512
db4caa99ef11
6787106: Hotspot 32 bit build fails on platforms having different definitions for intptr_t & int32_t
xlu
parents:
337
diff
changeset
|
136 movptr(oop_addr, NULL_WORD); |
0 | 137 verify_oop(rax, state); break; |
304 | 138 case ltos: |
139 movl(rdx, val_addr1); // fall through | |
0 | 140 case btos: // fall through |
141 case ctos: // fall through | |
142 case stos: // fall through | |
143 case itos: movl(rax, val_addr); break; | |
144 case ftos: fld_s(val_addr); break; | |
145 case dtos: fld_d(val_addr); break; | |
146 case vtos: /* nothing to do */ break; | |
147 default : ShouldNotReachHere(); | |
148 } | |
149 // Clean up tos value in the thread object | |
304 | 150 movl(tos_addr, (int32_t) ilgl); |
512
db4caa99ef11
6787106: Hotspot 32 bit build fails on platforms having different definitions for intptr_t & int32_t
xlu
parents:
337
diff
changeset
|
151 movptr(val_addr, NULL_WORD); |
533
dc3ad84615cf
6795913: A few remaining wrong casts need to be fixed for building hotspot successfully on Mac OS.
xlu
parents:
512
diff
changeset
|
152 NOT_LP64(movptr(val_addr1, NULL_WORD)); |
0 | 153 } |
154 | |
155 | |
156 void InterpreterMacroAssembler::check_and_handle_earlyret(Register java_thread) { | |
157 if (JvmtiExport::can_force_early_return()) { | |
158 Label L; | |
159 Register tmp = java_thread; | |
304 | 160 movptr(tmp, Address(tmp, JavaThread::jvmti_thread_state_offset())); |
161 testptr(tmp, tmp); | |
0 | 162 jcc(Assembler::zero, L); // if (thread->jvmti_thread_state() == NULL) exit; |
163 | |
164 // Initiate earlyret handling only if it is not already being processed. | |
165 // If the flag has the earlyret_processing bit set, it means that this code | |
166 // is called *during* earlyret handling - we don't want to reenter. | |
167 movl(tmp, Address(tmp, JvmtiThreadState::earlyret_state_offset())); | |
168 cmpl(tmp, JvmtiThreadState::earlyret_pending); | |
169 jcc(Assembler::notEqual, L); | |
170 | |
171 // Call Interpreter::remove_activation_early_entry() to get the address of the | |
172 // same-named entrypoint in the generated interpreter code. | |
173 get_thread(java_thread); | |
304 | 174 movptr(tmp, Address(java_thread, JavaThread::jvmti_thread_state_offset())); |
0 | 175 pushl(Address(tmp, JvmtiThreadState::earlyret_tos_offset())); |
176 call_VM_leaf(CAST_FROM_FN_PTR(address, Interpreter::remove_activation_early_entry), 1); | |
177 jmp(rax); | |
178 bind(L); | |
179 get_thread(java_thread); | |
180 } | |
181 } | |
182 | |
183 | |
184 void InterpreterMacroAssembler::get_unsigned_2_byte_index_at_bcp(Register reg, int bcp_offset) { | |
185 assert(bcp_offset >= 0, "bcp is still pointing to start of bytecode"); | |
186 movl(reg, Address(rsi, bcp_offset)); | |
304 | 187 bswapl(reg); |
0 | 188 shrl(reg, 16); |
189 } | |
190 | |
191 | |
1565 | 192 void InterpreterMacroAssembler::get_cache_index_at_bcp(Register reg, int bcp_offset, size_t index_size) { |
0 | 193 assert(bcp_offset > 0, "bcp is still pointing to start of bytecode"); |
1565 | 194 if (index_size == sizeof(u2)) { |
726
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
710
diff
changeset
|
195 load_unsigned_short(reg, Address(rsi, bcp_offset)); |
1565 | 196 } else if (index_size == sizeof(u4)) { |
726
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
710
diff
changeset
|
197 assert(EnableInvokeDynamic, "giant index used only for EnableInvokeDynamic"); |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
710
diff
changeset
|
198 movl(reg, Address(rsi, bcp_offset)); |
1108 | 199 // Check if the secondary index definition is still ~x, otherwise |
200 // we have to change the following assembler code to calculate the | |
201 // plain index. | |
726
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
710
diff
changeset
|
202 assert(constantPoolCacheOopDesc::decode_secondary_index(~123) == 123, "else change next line"); |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
710
diff
changeset
|
203 notl(reg); // convert to plain index |
1565 | 204 } else if (index_size == sizeof(u1)) { |
205 assert(EnableMethodHandles, "tiny index used only for EnableMethodHandles"); | |
206 load_unsigned_byte(reg, Address(rsi, bcp_offset)); | |
207 } else { | |
208 ShouldNotReachHere(); | |
726
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
710
diff
changeset
|
209 } |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
710
diff
changeset
|
210 } |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
710
diff
changeset
|
211 |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
710
diff
changeset
|
212 |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
710
diff
changeset
|
213 void InterpreterMacroAssembler::get_cache_and_index_at_bcp(Register cache, Register index, |
1565 | 214 int bcp_offset, size_t index_size) { |
0 | 215 assert(cache != index, "must use different registers"); |
1565 | 216 get_cache_index_at_bcp(index, bcp_offset, index_size); |
304 | 217 movptr(cache, Address(rbp, frame::interpreter_frame_cache_offset * wordSize)); |
0 | 218 assert(sizeof(ConstantPoolCacheEntry) == 4*wordSize, "adjust code below"); |
304 | 219 shlptr(index, 2); // convert from field index to ConstantPoolCacheEntry index |
0 | 220 } |
221 | |
222 | |
726
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
710
diff
changeset
|
223 void InterpreterMacroAssembler::get_cache_entry_pointer_at_bcp(Register cache, Register tmp, |
1565 | 224 int bcp_offset, size_t index_size) { |
0 | 225 assert(cache != tmp, "must use different register"); |
1565 | 226 get_cache_index_at_bcp(tmp, bcp_offset, index_size); |
0 | 227 assert(sizeof(ConstantPoolCacheEntry) == 4*wordSize, "adjust code below"); |
228 // convert from field index to ConstantPoolCacheEntry index | |
229 // and from word offset to byte offset | |
230 shll(tmp, 2 + LogBytesPerWord); | |
304 | 231 movptr(cache, Address(rbp, frame::interpreter_frame_cache_offset * wordSize)); |
0 | 232 // skip past the header |
304 | 233 addptr(cache, in_bytes(constantPoolCacheOopDesc::base_offset())); |
234 addptr(cache, tmp); // construct pointer to cache entry | |
0 | 235 } |
236 | |
237 | |
238 // Generate a subtype check: branch to ok_is_subtype if sub_klass is | |
239 // a subtype of super_klass. EAX holds the super_klass. Blows ECX. | |
240 // Resets EDI to locals. Register sub_klass cannot be any of the above. | |
241 void InterpreterMacroAssembler::gen_subtype_check( Register Rsub_klass, Label &ok_is_subtype ) { | |
242 assert( Rsub_klass != rax, "rax, holds superklass" ); | |
644
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
625
diff
changeset
|
243 assert( Rsub_klass != rcx, "used as a temp" ); |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
625
diff
changeset
|
244 assert( Rsub_klass != rdi, "used as a temp, restored from locals" ); |
0 | 245 |
246 // Profile the not-null value's klass. | |
644
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
625
diff
changeset
|
247 profile_typecheck(rcx, Rsub_klass, rdi); // blows rcx, reloads rdi |
0 | 248 |
644
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
625
diff
changeset
|
249 // Do the check. |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
625
diff
changeset
|
250 check_klass_subtype(Rsub_klass, rax, rcx, ok_is_subtype); // blows rcx |
0 | 251 |
644
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
625
diff
changeset
|
252 // Profile the failure of the check. |
0 | 253 profile_typecheck_failed(rcx); // blows rcx |
254 } | |
255 | |
256 void InterpreterMacroAssembler::f2ieee() { | |
257 if (IEEEPrecision) { | |
258 fstp_s(Address(rsp, 0)); | |
259 fld_s(Address(rsp, 0)); | |
260 } | |
261 } | |
262 | |
263 | |
264 void InterpreterMacroAssembler::d2ieee() { | |
265 if (IEEEPrecision) { | |
266 fstp_d(Address(rsp, 0)); | |
267 fld_d(Address(rsp, 0)); | |
268 } | |
269 } | |
270 | |
271 // Java Expression Stack | |
272 | |
273 void InterpreterMacroAssembler::pop_ptr(Register r) { | |
304 | 274 pop(r); |
0 | 275 } |
276 | |
277 void InterpreterMacroAssembler::pop_i(Register r) { | |
304 | 278 pop(r); |
0 | 279 } |
280 | |
281 void InterpreterMacroAssembler::pop_l(Register lo, Register hi) { | |
304 | 282 pop(lo); |
283 pop(hi); | |
0 | 284 } |
285 | |
286 void InterpreterMacroAssembler::pop_f() { | |
287 fld_s(Address(rsp, 0)); | |
304 | 288 addptr(rsp, 1 * wordSize); |
0 | 289 } |
290 | |
291 void InterpreterMacroAssembler::pop_d() { | |
292 fld_d(Address(rsp, 0)); | |
304 | 293 addptr(rsp, 2 * wordSize); |
0 | 294 } |
295 | |
296 | |
297 void InterpreterMacroAssembler::pop(TosState state) { | |
298 switch (state) { | |
299 case atos: pop_ptr(rax); break; | |
300 case btos: // fall through | |
301 case ctos: // fall through | |
302 case stos: // fall through | |
303 case itos: pop_i(rax); break; | |
304 case ltos: pop_l(rax, rdx); break; | |
305 case ftos: pop_f(); break; | |
306 case dtos: pop_d(); break; | |
307 case vtos: /* nothing to do */ break; | |
308 default : ShouldNotReachHere(); | |
309 } | |
310 verify_oop(rax, state); | |
311 } | |
312 | |
313 void InterpreterMacroAssembler::push_ptr(Register r) { | |
304 | 314 push(r); |
0 | 315 } |
316 | |
317 void InterpreterMacroAssembler::push_i(Register r) { | |
304 | 318 push(r); |
0 | 319 } |
320 | |
321 void InterpreterMacroAssembler::push_l(Register lo, Register hi) { | |
304 | 322 push(hi); |
323 push(lo); | |
0 | 324 } |
325 | |
326 void InterpreterMacroAssembler::push_f() { | |
327 // Do not schedule for no AGI! Never write beyond rsp! | |
304 | 328 subptr(rsp, 1 * wordSize); |
0 | 329 fstp_s(Address(rsp, 0)); |
330 } | |
331 | |
332 void InterpreterMacroAssembler::push_d(Register r) { | |
1506 | 333 // Do not schedule for no AGI! Never write beyond rsp! |
334 subptr(rsp, 2 * wordSize); | |
335 fstp_d(Address(rsp, 0)); | |
0 | 336 } |
337 | |
338 | |
339 void InterpreterMacroAssembler::push(TosState state) { | |
340 verify_oop(rax, state); | |
341 switch (state) { | |
342 case atos: push_ptr(rax); break; | |
343 case btos: // fall through | |
344 case ctos: // fall through | |
345 case stos: // fall through | |
346 case itos: push_i(rax); break; | |
347 case ltos: push_l(rax, rdx); break; | |
348 case ftos: push_f(); break; | |
349 case dtos: push_d(rax); break; | |
350 case vtos: /* nothing to do */ break; | |
351 default : ShouldNotReachHere(); | |
352 } | |
353 } | |
354 | |
355 | |
1506 | 356 // Helpers for swap and dup |
357 void InterpreterMacroAssembler::load_ptr(int n, Register val) { | |
304 | 358 movptr(val, Address(rsp, Interpreter::expr_offset_in_bytes(n))); |
0 | 359 } |
360 | |
1506 | 361 void InterpreterMacroAssembler::store_ptr(int n, Register val) { |
362 movptr(Address(rsp, Interpreter::expr_offset_in_bytes(n)), val); | |
0 | 363 } |
364 | |
365 void InterpreterMacroAssembler::super_call_VM_leaf(address entry_point) { | |
366 MacroAssembler::call_VM_leaf_base(entry_point, 0); | |
367 } | |
368 | |
369 | |
370 void InterpreterMacroAssembler::super_call_VM_leaf(address entry_point, Register arg_1) { | |
304 | 371 push(arg_1); |
0 | 372 MacroAssembler::call_VM_leaf_base(entry_point, 1); |
373 } | |
374 | |
375 | |
376 void InterpreterMacroAssembler::super_call_VM_leaf(address entry_point, Register arg_1, Register arg_2) { | |
304 | 377 push(arg_2); |
378 push(arg_1); | |
0 | 379 MacroAssembler::call_VM_leaf_base(entry_point, 2); |
380 } | |
381 | |
382 | |
383 void InterpreterMacroAssembler::super_call_VM_leaf(address entry_point, Register arg_1, Register arg_2, Register arg_3) { | |
304 | 384 push(arg_3); |
385 push(arg_2); | |
386 push(arg_1); | |
0 | 387 MacroAssembler::call_VM_leaf_base(entry_point, 3); |
388 } | |
389 | |
390 | |
710 | 391 void InterpreterMacroAssembler::prepare_to_jump_from_interpreted() { |
0 | 392 // set sender sp |
304 | 393 lea(rsi, Address(rsp, wordSize)); |
0 | 394 // record last_sp |
304 | 395 movptr(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), rsi); |
710 | 396 } |
397 | |
398 | |
399 // Jump to from_interpreted entry of a call unless single stepping is possible | |
400 // in this thread in which case we must call the i2i entry | |
401 void InterpreterMacroAssembler::jump_from_interpreted(Register method, Register temp) { | |
402 prepare_to_jump_from_interpreted(); | |
0 | 403 |
404 if (JvmtiExport::can_post_interpreter_events()) { | |
405 Label run_compiled_code; | |
406 // JVMTI events, such as single-stepping, are implemented partly by avoiding running | |
407 // compiled code in threads for which the event is enabled. Check here for | |
408 // interp_only_mode if these events CAN be enabled. | |
409 get_thread(temp); | |
410 // interp_only is an int, on little endian it is sufficient to test the byte only | |
411 // Is a cmpl faster (ce | |
412 cmpb(Address(temp, JavaThread::interp_only_mode_offset()), 0); | |
413 jcc(Assembler::zero, run_compiled_code); | |
414 jmp(Address(method, methodOopDesc::interpreter_entry_offset())); | |
415 bind(run_compiled_code); | |
416 } | |
417 | |
418 jmp(Address(method, methodOopDesc::from_interpreted_offset())); | |
419 | |
420 } | |
421 | |
422 | |
423 // The following two routines provide a hook so that an implementation | |
424 // can schedule the dispatch in two parts. Intel does not do this. | |
425 void InterpreterMacroAssembler::dispatch_prolog(TosState state, int step) { | |
426 // Nothing Intel-specific to be done here. | |
427 } | |
428 | |
429 void InterpreterMacroAssembler::dispatch_epilog(TosState state, int step) { | |
430 dispatch_next(state, step); | |
431 } | |
432 | |
433 void InterpreterMacroAssembler::dispatch_base(TosState state, address* table, | |
434 bool verifyoop) { | |
435 verify_FPU(1, state); | |
436 if (VerifyActivationFrameSize) { | |
437 Label L; | |
304 | 438 mov(rcx, rbp); |
439 subptr(rcx, rsp); | |
0 | 440 int min_frame_size = (frame::link_offset - frame::interpreter_frame_initial_sp_offset) * wordSize; |
304 | 441 cmpptr(rcx, min_frame_size); |
0 | 442 jcc(Assembler::greaterEqual, L); |
443 stop("broken stack frame"); | |
444 bind(L); | |
445 } | |
446 if (verifyoop) verify_oop(rax, state); | |
304 | 447 Address index(noreg, rbx, Address::times_ptr); |
0 | 448 ExternalAddress tbl((address)table); |
449 ArrayAddress dispatch(tbl, index); | |
450 jump(dispatch); | |
451 } | |
452 | |
453 | |
454 void InterpreterMacroAssembler::dispatch_only(TosState state) { | |
455 dispatch_base(state, Interpreter::dispatch_table(state)); | |
456 } | |
457 | |
458 | |
459 void InterpreterMacroAssembler::dispatch_only_normal(TosState state) { | |
460 dispatch_base(state, Interpreter::normal_table(state)); | |
461 } | |
462 | |
463 void InterpreterMacroAssembler::dispatch_only_noverify(TosState state) { | |
464 dispatch_base(state, Interpreter::normal_table(state), false); | |
465 } | |
466 | |
467 | |
468 void InterpreterMacroAssembler::dispatch_next(TosState state, int step) { | |
469 // load next bytecode (load before advancing rsi to prevent AGI) | |
470 load_unsigned_byte(rbx, Address(rsi, step)); | |
471 // advance rsi | |
472 increment(rsi, step); | |
473 dispatch_base(state, Interpreter::dispatch_table(state)); | |
474 } | |
475 | |
476 | |
477 void InterpreterMacroAssembler::dispatch_via(TosState state, address* table) { | |
478 // load current bytecode | |
479 load_unsigned_byte(rbx, Address(rsi, 0)); | |
480 dispatch_base(state, table); | |
481 } | |
482 | |
483 // remove activation | |
484 // | |
485 // Unlock the receiver if this is a synchronized method. | |
486 // Unlock any Java monitors from syncronized blocks. | |
487 // Remove the activation from the stack. | |
488 // | |
489 // If there are locked Java monitors | |
490 // If throw_monitor_exception | |
491 // throws IllegalMonitorStateException | |
492 // Else if install_monitor_exception | |
493 // installs IllegalMonitorStateException | |
494 // Else | |
495 // no error processing | |
496 void InterpreterMacroAssembler::remove_activation(TosState state, Register ret_addr, | |
497 bool throw_monitor_exception, | |
498 bool install_monitor_exception, | |
499 bool notify_jvmdi) { | |
500 // Note: Registers rax, rdx and FPU ST(0) may be in use for the result | |
501 // check if synchronized method | |
502 Label unlocked, unlock, no_unlock; | |
503 | |
504 get_thread(rcx); | |
505 const Address do_not_unlock_if_synchronized(rcx, | |
506 in_bytes(JavaThread::do_not_unlock_if_synchronized_offset())); | |
507 | |
508 movbool(rbx, do_not_unlock_if_synchronized); | |
304 | 509 mov(rdi,rbx); |
0 | 510 movbool(do_not_unlock_if_synchronized, false); // reset the flag |
511 | |
304 | 512 movptr(rbx, Address(rbp, frame::interpreter_frame_method_offset * wordSize)); // get method access flags |
0 | 513 movl(rcx, Address(rbx, methodOopDesc::access_flags_offset())); |
514 | |
515 testl(rcx, JVM_ACC_SYNCHRONIZED); | |
516 jcc(Assembler::zero, unlocked); | |
517 | |
518 // Don't unlock anything if the _do_not_unlock_if_synchronized flag | |
519 // is set. | |
304 | 520 mov(rcx,rdi); |
0 | 521 testbool(rcx); |
522 jcc(Assembler::notZero, no_unlock); | |
523 | |
524 // unlock monitor | |
525 push(state); // save result | |
526 | |
527 // BasicObjectLock will be first in list, since this is a synchronized method. However, need | |
528 // to check that the object has not been unlocked by an explicit monitorexit bytecode. | |
529 const Address monitor(rbp, frame::interpreter_frame_initial_sp_offset * wordSize - (int)sizeof(BasicObjectLock)); | |
304 | 530 lea (rdx, monitor); // address of first monitor |
0 | 531 |
304 | 532 movptr (rax, Address(rdx, BasicObjectLock::obj_offset_in_bytes())); |
533 testptr(rax, rax); | |
534 jcc (Assembler::notZero, unlock); | |
0 | 535 |
536 pop(state); | |
537 if (throw_monitor_exception) { | |
538 empty_FPU_stack(); // remove possible return value from FPU-stack, otherwise stack could overflow | |
539 | |
540 // Entry already unlocked, need to throw exception | |
541 call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_illegal_monitor_state_exception)); | |
542 should_not_reach_here(); | |
543 } else { | |
544 // Monitor already unlocked during a stack unroll. | |
545 // If requested, install an illegal_monitor_state_exception. | |
546 // Continue with stack unrolling. | |
547 if (install_monitor_exception) { | |
548 empty_FPU_stack(); // remove possible return value from FPU-stack, otherwise stack could overflow | |
549 call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::new_illegal_monitor_state_exception)); | |
550 } | |
551 jmp(unlocked); | |
552 } | |
553 | |
554 bind(unlock); | |
555 unlock_object(rdx); | |
556 pop(state); | |
557 | |
558 // Check that for block-structured locking (i.e., that all locked objects has been unlocked) | |
559 bind(unlocked); | |
560 | |
561 // rax, rdx: Might contain return value | |
562 | |
563 // Check that all monitors are unlocked | |
564 { | |
565 Label loop, exception, entry, restart; | |
566 const int entry_size = frame::interpreter_frame_monitor_size() * wordSize; | |
567 const Address monitor_block_top(rbp, frame::interpreter_frame_monitor_block_top_offset * wordSize); | |
568 const Address monitor_block_bot(rbp, frame::interpreter_frame_initial_sp_offset * wordSize); | |
569 | |
570 bind(restart); | |
304 | 571 movptr(rcx, monitor_block_top); // points to current entry, starting with top-most entry |
572 lea(rbx, monitor_block_bot); // points to word before bottom of monitor block | |
0 | 573 jmp(entry); |
574 | |
575 // Entry already locked, need to throw exception | |
576 bind(exception); | |
577 | |
578 if (throw_monitor_exception) { | |
579 empty_FPU_stack(); // remove possible return value from FPU-stack, otherwise stack could overflow | |
580 | |
581 // Throw exception | |
582 call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_illegal_monitor_state_exception)); | |
583 should_not_reach_here(); | |
584 } else { | |
585 // Stack unrolling. Unlock object and install illegal_monitor_exception | |
586 // Unlock does not block, so don't have to worry about the frame | |
587 | |
588 push(state); | |
304 | 589 mov(rdx, rcx); |
0 | 590 unlock_object(rdx); |
591 pop(state); | |
592 | |
593 if (install_monitor_exception) { | |
594 empty_FPU_stack(); // remove possible return value from FPU-stack, otherwise stack could overflow | |
595 call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::new_illegal_monitor_state_exception)); | |
596 } | |
597 | |
598 jmp(restart); | |
599 } | |
600 | |
601 bind(loop); | |
304 | 602 cmpptr(Address(rcx, BasicObjectLock::obj_offset_in_bytes()), (int32_t)NULL_WORD); // check if current entry is used |
0 | 603 jcc(Assembler::notEqual, exception); |
604 | |
304 | 605 addptr(rcx, entry_size); // otherwise advance to next entry |
0 | 606 bind(entry); |
304 | 607 cmpptr(rcx, rbx); // check if bottom reached |
0 | 608 jcc(Assembler::notEqual, loop); // if not at bottom then check this entry |
609 } | |
610 | |
611 bind(no_unlock); | |
612 | |
613 // jvmti support | |
614 if (notify_jvmdi) { | |
615 notify_method_exit(state, NotifyJVMTI); // preserve TOSCA | |
616 } else { | |
617 notify_method_exit(state, SkipNotifyJVMTI); // preserve TOSCA | |
618 } | |
619 | |
620 // remove activation | |
304 | 621 movptr(rbx, Address(rbp, frame::interpreter_frame_sender_sp_offset * wordSize)); // get sender sp |
0 | 622 leave(); // remove frame anchor |
304 | 623 pop(ret_addr); // get return address |
624 mov(rsp, rbx); // set sp to sender sp | |
0 | 625 if (UseSSE) { |
626 // float and double are returned in xmm register in SSE-mode | |
627 if (state == ftos && UseSSE >= 1) { | |
304 | 628 subptr(rsp, wordSize); |
0 | 629 fstp_s(Address(rsp, 0)); |
630 movflt(xmm0, Address(rsp, 0)); | |
304 | 631 addptr(rsp, wordSize); |
0 | 632 } else if (state == dtos && UseSSE >= 2) { |
304 | 633 subptr(rsp, 2*wordSize); |
0 | 634 fstp_d(Address(rsp, 0)); |
635 movdbl(xmm0, Address(rsp, 0)); | |
304 | 636 addptr(rsp, 2*wordSize); |
0 | 637 } |
638 } | |
639 } | |
640 | |
641 #endif /* !CC_INTERP */ | |
642 | |
643 | |
644 // Lock object | |
645 // | |
646 // Argument: rdx : Points to BasicObjectLock to be used for locking. Must | |
647 // be initialized with object to lock | |
648 void InterpreterMacroAssembler::lock_object(Register lock_reg) { | |
649 assert(lock_reg == rdx, "The argument is only for looks. It must be rdx"); | |
650 | |
651 if (UseHeavyMonitors) { | |
652 call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::monitorenter), lock_reg); | |
653 } else { | |
654 | |
655 Label done; | |
656 | |
657 const Register swap_reg = rax; // Must use rax, for cmpxchg instruction | |
658 const Register obj_reg = rcx; // Will contain the oop | |
659 | |
660 const int obj_offset = BasicObjectLock::obj_offset_in_bytes(); | |
661 const int lock_offset = BasicObjectLock::lock_offset_in_bytes (); | |
662 const int mark_offset = lock_offset + BasicLock::displaced_header_offset_in_bytes(); | |
663 | |
664 Label slow_case; | |
665 | |
666 // Load object pointer into obj_reg %rcx | |
304 | 667 movptr(obj_reg, Address(lock_reg, obj_offset)); |
0 | 668 |
669 if (UseBiasedLocking) { | |
670 // Note: we use noreg for the temporary register since it's hard | |
671 // to come up with a free register on all incoming code paths | |
672 biased_locking_enter(lock_reg, obj_reg, swap_reg, noreg, false, done, &slow_case); | |
673 } | |
674 | |
675 // Load immediate 1 into swap_reg %rax, | |
304 | 676 movptr(swap_reg, (int32_t)1); |
0 | 677 |
678 // Load (object->mark() | 1) into swap_reg %rax, | |
304 | 679 orptr(swap_reg, Address(obj_reg, 0)); |
0 | 680 |
681 // Save (object->mark() | 1) into BasicLock's displaced header | |
304 | 682 movptr(Address(lock_reg, mark_offset), swap_reg); |
0 | 683 |
684 assert(lock_offset == 0, "displached header must be first word in BasicObjectLock"); | |
685 if (os::is_MP()) { | |
686 lock(); | |
687 } | |
304 | 688 cmpxchgptr(lock_reg, Address(obj_reg, 0)); |
0 | 689 if (PrintBiasedLockingStatistics) { |
690 cond_inc32(Assembler::zero, | |
691 ExternalAddress((address) BiasedLocking::fast_path_entry_count_addr())); | |
692 } | |
693 jcc(Assembler::zero, done); | |
694 | |
695 // Test if the oopMark is an obvious stack pointer, i.e., | |
696 // 1) (mark & 3) == 0, and | |
697 // 2) rsp <= mark < mark + os::pagesize() | |
698 // | |
699 // These 3 tests can be done by evaluating the following | |
700 // expression: ((mark - rsp) & (3 - os::vm_page_size())), | |
701 // assuming both stack pointer and pagesize have their | |
702 // least significant 2 bits clear. | |
703 // NOTE: the oopMark is in swap_reg %rax, as the result of cmpxchg | |
304 | 704 subptr(swap_reg, rsp); |
705 andptr(swap_reg, 3 - os::vm_page_size()); | |
0 | 706 |
707 // Save the test result, for recursive case, the result is zero | |
304 | 708 movptr(Address(lock_reg, mark_offset), swap_reg); |
0 | 709 |
710 if (PrintBiasedLockingStatistics) { | |
711 cond_inc32(Assembler::zero, | |
712 ExternalAddress((address) BiasedLocking::fast_path_entry_count_addr())); | |
713 } | |
714 jcc(Assembler::zero, done); | |
715 | |
716 bind(slow_case); | |
717 | |
718 // Call the runtime routine for slow case | |
719 call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::monitorenter), lock_reg); | |
720 | |
721 bind(done); | |
722 } | |
723 } | |
724 | |
725 | |
726 // Unlocks an object. Used in monitorexit bytecode and remove_activation. | |
727 // | |
728 // Argument: rdx : Points to BasicObjectLock structure for lock | |
729 // Throw an IllegalMonitorException if object is not locked by current thread | |
730 // | |
731 // Uses: rax, rbx, rcx, rdx | |
732 void InterpreterMacroAssembler::unlock_object(Register lock_reg) { | |
733 assert(lock_reg == rdx, "The argument is only for looks. It must be rdx"); | |
734 | |
735 if (UseHeavyMonitors) { | |
736 call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::monitorexit), lock_reg); | |
737 } else { | |
738 Label done; | |
739 | |
740 const Register swap_reg = rax; // Must use rax, for cmpxchg instruction | |
741 const Register header_reg = rbx; // Will contain the old oopMark | |
742 const Register obj_reg = rcx; // Will contain the oop | |
743 | |
744 save_bcp(); // Save in case of exception | |
745 | |
746 // Convert from BasicObjectLock structure to object and BasicLock structure | |
747 // Store the BasicLock address into %rax, | |
304 | 748 lea(swap_reg, Address(lock_reg, BasicObjectLock::lock_offset_in_bytes())); |
0 | 749 |
750 // Load oop into obj_reg(%rcx) | |
304 | 751 movptr(obj_reg, Address(lock_reg, BasicObjectLock::obj_offset_in_bytes ())); |
0 | 752 |
753 // Free entry | |
512
db4caa99ef11
6787106: Hotspot 32 bit build fails on platforms having different definitions for intptr_t & int32_t
xlu
parents:
337
diff
changeset
|
754 movptr(Address(lock_reg, BasicObjectLock::obj_offset_in_bytes()), NULL_WORD); |
0 | 755 |
756 if (UseBiasedLocking) { | |
757 biased_locking_exit(obj_reg, header_reg, done); | |
758 } | |
759 | |
760 // Load the old header from BasicLock structure | |
304 | 761 movptr(header_reg, Address(swap_reg, BasicLock::displaced_header_offset_in_bytes())); |
0 | 762 |
763 // Test for recursion | |
304 | 764 testptr(header_reg, header_reg); |
0 | 765 |
766 // zero for recursive case | |
767 jcc(Assembler::zero, done); | |
768 | |
769 // Atomic swap back the old header | |
770 if (os::is_MP()) lock(); | |
304 | 771 cmpxchgptr(header_reg, Address(obj_reg, 0)); |
0 | 772 |
773 // zero for recursive case | |
774 jcc(Assembler::zero, done); | |
775 | |
776 // Call the runtime routine for slow case. | |
304 | 777 movptr(Address(lock_reg, BasicObjectLock::obj_offset_in_bytes()), obj_reg); // restore obj |
0 | 778 call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::monitorexit), lock_reg); |
779 | |
780 bind(done); | |
781 | |
782 restore_bcp(); | |
783 } | |
784 } | |
785 | |
786 | |
787 #ifndef CC_INTERP | |
788 | |
789 // Test ImethodDataPtr. If it is null, continue at the specified label | |
790 void InterpreterMacroAssembler::test_method_data_pointer(Register mdp, Label& zero_continue) { | |
791 assert(ProfileInterpreter, "must be profiling interpreter"); | |
304 | 792 movptr(mdp, Address(rbp, frame::interpreter_frame_mdx_offset * wordSize)); |
793 testptr(mdp, mdp); | |
0 | 794 jcc(Assembler::zero, zero_continue); |
795 } | |
796 | |
797 | |
798 // Set the method data pointer for the current bcp. | |
799 void InterpreterMacroAssembler::set_method_data_pointer_for_bcp() { | |
800 assert(ProfileInterpreter, "must be profiling interpreter"); | |
801 Label zero_continue; | |
304 | 802 push(rax); |
803 push(rbx); | |
0 | 804 |
805 get_method(rbx); | |
806 // Test MDO to avoid the call if it is NULL. | |
304 | 807 movptr(rax, Address(rbx, in_bytes(methodOopDesc::method_data_offset()))); |
808 testptr(rax, rax); | |
0 | 809 jcc(Assembler::zero, zero_continue); |
810 | |
811 // rbx,: method | |
812 // rsi: bcp | |
813 call_VM_leaf(CAST_FROM_FN_PTR(address, InterpreterRuntime::bcp_to_di), rbx, rsi); | |
814 // rax,: mdi | |
815 | |
304 | 816 movptr(rbx, Address(rbx, in_bytes(methodOopDesc::method_data_offset()))); |
817 testptr(rbx, rbx); | |
0 | 818 jcc(Assembler::zero, zero_continue); |
304 | 819 addptr(rbx, in_bytes(methodDataOopDesc::data_offset())); |
820 addptr(rbx, rax); | |
821 movptr(Address(rbp, frame::interpreter_frame_mdx_offset * wordSize), rbx); | |
0 | 822 |
823 bind(zero_continue); | |
304 | 824 pop(rbx); |
825 pop(rax); | |
0 | 826 } |
827 | |
828 void InterpreterMacroAssembler::verify_method_data_pointer() { | |
829 assert(ProfileInterpreter, "must be profiling interpreter"); | |
830 #ifdef ASSERT | |
831 Label verify_continue; | |
304 | 832 push(rax); |
833 push(rbx); | |
834 push(rcx); | |
835 push(rdx); | |
0 | 836 test_method_data_pointer(rcx, verify_continue); // If mdp is zero, continue |
837 get_method(rbx); | |
838 | |
839 // If the mdp is valid, it will point to a DataLayout header which is | |
840 // consistent with the bcp. The converse is highly probable also. | |
622
56aae7be60d4
6812678: macro assembler needs delayed binding of a few constants (for 6655638)
jrose
parents:
533
diff
changeset
|
841 load_unsigned_short(rdx, Address(rcx, in_bytes(DataLayout::bci_offset()))); |
304 | 842 addptr(rdx, Address(rbx, methodOopDesc::const_offset())); |
843 lea(rdx, Address(rdx, constMethodOopDesc::codes_offset())); | |
844 cmpptr(rdx, rsi); | |
0 | 845 jcc(Assembler::equal, verify_continue); |
846 // rbx,: method | |
847 // rsi: bcp | |
848 // rcx: mdp | |
849 call_VM_leaf(CAST_FROM_FN_PTR(address, InterpreterRuntime::verify_mdp), rbx, rsi, rcx); | |
850 bind(verify_continue); | |
304 | 851 pop(rdx); |
852 pop(rcx); | |
853 pop(rbx); | |
854 pop(rax); | |
0 | 855 #endif // ASSERT |
856 } | |
857 | |
858 | |
859 void InterpreterMacroAssembler::set_mdp_data_at(Register mdp_in, int constant, Register value) { | |
304 | 860 // %%% this seems to be used to store counter data which is surely 32bits |
861 // however 64bit side stores 64 bits which seems wrong | |
0 | 862 assert(ProfileInterpreter, "must be profiling interpreter"); |
863 Address data(mdp_in, constant); | |
304 | 864 movptr(data, value); |
0 | 865 } |
866 | |
867 | |
868 void InterpreterMacroAssembler::increment_mdp_data_at(Register mdp_in, | |
869 int constant, | |
870 bool decrement) { | |
871 // Counter address | |
872 Address data(mdp_in, constant); | |
873 | |
874 increment_mdp_data_at(data, decrement); | |
875 } | |
876 | |
877 | |
878 void InterpreterMacroAssembler::increment_mdp_data_at(Address data, | |
879 bool decrement) { | |
880 | |
881 assert( DataLayout::counter_increment==1, "flow-free idiom only works with 1" ); | |
882 assert(ProfileInterpreter, "must be profiling interpreter"); | |
883 | |
304 | 884 // %%% 64bit treats this as 64 bit which seems unlikely |
0 | 885 if (decrement) { |
886 // Decrement the register. Set condition codes. | |
887 addl(data, -DataLayout::counter_increment); | |
888 // If the decrement causes the counter to overflow, stay negative | |
889 Label L; | |
890 jcc(Assembler::negative, L); | |
891 addl(data, DataLayout::counter_increment); | |
892 bind(L); | |
893 } else { | |
894 assert(DataLayout::counter_increment == 1, | |
895 "flow-free idiom only works with 1"); | |
896 // Increment the register. Set carry flag. | |
897 addl(data, DataLayout::counter_increment); | |
898 // If the increment causes the counter to overflow, pull back by 1. | |
899 sbbl(data, 0); | |
900 } | |
901 } | |
902 | |
903 | |
904 void InterpreterMacroAssembler::increment_mdp_data_at(Register mdp_in, | |
905 Register reg, | |
906 int constant, | |
907 bool decrement) { | |
908 Address data(mdp_in, reg, Address::times_1, constant); | |
909 | |
910 increment_mdp_data_at(data, decrement); | |
911 } | |
912 | |
913 | |
914 void InterpreterMacroAssembler::set_mdp_flag_at(Register mdp_in, int flag_byte_constant) { | |
915 assert(ProfileInterpreter, "must be profiling interpreter"); | |
916 int header_offset = in_bytes(DataLayout::header_offset()); | |
917 int header_bits = DataLayout::flag_mask_to_header_mask(flag_byte_constant); | |
918 // Set the flag | |
919 orl(Address(mdp_in, header_offset), header_bits); | |
920 } | |
921 | |
922 | |
923 | |
924 void InterpreterMacroAssembler::test_mdp_data_at(Register mdp_in, | |
925 int offset, | |
926 Register value, | |
927 Register test_value_out, | |
928 Label& not_equal_continue) { | |
929 assert(ProfileInterpreter, "must be profiling interpreter"); | |
930 if (test_value_out == noreg) { | |
304 | 931 cmpptr(value, Address(mdp_in, offset)); |
0 | 932 } else { |
933 // Put the test value into a register, so caller can use it: | |
304 | 934 movptr(test_value_out, Address(mdp_in, offset)); |
935 cmpptr(test_value_out, value); | |
0 | 936 } |
937 jcc(Assembler::notEqual, not_equal_continue); | |
938 } | |
939 | |
940 | |
941 void InterpreterMacroAssembler::update_mdp_by_offset(Register mdp_in, int offset_of_disp) { | |
942 assert(ProfileInterpreter, "must be profiling interpreter"); | |
943 Address disp_address(mdp_in, offset_of_disp); | |
304 | 944 addptr(mdp_in,disp_address); |
945 movptr(Address(rbp, frame::interpreter_frame_mdx_offset * wordSize), mdp_in); | |
0 | 946 } |
947 | |
948 | |
949 void InterpreterMacroAssembler::update_mdp_by_offset(Register mdp_in, Register reg, int offset_of_disp) { | |
950 assert(ProfileInterpreter, "must be profiling interpreter"); | |
951 Address disp_address(mdp_in, reg, Address::times_1, offset_of_disp); | |
304 | 952 addptr(mdp_in, disp_address); |
953 movptr(Address(rbp, frame::interpreter_frame_mdx_offset * wordSize), mdp_in); | |
0 | 954 } |
955 | |
956 | |
957 void InterpreterMacroAssembler::update_mdp_by_constant(Register mdp_in, int constant) { | |
958 assert(ProfileInterpreter, "must be profiling interpreter"); | |
304 | 959 addptr(mdp_in, constant); |
960 movptr(Address(rbp, frame::interpreter_frame_mdx_offset * wordSize), mdp_in); | |
0 | 961 } |
962 | |
963 | |
964 void InterpreterMacroAssembler::update_mdp_for_ret(Register return_bci) { | |
965 assert(ProfileInterpreter, "must be profiling interpreter"); | |
304 | 966 push(return_bci); // save/restore across call_VM |
0 | 967 call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::update_mdp_for_ret), return_bci); |
304 | 968 pop(return_bci); |
0 | 969 } |
970 | |
971 | |
972 void InterpreterMacroAssembler::profile_taken_branch(Register mdp, Register bumped_count) { | |
973 if (ProfileInterpreter) { | |
974 Label profile_continue; | |
975 | |
976 // If no method data exists, go to profile_continue. | |
977 // Otherwise, assign to mdp | |
978 test_method_data_pointer(mdp, profile_continue); | |
979 | |
980 // We are taking a branch. Increment the taken count. | |
981 // We inline increment_mdp_data_at to return bumped_count in a register | |
982 //increment_mdp_data_at(mdp, in_bytes(JumpData::taken_offset())); | |
983 Address data(mdp, in_bytes(JumpData::taken_offset())); | |
304 | 984 |
985 // %%% 64bit treats these cells as 64 bit but they seem to be 32 bit | |
0 | 986 movl(bumped_count,data); |
987 assert( DataLayout::counter_increment==1, "flow-free idiom only works with 1" ); | |
988 addl(bumped_count, DataLayout::counter_increment); | |
989 sbbl(bumped_count, 0); | |
990 movl(data,bumped_count); // Store back out | |
991 | |
992 // The method data pointer needs to be updated to reflect the new target. | |
993 update_mdp_by_offset(mdp, in_bytes(JumpData::displacement_offset())); | |
994 bind (profile_continue); | |
995 } | |
996 } | |
997 | |
998 | |
999 void InterpreterMacroAssembler::profile_not_taken_branch(Register mdp) { | |
1000 if (ProfileInterpreter) { | |
1001 Label profile_continue; | |
1002 | |
1003 // If no method data exists, go to profile_continue. | |
1004 test_method_data_pointer(mdp, profile_continue); | |
1005 | |
1006 // We are taking a branch. Increment the not taken count. | |
1007 increment_mdp_data_at(mdp, in_bytes(BranchData::not_taken_offset())); | |
1008 | |
1009 // The method data pointer needs to be updated to correspond to the next bytecode | |
1010 update_mdp_by_constant(mdp, in_bytes(BranchData::branch_data_size())); | |
1011 bind (profile_continue); | |
1012 } | |
1013 } | |
1014 | |
1015 | |
1016 void InterpreterMacroAssembler::profile_call(Register mdp) { | |
1017 if (ProfileInterpreter) { | |
1018 Label profile_continue; | |
1019 | |
1020 // If no method data exists, go to profile_continue. | |
1021 test_method_data_pointer(mdp, profile_continue); | |
1022 | |
1023 // We are making a call. Increment the count. | |
1024 increment_mdp_data_at(mdp, in_bytes(CounterData::count_offset())); | |
1025 | |
1026 // The method data pointer needs to be updated to reflect the new target. | |
1027 update_mdp_by_constant(mdp, in_bytes(CounterData::counter_data_size())); | |
1028 bind (profile_continue); | |
1029 } | |
1030 } | |
1031 | |
1032 | |
1033 void InterpreterMacroAssembler::profile_final_call(Register mdp) { | |
1034 if (ProfileInterpreter) { | |
1035 Label profile_continue; | |
1036 | |
1037 // If no method data exists, go to profile_continue. | |
1038 test_method_data_pointer(mdp, profile_continue); | |
1039 | |
1040 // We are making a call. Increment the count. | |
1041 increment_mdp_data_at(mdp, in_bytes(CounterData::count_offset())); | |
1042 | |
1043 // The method data pointer needs to be updated to reflect the new target. | |
1044 update_mdp_by_constant(mdp, in_bytes(VirtualCallData::virtual_call_data_size())); | |
1045 bind (profile_continue); | |
1046 } | |
1047 } | |
1048 | |
1049 | |
726
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
710
diff
changeset
|
1050 void InterpreterMacroAssembler::profile_virtual_call(Register receiver, Register mdp, |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
710
diff
changeset
|
1051 Register reg2, |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
710
diff
changeset
|
1052 bool receiver_can_be_null) { |
0 | 1053 if (ProfileInterpreter) { |
1054 Label profile_continue; | |
1055 | |
1056 // If no method data exists, go to profile_continue. | |
1057 test_method_data_pointer(mdp, profile_continue); | |
1058 | |
726
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
710
diff
changeset
|
1059 Label skip_receiver_profile; |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
710
diff
changeset
|
1060 if (receiver_can_be_null) { |
1206
87684f1a88b5
6614597: Performance variability in jvm2008 xml.validation
kvn
parents:
1108
diff
changeset
|
1061 Label not_null; |
726
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
710
diff
changeset
|
1062 testptr(receiver, receiver); |
1206
87684f1a88b5
6614597: Performance variability in jvm2008 xml.validation
kvn
parents:
1108
diff
changeset
|
1063 jccb(Assembler::notZero, not_null); |
87684f1a88b5
6614597: Performance variability in jvm2008 xml.validation
kvn
parents:
1108
diff
changeset
|
1064 // We are making a call. Increment the count for null receiver. |
87684f1a88b5
6614597: Performance variability in jvm2008 xml.validation
kvn
parents:
1108
diff
changeset
|
1065 increment_mdp_data_at(mdp, in_bytes(CounterData::count_offset())); |
87684f1a88b5
6614597: Performance variability in jvm2008 xml.validation
kvn
parents:
1108
diff
changeset
|
1066 jmp(skip_receiver_profile); |
87684f1a88b5
6614597: Performance variability in jvm2008 xml.validation
kvn
parents:
1108
diff
changeset
|
1067 bind(not_null); |
726
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
710
diff
changeset
|
1068 } |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
710
diff
changeset
|
1069 |
0 | 1070 // Record the receiver type. |
1206
87684f1a88b5
6614597: Performance variability in jvm2008 xml.validation
kvn
parents:
1108
diff
changeset
|
1071 record_klass_in_profile(receiver, mdp, reg2, true); |
726
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
710
diff
changeset
|
1072 bind(skip_receiver_profile); |
0 | 1073 |
1074 // The method data pointer needs to be updated to reflect the new target. | |
1075 update_mdp_by_constant(mdp, | |
1076 in_bytes(VirtualCallData:: | |
1077 virtual_call_data_size())); | |
1078 bind(profile_continue); | |
1079 } | |
1080 } | |
1081 | |
1082 | |
1083 void InterpreterMacroAssembler::record_klass_in_profile_helper( | |
1084 Register receiver, Register mdp, | |
1206
87684f1a88b5
6614597: Performance variability in jvm2008 xml.validation
kvn
parents:
1108
diff
changeset
|
1085 Register reg2, int start_row, |
87684f1a88b5
6614597: Performance variability in jvm2008 xml.validation
kvn
parents:
1108
diff
changeset
|
1086 Label& done, bool is_virtual_call) { |
87684f1a88b5
6614597: Performance variability in jvm2008 xml.validation
kvn
parents:
1108
diff
changeset
|
1087 if (TypeProfileWidth == 0) { |
87684f1a88b5
6614597: Performance variability in jvm2008 xml.validation
kvn
parents:
1108
diff
changeset
|
1088 if (is_virtual_call) { |
87684f1a88b5
6614597: Performance variability in jvm2008 xml.validation
kvn
parents:
1108
diff
changeset
|
1089 increment_mdp_data_at(mdp, in_bytes(CounterData::count_offset())); |
87684f1a88b5
6614597: Performance variability in jvm2008 xml.validation
kvn
parents:
1108
diff
changeset
|
1090 } |
967
6918603297f7
6858208: jvm crash when specifying TypeProfileWidth=0 on jdk 6.0
poonam
parents:
826
diff
changeset
|
1091 return; |
1206
87684f1a88b5
6614597: Performance variability in jvm2008 xml.validation
kvn
parents:
1108
diff
changeset
|
1092 } |
967
6918603297f7
6858208: jvm crash when specifying TypeProfileWidth=0 on jdk 6.0
poonam
parents:
826
diff
changeset
|
1093 |
0 | 1094 int last_row = VirtualCallData::row_limit() - 1; |
1095 assert(start_row <= last_row, "must be work left to do"); | |
1096 // Test this row for both the receiver and for null. | |
1097 // Take any of three different outcomes: | |
1098 // 1. found receiver => increment count and goto done | |
1099 // 2. found null => keep looking for case 1, maybe allocate this cell | |
1100 // 3. found something else => keep looking for cases 1 and 2 | |
1101 // Case 3 is handled by a recursive call. | |
1102 for (int row = start_row; row <= last_row; row++) { | |
1103 Label next_test; | |
1104 bool test_for_null_also = (row == start_row); | |
1105 | |
1106 // See if the receiver is receiver[n]. | |
1107 int recvr_offset = in_bytes(VirtualCallData::receiver_offset(row)); | |
1108 test_mdp_data_at(mdp, recvr_offset, receiver, | |
1109 (test_for_null_also ? reg2 : noreg), | |
1110 next_test); | |
1111 // (Reg2 now contains the receiver from the CallData.) | |
1112 | |
1113 // The receiver is receiver[n]. Increment count[n]. | |
1114 int count_offset = in_bytes(VirtualCallData::receiver_count_offset(row)); | |
1115 increment_mdp_data_at(mdp, count_offset); | |
1116 jmp(done); | |
1117 bind(next_test); | |
1118 | |
1119 if (row == start_row) { | |
1206
87684f1a88b5
6614597: Performance variability in jvm2008 xml.validation
kvn
parents:
1108
diff
changeset
|
1120 Label found_null; |
0 | 1121 // Failed the equality check on receiver[n]... Test for null. |
304 | 1122 testptr(reg2, reg2); |
0 | 1123 if (start_row == last_row) { |
1124 // The only thing left to do is handle the null case. | |
1206
87684f1a88b5
6614597: Performance variability in jvm2008 xml.validation
kvn
parents:
1108
diff
changeset
|
1125 if (is_virtual_call) { |
87684f1a88b5
6614597: Performance variability in jvm2008 xml.validation
kvn
parents:
1108
diff
changeset
|
1126 jccb(Assembler::zero, found_null); |
87684f1a88b5
6614597: Performance variability in jvm2008 xml.validation
kvn
parents:
1108
diff
changeset
|
1127 // Receiver did not match any saved receiver and there is no empty row for it. |
1251
576e77447e3c
6923002: assert(false,"this call site should not be polymorphic")
kvn
parents:
1206
diff
changeset
|
1128 // Increment total counter to indicate polymorphic case. |
1206
87684f1a88b5
6614597: Performance variability in jvm2008 xml.validation
kvn
parents:
1108
diff
changeset
|
1129 increment_mdp_data_at(mdp, in_bytes(CounterData::count_offset())); |
87684f1a88b5
6614597: Performance variability in jvm2008 xml.validation
kvn
parents:
1108
diff
changeset
|
1130 jmp(done); |
87684f1a88b5
6614597: Performance variability in jvm2008 xml.validation
kvn
parents:
1108
diff
changeset
|
1131 bind(found_null); |
87684f1a88b5
6614597: Performance variability in jvm2008 xml.validation
kvn
parents:
1108
diff
changeset
|
1132 } else { |
87684f1a88b5
6614597: Performance variability in jvm2008 xml.validation
kvn
parents:
1108
diff
changeset
|
1133 jcc(Assembler::notZero, done); |
87684f1a88b5
6614597: Performance variability in jvm2008 xml.validation
kvn
parents:
1108
diff
changeset
|
1134 } |
0 | 1135 break; |
1136 } | |
1137 // Since null is rare, make it be the branch-taken case. | |
1138 jcc(Assembler::zero, found_null); | |
1139 | |
1140 // Put all the "Case 3" tests here. | |
1206
87684f1a88b5
6614597: Performance variability in jvm2008 xml.validation
kvn
parents:
1108
diff
changeset
|
1141 record_klass_in_profile_helper(receiver, mdp, reg2, start_row + 1, done, is_virtual_call); |
0 | 1142 |
1143 // Found a null. Keep searching for a matching receiver, | |
1144 // but remember that this is an empty (unused) slot. | |
1145 bind(found_null); | |
1146 } | |
1147 } | |
1148 | |
1149 // In the fall-through case, we found no matching receiver, but we | |
1150 // observed the receiver[start_row] is NULL. | |
1151 | |
1152 // Fill in the receiver field and increment the count. | |
1153 int recvr_offset = in_bytes(VirtualCallData::receiver_offset(start_row)); | |
1154 set_mdp_data_at(mdp, recvr_offset, receiver); | |
1155 int count_offset = in_bytes(VirtualCallData::receiver_count_offset(start_row)); | |
304 | 1156 movptr(reg2, (int32_t)DataLayout::counter_increment); |
0 | 1157 set_mdp_data_at(mdp, count_offset, reg2); |
1206
87684f1a88b5
6614597: Performance variability in jvm2008 xml.validation
kvn
parents:
1108
diff
changeset
|
1158 if (start_row > 0) { |
87684f1a88b5
6614597: Performance variability in jvm2008 xml.validation
kvn
parents:
1108
diff
changeset
|
1159 jmp(done); |
87684f1a88b5
6614597: Performance variability in jvm2008 xml.validation
kvn
parents:
1108
diff
changeset
|
1160 } |
0 | 1161 } |
1162 | |
1163 void InterpreterMacroAssembler::record_klass_in_profile(Register receiver, | |
1206
87684f1a88b5
6614597: Performance variability in jvm2008 xml.validation
kvn
parents:
1108
diff
changeset
|
1164 Register mdp, Register reg2, |
87684f1a88b5
6614597: Performance variability in jvm2008 xml.validation
kvn
parents:
1108
diff
changeset
|
1165 bool is_virtual_call) { |
0 | 1166 assert(ProfileInterpreter, "must be profiling"); |
1167 Label done; | |
1168 | |
1206
87684f1a88b5
6614597: Performance variability in jvm2008 xml.validation
kvn
parents:
1108
diff
changeset
|
1169 record_klass_in_profile_helper(receiver, mdp, reg2, 0, done, is_virtual_call); |
0 | 1170 |
1171 bind (done); | |
1172 } | |
1173 | |
1174 void InterpreterMacroAssembler::profile_ret(Register return_bci, Register mdp) { | |
1175 if (ProfileInterpreter) { | |
1176 Label profile_continue; | |
1177 uint row; | |
1178 | |
1179 // If no method data exists, go to profile_continue. | |
1180 test_method_data_pointer(mdp, profile_continue); | |
1181 | |
1182 // Update the total ret count. | |
1183 increment_mdp_data_at(mdp, in_bytes(CounterData::count_offset())); | |
1184 | |
1185 for (row = 0; row < RetData::row_limit(); row++) { | |
1186 Label next_test; | |
1187 | |
1188 // See if return_bci is equal to bci[n]: | |
1189 test_mdp_data_at(mdp, in_bytes(RetData::bci_offset(row)), return_bci, | |
1190 noreg, next_test); | |
1191 | |
1192 // return_bci is equal to bci[n]. Increment the count. | |
1193 increment_mdp_data_at(mdp, in_bytes(RetData::bci_count_offset(row))); | |
1194 | |
1195 // The method data pointer needs to be updated to reflect the new target. | |
1196 update_mdp_by_offset(mdp, in_bytes(RetData::bci_displacement_offset(row))); | |
1197 jmp(profile_continue); | |
1198 bind(next_test); | |
1199 } | |
1200 | |
1201 update_mdp_for_ret(return_bci); | |
1202 | |
1203 bind (profile_continue); | |
1204 } | |
1205 } | |
1206 | |
1207 | |
1208 void InterpreterMacroAssembler::profile_null_seen(Register mdp) { | |
1209 if (ProfileInterpreter) { | |
1210 Label profile_continue; | |
1211 | |
1212 // If no method data exists, go to profile_continue. | |
1213 test_method_data_pointer(mdp, profile_continue); | |
1214 | |
826
3f06f139ef53
6851908: interpreter null check profiling broken causing extra compilation invalidation
never
parents:
726
diff
changeset
|
1215 set_mdp_flag_at(mdp, BitData::null_seen_byte_constant()); |
3f06f139ef53
6851908: interpreter null check profiling broken causing extra compilation invalidation
never
parents:
726
diff
changeset
|
1216 |
0 | 1217 // The method data pointer needs to be updated. |
1218 int mdp_delta = in_bytes(BitData::bit_data_size()); | |
1219 if (TypeProfileCasts) { | |
1220 mdp_delta = in_bytes(VirtualCallData::virtual_call_data_size()); | |
1221 } | |
1222 update_mdp_by_constant(mdp, mdp_delta); | |
1223 | |
1224 bind (profile_continue); | |
1225 } | |
1226 } | |
1227 | |
1228 | |
1229 void InterpreterMacroAssembler::profile_typecheck_failed(Register mdp) { | |
1230 if (ProfileInterpreter && TypeProfileCasts) { | |
1231 Label profile_continue; | |
1232 | |
1233 // If no method data exists, go to profile_continue. | |
1234 test_method_data_pointer(mdp, profile_continue); | |
1235 | |
1236 int count_offset = in_bytes(CounterData::count_offset()); | |
1237 // Back up the address, since we have already bumped the mdp. | |
1238 count_offset -= in_bytes(VirtualCallData::virtual_call_data_size()); | |
1239 | |
1240 // *Decrement* the counter. We expect to see zero or small negatives. | |
1241 increment_mdp_data_at(mdp, count_offset, true); | |
1242 | |
1243 bind (profile_continue); | |
1244 } | |
1245 } | |
1246 | |
1247 | |
1248 void InterpreterMacroAssembler::profile_typecheck(Register mdp, Register klass, Register reg2) | |
1249 { | |
1250 if (ProfileInterpreter) { | |
1251 Label profile_continue; | |
1252 | |
1253 // If no method data exists, go to profile_continue. | |
1254 test_method_data_pointer(mdp, profile_continue); | |
1255 | |
1256 // The method data pointer needs to be updated. | |
1257 int mdp_delta = in_bytes(BitData::bit_data_size()); | |
1258 if (TypeProfileCasts) { | |
1259 mdp_delta = in_bytes(VirtualCallData::virtual_call_data_size()); | |
1260 | |
1261 // Record the object type. | |
1206
87684f1a88b5
6614597: Performance variability in jvm2008 xml.validation
kvn
parents:
1108
diff
changeset
|
1262 record_klass_in_profile(klass, mdp, reg2, false); |
0 | 1263 assert(reg2 == rdi, "we know how to fix this blown reg"); |
1264 restore_locals(); // Restore EDI | |
1265 } | |
1266 update_mdp_by_constant(mdp, mdp_delta); | |
1267 | |
1268 bind(profile_continue); | |
1269 } | |
1270 } | |
1271 | |
1272 | |
1273 void InterpreterMacroAssembler::profile_switch_default(Register mdp) { | |
1274 if (ProfileInterpreter) { | |
1275 Label profile_continue; | |
1276 | |
1277 // If no method data exists, go to profile_continue. | |
1278 test_method_data_pointer(mdp, profile_continue); | |
1279 | |
1280 // Update the default case count | |
1281 increment_mdp_data_at(mdp, in_bytes(MultiBranchData::default_count_offset())); | |
1282 | |
1283 // The method data pointer needs to be updated. | |
1284 update_mdp_by_offset(mdp, in_bytes(MultiBranchData::default_displacement_offset())); | |
1285 | |
1286 bind (profile_continue); | |
1287 } | |
1288 } | |
1289 | |
1290 | |
1291 void InterpreterMacroAssembler::profile_switch_case(Register index, Register mdp, Register reg2) { | |
1292 if (ProfileInterpreter) { | |
1293 Label profile_continue; | |
1294 | |
1295 // If no method data exists, go to profile_continue. | |
1296 test_method_data_pointer(mdp, profile_continue); | |
1297 | |
1298 // Build the base (index * per_case_size_in_bytes()) + case_array_offset_in_bytes() | |
304 | 1299 movptr(reg2, (int32_t)in_bytes(MultiBranchData::per_case_size())); |
1300 // index is positive and so should have correct value if this code were | |
1301 // used on 64bits | |
1302 imulptr(index, reg2); | |
1303 addptr(index, in_bytes(MultiBranchData::case_array_offset())); | |
0 | 1304 |
1305 // Update the case count | |
1306 increment_mdp_data_at(mdp, index, in_bytes(MultiBranchData::relative_count_offset())); | |
1307 | |
1308 // The method data pointer needs to be updated. | |
1309 update_mdp_by_offset(mdp, index, in_bytes(MultiBranchData::relative_displacement_offset())); | |
1310 | |
1311 bind (profile_continue); | |
1312 } | |
1313 } | |
1314 | |
1315 #endif // !CC_INTERP | |
1316 | |
1317 | |
1318 | |
1319 void InterpreterMacroAssembler::verify_oop(Register reg, TosState state) { | |
1320 if (state == atos) MacroAssembler::verify_oop(reg); | |
1321 } | |
1322 | |
1323 | |
1324 #ifndef CC_INTERP | |
1325 void InterpreterMacroAssembler::verify_FPU(int stack_depth, TosState state) { | |
1326 if (state == ftos || state == dtos) MacroAssembler::verify_FPU(stack_depth); | |
1327 } | |
1328 | |
1329 #endif /* CC_INTERP */ | |
1330 | |
1331 | |
1332 void InterpreterMacroAssembler::notify_method_entry() { | |
1333 // Whenever JVMTI is interp_only_mode, method entry/exit events are sent to | |
1334 // track stack depth. If it is possible to enter interp_only_mode we add | |
1335 // the code to check if the event should be sent. | |
1336 if (JvmtiExport::can_post_interpreter_events()) { | |
1337 Label L; | |
1338 get_thread(rcx); | |
1339 movl(rcx, Address(rcx, JavaThread::interp_only_mode_offset())); | |
1340 testl(rcx,rcx); | |
1341 jcc(Assembler::zero, L); | |
1342 call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::post_method_entry)); | |
1343 bind(L); | |
1344 } | |
1345 | |
1346 { | |
1347 SkipIfEqual skip_if(this, &DTraceMethodProbes, 0); | |
1348 get_thread(rcx); | |
1349 get_method(rbx); | |
1350 call_VM_leaf( | |
1351 CAST_FROM_FN_PTR(address, SharedRuntime::dtrace_method_entry), rcx, rbx); | |
1352 } | |
610
70998f2e05ef
6805864: 4/3 Problem with jvmti->redefineClasses: some methods don't get redefined
dcubed
parents:
337
diff
changeset
|
1353 |
70998f2e05ef
6805864: 4/3 Problem with jvmti->redefineClasses: some methods don't get redefined
dcubed
parents:
337
diff
changeset
|
1354 // RedefineClasses() tracing support for obsolete method entry |
70998f2e05ef
6805864: 4/3 Problem with jvmti->redefineClasses: some methods don't get redefined
dcubed
parents:
337
diff
changeset
|
1355 if (RC_TRACE_IN_RANGE(0x00001000, 0x00002000)) { |
70998f2e05ef
6805864: 4/3 Problem with jvmti->redefineClasses: some methods don't get redefined
dcubed
parents:
337
diff
changeset
|
1356 get_thread(rcx); |
70998f2e05ef
6805864: 4/3 Problem with jvmti->redefineClasses: some methods don't get redefined
dcubed
parents:
337
diff
changeset
|
1357 get_method(rbx); |
70998f2e05ef
6805864: 4/3 Problem with jvmti->redefineClasses: some methods don't get redefined
dcubed
parents:
337
diff
changeset
|
1358 call_VM_leaf( |
70998f2e05ef
6805864: 4/3 Problem with jvmti->redefineClasses: some methods don't get redefined
dcubed
parents:
337
diff
changeset
|
1359 CAST_FROM_FN_PTR(address, SharedRuntime::rc_trace_method_entry), |
70998f2e05ef
6805864: 4/3 Problem with jvmti->redefineClasses: some methods don't get redefined
dcubed
parents:
337
diff
changeset
|
1360 rcx, rbx); |
70998f2e05ef
6805864: 4/3 Problem with jvmti->redefineClasses: some methods don't get redefined
dcubed
parents:
337
diff
changeset
|
1361 } |
0 | 1362 } |
1363 | |
1364 | |
1365 void InterpreterMacroAssembler::notify_method_exit( | |
1366 TosState state, NotifyMethodExitMode mode) { | |
1367 // Whenever JVMTI is interp_only_mode, method entry/exit events are sent to | |
1368 // track stack depth. If it is possible to enter interp_only_mode we add | |
1369 // the code to check if the event should be sent. | |
1370 if (mode == NotifyJVMTI && JvmtiExport::can_post_interpreter_events()) { | |
1371 Label L; | |
1372 // Note: frame::interpreter_frame_result has a dependency on how the | |
1373 // method result is saved across the call to post_method_exit. If this | |
1374 // is changed then the interpreter_frame_result implementation will | |
1375 // need to be updated too. | |
1376 | |
1377 // For c++ interpreter the result is always stored at a known location in the frame | |
1378 // template interpreter will leave it on the top of the stack. | |
1379 NOT_CC_INTERP(push(state);) | |
1380 get_thread(rcx); | |
1381 movl(rcx, Address(rcx, JavaThread::interp_only_mode_offset())); | |
1382 testl(rcx,rcx); | |
1383 jcc(Assembler::zero, L); | |
1384 call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::post_method_exit)); | |
1385 bind(L); | |
1386 NOT_CC_INTERP(pop(state);) | |
1387 } | |
1388 | |
1389 { | |
1390 SkipIfEqual skip_if(this, &DTraceMethodProbes, 0); | |
304 | 1391 NOT_CC_INTERP(push(state)); |
0 | 1392 get_thread(rbx); |
1393 get_method(rcx); | |
1394 call_VM_leaf( | |
1395 CAST_FROM_FN_PTR(address, SharedRuntime::dtrace_method_exit), | |
1396 rbx, rcx); | |
304 | 1397 NOT_CC_INTERP(pop(state)); |
0 | 1398 } |
1399 } |