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