Mercurial > hg > truffle
annotate src/cpu/x86/vm/interp_masm_x86_32.cpp @ 2007:5ddfcf4b079e
7003554: (tiered) assert(is_null_object() || handle() != NULL) failed: cannot embed null pointer
Summary: C1 with profiling doesn't check whether the MDO has been really allocated, which can silently fail if the perm gen is full. The solution is to check if the allocation failed and bailout out of inlining or compilation.
Reviewed-by: kvn, never
author | iveresov |
---|---|
date | Thu, 02 Dec 2010 17:21:12 -0800 |
parents | f95d63e2154a |
children | dd031b2226de |
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 | |
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)) { |
726
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
710
diff
changeset
|
218 assert(EnableInvokeDynamic, "giant index used only for EnableInvokeDynamic"); |
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)) { |
226 assert(EnableMethodHandles, "tiny index used only for EnableMethodHandles"); | |
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"); | |
822 Label zero_continue; | |
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); | |
0 | 830 jcc(Assembler::zero, zero_continue); |
831 | |
832 // rbx,: method | |
833 // rsi: bcp | |
834 call_VM_leaf(CAST_FROM_FN_PTR(address, InterpreterRuntime::bcp_to_di), rbx, rsi); | |
835 // rax,: mdi | |
836 | |
304 | 837 movptr(rbx, Address(rbx, in_bytes(methodOopDesc::method_data_offset()))); |
838 testptr(rbx, rbx); | |
0 | 839 jcc(Assembler::zero, zero_continue); |
304 | 840 addptr(rbx, in_bytes(methodDataOopDesc::data_offset())); |
841 addptr(rbx, rax); | |
842 movptr(Address(rbp, frame::interpreter_frame_mdx_offset * wordSize), rbx); | |
0 | 843 |
844 bind(zero_continue); | |
304 | 845 pop(rbx); |
846 pop(rax); | |
0 | 847 } |
848 | |
849 void InterpreterMacroAssembler::verify_method_data_pointer() { | |
850 assert(ProfileInterpreter, "must be profiling interpreter"); | |
851 #ifdef ASSERT | |
852 Label verify_continue; | |
304 | 853 push(rax); |
854 push(rbx); | |
855 push(rcx); | |
856 push(rdx); | |
0 | 857 test_method_data_pointer(rcx, verify_continue); // If mdp is zero, continue |
858 get_method(rbx); | |
859 | |
860 // If the mdp is valid, it will point to a DataLayout header which is | |
861 // 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
|
862 load_unsigned_short(rdx, Address(rcx, in_bytes(DataLayout::bci_offset()))); |
304 | 863 addptr(rdx, Address(rbx, methodOopDesc::const_offset())); |
864 lea(rdx, Address(rdx, constMethodOopDesc::codes_offset())); | |
865 cmpptr(rdx, rsi); | |
0 | 866 jcc(Assembler::equal, verify_continue); |
867 // rbx,: method | |
868 // rsi: bcp | |
869 // rcx: mdp | |
870 call_VM_leaf(CAST_FROM_FN_PTR(address, InterpreterRuntime::verify_mdp), rbx, rsi, rcx); | |
871 bind(verify_continue); | |
304 | 872 pop(rdx); |
873 pop(rcx); | |
874 pop(rbx); | |
875 pop(rax); | |
0 | 876 #endif // ASSERT |
877 } | |
878 | |
879 | |
880 void InterpreterMacroAssembler::set_mdp_data_at(Register mdp_in, int constant, Register value) { | |
304 | 881 // %%% this seems to be used to store counter data which is surely 32bits |
882 // however 64bit side stores 64 bits which seems wrong | |
0 | 883 assert(ProfileInterpreter, "must be profiling interpreter"); |
884 Address data(mdp_in, constant); | |
304 | 885 movptr(data, value); |
0 | 886 } |
887 | |
888 | |
889 void InterpreterMacroAssembler::increment_mdp_data_at(Register mdp_in, | |
890 int constant, | |
891 bool decrement) { | |
892 // Counter address | |
893 Address data(mdp_in, constant); | |
894 | |
895 increment_mdp_data_at(data, decrement); | |
896 } | |
897 | |
898 | |
899 void InterpreterMacroAssembler::increment_mdp_data_at(Address data, | |
900 bool decrement) { | |
901 | |
902 assert( DataLayout::counter_increment==1, "flow-free idiom only works with 1" ); | |
903 assert(ProfileInterpreter, "must be profiling interpreter"); | |
904 | |
304 | 905 // %%% 64bit treats this as 64 bit which seems unlikely |
0 | 906 if (decrement) { |
907 // Decrement the register. Set condition codes. | |
908 addl(data, -DataLayout::counter_increment); | |
909 // If the decrement causes the counter to overflow, stay negative | |
910 Label L; | |
911 jcc(Assembler::negative, L); | |
912 addl(data, DataLayout::counter_increment); | |
913 bind(L); | |
914 } else { | |
915 assert(DataLayout::counter_increment == 1, | |
916 "flow-free idiom only works with 1"); | |
917 // Increment the register. Set carry flag. | |
918 addl(data, DataLayout::counter_increment); | |
919 // If the increment causes the counter to overflow, pull back by 1. | |
920 sbbl(data, 0); | |
921 } | |
922 } | |
923 | |
924 | |
925 void InterpreterMacroAssembler::increment_mdp_data_at(Register mdp_in, | |
926 Register reg, | |
927 int constant, | |
928 bool decrement) { | |
929 Address data(mdp_in, reg, Address::times_1, constant); | |
930 | |
931 increment_mdp_data_at(data, decrement); | |
932 } | |
933 | |
934 | |
935 void InterpreterMacroAssembler::set_mdp_flag_at(Register mdp_in, int flag_byte_constant) { | |
936 assert(ProfileInterpreter, "must be profiling interpreter"); | |
937 int header_offset = in_bytes(DataLayout::header_offset()); | |
938 int header_bits = DataLayout::flag_mask_to_header_mask(flag_byte_constant); | |
939 // Set the flag | |
940 orl(Address(mdp_in, header_offset), header_bits); | |
941 } | |
942 | |
943 | |
944 | |
945 void InterpreterMacroAssembler::test_mdp_data_at(Register mdp_in, | |
946 int offset, | |
947 Register value, | |
948 Register test_value_out, | |
949 Label& not_equal_continue) { | |
950 assert(ProfileInterpreter, "must be profiling interpreter"); | |
951 if (test_value_out == noreg) { | |
304 | 952 cmpptr(value, Address(mdp_in, offset)); |
0 | 953 } else { |
954 // Put the test value into a register, so caller can use it: | |
304 | 955 movptr(test_value_out, Address(mdp_in, offset)); |
956 cmpptr(test_value_out, value); | |
0 | 957 } |
958 jcc(Assembler::notEqual, not_equal_continue); | |
959 } | |
960 | |
961 | |
962 void InterpreterMacroAssembler::update_mdp_by_offset(Register mdp_in, int offset_of_disp) { | |
963 assert(ProfileInterpreter, "must be profiling interpreter"); | |
964 Address disp_address(mdp_in, offset_of_disp); | |
304 | 965 addptr(mdp_in,disp_address); |
966 movptr(Address(rbp, frame::interpreter_frame_mdx_offset * wordSize), mdp_in); | |
0 | 967 } |
968 | |
969 | |
970 void InterpreterMacroAssembler::update_mdp_by_offset(Register mdp_in, Register reg, int offset_of_disp) { | |
971 assert(ProfileInterpreter, "must be profiling interpreter"); | |
972 Address disp_address(mdp_in, reg, Address::times_1, offset_of_disp); | |
304 | 973 addptr(mdp_in, disp_address); |
974 movptr(Address(rbp, frame::interpreter_frame_mdx_offset * wordSize), mdp_in); | |
0 | 975 } |
976 | |
977 | |
978 void InterpreterMacroAssembler::update_mdp_by_constant(Register mdp_in, int constant) { | |
979 assert(ProfileInterpreter, "must be profiling interpreter"); | |
304 | 980 addptr(mdp_in, constant); |
981 movptr(Address(rbp, frame::interpreter_frame_mdx_offset * wordSize), mdp_in); | |
0 | 982 } |
983 | |
984 | |
985 void InterpreterMacroAssembler::update_mdp_for_ret(Register return_bci) { | |
986 assert(ProfileInterpreter, "must be profiling interpreter"); | |
304 | 987 push(return_bci); // save/restore across call_VM |
0 | 988 call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::update_mdp_for_ret), return_bci); |
304 | 989 pop(return_bci); |
0 | 990 } |
991 | |
992 | |
993 void InterpreterMacroAssembler::profile_taken_branch(Register mdp, Register bumped_count) { | |
994 if (ProfileInterpreter) { | |
995 Label profile_continue; | |
996 | |
997 // If no method data exists, go to profile_continue. | |
998 // Otherwise, assign to mdp | |
999 test_method_data_pointer(mdp, profile_continue); | |
1000 | |
1001 // We are taking a branch. Increment the taken count. | |
1002 // We inline increment_mdp_data_at to return bumped_count in a register | |
1003 //increment_mdp_data_at(mdp, in_bytes(JumpData::taken_offset())); | |
1004 Address data(mdp, in_bytes(JumpData::taken_offset())); | |
304 | 1005 |
1006 // %%% 64bit treats these cells as 64 bit but they seem to be 32 bit | |
0 | 1007 movl(bumped_count,data); |
1008 assert( DataLayout::counter_increment==1, "flow-free idiom only works with 1" ); | |
1009 addl(bumped_count, DataLayout::counter_increment); | |
1010 sbbl(bumped_count, 0); | |
1011 movl(data,bumped_count); // Store back out | |
1012 | |
1013 // The method data pointer needs to be updated to reflect the new target. | |
1014 update_mdp_by_offset(mdp, in_bytes(JumpData::displacement_offset())); | |
1015 bind (profile_continue); | |
1016 } | |
1017 } | |
1018 | |
1019 | |
1020 void InterpreterMacroAssembler::profile_not_taken_branch(Register mdp) { | |
1021 if (ProfileInterpreter) { | |
1022 Label profile_continue; | |
1023 | |
1024 // If no method data exists, go to profile_continue. | |
1025 test_method_data_pointer(mdp, profile_continue); | |
1026 | |
1027 // We are taking a branch. Increment the not taken count. | |
1028 increment_mdp_data_at(mdp, in_bytes(BranchData::not_taken_offset())); | |
1029 | |
1030 // The method data pointer needs to be updated to correspond to the next bytecode | |
1031 update_mdp_by_constant(mdp, in_bytes(BranchData::branch_data_size())); | |
1032 bind (profile_continue); | |
1033 } | |
1034 } | |
1035 | |
1036 | |
1037 void InterpreterMacroAssembler::profile_call(Register mdp) { | |
1038 if (ProfileInterpreter) { | |
1039 Label profile_continue; | |
1040 | |
1041 // If no method data exists, go to profile_continue. | |
1042 test_method_data_pointer(mdp, profile_continue); | |
1043 | |
1044 // We are making a call. Increment the count. | |
1045 increment_mdp_data_at(mdp, in_bytes(CounterData::count_offset())); | |
1046 | |
1047 // The method data pointer needs to be updated to reflect the new target. | |
1048 update_mdp_by_constant(mdp, in_bytes(CounterData::counter_data_size())); | |
1049 bind (profile_continue); | |
1050 } | |
1051 } | |
1052 | |
1053 | |
1054 void InterpreterMacroAssembler::profile_final_call(Register mdp) { | |
1055 if (ProfileInterpreter) { | |
1056 Label profile_continue; | |
1057 | |
1058 // If no method data exists, go to profile_continue. | |
1059 test_method_data_pointer(mdp, profile_continue); | |
1060 | |
1061 // We are making a call. Increment the count. | |
1062 increment_mdp_data_at(mdp, in_bytes(CounterData::count_offset())); | |
1063 | |
1064 // The method data pointer needs to be updated to reflect the new target. | |
1065 update_mdp_by_constant(mdp, in_bytes(VirtualCallData::virtual_call_data_size())); | |
1066 bind (profile_continue); | |
1067 } | |
1068 } | |
1069 | |
1070 | |
726
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
710
diff
changeset
|
1071 void InterpreterMacroAssembler::profile_virtual_call(Register receiver, Register mdp, |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
710
diff
changeset
|
1072 Register reg2, |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
710
diff
changeset
|
1073 bool receiver_can_be_null) { |
0 | 1074 if (ProfileInterpreter) { |
1075 Label profile_continue; | |
1076 | |
1077 // If no method data exists, go to profile_continue. | |
1078 test_method_data_pointer(mdp, profile_continue); | |
1079 | |
726
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
710
diff
changeset
|
1080 Label skip_receiver_profile; |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
710
diff
changeset
|
1081 if (receiver_can_be_null) { |
1206
87684f1a88b5
6614597: Performance variability in jvm2008 xml.validation
kvn
parents:
1108
diff
changeset
|
1082 Label not_null; |
726
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
710
diff
changeset
|
1083 testptr(receiver, receiver); |
1206
87684f1a88b5
6614597: Performance variability in jvm2008 xml.validation
kvn
parents:
1108
diff
changeset
|
1084 jccb(Assembler::notZero, not_null); |
87684f1a88b5
6614597: Performance variability in jvm2008 xml.validation
kvn
parents:
1108
diff
changeset
|
1085 // We are making a call. Increment the count for null receiver. |
87684f1a88b5
6614597: Performance variability in jvm2008 xml.validation
kvn
parents:
1108
diff
changeset
|
1086 increment_mdp_data_at(mdp, in_bytes(CounterData::count_offset())); |
87684f1a88b5
6614597: Performance variability in jvm2008 xml.validation
kvn
parents:
1108
diff
changeset
|
1087 jmp(skip_receiver_profile); |
87684f1a88b5
6614597: Performance variability in jvm2008 xml.validation
kvn
parents:
1108
diff
changeset
|
1088 bind(not_null); |
726
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
710
diff
changeset
|
1089 } |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
710
diff
changeset
|
1090 |
0 | 1091 // Record the receiver type. |
1206
87684f1a88b5
6614597: Performance variability in jvm2008 xml.validation
kvn
parents:
1108
diff
changeset
|
1092 record_klass_in_profile(receiver, mdp, reg2, true); |
726
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
710
diff
changeset
|
1093 bind(skip_receiver_profile); |
0 | 1094 |
1095 // The method data pointer needs to be updated to reflect the new target. | |
1096 update_mdp_by_constant(mdp, | |
1097 in_bytes(VirtualCallData:: | |
1098 virtual_call_data_size())); | |
1099 bind(profile_continue); | |
1100 } | |
1101 } | |
1102 | |
1103 | |
1104 void InterpreterMacroAssembler::record_klass_in_profile_helper( | |
1105 Register receiver, Register mdp, | |
1206
87684f1a88b5
6614597: Performance variability in jvm2008 xml.validation
kvn
parents:
1108
diff
changeset
|
1106 Register reg2, int start_row, |
87684f1a88b5
6614597: Performance variability in jvm2008 xml.validation
kvn
parents:
1108
diff
changeset
|
1107 Label& done, bool is_virtual_call) { |
87684f1a88b5
6614597: Performance variability in jvm2008 xml.validation
kvn
parents:
1108
diff
changeset
|
1108 if (TypeProfileWidth == 0) { |
87684f1a88b5
6614597: Performance variability in jvm2008 xml.validation
kvn
parents:
1108
diff
changeset
|
1109 if (is_virtual_call) { |
87684f1a88b5
6614597: Performance variability in jvm2008 xml.validation
kvn
parents:
1108
diff
changeset
|
1110 increment_mdp_data_at(mdp, in_bytes(CounterData::count_offset())); |
87684f1a88b5
6614597: Performance variability in jvm2008 xml.validation
kvn
parents:
1108
diff
changeset
|
1111 } |
967
6918603297f7
6858208: jvm crash when specifying TypeProfileWidth=0 on jdk 6.0
poonam
parents:
826
diff
changeset
|
1112 return; |
1206
87684f1a88b5
6614597: Performance variability in jvm2008 xml.validation
kvn
parents:
1108
diff
changeset
|
1113 } |
967
6918603297f7
6858208: jvm crash when specifying TypeProfileWidth=0 on jdk 6.0
poonam
parents:
826
diff
changeset
|
1114 |
0 | 1115 int last_row = VirtualCallData::row_limit() - 1; |
1116 assert(start_row <= last_row, "must be work left to do"); | |
1117 // Test this row for both the receiver and for null. | |
1118 // Take any of three different outcomes: | |
1119 // 1. found receiver => increment count and goto done | |
1120 // 2. found null => keep looking for case 1, maybe allocate this cell | |
1121 // 3. found something else => keep looking for cases 1 and 2 | |
1122 // Case 3 is handled by a recursive call. | |
1123 for (int row = start_row; row <= last_row; row++) { | |
1124 Label next_test; | |
1125 bool test_for_null_also = (row == start_row); | |
1126 | |
1127 // See if the receiver is receiver[n]. | |
1128 int recvr_offset = in_bytes(VirtualCallData::receiver_offset(row)); | |
1129 test_mdp_data_at(mdp, recvr_offset, receiver, | |
1130 (test_for_null_also ? reg2 : noreg), | |
1131 next_test); | |
1132 // (Reg2 now contains the receiver from the CallData.) | |
1133 | |
1134 // The receiver is receiver[n]. Increment count[n]. | |
1135 int count_offset = in_bytes(VirtualCallData::receiver_count_offset(row)); | |
1136 increment_mdp_data_at(mdp, count_offset); | |
1137 jmp(done); | |
1138 bind(next_test); | |
1139 | |
1140 if (row == start_row) { | |
1206
87684f1a88b5
6614597: Performance variability in jvm2008 xml.validation
kvn
parents:
1108
diff
changeset
|
1141 Label found_null; |
0 | 1142 // Failed the equality check on receiver[n]... Test for null. |
304 | 1143 testptr(reg2, reg2); |
0 | 1144 if (start_row == last_row) { |
1145 // 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
|
1146 if (is_virtual_call) { |
87684f1a88b5
6614597: Performance variability in jvm2008 xml.validation
kvn
parents:
1108
diff
changeset
|
1147 jccb(Assembler::zero, found_null); |
87684f1a88b5
6614597: Performance variability in jvm2008 xml.validation
kvn
parents:
1108
diff
changeset
|
1148 // 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
|
1149 // Increment total counter to indicate polymorphic case. |
1206
87684f1a88b5
6614597: Performance variability in jvm2008 xml.validation
kvn
parents:
1108
diff
changeset
|
1150 increment_mdp_data_at(mdp, in_bytes(CounterData::count_offset())); |
87684f1a88b5
6614597: Performance variability in jvm2008 xml.validation
kvn
parents:
1108
diff
changeset
|
1151 jmp(done); |
87684f1a88b5
6614597: Performance variability in jvm2008 xml.validation
kvn
parents:
1108
diff
changeset
|
1152 bind(found_null); |
87684f1a88b5
6614597: Performance variability in jvm2008 xml.validation
kvn
parents:
1108
diff
changeset
|
1153 } else { |
87684f1a88b5
6614597: Performance variability in jvm2008 xml.validation
kvn
parents:
1108
diff
changeset
|
1154 jcc(Assembler::notZero, done); |
87684f1a88b5
6614597: Performance variability in jvm2008 xml.validation
kvn
parents:
1108
diff
changeset
|
1155 } |
0 | 1156 break; |
1157 } | |
1158 // Since null is rare, make it be the branch-taken case. | |
1159 jcc(Assembler::zero, found_null); | |
1160 | |
1161 // Put all the "Case 3" tests here. | |
1206
87684f1a88b5
6614597: Performance variability in jvm2008 xml.validation
kvn
parents:
1108
diff
changeset
|
1162 record_klass_in_profile_helper(receiver, mdp, reg2, start_row + 1, done, is_virtual_call); |
0 | 1163 |
1164 // Found a null. Keep searching for a matching receiver, | |
1165 // but remember that this is an empty (unused) slot. | |
1166 bind(found_null); | |
1167 } | |
1168 } | |
1169 | |
1170 // In the fall-through case, we found no matching receiver, but we | |
1171 // observed the receiver[start_row] is NULL. | |
1172 | |
1173 // Fill in the receiver field and increment the count. | |
1174 int recvr_offset = in_bytes(VirtualCallData::receiver_offset(start_row)); | |
1175 set_mdp_data_at(mdp, recvr_offset, receiver); | |
1176 int count_offset = in_bytes(VirtualCallData::receiver_count_offset(start_row)); | |
304 | 1177 movptr(reg2, (int32_t)DataLayout::counter_increment); |
0 | 1178 set_mdp_data_at(mdp, count_offset, reg2); |
1206
87684f1a88b5
6614597: Performance variability in jvm2008 xml.validation
kvn
parents:
1108
diff
changeset
|
1179 if (start_row > 0) { |
87684f1a88b5
6614597: Performance variability in jvm2008 xml.validation
kvn
parents:
1108
diff
changeset
|
1180 jmp(done); |
87684f1a88b5
6614597: Performance variability in jvm2008 xml.validation
kvn
parents:
1108
diff
changeset
|
1181 } |
0 | 1182 } |
1183 | |
1184 void InterpreterMacroAssembler::record_klass_in_profile(Register receiver, | |
1206
87684f1a88b5
6614597: Performance variability in jvm2008 xml.validation
kvn
parents:
1108
diff
changeset
|
1185 Register mdp, Register reg2, |
87684f1a88b5
6614597: Performance variability in jvm2008 xml.validation
kvn
parents:
1108
diff
changeset
|
1186 bool is_virtual_call) { |
0 | 1187 assert(ProfileInterpreter, "must be profiling"); |
1188 Label done; | |
1189 | |
1206
87684f1a88b5
6614597: Performance variability in jvm2008 xml.validation
kvn
parents:
1108
diff
changeset
|
1190 record_klass_in_profile_helper(receiver, mdp, reg2, 0, done, is_virtual_call); |
0 | 1191 |
1192 bind (done); | |
1193 } | |
1194 | |
1195 void InterpreterMacroAssembler::profile_ret(Register return_bci, Register mdp) { | |
1196 if (ProfileInterpreter) { | |
1197 Label profile_continue; | |
1198 uint row; | |
1199 | |
1200 // If no method data exists, go to profile_continue. | |
1201 test_method_data_pointer(mdp, profile_continue); | |
1202 | |
1203 // Update the total ret count. | |
1204 increment_mdp_data_at(mdp, in_bytes(CounterData::count_offset())); | |
1205 | |
1206 for (row = 0; row < RetData::row_limit(); row++) { | |
1207 Label next_test; | |
1208 | |
1209 // See if return_bci is equal to bci[n]: | |
1210 test_mdp_data_at(mdp, in_bytes(RetData::bci_offset(row)), return_bci, | |
1211 noreg, next_test); | |
1212 | |
1213 // return_bci is equal to bci[n]. Increment the count. | |
1214 increment_mdp_data_at(mdp, in_bytes(RetData::bci_count_offset(row))); | |
1215 | |
1216 // The method data pointer needs to be updated to reflect the new target. | |
1217 update_mdp_by_offset(mdp, in_bytes(RetData::bci_displacement_offset(row))); | |
1218 jmp(profile_continue); | |
1219 bind(next_test); | |
1220 } | |
1221 | |
1222 update_mdp_for_ret(return_bci); | |
1223 | |
1224 bind (profile_continue); | |
1225 } | |
1226 } | |
1227 | |
1228 | |
1229 void InterpreterMacroAssembler::profile_null_seen(Register mdp) { | |
1230 if (ProfileInterpreter) { | |
1231 Label profile_continue; | |
1232 | |
1233 // If no method data exists, go to profile_continue. | |
1234 test_method_data_pointer(mdp, profile_continue); | |
1235 | |
826
3f06f139ef53
6851908: interpreter null check profiling broken causing extra compilation invalidation
never
parents:
726
diff
changeset
|
1236 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
|
1237 |
0 | 1238 // The method data pointer needs to be updated. |
1239 int mdp_delta = in_bytes(BitData::bit_data_size()); | |
1240 if (TypeProfileCasts) { | |
1241 mdp_delta = in_bytes(VirtualCallData::virtual_call_data_size()); | |
1242 } | |
1243 update_mdp_by_constant(mdp, mdp_delta); | |
1244 | |
1245 bind (profile_continue); | |
1246 } | |
1247 } | |
1248 | |
1249 | |
1250 void InterpreterMacroAssembler::profile_typecheck_failed(Register mdp) { | |
1251 if (ProfileInterpreter && TypeProfileCasts) { | |
1252 Label profile_continue; | |
1253 | |
1254 // If no method data exists, go to profile_continue. | |
1255 test_method_data_pointer(mdp, profile_continue); | |
1256 | |
1257 int count_offset = in_bytes(CounterData::count_offset()); | |
1258 // Back up the address, since we have already bumped the mdp. | |
1259 count_offset -= in_bytes(VirtualCallData::virtual_call_data_size()); | |
1260 | |
1261 // *Decrement* the counter. We expect to see zero or small negatives. | |
1262 increment_mdp_data_at(mdp, count_offset, true); | |
1263 | |
1264 bind (profile_continue); | |
1265 } | |
1266 } | |
1267 | |
1268 | |
1269 void InterpreterMacroAssembler::profile_typecheck(Register mdp, Register klass, Register reg2) | |
1270 { | |
1271 if (ProfileInterpreter) { | |
1272 Label profile_continue; | |
1273 | |
1274 // If no method data exists, go to profile_continue. | |
1275 test_method_data_pointer(mdp, profile_continue); | |
1276 | |
1277 // The method data pointer needs to be updated. | |
1278 int mdp_delta = in_bytes(BitData::bit_data_size()); | |
1279 if (TypeProfileCasts) { | |
1280 mdp_delta = in_bytes(VirtualCallData::virtual_call_data_size()); | |
1281 | |
1282 // Record the object type. | |
1206
87684f1a88b5
6614597: Performance variability in jvm2008 xml.validation
kvn
parents:
1108
diff
changeset
|
1283 record_klass_in_profile(klass, mdp, reg2, false); |
0 | 1284 assert(reg2 == rdi, "we know how to fix this blown reg"); |
1285 restore_locals(); // Restore EDI | |
1286 } | |
1287 update_mdp_by_constant(mdp, mdp_delta); | |
1288 | |
1289 bind(profile_continue); | |
1290 } | |
1291 } | |
1292 | |
1293 | |
1294 void InterpreterMacroAssembler::profile_switch_default(Register mdp) { | |
1295 if (ProfileInterpreter) { | |
1296 Label profile_continue; | |
1297 | |
1298 // If no method data exists, go to profile_continue. | |
1299 test_method_data_pointer(mdp, profile_continue); | |
1300 | |
1301 // Update the default case count | |
1302 increment_mdp_data_at(mdp, in_bytes(MultiBranchData::default_count_offset())); | |
1303 | |
1304 // The method data pointer needs to be updated. | |
1305 update_mdp_by_offset(mdp, in_bytes(MultiBranchData::default_displacement_offset())); | |
1306 | |
1307 bind (profile_continue); | |
1308 } | |
1309 } | |
1310 | |
1311 | |
1312 void InterpreterMacroAssembler::profile_switch_case(Register index, Register mdp, Register reg2) { | |
1313 if (ProfileInterpreter) { | |
1314 Label profile_continue; | |
1315 | |
1316 // If no method data exists, go to profile_continue. | |
1317 test_method_data_pointer(mdp, profile_continue); | |
1318 | |
1319 // Build the base (index * per_case_size_in_bytes()) + case_array_offset_in_bytes() | |
304 | 1320 movptr(reg2, (int32_t)in_bytes(MultiBranchData::per_case_size())); |
1321 // index is positive and so should have correct value if this code were | |
1322 // used on 64bits | |
1323 imulptr(index, reg2); | |
1324 addptr(index, in_bytes(MultiBranchData::case_array_offset())); | |
0 | 1325 |
1326 // Update the case count | |
1327 increment_mdp_data_at(mdp, index, in_bytes(MultiBranchData::relative_count_offset())); | |
1328 | |
1329 // The method data pointer needs to be updated. | |
1330 update_mdp_by_offset(mdp, index, in_bytes(MultiBranchData::relative_displacement_offset())); | |
1331 | |
1332 bind (profile_continue); | |
1333 } | |
1334 } | |
1335 | |
1336 #endif // !CC_INTERP | |
1337 | |
1338 | |
1339 | |
1340 void InterpreterMacroAssembler::verify_oop(Register reg, TosState state) { | |
1341 if (state == atos) MacroAssembler::verify_oop(reg); | |
1342 } | |
1343 | |
1344 | |
1345 #ifndef CC_INTERP | |
1346 void InterpreterMacroAssembler::verify_FPU(int stack_depth, TosState state) { | |
1347 if (state == ftos || state == dtos) MacroAssembler::verify_FPU(stack_depth); | |
1348 } | |
1349 | |
1350 #endif /* CC_INTERP */ | |
1351 | |
1352 | |
1353 void InterpreterMacroAssembler::notify_method_entry() { | |
1354 // Whenever JVMTI is interp_only_mode, method entry/exit events are sent to | |
1355 // track stack depth. If it is possible to enter interp_only_mode we add | |
1356 // the code to check if the event should be sent. | |
1357 if (JvmtiExport::can_post_interpreter_events()) { | |
1358 Label L; | |
1359 get_thread(rcx); | |
1360 movl(rcx, Address(rcx, JavaThread::interp_only_mode_offset())); | |
1361 testl(rcx,rcx); | |
1362 jcc(Assembler::zero, L); | |
1363 call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::post_method_entry)); | |
1364 bind(L); | |
1365 } | |
1366 | |
1367 { | |
1368 SkipIfEqual skip_if(this, &DTraceMethodProbes, 0); | |
1369 get_thread(rcx); | |
1370 get_method(rbx); | |
1371 call_VM_leaf( | |
1372 CAST_FROM_FN_PTR(address, SharedRuntime::dtrace_method_entry), rcx, rbx); | |
1373 } | |
610
70998f2e05ef
6805864: 4/3 Problem with jvmti->redefineClasses: some methods don't get redefined
dcubed
parents:
337
diff
changeset
|
1374 |
70998f2e05ef
6805864: 4/3 Problem with jvmti->redefineClasses: some methods don't get redefined
dcubed
parents:
337
diff
changeset
|
1375 // 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
|
1376 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
|
1377 get_thread(rcx); |
70998f2e05ef
6805864: 4/3 Problem with jvmti->redefineClasses: some methods don't get redefined
dcubed
parents:
337
diff
changeset
|
1378 get_method(rbx); |
70998f2e05ef
6805864: 4/3 Problem with jvmti->redefineClasses: some methods don't get redefined
dcubed
parents:
337
diff
changeset
|
1379 call_VM_leaf( |
70998f2e05ef
6805864: 4/3 Problem with jvmti->redefineClasses: some methods don't get redefined
dcubed
parents:
337
diff
changeset
|
1380 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
|
1381 rcx, rbx); |
70998f2e05ef
6805864: 4/3 Problem with jvmti->redefineClasses: some methods don't get redefined
dcubed
parents:
337
diff
changeset
|
1382 } |
0 | 1383 } |
1384 | |
1385 | |
1386 void InterpreterMacroAssembler::notify_method_exit( | |
1387 TosState state, NotifyMethodExitMode mode) { | |
1388 // Whenever JVMTI is interp_only_mode, method entry/exit events are sent to | |
1389 // track stack depth. If it is possible to enter interp_only_mode we add | |
1390 // the code to check if the event should be sent. | |
1391 if (mode == NotifyJVMTI && JvmtiExport::can_post_interpreter_events()) { | |
1392 Label L; | |
1393 // Note: frame::interpreter_frame_result has a dependency on how the | |
1394 // method result is saved across the call to post_method_exit. If this | |
1395 // is changed then the interpreter_frame_result implementation will | |
1396 // need to be updated too. | |
1397 | |
1398 // For c++ interpreter the result is always stored at a known location in the frame | |
1399 // template interpreter will leave it on the top of the stack. | |
1400 NOT_CC_INTERP(push(state);) | |
1401 get_thread(rcx); | |
1402 movl(rcx, Address(rcx, JavaThread::interp_only_mode_offset())); | |
1403 testl(rcx,rcx); | |
1404 jcc(Assembler::zero, L); | |
1405 call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::post_method_exit)); | |
1406 bind(L); | |
1407 NOT_CC_INTERP(pop(state);) | |
1408 } | |
1409 | |
1410 { | |
1411 SkipIfEqual skip_if(this, &DTraceMethodProbes, 0); | |
304 | 1412 NOT_CC_INTERP(push(state)); |
0 | 1413 get_thread(rbx); |
1414 get_method(rcx); | |
1415 call_VM_leaf( | |
1416 CAST_FROM_FN_PTR(address, SharedRuntime::dtrace_method_exit), | |
1417 rbx, rcx); | |
304 | 1418 NOT_CC_INTERP(pop(state)); |
0 | 1419 } |
1420 } | |
1783 | 1421 |
1422 // Jump if ((*counter_addr += increment) & mask) satisfies the condition. | |
1423 void InterpreterMacroAssembler::increment_mask_and_jump(Address counter_addr, | |
1424 int increment, int mask, | |
1425 Register scratch, bool preloaded, | |
1426 Condition cond, Label* where) { | |
1427 if (!preloaded) { | |
1428 movl(scratch, counter_addr); | |
1429 } | |
1430 incrementl(scratch, increment); | |
1431 movl(counter_addr, scratch); | |
1432 andl(scratch, mask); | |
1433 jcc(cond, *where); | |
1434 } |