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