Mercurial > hg > truffle
annotate src/cpu/x86/vm/c1_LIRAssembler_x86.cpp @ 17716:cdb71841f4bc
6498581: ThreadInterruptTest3 produces wrong output on Windows
Summary: There is race condition between os::interrupt and os::is_interrupted on Windows. In JVM_Sleep(Thread.sleep), check if thread gets interrupted, it may see interrupted but not really interrupted so cause spurious waking up (early return from sleep). Fix by checking if interrupt event really gets set thus prevent false return. For intrinsic of _isInterrupted, on Windows, go fastpath only on bit not set.
Reviewed-by: acorn, kvn
Contributed-by: david.holmes@oracle.com, yumin.qi@oracle.com
author | minqi |
---|---|
date | Wed, 26 Feb 2014 15:20:41 -0800 |
parents | 12ad8db39f76 |
children | 4ca6dc0799b6 876390ee9b6f |
rev | line source |
---|---|
0 | 1 /* |
11080
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
8860
diff
changeset
|
2 * Copyright (c) 2000, 2013, 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:
1491
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1491
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:
1491
diff
changeset
|
21 * questions. |
0 | 22 * |
23 */ | |
24 | |
1972 | 25 #include "precompiled.hpp" |
7199
cd3d6a6b95d9
8003240: x86: move MacroAssembler into separate file
twisti
parents:
6853
diff
changeset
|
26 #include "asm/macroAssembler.hpp" |
cd3d6a6b95d9
8003240: x86: move MacroAssembler into separate file
twisti
parents:
6853
diff
changeset
|
27 #include "asm/macroAssembler.inline.hpp" |
1972 | 28 #include "c1/c1_Compilation.hpp" |
29 #include "c1/c1_LIRAssembler.hpp" | |
30 #include "c1/c1_MacroAssembler.hpp" | |
31 #include "c1/c1_Runtime1.hpp" | |
32 #include "c1/c1_ValueStack.hpp" | |
33 #include "ci/ciArrayKlass.hpp" | |
34 #include "ci/ciInstance.hpp" | |
35 #include "gc_interface/collectedHeap.hpp" | |
36 #include "memory/barrierSet.hpp" | |
37 #include "memory/cardTableModRefBS.hpp" | |
38 #include "nativeInst_x86.hpp" | |
39 #include "oops/objArrayKlass.hpp" | |
40 #include "runtime/sharedRuntime.hpp" | |
17496
12ad8db39f76
8028764: dtrace/hotspot_jni/ALL/ALL001 crashes the vm on Solaris-amd64, SIGSEGV in MarkSweep::follow_stack()+0x8a
roland
parents:
12969
diff
changeset
|
41 #include "vmreg_x86.inline.hpp" |
0 | 42 |
43 | |
44 // These masks are used to provide 128-bit aligned bitmasks to the XMM | |
45 // instructions, to allow sign-masking or sign-bit flipping. They allow | |
46 // fast versions of NegF/NegD and AbsF/AbsD. | |
47 | |
48 // Note: 'double' and 'long long' have 32-bits alignment on x86. | |
49 static jlong* double_quadword(jlong *adr, jlong lo, jlong hi) { | |
50 // Use the expression (adr)&(~0xF) to provide 128-bits aligned address | |
51 // of 128-bits operands for SSE instructions. | |
3401
ccf072cdba91
7046893: LP64 problem with double_quadword in c1_LIRAssembler_x86.cpp
iveresov
parents:
2479
diff
changeset
|
52 jlong *operand = (jlong*)(((intptr_t)adr) & ((intptr_t)(~0xF))); |
0 | 53 // Store the value to a 128-bits operand. |
54 operand[0] = lo; | |
55 operand[1] = hi; | |
56 return operand; | |
57 } | |
58 | |
59 // Buffer for 128-bits masks used by SSE instructions. | |
60 static jlong fp_signmask_pool[(4+1)*2]; // 4*128bits(data) + 128bits(alignment) | |
61 | |
62 // Static initialization during VM startup. | |
63 static jlong *float_signmask_pool = double_quadword(&fp_signmask_pool[1*2], CONST64(0x7FFFFFFF7FFFFFFF), CONST64(0x7FFFFFFF7FFFFFFF)); | |
64 static jlong *double_signmask_pool = double_quadword(&fp_signmask_pool[2*2], CONST64(0x7FFFFFFFFFFFFFFF), CONST64(0x7FFFFFFFFFFFFFFF)); | |
65 static jlong *float_signflip_pool = double_quadword(&fp_signmask_pool[3*2], CONST64(0x8000000080000000), CONST64(0x8000000080000000)); | |
66 static jlong *double_signflip_pool = double_quadword(&fp_signmask_pool[4*2], CONST64(0x8000000000000000), CONST64(0x8000000000000000)); | |
67 | |
68 | |
69 | |
70 NEEDS_CLEANUP // remove this definitions ? | |
71 const Register IC_Klass = rax; // where the IC klass is cached | |
72 const Register SYNC_header = rax; // synchronization header | |
73 const Register SHIFT_count = rcx; // where count for shift operations must be | |
74 | |
75 #define __ _masm-> | |
76 | |
77 | |
78 static void select_different_registers(Register preserve, | |
79 Register extra, | |
80 Register &tmp1, | |
81 Register &tmp2) { | |
82 if (tmp1 == preserve) { | |
83 assert_different_registers(tmp1, tmp2, extra); | |
84 tmp1 = extra; | |
85 } else if (tmp2 == preserve) { | |
86 assert_different_registers(tmp1, tmp2, extra); | |
87 tmp2 = extra; | |
88 } | |
89 assert_different_registers(preserve, tmp1, tmp2); | |
90 } | |
91 | |
92 | |
93 | |
94 static void select_different_registers(Register preserve, | |
95 Register extra, | |
96 Register &tmp1, | |
97 Register &tmp2, | |
98 Register &tmp3) { | |
99 if (tmp1 == preserve) { | |
100 assert_different_registers(tmp1, tmp2, tmp3, extra); | |
101 tmp1 = extra; | |
102 } else if (tmp2 == preserve) { | |
103 assert_different_registers(tmp1, tmp2, tmp3, extra); | |
104 tmp2 = extra; | |
105 } else if (tmp3 == preserve) { | |
106 assert_different_registers(tmp1, tmp2, tmp3, extra); | |
107 tmp3 = extra; | |
108 } | |
109 assert_different_registers(preserve, tmp1, tmp2, tmp3); | |
110 } | |
111 | |
112 | |
113 | |
114 bool LIR_Assembler::is_small_constant(LIR_Opr opr) { | |
115 if (opr->is_constant()) { | |
116 LIR_Const* constant = opr->as_constant_ptr(); | |
117 switch (constant->type()) { | |
118 case T_INT: { | |
119 return true; | |
120 } | |
121 | |
122 default: | |
123 return false; | |
124 } | |
125 } | |
126 return false; | |
127 } | |
128 | |
129 | |
130 LIR_Opr LIR_Assembler::receiverOpr() { | |
304 | 131 return FrameMap::receiver_opr; |
0 | 132 } |
133 | |
134 LIR_Opr LIR_Assembler::osrBufferPointer() { | |
304 | 135 return FrameMap::as_pointer_opr(receiverOpr()->as_register()); |
0 | 136 } |
137 | |
138 //--------------fpu register translations----------------------- | |
139 | |
140 | |
141 address LIR_Assembler::float_constant(float f) { | |
142 address const_addr = __ float_constant(f); | |
143 if (const_addr == NULL) { | |
144 bailout("const section overflow"); | |
145 return __ code()->consts()->start(); | |
146 } else { | |
147 return const_addr; | |
148 } | |
149 } | |
150 | |
151 | |
152 address LIR_Assembler::double_constant(double d) { | |
153 address const_addr = __ double_constant(d); | |
154 if (const_addr == NULL) { | |
155 bailout("const section overflow"); | |
156 return __ code()->consts()->start(); | |
157 } else { | |
158 return const_addr; | |
159 } | |
160 } | |
161 | |
162 | |
163 void LIR_Assembler::set_24bit_FPU() { | |
164 __ fldcw(ExternalAddress(StubRoutines::addr_fpu_cntrl_wrd_24())); | |
165 } | |
166 | |
167 void LIR_Assembler::reset_FPU() { | |
168 __ fldcw(ExternalAddress(StubRoutines::addr_fpu_cntrl_wrd_std())); | |
169 } | |
170 | |
171 void LIR_Assembler::fpop() { | |
172 __ fpop(); | |
173 } | |
174 | |
175 void LIR_Assembler::fxch(int i) { | |
176 __ fxch(i); | |
177 } | |
178 | |
179 void LIR_Assembler::fld(int i) { | |
180 __ fld_s(i); | |
181 } | |
182 | |
183 void LIR_Assembler::ffree(int i) { | |
184 __ ffree(i); | |
185 } | |
186 | |
187 void LIR_Assembler::breakpoint() { | |
188 __ int3(); | |
189 } | |
190 | |
191 void LIR_Assembler::push(LIR_Opr opr) { | |
192 if (opr->is_single_cpu()) { | |
193 __ push_reg(opr->as_register()); | |
194 } else if (opr->is_double_cpu()) { | |
304 | 195 NOT_LP64(__ push_reg(opr->as_register_hi())); |
0 | 196 __ push_reg(opr->as_register_lo()); |
197 } else if (opr->is_stack()) { | |
198 __ push_addr(frame_map()->address_for_slot(opr->single_stack_ix())); | |
199 } else if (opr->is_constant()) { | |
200 LIR_Const* const_opr = opr->as_constant_ptr(); | |
201 if (const_opr->type() == T_OBJECT) { | |
202 __ push_oop(const_opr->as_jobject()); | |
203 } else if (const_opr->type() == T_INT) { | |
204 __ push_jint(const_opr->as_jint()); | |
205 } else { | |
206 ShouldNotReachHere(); | |
207 } | |
208 | |
209 } else { | |
210 ShouldNotReachHere(); | |
211 } | |
212 } | |
213 | |
214 void LIR_Assembler::pop(LIR_Opr opr) { | |
215 if (opr->is_single_cpu()) { | |
304 | 216 __ pop_reg(opr->as_register()); |
0 | 217 } else { |
218 ShouldNotReachHere(); | |
219 } | |
220 } | |
221 | |
304 | 222 bool LIR_Assembler::is_literal_address(LIR_Address* addr) { |
223 return addr->base()->is_illegal() && addr->index()->is_illegal(); | |
224 } | |
225 | |
0 | 226 //------------------------------------------- |
304 | 227 |
0 | 228 Address LIR_Assembler::as_Address(LIR_Address* addr) { |
304 | 229 return as_Address(addr, rscratch1); |
230 } | |
231 | |
232 Address LIR_Assembler::as_Address(LIR_Address* addr, Register tmp) { | |
0 | 233 if (addr->base()->is_illegal()) { |
234 assert(addr->index()->is_illegal(), "must be illegal too"); | |
304 | 235 AddressLiteral laddr((address)addr->disp(), relocInfo::none); |
236 if (! __ reachable(laddr)) { | |
237 __ movptr(tmp, laddr.addr()); | |
238 Address res(tmp, 0); | |
239 return res; | |
240 } else { | |
241 return __ as_Address(laddr); | |
242 } | |
0 | 243 } |
244 | |
304 | 245 Register base = addr->base()->as_pointer_register(); |
0 | 246 |
247 if (addr->index()->is_illegal()) { | |
248 return Address( base, addr->disp()); | |
304 | 249 } else if (addr->index()->is_cpu_register()) { |
250 Register index = addr->index()->as_pointer_register(); | |
0 | 251 return Address(base, index, (Address::ScaleFactor) addr->scale(), addr->disp()); |
252 } else if (addr->index()->is_constant()) { | |
304 | 253 intptr_t addr_offset = (addr->index()->as_constant_ptr()->as_jint() << addr->scale()) + addr->disp(); |
254 assert(Assembler::is_simm32(addr_offset), "must be"); | |
0 | 255 |
256 return Address(base, addr_offset); | |
257 } else { | |
258 Unimplemented(); | |
259 return Address(); | |
260 } | |
261 } | |
262 | |
263 | |
264 Address LIR_Assembler::as_Address_hi(LIR_Address* addr) { | |
265 Address base = as_Address(addr); | |
266 return Address(base._base, base._index, base._scale, base._disp + BytesPerWord); | |
267 } | |
268 | |
269 | |
270 Address LIR_Assembler::as_Address_lo(LIR_Address* addr) { | |
271 return as_Address(addr); | |
272 } | |
273 | |
274 | |
275 void LIR_Assembler::osr_entry() { | |
276 offsets()->set_value(CodeOffsets::OSR_Entry, code_offset()); | |
277 BlockBegin* osr_entry = compilation()->hir()->osr_entry(); | |
278 ValueStack* entry_state = osr_entry->state(); | |
279 int number_of_locks = entry_state->locks_size(); | |
280 | |
281 // we jump here if osr happens with the interpreter | |
282 // state set up to continue at the beginning of the | |
283 // loop that triggered osr - in particular, we have | |
284 // the following registers setup: | |
285 // | |
286 // rcx: osr buffer | |
287 // | |
288 | |
289 // build frame | |
290 ciMethod* m = compilation()->method(); | |
291 __ build_frame(initial_frame_size_in_bytes()); | |
292 | |
293 // OSR buffer is | |
294 // | |
295 // locals[nlocals-1..0] | |
296 // monitors[0..number_of_locks] | |
297 // | |
298 // locals is a direct copy of the interpreter frame so in the osr buffer | |
299 // so first slot in the local array is the last local from the interpreter | |
300 // and last slot is local[0] (receiver) from the interpreter | |
301 // | |
302 // Similarly with locks. The first lock slot in the osr buffer is the nth lock | |
303 // from the interpreter frame, the nth lock slot in the osr buffer is 0th lock | |
304 // in the interpreter frame (the method lock if a sync method) | |
305 | |
306 // Initialize monitors in the compiled activation. | |
307 // rcx: pointer to osr buffer | |
308 // | |
309 // All other registers are dead at this point and the locals will be | |
310 // copied into place by code emitted in the IR. | |
311 | |
304 | 312 Register OSR_buf = osrBufferPointer()->as_pointer_register(); |
0 | 313 { assert(frame::interpreter_frame_monitor_size() == BasicObjectLock::size(), "adjust code below"); |
314 int monitor_offset = BytesPerWord * method()->max_locals() + | |
1060 | 315 (2 * BytesPerWord) * (number_of_locks - 1); |
316 // SharedRuntime::OSR_migration_begin() packs BasicObjectLocks in | |
317 // the OSR buffer using 2 word entries: first the lock and then | |
318 // the oop. | |
0 | 319 for (int i = 0; i < number_of_locks; i++) { |
1060 | 320 int slot_offset = monitor_offset - ((i * 2) * BytesPerWord); |
0 | 321 #ifdef ASSERT |
322 // verify the interpreter's monitor has a non-null object | |
323 { | |
324 Label L; | |
1060 | 325 __ cmpptr(Address(OSR_buf, slot_offset + 1*BytesPerWord), (int32_t)NULL_WORD); |
0 | 326 __ jcc(Assembler::notZero, L); |
327 __ stop("locked object is NULL"); | |
328 __ bind(L); | |
329 } | |
330 #endif | |
1060 | 331 __ movptr(rbx, Address(OSR_buf, slot_offset + 0)); |
304 | 332 __ movptr(frame_map()->address_for_monitor_lock(i), rbx); |
1060 | 333 __ movptr(rbx, Address(OSR_buf, slot_offset + 1*BytesPerWord)); |
304 | 334 __ movptr(frame_map()->address_for_monitor_object(i), rbx); |
0 | 335 } |
336 } | |
337 } | |
338 | |
339 | |
340 // inline cache check; done before the frame is built. | |
341 int LIR_Assembler::check_icache() { | |
342 Register receiver = FrameMap::receiver_opr->as_register(); | |
343 Register ic_klass = IC_Klass; | |
304 | 344 const int ic_cmp_size = LP64_ONLY(10) NOT_LP64(9); |
12226
7944aba7ba41
8015107: NPG: Use consistent naming for metaspace concepts
ehelin
parents:
12160
diff
changeset
|
345 const bool do_post_padding = VerifyOops || UseCompressedClassPointers; |
2002 | 346 if (!do_post_padding) { |
0 | 347 // insert some nops so that the verified entry point is aligned on CodeEntryAlignment |
304 | 348 while ((__ offset() + ic_cmp_size) % CodeEntryAlignment != 0) { |
0 | 349 __ nop(); |
350 } | |
351 } | |
352 int offset = __ offset(); | |
353 __ inline_cache_check(receiver, IC_Klass); | |
2002 | 354 assert(__ offset() % CodeEntryAlignment == 0 || do_post_padding, "alignment must be correct"); |
355 if (do_post_padding) { | |
0 | 356 // force alignment after the cache check. |
357 // It's been verified to be aligned if !VerifyOops | |
358 __ align(CodeEntryAlignment); | |
359 } | |
360 return offset; | |
361 } | |
362 | |
363 | |
364 void LIR_Assembler::jobject2reg_with_patching(Register reg, CodeEmitInfo* info) { | |
365 jobject o = NULL; | |
12160
f98f5d48f511
7199175: JSR 292: C1 needs patching when invokedynamic/invokehandle call site is not linked
roland
parents:
11080
diff
changeset
|
366 PatchingStub* patch = new PatchingStub(_masm, patching_id(info)); |
0 | 367 __ movoop(reg, o); |
368 patching_epilog(patch, lir_patch_normal, reg, info); | |
369 } | |
370 | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
371 void LIR_Assembler::klass2reg_with_patching(Register reg, CodeEmitInfo* info) { |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
372 Metadata* o = NULL; |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
373 PatchingStub* patch = new PatchingStub(_masm, PatchingStub::load_klass_id); |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
374 __ mov_metadata(reg, o); |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
375 patching_epilog(patch, lir_patch_normal, reg, info); |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
376 } |
0 | 377 |
378 // This specifies the rsp decrement needed to build the frame | |
379 int LIR_Assembler::initial_frame_size_in_bytes() { | |
380 // if rounding, must let FrameMap know! | |
304 | 381 |
382 // The frame_map records size in slots (32bit word) | |
383 | |
384 // subtract two words to account for return address and link | |
385 return (frame_map()->framesize() - (2*VMRegImpl::slots_per_word)) * VMRegImpl::stack_slot_size; | |
0 | 386 } |
387 | |
388 | |
1204 | 389 int LIR_Assembler::emit_exception_handler() { |
0 | 390 // if the last instruction is a call (typically to do a throw which |
391 // is coming at the end after block reordering) the return address | |
392 // must still point into the code area in order to avoid assertion | |
393 // failures when searching for the corresponding bci => add a nop | |
394 // (was bug 5/14/1999 - gri) | |
395 __ nop(); | |
396 | |
397 // generate code for exception handler | |
398 address handler_base = __ start_a_stub(exception_handler_size); | |
399 if (handler_base == NULL) { | |
400 // not enough space left for the handler | |
401 bailout("exception handler overflow"); | |
1204 | 402 return -1; |
0 | 403 } |
1204 | 404 |
0 | 405 int offset = code_offset(); |
406 | |
1295 | 407 // the exception oop and pc are in rax, and rdx |
0 | 408 // no other registers need to be preserved, so invalidate them |
1295 | 409 __ invalidate_registers(false, true, true, false, true, true); |
0 | 410 |
411 // check that there is really an exception | |
412 __ verify_not_null_oop(rax); | |
413 | |
1295 | 414 // search an exception handler (rax: exception oop, rdx: throwing pc) |
2321
1b4e6a5d98e0
7012914: JSR 292 MethodHandlesTest C1: frame::verify_return_pc(return_address) failed: must be a return pc
twisti
parents:
2112
diff
changeset
|
415 __ call(RuntimeAddress(Runtime1::entry_for(Runtime1::handle_exception_from_callee_id))); |
1b4e6a5d98e0
7012914: JSR 292 MethodHandlesTest C1: frame::verify_return_pc(return_address) failed: must be a return pc
twisti
parents:
2112
diff
changeset
|
416 __ should_not_reach_here(); |
4808
898522ae3c32
7131288: COMPILE SKIPPED: deopt handler overflow (retry at different tier)
iveresov
parents:
4771
diff
changeset
|
417 guarantee(code_offset() - offset <= exception_handler_size, "overflow"); |
0 | 418 __ end_a_stub(); |
1204 | 419 |
420 return offset; | |
0 | 421 } |
422 | |
1204 | 423 |
1378
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
424 // Emit the code to remove the frame from the stack in the exception |
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
425 // unwind path. |
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
426 int LIR_Assembler::emit_unwind_handler() { |
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
427 #ifndef PRODUCT |
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
428 if (CommentedAssembly) { |
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
429 _masm->block_comment("Unwind handler"); |
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
430 } |
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
431 #endif |
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
432 |
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
433 int offset = code_offset(); |
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
434 |
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
435 // Fetch the exception from TLS and clear out exception related thread state |
12969
9acbfe04b5c3
8026495: JVM Crashes when started with -XX:+DTraceMethodProbes on Solaris x86_64
iveresov
parents:
12955
diff
changeset
|
436 Register thread = NOT_LP64(rsi) LP64_ONLY(r15_thread); |
9acbfe04b5c3
8026495: JVM Crashes when started with -XX:+DTraceMethodProbes on Solaris x86_64
iveresov
parents:
12955
diff
changeset
|
437 NOT_LP64(__ get_thread(rsi)); |
9acbfe04b5c3
8026495: JVM Crashes when started with -XX:+DTraceMethodProbes on Solaris x86_64
iveresov
parents:
12955
diff
changeset
|
438 __ movptr(rax, Address(thread, JavaThread::exception_oop_offset())); |
9acbfe04b5c3
8026495: JVM Crashes when started with -XX:+DTraceMethodProbes on Solaris x86_64
iveresov
parents:
12955
diff
changeset
|
439 __ movptr(Address(thread, JavaThread::exception_oop_offset()), (intptr_t)NULL_WORD); |
9acbfe04b5c3
8026495: JVM Crashes when started with -XX:+DTraceMethodProbes on Solaris x86_64
iveresov
parents:
12955
diff
changeset
|
440 __ movptr(Address(thread, JavaThread::exception_pc_offset()), (intptr_t)NULL_WORD); |
1378
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
441 |
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
442 __ bind(_unwind_handler_entry); |
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
443 __ verify_not_null_oop(rax); |
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
444 if (method()->is_synchronized() || compilation()->env()->dtrace_method_probes()) { |
12969
9acbfe04b5c3
8026495: JVM Crashes when started with -XX:+DTraceMethodProbes on Solaris x86_64
iveresov
parents:
12955
diff
changeset
|
445 __ mov(rbx, rax); // Preserve the exception (rbx is always callee-saved) |
1378
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
446 } |
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
447 |
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
448 // Preform needed unlocking |
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
449 MonitorExitStub* stub = NULL; |
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
450 if (method()->is_synchronized()) { |
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
451 monitor_address(0, FrameMap::rax_opr); |
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
452 stub = new MonitorExitStub(FrameMap::rax_opr, true, 0); |
12969
9acbfe04b5c3
8026495: JVM Crashes when started with -XX:+DTraceMethodProbes on Solaris x86_64
iveresov
parents:
12955
diff
changeset
|
453 __ unlock_object(rdi, rsi, rax, *stub->entry()); |
1378
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
454 __ bind(*stub->continuation()); |
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
455 } |
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
456 |
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
457 if (compilation()->env()->dtrace_method_probes()) { |
12969
9acbfe04b5c3
8026495: JVM Crashes when started with -XX:+DTraceMethodProbes on Solaris x86_64
iveresov
parents:
12955
diff
changeset
|
458 #ifdef _LP64 |
9acbfe04b5c3
8026495: JVM Crashes when started with -XX:+DTraceMethodProbes on Solaris x86_64
iveresov
parents:
12955
diff
changeset
|
459 __ mov(rdi, r15_thread); |
9acbfe04b5c3
8026495: JVM Crashes when started with -XX:+DTraceMethodProbes on Solaris x86_64
iveresov
parents:
12955
diff
changeset
|
460 __ mov_metadata(rsi, method()->constant_encoding()); |
9acbfe04b5c3
8026495: JVM Crashes when started with -XX:+DTraceMethodProbes on Solaris x86_64
iveresov
parents:
12955
diff
changeset
|
461 #else |
1830
a3f7f95b0165
6988018: dtrace/hotspot/MethodInvocation/MethodInvocation002 crashes with client compiler
never
parents:
1791
diff
changeset
|
462 __ get_thread(rax); |
a3f7f95b0165
6988018: dtrace/hotspot/MethodInvocation/MethodInvocation002 crashes with client compiler
never
parents:
1791
diff
changeset
|
463 __ movptr(Address(rsp, 0), rax); |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
464 __ mov_metadata(Address(rsp, sizeof(void*)), method()->constant_encoding()); |
12969
9acbfe04b5c3
8026495: JVM Crashes when started with -XX:+DTraceMethodProbes on Solaris x86_64
iveresov
parents:
12955
diff
changeset
|
465 #endif |
1378
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
466 __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, SharedRuntime::dtrace_method_exit))); |
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
467 } |
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
468 |
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
469 if (method()->is_synchronized() || compilation()->env()->dtrace_method_probes()) { |
12969
9acbfe04b5c3
8026495: JVM Crashes when started with -XX:+DTraceMethodProbes on Solaris x86_64
iveresov
parents:
12955
diff
changeset
|
470 __ mov(rax, rbx); // Restore the exception |
1378
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
471 } |
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
472 |
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
473 // remove the activation and dispatch to the unwind handler |
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
474 __ remove_frame(initial_frame_size_in_bytes()); |
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
475 __ jump(RuntimeAddress(Runtime1::entry_for(Runtime1::unwind_exception_id))); |
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
476 |
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
477 // Emit the slow path assembly |
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
478 if (stub != NULL) { |
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
479 stub->emit_code(this); |
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
480 } |
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
481 |
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
482 return offset; |
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
483 } |
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
484 |
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
485 |
1204 | 486 int LIR_Assembler::emit_deopt_handler() { |
0 | 487 // if the last instruction is a call (typically to do a throw which |
488 // is coming at the end after block reordering) the return address | |
489 // must still point into the code area in order to avoid assertion | |
490 // failures when searching for the corresponding bci => add a nop | |
491 // (was bug 5/14/1999 - gri) | |
492 __ nop(); | |
493 | |
494 // generate code for exception handler | |
495 address handler_base = __ start_a_stub(deopt_handler_size); | |
496 if (handler_base == NULL) { | |
497 // not enough space left for the handler | |
498 bailout("deopt handler overflow"); | |
1204 | 499 return -1; |
0 | 500 } |
1204 | 501 |
0 | 502 int offset = code_offset(); |
503 InternalAddress here(__ pc()); | |
1295 | 504 |
0 | 505 __ pushptr(here.addr()); |
506 __ jump(RuntimeAddress(SharedRuntime::deopt_blob()->unpack())); | |
4808
898522ae3c32
7131288: COMPILE SKIPPED: deopt handler overflow (retry at different tier)
iveresov
parents:
4771
diff
changeset
|
507 guarantee(code_offset() - offset <= deopt_handler_size, "overflow"); |
0 | 508 __ end_a_stub(); |
509 | |
1204 | 510 return offset; |
0 | 511 } |
512 | |
513 | |
514 // This is the fast version of java.lang.String.compare; it has not | |
515 // OSR-entry and therefore, we generate a slow version for OSR's | |
516 void LIR_Assembler::emit_string_compare(LIR_Opr arg0, LIR_Opr arg1, LIR_Opr dst, CodeEmitInfo* info) { | |
304 | 517 __ movptr (rbx, rcx); // receiver is in rcx |
518 __ movptr (rax, arg1->as_register()); | |
0 | 519 |
520 // Get addresses of first characters from both Strings | |
2002 | 521 __ load_heap_oop(rsi, Address(rax, java_lang_String::value_offset_in_bytes())); |
6057 | 522 if (java_lang_String::has_offset_field()) { |
523 __ movptr (rcx, Address(rax, java_lang_String::offset_offset_in_bytes())); | |
524 __ movl (rax, Address(rax, java_lang_String::count_offset_in_bytes())); | |
525 __ lea (rsi, Address(rsi, rcx, Address::times_2, arrayOopDesc::base_offset_in_bytes(T_CHAR))); | |
526 } else { | |
527 __ movl (rax, Address(rsi, arrayOopDesc::length_offset_in_bytes())); | |
528 __ lea (rsi, Address(rsi, arrayOopDesc::base_offset_in_bytes(T_CHAR))); | |
529 } | |
0 | 530 |
531 // rbx, may be NULL | |
532 add_debug_info_for_null_check_here(info); | |
2002 | 533 __ load_heap_oop(rdi, Address(rbx, java_lang_String::value_offset_in_bytes())); |
6057 | 534 if (java_lang_String::has_offset_field()) { |
535 __ movptr (rcx, Address(rbx, java_lang_String::offset_offset_in_bytes())); | |
536 __ movl (rbx, Address(rbx, java_lang_String::count_offset_in_bytes())); | |
537 __ lea (rdi, Address(rdi, rcx, Address::times_2, arrayOopDesc::base_offset_in_bytes(T_CHAR))); | |
538 } else { | |
539 __ movl (rbx, Address(rdi, arrayOopDesc::length_offset_in_bytes())); | |
540 __ lea (rdi, Address(rdi, arrayOopDesc::base_offset_in_bytes(T_CHAR))); | |
541 } | |
0 | 542 |
543 // compute minimum length (in rax) and difference of lengths (on top of stack) | |
2415
09f96c3ff1ad
7032388: guarantee(VM_Version::supports_cmov()) failed: illegal instruction on i586 after 6919934
twisti
parents:
2404
diff
changeset
|
544 __ mov (rcx, rbx); |
09f96c3ff1ad
7032388: guarantee(VM_Version::supports_cmov()) failed: illegal instruction on i586 after 6919934
twisti
parents:
2404
diff
changeset
|
545 __ subptr(rbx, rax); // subtract lengths |
09f96c3ff1ad
7032388: guarantee(VM_Version::supports_cmov()) failed: illegal instruction on i586 after 6919934
twisti
parents:
2404
diff
changeset
|
546 __ push (rbx); // result |
09f96c3ff1ad
7032388: guarantee(VM_Version::supports_cmov()) failed: illegal instruction on i586 after 6919934
twisti
parents:
2404
diff
changeset
|
547 __ cmov (Assembler::lessEqual, rax, rcx); |
09f96c3ff1ad
7032388: guarantee(VM_Version::supports_cmov()) failed: illegal instruction on i586 after 6919934
twisti
parents:
2404
diff
changeset
|
548 |
0 | 549 // is minimum length 0? |
550 Label noLoop, haveResult; | |
304 | 551 __ testptr (rax, rax); |
0 | 552 __ jcc (Assembler::zero, noLoop); |
553 | |
554 // compare first characters | |
622
56aae7be60d4
6812678: macro assembler needs delayed binding of a few constants (for 6655638)
jrose
parents:
512
diff
changeset
|
555 __ load_unsigned_short(rcx, Address(rdi, 0)); |
56aae7be60d4
6812678: macro assembler needs delayed binding of a few constants (for 6655638)
jrose
parents:
512
diff
changeset
|
556 __ load_unsigned_short(rbx, Address(rsi, 0)); |
0 | 557 __ subl(rcx, rbx); |
558 __ jcc(Assembler::notZero, haveResult); | |
559 // starting loop | |
560 __ decrement(rax); // we already tested index: skip one | |
561 __ jcc(Assembler::zero, noLoop); | |
562 | |
563 // set rsi.edi to the end of the arrays (arrays have same length) | |
564 // negate the index | |
565 | |
304 | 566 __ lea(rsi, Address(rsi, rax, Address::times_2, type2aelembytes(T_CHAR))); |
567 __ lea(rdi, Address(rdi, rax, Address::times_2, type2aelembytes(T_CHAR))); | |
568 __ negptr(rax); | |
0 | 569 |
570 // compare the strings in a loop | |
571 | |
572 Label loop; | |
573 __ align(wordSize); | |
574 __ bind(loop); | |
622
56aae7be60d4
6812678: macro assembler needs delayed binding of a few constants (for 6655638)
jrose
parents:
512
diff
changeset
|
575 __ load_unsigned_short(rcx, Address(rdi, rax, Address::times_2, 0)); |
56aae7be60d4
6812678: macro assembler needs delayed binding of a few constants (for 6655638)
jrose
parents:
512
diff
changeset
|
576 __ load_unsigned_short(rbx, Address(rsi, rax, Address::times_2, 0)); |
0 | 577 __ subl(rcx, rbx); |
578 __ jcc(Assembler::notZero, haveResult); | |
579 __ increment(rax); | |
580 __ jcc(Assembler::notZero, loop); | |
581 | |
582 // strings are equal up to min length | |
583 | |
584 __ bind(noLoop); | |
304 | 585 __ pop(rax); |
0 | 586 return_op(LIR_OprFact::illegalOpr); |
587 | |
588 __ bind(haveResult); | |
589 // leave instruction is going to discard the TOS value | |
304 | 590 __ mov (rax, rcx); // result of call is in rax, |
0 | 591 } |
592 | |
593 | |
594 void LIR_Assembler::return_op(LIR_Opr result) { | |
595 assert(result->is_illegal() || !result->is_single_cpu() || result->as_register() == rax, "word returns are in rax,"); | |
596 if (!result->is_illegal() && result->is_float_kind() && !result->is_xmm_register()) { | |
597 assert(result->fpu() == 0, "result must already be on TOS"); | |
598 } | |
599 | |
600 // Pop the stack before the safepoint code | |
1295 | 601 __ remove_frame(initial_frame_size_in_bytes()); |
0 | 602 |
603 bool result_is_oop = result->is_valid() ? result->is_oop() : false; | |
604 | |
605 // Note: we do not need to round double result; float result has the right precision | |
606 // the poll sets the condition code, but no data registers | |
607 AddressLiteral polling_page(os::get_polling_page() + (SafepointPollOffset % os::vm_page_size()), | |
608 relocInfo::poll_return_type); | |
304 | 609 |
2404
b40d4fa697bf
6964776: c2 should ensure the polling page is reachable on 64 bit
iveresov
parents:
2321
diff
changeset
|
610 if (Assembler::is_polling_page_far()) { |
b40d4fa697bf
6964776: c2 should ensure the polling page is reachable on 64 bit
iveresov
parents:
2321
diff
changeset
|
611 __ lea(rscratch1, polling_page); |
b40d4fa697bf
6964776: c2 should ensure the polling page is reachable on 64 bit
iveresov
parents:
2321
diff
changeset
|
612 __ relocate(relocInfo::poll_return_type); |
b40d4fa697bf
6964776: c2 should ensure the polling page is reachable on 64 bit
iveresov
parents:
2321
diff
changeset
|
613 __ testl(rax, Address(rscratch1, 0)); |
b40d4fa697bf
6964776: c2 should ensure the polling page is reachable on 64 bit
iveresov
parents:
2321
diff
changeset
|
614 } else { |
b40d4fa697bf
6964776: c2 should ensure the polling page is reachable on 64 bit
iveresov
parents:
2321
diff
changeset
|
615 __ testl(rax, polling_page); |
b40d4fa697bf
6964776: c2 should ensure the polling page is reachable on 64 bit
iveresov
parents:
2321
diff
changeset
|
616 } |
0 | 617 __ ret(0); |
618 } | |
619 | |
620 | |
621 int LIR_Assembler::safepoint_poll(LIR_Opr tmp, CodeEmitInfo* info) { | |
622 AddressLiteral polling_page(os::get_polling_page() + (SafepointPollOffset % os::vm_page_size()), | |
623 relocInfo::poll_type); | |
2404
b40d4fa697bf
6964776: c2 should ensure the polling page is reachable on 64 bit
iveresov
parents:
2321
diff
changeset
|
624 guarantee(info != NULL, "Shouldn't be NULL"); |
b40d4fa697bf
6964776: c2 should ensure the polling page is reachable on 64 bit
iveresov
parents:
2321
diff
changeset
|
625 int offset = __ offset(); |
b40d4fa697bf
6964776: c2 should ensure the polling page is reachable on 64 bit
iveresov
parents:
2321
diff
changeset
|
626 if (Assembler::is_polling_page_far()) { |
b40d4fa697bf
6964776: c2 should ensure the polling page is reachable on 64 bit
iveresov
parents:
2321
diff
changeset
|
627 __ lea(rscratch1, polling_page); |
b40d4fa697bf
6964776: c2 should ensure the polling page is reachable on 64 bit
iveresov
parents:
2321
diff
changeset
|
628 offset = __ offset(); |
0 | 629 add_debug_info_for_branch(info); |
2404
b40d4fa697bf
6964776: c2 should ensure the polling page is reachable on 64 bit
iveresov
parents:
2321
diff
changeset
|
630 __ testl(rax, Address(rscratch1, 0)); |
0 | 631 } else { |
2404
b40d4fa697bf
6964776: c2 should ensure the polling page is reachable on 64 bit
iveresov
parents:
2321
diff
changeset
|
632 add_debug_info_for_branch(info); |
b40d4fa697bf
6964776: c2 should ensure the polling page is reachable on 64 bit
iveresov
parents:
2321
diff
changeset
|
633 __ testl(rax, polling_page); |
0 | 634 } |
635 return offset; | |
636 } | |
637 | |
638 | |
639 void LIR_Assembler::move_regs(Register from_reg, Register to_reg) { | |
304 | 640 if (from_reg != to_reg) __ mov(to_reg, from_reg); |
0 | 641 } |
642 | |
643 void LIR_Assembler::swap_reg(Register a, Register b) { | |
304 | 644 __ xchgptr(a, b); |
0 | 645 } |
646 | |
647 | |
648 void LIR_Assembler::const2reg(LIR_Opr src, LIR_Opr dest, LIR_PatchCode patch_code, CodeEmitInfo* info) { | |
649 assert(src->is_constant(), "should not call otherwise"); | |
650 assert(dest->is_register(), "should not call otherwise"); | |
651 LIR_Const* c = src->as_constant_ptr(); | |
652 | |
653 switch (c->type()) { | |
2002 | 654 case T_INT: { |
655 assert(patch_code == lir_patch_none, "no patching handled here"); | |
656 __ movl(dest->as_register(), c->as_jint()); | |
657 break; | |
658 } | |
659 | |
1297
c466efa608d5
6932496: c1: deoptimization of jsr subroutine fails on sparcv9
roland
parents:
1295
diff
changeset
|
660 case T_ADDRESS: { |
0 | 661 assert(patch_code == lir_patch_none, "no patching handled here"); |
2002 | 662 __ movptr(dest->as_register(), c->as_jint()); |
0 | 663 break; |
664 } | |
665 | |
666 case T_LONG: { | |
667 assert(patch_code == lir_patch_none, "no patching handled here"); | |
304 | 668 #ifdef _LP64 |
669 __ movptr(dest->as_register_lo(), (intptr_t)c->as_jlong()); | |
670 #else | |
671 __ movptr(dest->as_register_lo(), c->as_jint_lo()); | |
672 __ movptr(dest->as_register_hi(), c->as_jint_hi()); | |
673 #endif // _LP64 | |
0 | 674 break; |
675 } | |
676 | |
677 case T_OBJECT: { | |
678 if (patch_code != lir_patch_none) { | |
679 jobject2reg_with_patching(dest->as_register(), info); | |
680 } else { | |
681 __ movoop(dest->as_register(), c->as_jobject()); | |
682 } | |
683 break; | |
684 } | |
685 | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
686 case T_METADATA: { |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
687 if (patch_code != lir_patch_none) { |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
688 klass2reg_with_patching(dest->as_register(), info); |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
689 } else { |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
690 __ mov_metadata(dest->as_register(), c->as_metadata()); |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
691 } |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
692 break; |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
693 } |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
694 |
0 | 695 case T_FLOAT: { |
696 if (dest->is_single_xmm()) { | |
697 if (c->is_zero_float()) { | |
698 __ xorps(dest->as_xmm_float_reg(), dest->as_xmm_float_reg()); | |
699 } else { | |
700 __ movflt(dest->as_xmm_float_reg(), | |
701 InternalAddress(float_constant(c->as_jfloat()))); | |
702 } | |
703 } else { | |
704 assert(dest->is_single_fpu(), "must be"); | |
705 assert(dest->fpu_regnr() == 0, "dest must be TOS"); | |
706 if (c->is_zero_float()) { | |
707 __ fldz(); | |
708 } else if (c->is_one_float()) { | |
709 __ fld1(); | |
710 } else { | |
711 __ fld_s (InternalAddress(float_constant(c->as_jfloat()))); | |
712 } | |
713 } | |
714 break; | |
715 } | |
716 | |
717 case T_DOUBLE: { | |
718 if (dest->is_double_xmm()) { | |
719 if (c->is_zero_double()) { | |
720 __ xorpd(dest->as_xmm_double_reg(), dest->as_xmm_double_reg()); | |
721 } else { | |
722 __ movdbl(dest->as_xmm_double_reg(), | |
723 InternalAddress(double_constant(c->as_jdouble()))); | |
724 } | |
725 } else { | |
726 assert(dest->is_double_fpu(), "must be"); | |
727 assert(dest->fpu_regnrLo() == 0, "dest must be TOS"); | |
728 if (c->is_zero_double()) { | |
729 __ fldz(); | |
730 } else if (c->is_one_double()) { | |
731 __ fld1(); | |
732 } else { | |
733 __ fld_d (InternalAddress(double_constant(c->as_jdouble()))); | |
734 } | |
735 } | |
736 break; | |
737 } | |
738 | |
739 default: | |
740 ShouldNotReachHere(); | |
741 } | |
742 } | |
743 | |
744 void LIR_Assembler::const2stack(LIR_Opr src, LIR_Opr dest) { | |
745 assert(src->is_constant(), "should not call otherwise"); | |
746 assert(dest->is_stack(), "should not call otherwise"); | |
747 LIR_Const* c = src->as_constant_ptr(); | |
748 | |
749 switch (c->type()) { | |
750 case T_INT: // fall through | |
751 case T_FLOAT: | |
2002 | 752 __ movl(frame_map()->address_for_slot(dest->single_stack_ix()), c->as_jint_bits()); |
753 break; | |
754 | |
1297
c466efa608d5
6932496: c1: deoptimization of jsr subroutine fails on sparcv9
roland
parents:
1295
diff
changeset
|
755 case T_ADDRESS: |
2002 | 756 __ movptr(frame_map()->address_for_slot(dest->single_stack_ix()), c->as_jint_bits()); |
0 | 757 break; |
758 | |
759 case T_OBJECT: | |
760 __ movoop(frame_map()->address_for_slot(dest->single_stack_ix()), c->as_jobject()); | |
761 break; | |
762 | |
763 case T_LONG: // fall through | |
764 case T_DOUBLE: | |
304 | 765 #ifdef _LP64 |
766 __ movptr(frame_map()->address_for_slot(dest->double_stack_ix(), | |
767 lo_word_offset_in_bytes), (intptr_t)c->as_jlong_bits()); | |
768 #else | |
769 __ movptr(frame_map()->address_for_slot(dest->double_stack_ix(), | |
770 lo_word_offset_in_bytes), c->as_jint_lo_bits()); | |
771 __ movptr(frame_map()->address_for_slot(dest->double_stack_ix(), | |
772 hi_word_offset_in_bytes), c->as_jint_hi_bits()); | |
773 #endif // _LP64 | |
0 | 774 break; |
775 | |
776 default: | |
777 ShouldNotReachHere(); | |
778 } | |
779 } | |
780 | |
2002 | 781 void LIR_Assembler::const2mem(LIR_Opr src, LIR_Opr dest, BasicType type, CodeEmitInfo* info, bool wide) { |
0 | 782 assert(src->is_constant(), "should not call otherwise"); |
783 assert(dest->is_address(), "should not call otherwise"); | |
784 LIR_Const* c = src->as_constant_ptr(); | |
785 LIR_Address* addr = dest->as_address_ptr(); | |
786 | |
304 | 787 int null_check_here = code_offset(); |
0 | 788 switch (type) { |
789 case T_INT: // fall through | |
790 case T_FLOAT: | |
2002 | 791 __ movl(as_Address(addr), c->as_jint_bits()); |
792 break; | |
793 | |
1297
c466efa608d5
6932496: c1: deoptimization of jsr subroutine fails on sparcv9
roland
parents:
1295
diff
changeset
|
794 case T_ADDRESS: |
2002 | 795 __ movptr(as_Address(addr), c->as_jint_bits()); |
0 | 796 break; |
797 | |
798 case T_OBJECT: // fall through | |
799 case T_ARRAY: | |
800 if (c->as_jobject() == NULL) { | |
2002 | 801 if (UseCompressedOops && !wide) { |
802 __ movl(as_Address(addr), (int32_t)NULL_WORD); | |
803 } else { | |
804 __ movptr(as_Address(addr), NULL_WORD); | |
805 } | |
0 | 806 } else { |
304 | 807 if (is_literal_address(addr)) { |
808 ShouldNotReachHere(); | |
809 __ movoop(as_Address(addr, noreg), c->as_jobject()); | |
810 } else { | |
1060 | 811 #ifdef _LP64 |
812 __ movoop(rscratch1, c->as_jobject()); | |
2002 | 813 if (UseCompressedOops && !wide) { |
814 __ encode_heap_oop(rscratch1); | |
815 null_check_here = code_offset(); | |
816 __ movl(as_Address_lo(addr), rscratch1); | |
817 } else { | |
818 null_check_here = code_offset(); | |
819 __ movptr(as_Address_lo(addr), rscratch1); | |
820 } | |
1060 | 821 #else |
304 | 822 __ movoop(as_Address(addr), c->as_jobject()); |
1060 | 823 #endif |
304 | 824 } |
0 | 825 } |
826 break; | |
827 | |
828 case T_LONG: // fall through | |
829 case T_DOUBLE: | |
304 | 830 #ifdef _LP64 |
831 if (is_literal_address(addr)) { | |
832 ShouldNotReachHere(); | |
833 __ movptr(as_Address(addr, r15_thread), (intptr_t)c->as_jlong_bits()); | |
834 } else { | |
835 __ movptr(r10, (intptr_t)c->as_jlong_bits()); | |
836 null_check_here = code_offset(); | |
837 __ movptr(as_Address_lo(addr), r10); | |
838 } | |
839 #else | |
840 // Always reachable in 32bit so this doesn't produce useless move literal | |
841 __ movptr(as_Address_hi(addr), c->as_jint_hi_bits()); | |
842 __ movptr(as_Address_lo(addr), c->as_jint_lo_bits()); | |
843 #endif // _LP64 | |
0 | 844 break; |
845 | |
846 case T_BOOLEAN: // fall through | |
847 case T_BYTE: | |
848 __ movb(as_Address(addr), c->as_jint() & 0xFF); | |
849 break; | |
850 | |
851 case T_CHAR: // fall through | |
852 case T_SHORT: | |
853 __ movw(as_Address(addr), c->as_jint() & 0xFFFF); | |
854 break; | |
855 | |
856 default: | |
857 ShouldNotReachHere(); | |
858 }; | |
304 | 859 |
860 if (info != NULL) { | |
861 add_debug_info_for_null_check(null_check_here, info); | |
862 } | |
0 | 863 } |
864 | |
865 | |
866 void LIR_Assembler::reg2reg(LIR_Opr src, LIR_Opr dest) { | |
867 assert(src->is_register(), "should not call otherwise"); | |
868 assert(dest->is_register(), "should not call otherwise"); | |
869 | |
870 // move between cpu-registers | |
871 if (dest->is_single_cpu()) { | |
304 | 872 #ifdef _LP64 |
873 if (src->type() == T_LONG) { | |
874 // Can do LONG -> OBJECT | |
875 move_regs(src->as_register_lo(), dest->as_register()); | |
876 return; | |
877 } | |
878 #endif | |
0 | 879 assert(src->is_single_cpu(), "must match"); |
880 if (src->type() == T_OBJECT) { | |
881 __ verify_oop(src->as_register()); | |
882 } | |
883 move_regs(src->as_register(), dest->as_register()); | |
884 | |
885 } else if (dest->is_double_cpu()) { | |
304 | 886 #ifdef _LP64 |
887 if (src->type() == T_OBJECT || src->type() == T_ARRAY) { | |
888 // Surprising to me but we can see move of a long to t_object | |
889 __ verify_oop(src->as_register()); | |
890 move_regs(src->as_register(), dest->as_register_lo()); | |
891 return; | |
892 } | |
893 #endif | |
0 | 894 assert(src->is_double_cpu(), "must match"); |
895 Register f_lo = src->as_register_lo(); | |
896 Register f_hi = src->as_register_hi(); | |
897 Register t_lo = dest->as_register_lo(); | |
898 Register t_hi = dest->as_register_hi(); | |
304 | 899 #ifdef _LP64 |
900 assert(f_hi == f_lo, "must be same"); | |
901 assert(t_hi == t_lo, "must be same"); | |
902 move_regs(f_lo, t_lo); | |
903 #else | |
0 | 904 assert(f_lo != f_hi && t_lo != t_hi, "invalid register allocation"); |
905 | |
304 | 906 |
0 | 907 if (f_lo == t_hi && f_hi == t_lo) { |
908 swap_reg(f_lo, f_hi); | |
909 } else if (f_hi == t_lo) { | |
910 assert(f_lo != t_hi, "overwriting register"); | |
911 move_regs(f_hi, t_hi); | |
912 move_regs(f_lo, t_lo); | |
913 } else { | |
914 assert(f_hi != t_lo, "overwriting register"); | |
915 move_regs(f_lo, t_lo); | |
916 move_regs(f_hi, t_hi); | |
917 } | |
304 | 918 #endif // LP64 |
0 | 919 |
920 // special moves from fpu-register to xmm-register | |
921 // necessary for method results | |
922 } else if (src->is_single_xmm() && !dest->is_single_xmm()) { | |
923 __ movflt(Address(rsp, 0), src->as_xmm_float_reg()); | |
924 __ fld_s(Address(rsp, 0)); | |
925 } else if (src->is_double_xmm() && !dest->is_double_xmm()) { | |
926 __ movdbl(Address(rsp, 0), src->as_xmm_double_reg()); | |
927 __ fld_d(Address(rsp, 0)); | |
928 } else if (dest->is_single_xmm() && !src->is_single_xmm()) { | |
929 __ fstp_s(Address(rsp, 0)); | |
930 __ movflt(dest->as_xmm_float_reg(), Address(rsp, 0)); | |
931 } else if (dest->is_double_xmm() && !src->is_double_xmm()) { | |
932 __ fstp_d(Address(rsp, 0)); | |
933 __ movdbl(dest->as_xmm_double_reg(), Address(rsp, 0)); | |
934 | |
935 // move between xmm-registers | |
936 } else if (dest->is_single_xmm()) { | |
937 assert(src->is_single_xmm(), "must match"); | |
938 __ movflt(dest->as_xmm_float_reg(), src->as_xmm_float_reg()); | |
939 } else if (dest->is_double_xmm()) { | |
940 assert(src->is_double_xmm(), "must match"); | |
941 __ movdbl(dest->as_xmm_double_reg(), src->as_xmm_double_reg()); | |
942 | |
943 // move between fpu-registers (no instruction necessary because of fpu-stack) | |
944 } else if (dest->is_single_fpu() || dest->is_double_fpu()) { | |
945 assert(src->is_single_fpu() || src->is_double_fpu(), "must match"); | |
946 assert(src->fpu() == dest->fpu(), "currently should be nothing to do"); | |
947 } else { | |
948 ShouldNotReachHere(); | |
949 } | |
950 } | |
951 | |
952 void LIR_Assembler::reg2stack(LIR_Opr src, LIR_Opr dest, BasicType type, bool pop_fpu_stack) { | |
953 assert(src->is_register(), "should not call otherwise"); | |
954 assert(dest->is_stack(), "should not call otherwise"); | |
955 | |
956 if (src->is_single_cpu()) { | |
957 Address dst = frame_map()->address_for_slot(dest->single_stack_ix()); | |
958 if (type == T_OBJECT || type == T_ARRAY) { | |
959 __ verify_oop(src->as_register()); | |
304 | 960 __ movptr (dst, src->as_register()); |
6739
8a02ca5e5576
7195816: NPG: Crash in c1_ValueType - ShouldNotReachHere
roland
parents:
6725
diff
changeset
|
961 } else if (type == T_METADATA) { |
8a02ca5e5576
7195816: NPG: Crash in c1_ValueType - ShouldNotReachHere
roland
parents:
6725
diff
changeset
|
962 __ movptr (dst, src->as_register()); |
304 | 963 } else { |
964 __ movl (dst, src->as_register()); | |
0 | 965 } |
966 | |
967 } else if (src->is_double_cpu()) { | |
968 Address dstLO = frame_map()->address_for_slot(dest->double_stack_ix(), lo_word_offset_in_bytes); | |
969 Address dstHI = frame_map()->address_for_slot(dest->double_stack_ix(), hi_word_offset_in_bytes); | |
304 | 970 __ movptr (dstLO, src->as_register_lo()); |
971 NOT_LP64(__ movptr (dstHI, src->as_register_hi())); | |
0 | 972 |
973 } else if (src->is_single_xmm()) { | |
974 Address dst_addr = frame_map()->address_for_slot(dest->single_stack_ix()); | |
975 __ movflt(dst_addr, src->as_xmm_float_reg()); | |
976 | |
977 } else if (src->is_double_xmm()) { | |
978 Address dst_addr = frame_map()->address_for_slot(dest->double_stack_ix()); | |
979 __ movdbl(dst_addr, src->as_xmm_double_reg()); | |
980 | |
981 } else if (src->is_single_fpu()) { | |
982 assert(src->fpu_regnr() == 0, "argument must be on TOS"); | |
983 Address dst_addr = frame_map()->address_for_slot(dest->single_stack_ix()); | |
984 if (pop_fpu_stack) __ fstp_s (dst_addr); | |
985 else __ fst_s (dst_addr); | |
986 | |
987 } else if (src->is_double_fpu()) { | |
988 assert(src->fpu_regnrLo() == 0, "argument must be on TOS"); | |
989 Address dst_addr = frame_map()->address_for_slot(dest->double_stack_ix()); | |
990 if (pop_fpu_stack) __ fstp_d (dst_addr); | |
991 else __ fst_d (dst_addr); | |
992 | |
993 } else { | |
994 ShouldNotReachHere(); | |
995 } | |
996 } | |
997 | |
998 | |
2002 | 999 void LIR_Assembler::reg2mem(LIR_Opr src, LIR_Opr dest, BasicType type, LIR_PatchCode patch_code, CodeEmitInfo* info, bool pop_fpu_stack, bool wide, bool /* unaligned */) { |
0 | 1000 LIR_Address* to_addr = dest->as_address_ptr(); |
1001 PatchingStub* patch = NULL; | |
2002 | 1002 Register compressed_src = rscratch1; |
0 | 1003 |
1004 if (type == T_ARRAY || type == T_OBJECT) { | |
1005 __ verify_oop(src->as_register()); | |
2002 | 1006 #ifdef _LP64 |
1007 if (UseCompressedOops && !wide) { | |
1008 __ movptr(compressed_src, src->as_register()); | |
1009 __ encode_heap_oop(compressed_src); | |
17496
12ad8db39f76
8028764: dtrace/hotspot_jni/ALL/ALL001 crashes the vm on Solaris-amd64, SIGSEGV in MarkSweep::follow_stack()+0x8a
roland
parents:
12969
diff
changeset
|
1010 if (patch_code != lir_patch_none) { |
12ad8db39f76
8028764: dtrace/hotspot_jni/ALL/ALL001 crashes the vm on Solaris-amd64, SIGSEGV in MarkSweep::follow_stack()+0x8a
roland
parents:
12969
diff
changeset
|
1011 info->oop_map()->set_narrowoop(compressed_src->as_VMReg()); |
12ad8db39f76
8028764: dtrace/hotspot_jni/ALL/ALL001 crashes the vm on Solaris-amd64, SIGSEGV in MarkSweep::follow_stack()+0x8a
roland
parents:
12969
diff
changeset
|
1012 } |
2002 | 1013 } |
1014 #endif | |
0 | 1015 } |
2002 | 1016 |
0 | 1017 if (patch_code != lir_patch_none) { |
1018 patch = new PatchingStub(_masm, PatchingStub::access_field_id); | |
304 | 1019 Address toa = as_Address(to_addr); |
1020 assert(toa.disp() != 0, "must have"); | |
0 | 1021 } |
2002 | 1022 |
1023 int null_check_here = code_offset(); | |
0 | 1024 switch (type) { |
1025 case T_FLOAT: { | |
1026 if (src->is_single_xmm()) { | |
1027 __ movflt(as_Address(to_addr), src->as_xmm_float_reg()); | |
1028 } else { | |
1029 assert(src->is_single_fpu(), "must be"); | |
1030 assert(src->fpu_regnr() == 0, "argument must be on TOS"); | |
1031 if (pop_fpu_stack) __ fstp_s(as_Address(to_addr)); | |
1032 else __ fst_s (as_Address(to_addr)); | |
1033 } | |
1034 break; | |
1035 } | |
1036 | |
1037 case T_DOUBLE: { | |
1038 if (src->is_double_xmm()) { | |
1039 __ movdbl(as_Address(to_addr), src->as_xmm_double_reg()); | |
1040 } else { | |
1041 assert(src->is_double_fpu(), "must be"); | |
1042 assert(src->fpu_regnrLo() == 0, "argument must be on TOS"); | |
1043 if (pop_fpu_stack) __ fstp_d(as_Address(to_addr)); | |
1044 else __ fst_d (as_Address(to_addr)); | |
1045 } | |
1046 break; | |
1047 } | |
1048 | |
1049 case T_ARRAY: // fall through | |
1050 case T_OBJECT: // fall through | |
2002 | 1051 if (UseCompressedOops && !wide) { |
1052 __ movl(as_Address(to_addr), compressed_src); | |
1053 } else { | |
1054 __ movptr(as_Address(to_addr), src->as_register()); | |
1055 } | |
1056 break; | |
6739
8a02ca5e5576
7195816: NPG: Crash in c1_ValueType - ShouldNotReachHere
roland
parents:
6725
diff
changeset
|
1057 case T_METADATA: |
8a02ca5e5576
7195816: NPG: Crash in c1_ValueType - ShouldNotReachHere
roland
parents:
6725
diff
changeset
|
1058 // We get here to store a method pointer to the stack to pass to |
8a02ca5e5576
7195816: NPG: Crash in c1_ValueType - ShouldNotReachHere
roland
parents:
6725
diff
changeset
|
1059 // a dtrace runtime call. This can't work on 64 bit with |
8a02ca5e5576
7195816: NPG: Crash in c1_ValueType - ShouldNotReachHere
roland
parents:
6725
diff
changeset
|
1060 // compressed klass ptrs: T_METADATA can be a compressed klass |
8a02ca5e5576
7195816: NPG: Crash in c1_ValueType - ShouldNotReachHere
roland
parents:
6725
diff
changeset
|
1061 // ptr or a 64 bit method pointer. |
8a02ca5e5576
7195816: NPG: Crash in c1_ValueType - ShouldNotReachHere
roland
parents:
6725
diff
changeset
|
1062 LP64_ONLY(ShouldNotReachHere()); |
8a02ca5e5576
7195816: NPG: Crash in c1_ValueType - ShouldNotReachHere
roland
parents:
6725
diff
changeset
|
1063 __ movptr(as_Address(to_addr), src->as_register()); |
8a02ca5e5576
7195816: NPG: Crash in c1_ValueType - ShouldNotReachHere
roland
parents:
6725
diff
changeset
|
1064 break; |
2002 | 1065 case T_ADDRESS: |
304 | 1066 __ movptr(as_Address(to_addr), src->as_register()); |
1067 break; | |
0 | 1068 case T_INT: |
1069 __ movl(as_Address(to_addr), src->as_register()); | |
1070 break; | |
1071 | |
1072 case T_LONG: { | |
1073 Register from_lo = src->as_register_lo(); | |
1074 Register from_hi = src->as_register_hi(); | |
304 | 1075 #ifdef _LP64 |
1076 __ movptr(as_Address_lo(to_addr), from_lo); | |
1077 #else | |
0 | 1078 Register base = to_addr->base()->as_register(); |
1079 Register index = noreg; | |
1080 if (to_addr->index()->is_register()) { | |
1081 index = to_addr->index()->as_register(); | |
1082 } | |
1083 if (base == from_lo || index == from_lo) { | |
1084 assert(base != from_hi, "can't be"); | |
1085 assert(index == noreg || (index != base && index != from_hi), "can't handle this"); | |
1086 __ movl(as_Address_hi(to_addr), from_hi); | |
1087 if (patch != NULL) { | |
1088 patching_epilog(patch, lir_patch_high, base, info); | |
1089 patch = new PatchingStub(_masm, PatchingStub::access_field_id); | |
1090 patch_code = lir_patch_low; | |
1091 } | |
1092 __ movl(as_Address_lo(to_addr), from_lo); | |
1093 } else { | |
1094 assert(index == noreg || (index != base && index != from_lo), "can't handle this"); | |
1095 __ movl(as_Address_lo(to_addr), from_lo); | |
1096 if (patch != NULL) { | |
1097 patching_epilog(patch, lir_patch_low, base, info); | |
1098 patch = new PatchingStub(_masm, PatchingStub::access_field_id); | |
1099 patch_code = lir_patch_high; | |
1100 } | |
1101 __ movl(as_Address_hi(to_addr), from_hi); | |
1102 } | |
304 | 1103 #endif // _LP64 |
0 | 1104 break; |
1105 } | |
1106 | |
1107 case T_BYTE: // fall through | |
1108 case T_BOOLEAN: { | |
1109 Register src_reg = src->as_register(); | |
1110 Address dst_addr = as_Address(to_addr); | |
1111 assert(VM_Version::is_P6() || src_reg->has_byte_register(), "must use byte registers if not P6"); | |
1112 __ movb(dst_addr, src_reg); | |
1113 break; | |
1114 } | |
1115 | |
1116 case T_CHAR: // fall through | |
1117 case T_SHORT: | |
1118 __ movw(as_Address(to_addr), src->as_register()); | |
1119 break; | |
1120 | |
1121 default: | |
1122 ShouldNotReachHere(); | |
1123 } | |
2002 | 1124 if (info != NULL) { |
1125 add_debug_info_for_null_check(null_check_here, info); | |
1126 } | |
0 | 1127 |
1128 if (patch_code != lir_patch_none) { | |
1129 patching_epilog(patch, patch_code, to_addr->base()->as_register(), info); | |
1130 } | |
1131 } | |
1132 | |
1133 | |
1134 void LIR_Assembler::stack2reg(LIR_Opr src, LIR_Opr dest, BasicType type) { | |
1135 assert(src->is_stack(), "should not call otherwise"); | |
1136 assert(dest->is_register(), "should not call otherwise"); | |
1137 | |
1138 if (dest->is_single_cpu()) { | |
1139 if (type == T_ARRAY || type == T_OBJECT) { | |
304 | 1140 __ movptr(dest->as_register(), frame_map()->address_for_slot(src->single_stack_ix())); |
0 | 1141 __ verify_oop(dest->as_register()); |
6739
8a02ca5e5576
7195816: NPG: Crash in c1_ValueType - ShouldNotReachHere
roland
parents:
6725
diff
changeset
|
1142 } else if (type == T_METADATA) { |
8a02ca5e5576
7195816: NPG: Crash in c1_ValueType - ShouldNotReachHere
roland
parents:
6725
diff
changeset
|
1143 __ movptr(dest->as_register(), frame_map()->address_for_slot(src->single_stack_ix())); |
304 | 1144 } else { |
1145 __ movl(dest->as_register(), frame_map()->address_for_slot(src->single_stack_ix())); | |
0 | 1146 } |
1147 | |
1148 } else if (dest->is_double_cpu()) { | |
1149 Address src_addr_LO = frame_map()->address_for_slot(src->double_stack_ix(), lo_word_offset_in_bytes); | |
1150 Address src_addr_HI = frame_map()->address_for_slot(src->double_stack_ix(), hi_word_offset_in_bytes); | |
304 | 1151 __ movptr(dest->as_register_lo(), src_addr_LO); |
1152 NOT_LP64(__ movptr(dest->as_register_hi(), src_addr_HI)); | |
0 | 1153 |
1154 } else if (dest->is_single_xmm()) { | |
1155 Address src_addr = frame_map()->address_for_slot(src->single_stack_ix()); | |
1156 __ movflt(dest->as_xmm_float_reg(), src_addr); | |
1157 | |
1158 } else if (dest->is_double_xmm()) { | |
1159 Address src_addr = frame_map()->address_for_slot(src->double_stack_ix()); | |
1160 __ movdbl(dest->as_xmm_double_reg(), src_addr); | |
1161 | |
1162 } else if (dest->is_single_fpu()) { | |
1163 assert(dest->fpu_regnr() == 0, "dest must be TOS"); | |
1164 Address src_addr = frame_map()->address_for_slot(src->single_stack_ix()); | |
1165 __ fld_s(src_addr); | |
1166 | |
1167 } else if (dest->is_double_fpu()) { | |
1168 assert(dest->fpu_regnrLo() == 0, "dest must be TOS"); | |
1169 Address src_addr = frame_map()->address_for_slot(src->double_stack_ix()); | |
1170 __ fld_d(src_addr); | |
1171 | |
1172 } else { | |
1173 ShouldNotReachHere(); | |
1174 } | |
1175 } | |
1176 | |
1177 | |
1178 void LIR_Assembler::stack2stack(LIR_Opr src, LIR_Opr dest, BasicType type) { | |
1179 if (src->is_single_stack()) { | |
304 | 1180 if (type == T_OBJECT || type == T_ARRAY) { |
1181 __ pushptr(frame_map()->address_for_slot(src ->single_stack_ix())); | |
1182 __ popptr (frame_map()->address_for_slot(dest->single_stack_ix())); | |
1183 } else { | |
1060 | 1184 #ifndef _LP64 |
304 | 1185 __ pushl(frame_map()->address_for_slot(src ->single_stack_ix())); |
1186 __ popl (frame_map()->address_for_slot(dest->single_stack_ix())); | |
1060 | 1187 #else |
1188 //no pushl on 64bits | |
1189 __ movl(rscratch1, frame_map()->address_for_slot(src ->single_stack_ix())); | |
1190 __ movl(frame_map()->address_for_slot(dest->single_stack_ix()), rscratch1); | |
1191 #endif | |
304 | 1192 } |
0 | 1193 |
1194 } else if (src->is_double_stack()) { | |
304 | 1195 #ifdef _LP64 |
1196 __ pushptr(frame_map()->address_for_slot(src ->double_stack_ix())); | |
1197 __ popptr (frame_map()->address_for_slot(dest->double_stack_ix())); | |
1198 #else | |
0 | 1199 __ pushl(frame_map()->address_for_slot(src ->double_stack_ix(), 0)); |
304 | 1200 // push and pop the part at src + wordSize, adding wordSize for the previous push |
321
6e7305abe64c
6746320: Hotspot regression test for 6512111 fails in -Xmixed mode
never
parents:
304
diff
changeset
|
1201 __ pushl(frame_map()->address_for_slot(src ->double_stack_ix(), 2 * wordSize)); |
6e7305abe64c
6746320: Hotspot regression test for 6512111 fails in -Xmixed mode
never
parents:
304
diff
changeset
|
1202 __ popl (frame_map()->address_for_slot(dest->double_stack_ix(), 2 * wordSize)); |
0 | 1203 __ popl (frame_map()->address_for_slot(dest->double_stack_ix(), 0)); |
304 | 1204 #endif // _LP64 |
0 | 1205 |
1206 } else { | |
1207 ShouldNotReachHere(); | |
1208 } | |
1209 } | |
1210 | |
1211 | |
2002 | 1212 void LIR_Assembler::mem2reg(LIR_Opr src, LIR_Opr dest, BasicType type, LIR_PatchCode patch_code, CodeEmitInfo* info, bool wide, bool /* unaligned */) { |
0 | 1213 assert(src->is_address(), "should not call otherwise"); |
1214 assert(dest->is_register(), "should not call otherwise"); | |
1215 | |
1216 LIR_Address* addr = src->as_address_ptr(); | |
1217 Address from_addr = as_Address(addr); | |
1218 | |
12955 | 1219 if (addr->base()->type() == T_OBJECT) { |
1220 __ verify_oop(addr->base()->as_pointer_register()); | |
1221 } | |
1222 | |
0 | 1223 switch (type) { |
1224 case T_BOOLEAN: // fall through | |
1225 case T_BYTE: // fall through | |
1226 case T_CHAR: // fall through | |
1227 case T_SHORT: | |
1228 if (!VM_Version::is_P6() && !from_addr.uses(dest->as_register())) { | |
1229 // on pre P6 processors we may get partial register stalls | |
1230 // so blow away the value of to_rinfo before loading a | |
1231 // partial word into it. Do it here so that it precedes | |
1232 // the potential patch point below. | |
304 | 1233 __ xorptr(dest->as_register(), dest->as_register()); |
0 | 1234 } |
1235 break; | |
1236 } | |
1237 | |
1238 PatchingStub* patch = NULL; | |
1239 if (patch_code != lir_patch_none) { | |
1240 patch = new PatchingStub(_masm, PatchingStub::access_field_id); | |
304 | 1241 assert(from_addr.disp() != 0, "must have"); |
0 | 1242 } |
1243 if (info != NULL) { | |
1244 add_debug_info_for_null_check_here(info); | |
1245 } | |
1246 | |
1247 switch (type) { | |
1248 case T_FLOAT: { | |
1249 if (dest->is_single_xmm()) { | |
1250 __ movflt(dest->as_xmm_float_reg(), from_addr); | |
1251 } else { | |
1252 assert(dest->is_single_fpu(), "must be"); | |
1253 assert(dest->fpu_regnr() == 0, "dest must be TOS"); | |
1254 __ fld_s(from_addr); | |
1255 } | |
1256 break; | |
1257 } | |
1258 | |
1259 case T_DOUBLE: { | |
1260 if (dest->is_double_xmm()) { | |
1261 __ movdbl(dest->as_xmm_double_reg(), from_addr); | |
1262 } else { | |
1263 assert(dest->is_double_fpu(), "must be"); | |
1264 assert(dest->fpu_regnrLo() == 0, "dest must be TOS"); | |
1265 __ fld_d(from_addr); | |
1266 } | |
1267 break; | |
1268 } | |
1269 | |
1270 case T_OBJECT: // fall through | |
1271 case T_ARRAY: // fall through | |
2002 | 1272 if (UseCompressedOops && !wide) { |
1273 __ movl(dest->as_register(), from_addr); | |
1274 } else { | |
1275 __ movptr(dest->as_register(), from_addr); | |
1276 } | |
1277 break; | |
1278 | |
1279 case T_ADDRESS: | |
12226
7944aba7ba41
8015107: NPG: Use consistent naming for metaspace concepts
ehelin
parents:
12160
diff
changeset
|
1280 if (UseCompressedClassPointers && addr->disp() == oopDesc::klass_offset_in_bytes()) { |
6848
8e47bac5643a
7054512: Compress class pointers after perm gen removal
roland
parents:
6795
diff
changeset
|
1281 __ movl(dest->as_register(), from_addr); |
8e47bac5643a
7054512: Compress class pointers after perm gen removal
roland
parents:
6795
diff
changeset
|
1282 } else { |
8e47bac5643a
7054512: Compress class pointers after perm gen removal
roland
parents:
6795
diff
changeset
|
1283 __ movptr(dest->as_register(), from_addr); |
8e47bac5643a
7054512: Compress class pointers after perm gen removal
roland
parents:
6795
diff
changeset
|
1284 } |
304 | 1285 break; |
0 | 1286 case T_INT: |
1398
314e17ca2c23
6946892: c1 shouldn't sign-extend to upper 32bits on x64
iveresov
parents:
1378
diff
changeset
|
1287 __ movl(dest->as_register(), from_addr); |
0 | 1288 break; |
1289 | |
1290 case T_LONG: { | |
1291 Register to_lo = dest->as_register_lo(); | |
1292 Register to_hi = dest->as_register_hi(); | |
304 | 1293 #ifdef _LP64 |
1294 __ movptr(to_lo, as_Address_lo(addr)); | |
1295 #else | |
0 | 1296 Register base = addr->base()->as_register(); |
1297 Register index = noreg; | |
1298 if (addr->index()->is_register()) { | |
1299 index = addr->index()->as_register(); | |
1300 } | |
1301 if ((base == to_lo && index == to_hi) || | |
1302 (base == to_hi && index == to_lo)) { | |
1303 // addresses with 2 registers are only formed as a result of | |
1304 // array access so this code will never have to deal with | |
1305 // patches or null checks. | |
1306 assert(info == NULL && patch == NULL, "must be"); | |
304 | 1307 __ lea(to_hi, as_Address(addr)); |
0 | 1308 __ movl(to_lo, Address(to_hi, 0)); |
1309 __ movl(to_hi, Address(to_hi, BytesPerWord)); | |
1310 } else if (base == to_lo || index == to_lo) { | |
1311 assert(base != to_hi, "can't be"); | |
1312 assert(index == noreg || (index != base && index != to_hi), "can't handle this"); | |
1313 __ movl(to_hi, as_Address_hi(addr)); | |
1314 if (patch != NULL) { | |
1315 patching_epilog(patch, lir_patch_high, base, info); | |
1316 patch = new PatchingStub(_masm, PatchingStub::access_field_id); | |
1317 patch_code = lir_patch_low; | |
1318 } | |
1319 __ movl(to_lo, as_Address_lo(addr)); | |
1320 } else { | |
1321 assert(index == noreg || (index != base && index != to_lo), "can't handle this"); | |
1322 __ movl(to_lo, as_Address_lo(addr)); | |
1323 if (patch != NULL) { | |
1324 patching_epilog(patch, lir_patch_low, base, info); | |
1325 patch = new PatchingStub(_masm, PatchingStub::access_field_id); | |
1326 patch_code = lir_patch_high; | |
1327 } | |
1328 __ movl(to_hi, as_Address_hi(addr)); | |
1329 } | |
304 | 1330 #endif // _LP64 |
0 | 1331 break; |
1332 } | |
1333 | |
1334 case T_BOOLEAN: // fall through | |
1335 case T_BYTE: { | |
1336 Register dest_reg = dest->as_register(); | |
1337 assert(VM_Version::is_P6() || dest_reg->has_byte_register(), "must use byte registers if not P6"); | |
1338 if (VM_Version::is_P6() || from_addr.uses(dest_reg)) { | |
304 | 1339 __ movsbl(dest_reg, from_addr); |
0 | 1340 } else { |
1341 __ movb(dest_reg, from_addr); | |
1342 __ shll(dest_reg, 24); | |
1343 __ sarl(dest_reg, 24); | |
1344 } | |
1345 break; | |
1346 } | |
1347 | |
1348 case T_CHAR: { | |
1349 Register dest_reg = dest->as_register(); | |
1350 assert(VM_Version::is_P6() || dest_reg->has_byte_register(), "must use byte registers if not P6"); | |
1351 if (VM_Version::is_P6() || from_addr.uses(dest_reg)) { | |
304 | 1352 __ movzwl(dest_reg, from_addr); |
0 | 1353 } else { |
1354 __ movw(dest_reg, from_addr); | |
1355 } | |
1356 break; | |
1357 } | |
1358 | |
1359 case T_SHORT: { | |
1360 Register dest_reg = dest->as_register(); | |
1361 if (VM_Version::is_P6() || from_addr.uses(dest_reg)) { | |
304 | 1362 __ movswl(dest_reg, from_addr); |
0 | 1363 } else { |
1364 __ movw(dest_reg, from_addr); | |
1365 __ shll(dest_reg, 16); | |
1366 __ sarl(dest_reg, 16); | |
1367 } | |
1368 break; | |
1369 } | |
1370 | |
1371 default: | |
1372 ShouldNotReachHere(); | |
1373 } | |
1374 | |
1375 if (patch != NULL) { | |
1376 patching_epilog(patch, patch_code, addr->base()->as_register(), info); | |
1377 } | |
1378 | |
1379 if (type == T_ARRAY || type == T_OBJECT) { | |
2002 | 1380 #ifdef _LP64 |
1381 if (UseCompressedOops && !wide) { | |
1382 __ decode_heap_oop(dest->as_register()); | |
1383 } | |
1384 #endif | |
0 | 1385 __ verify_oop(dest->as_register()); |
6848
8e47bac5643a
7054512: Compress class pointers after perm gen removal
roland
parents:
6795
diff
changeset
|
1386 } else if (type == T_ADDRESS && addr->disp() == oopDesc::klass_offset_in_bytes()) { |
8e47bac5643a
7054512: Compress class pointers after perm gen removal
roland
parents:
6795
diff
changeset
|
1387 #ifdef _LP64 |
12226
7944aba7ba41
8015107: NPG: Use consistent naming for metaspace concepts
ehelin
parents:
12160
diff
changeset
|
1388 if (UseCompressedClassPointers) { |
6848
8e47bac5643a
7054512: Compress class pointers after perm gen removal
roland
parents:
6795
diff
changeset
|
1389 __ decode_klass_not_null(dest->as_register()); |
8e47bac5643a
7054512: Compress class pointers after perm gen removal
roland
parents:
6795
diff
changeset
|
1390 } |
8e47bac5643a
7054512: Compress class pointers after perm gen removal
roland
parents:
6795
diff
changeset
|
1391 #endif |
0 | 1392 } |
1393 } | |
1394 | |
1395 | |
1396 void LIR_Assembler::prefetchr(LIR_Opr src) { | |
1397 LIR_Address* addr = src->as_address_ptr(); | |
1398 Address from_addr = as_Address(addr); | |
1399 | |
1400 if (VM_Version::supports_sse()) { | |
1401 switch (ReadPrefetchInstr) { | |
1402 case 0: | |
1403 __ prefetchnta(from_addr); break; | |
1404 case 1: | |
1405 __ prefetcht0(from_addr); break; | |
1406 case 2: | |
1407 __ prefetcht2(from_addr); break; | |
1408 default: | |
1409 ShouldNotReachHere(); break; | |
1410 } | |
2479 | 1411 } else if (VM_Version::supports_3dnow_prefetch()) { |
0 | 1412 __ prefetchr(from_addr); |
1413 } | |
1414 } | |
1415 | |
1416 | |
1417 void LIR_Assembler::prefetchw(LIR_Opr src) { | |
1418 LIR_Address* addr = src->as_address_ptr(); | |
1419 Address from_addr = as_Address(addr); | |
1420 | |
1421 if (VM_Version::supports_sse()) { | |
1422 switch (AllocatePrefetchInstr) { | |
1423 case 0: | |
1424 __ prefetchnta(from_addr); break; | |
1425 case 1: | |
1426 __ prefetcht0(from_addr); break; | |
1427 case 2: | |
1428 __ prefetcht2(from_addr); break; | |
1429 case 3: | |
1430 __ prefetchw(from_addr); break; | |
1431 default: | |
1432 ShouldNotReachHere(); break; | |
1433 } | |
2479 | 1434 } else if (VM_Version::supports_3dnow_prefetch()) { |
0 | 1435 __ prefetchw(from_addr); |
1436 } | |
1437 } | |
1438 | |
1439 | |
1440 NEEDS_CLEANUP; // This could be static? | |
1441 Address::ScaleFactor LIR_Assembler::array_element_size(BasicType type) const { | |
29
d5fc211aea19
6633953: type2aelembytes{T_ADDRESS} should be 8 bytes in 64 bit VM
kvn
parents:
0
diff
changeset
|
1442 int elem_size = type2aelembytes(type); |
0 | 1443 switch (elem_size) { |
1444 case 1: return Address::times_1; | |
1445 case 2: return Address::times_2; | |
1446 case 4: return Address::times_4; | |
1447 case 8: return Address::times_8; | |
1448 } | |
1449 ShouldNotReachHere(); | |
1450 return Address::no_scale; | |
1451 } | |
1452 | |
1453 | |
1454 void LIR_Assembler::emit_op3(LIR_Op3* op) { | |
1455 switch (op->code()) { | |
1456 case lir_idiv: | |
1457 case lir_irem: | |
1458 arithmetic_idiv(op->code(), | |
1459 op->in_opr1(), | |
1460 op->in_opr2(), | |
1461 op->in_opr3(), | |
1462 op->result_opr(), | |
1463 op->info()); | |
1464 break; | |
1465 default: ShouldNotReachHere(); break; | |
1466 } | |
1467 } | |
1468 | |
1469 void LIR_Assembler::emit_opBranch(LIR_OpBranch* op) { | |
1470 #ifdef ASSERT | |
1471 assert(op->block() == NULL || op->block()->label() == op->label(), "wrong label"); | |
1472 if (op->block() != NULL) _branch_target_blocks.append(op->block()); | |
1473 if (op->ublock() != NULL) _branch_target_blocks.append(op->ublock()); | |
1474 #endif | |
1475 | |
1476 if (op->cond() == lir_cond_always) { | |
1477 if (op->info() != NULL) add_debug_info_for_branch(op->info()); | |
1478 __ jmp (*(op->label())); | |
1479 } else { | |
1480 Assembler::Condition acond = Assembler::zero; | |
1481 if (op->code() == lir_cond_float_branch) { | |
1482 assert(op->ublock() != NULL, "must have unordered successor"); | |
1483 __ jcc(Assembler::parity, *(op->ublock()->label())); | |
1484 switch(op->cond()) { | |
1485 case lir_cond_equal: acond = Assembler::equal; break; | |
1486 case lir_cond_notEqual: acond = Assembler::notEqual; break; | |
1487 case lir_cond_less: acond = Assembler::below; break; | |
1488 case lir_cond_lessEqual: acond = Assembler::belowEqual; break; | |
1489 case lir_cond_greaterEqual: acond = Assembler::aboveEqual; break; | |
1490 case lir_cond_greater: acond = Assembler::above; break; | |
1491 default: ShouldNotReachHere(); | |
1492 } | |
1493 } else { | |
1494 switch (op->cond()) { | |
1495 case lir_cond_equal: acond = Assembler::equal; break; | |
1496 case lir_cond_notEqual: acond = Assembler::notEqual; break; | |
1497 case lir_cond_less: acond = Assembler::less; break; | |
1498 case lir_cond_lessEqual: acond = Assembler::lessEqual; break; | |
1499 case lir_cond_greaterEqual: acond = Assembler::greaterEqual;break; | |
1500 case lir_cond_greater: acond = Assembler::greater; break; | |
1501 case lir_cond_belowEqual: acond = Assembler::belowEqual; break; | |
1502 case lir_cond_aboveEqual: acond = Assembler::aboveEqual; break; | |
1503 default: ShouldNotReachHere(); | |
1504 } | |
1505 } | |
1506 __ jcc(acond,*(op->label())); | |
1507 } | |
1508 } | |
1509 | |
1510 void LIR_Assembler::emit_opConvert(LIR_OpConvert* op) { | |
1511 LIR_Opr src = op->in_opr(); | |
1512 LIR_Opr dest = op->result_opr(); | |
1513 | |
1514 switch (op->bytecode()) { | |
1515 case Bytecodes::_i2l: | |
304 | 1516 #ifdef _LP64 |
1517 __ movl2ptr(dest->as_register_lo(), src->as_register()); | |
1518 #else | |
0 | 1519 move_regs(src->as_register(), dest->as_register_lo()); |
1520 move_regs(src->as_register(), dest->as_register_hi()); | |
1521 __ sarl(dest->as_register_hi(), 31); | |
304 | 1522 #endif // LP64 |
0 | 1523 break; |
1524 | |
1525 case Bytecodes::_l2i: | |
6041 | 1526 #ifdef _LP64 |
1527 __ movl(dest->as_register(), src->as_register_lo()); | |
1528 #else | |
0 | 1529 move_regs(src->as_register_lo(), dest->as_register()); |
6041 | 1530 #endif |
0 | 1531 break; |
1532 | |
1533 case Bytecodes::_i2b: | |
1534 move_regs(src->as_register(), dest->as_register()); | |
1535 __ sign_extend_byte(dest->as_register()); | |
1536 break; | |
1537 | |
1538 case Bytecodes::_i2c: | |
1539 move_regs(src->as_register(), dest->as_register()); | |
1540 __ andl(dest->as_register(), 0xFFFF); | |
1541 break; | |
1542 | |
1543 case Bytecodes::_i2s: | |
1544 move_regs(src->as_register(), dest->as_register()); | |
1545 __ sign_extend_short(dest->as_register()); | |
1546 break; | |
1547 | |
1548 | |
1549 case Bytecodes::_f2d: | |
1550 case Bytecodes::_d2f: | |
1551 if (dest->is_single_xmm()) { | |
1552 __ cvtsd2ss(dest->as_xmm_float_reg(), src->as_xmm_double_reg()); | |
1553 } else if (dest->is_double_xmm()) { | |
1554 __ cvtss2sd(dest->as_xmm_double_reg(), src->as_xmm_float_reg()); | |
1555 } else { | |
1556 assert(src->fpu() == dest->fpu(), "register must be equal"); | |
1557 // do nothing (float result is rounded later through spilling) | |
1558 } | |
1559 break; | |
1560 | |
1561 case Bytecodes::_i2f: | |
1562 case Bytecodes::_i2d: | |
1563 if (dest->is_single_xmm()) { | |
304 | 1564 __ cvtsi2ssl(dest->as_xmm_float_reg(), src->as_register()); |
0 | 1565 } else if (dest->is_double_xmm()) { |
304 | 1566 __ cvtsi2sdl(dest->as_xmm_double_reg(), src->as_register()); |
0 | 1567 } else { |
1568 assert(dest->fpu() == 0, "result must be on TOS"); | |
1569 __ movl(Address(rsp, 0), src->as_register()); | |
1570 __ fild_s(Address(rsp, 0)); | |
1571 } | |
1572 break; | |
1573 | |
1574 case Bytecodes::_f2i: | |
1575 case Bytecodes::_d2i: | |
1576 if (src->is_single_xmm()) { | |
304 | 1577 __ cvttss2sil(dest->as_register(), src->as_xmm_float_reg()); |
0 | 1578 } else if (src->is_double_xmm()) { |
304 | 1579 __ cvttsd2sil(dest->as_register(), src->as_xmm_double_reg()); |
0 | 1580 } else { |
1581 assert(src->fpu() == 0, "input must be on TOS"); | |
1582 __ fldcw(ExternalAddress(StubRoutines::addr_fpu_cntrl_wrd_trunc())); | |
1583 __ fist_s(Address(rsp, 0)); | |
1584 __ movl(dest->as_register(), Address(rsp, 0)); | |
1585 __ fldcw(ExternalAddress(StubRoutines::addr_fpu_cntrl_wrd_std())); | |
1586 } | |
1587 | |
1588 // IA32 conversion instructions do not match JLS for overflow, underflow and NaN -> fixup in stub | |
1589 assert(op->stub() != NULL, "stub required"); | |
1590 __ cmpl(dest->as_register(), 0x80000000); | |
1591 __ jcc(Assembler::equal, *op->stub()->entry()); | |
1592 __ bind(*op->stub()->continuation()); | |
1593 break; | |
1594 | |
1595 case Bytecodes::_l2f: | |
1596 case Bytecodes::_l2d: | |
1597 assert(!dest->is_xmm_register(), "result in xmm register not supported (no SSE instruction present)"); | |
1598 assert(dest->fpu() == 0, "result must be on TOS"); | |
1599 | |
304 | 1600 __ movptr(Address(rsp, 0), src->as_register_lo()); |
1601 NOT_LP64(__ movl(Address(rsp, BytesPerWord), src->as_register_hi())); | |
0 | 1602 __ fild_d(Address(rsp, 0)); |
1603 // float result is rounded later through spilling | |
1604 break; | |
1605 | |
1606 case Bytecodes::_f2l: | |
1607 case Bytecodes::_d2l: | |
1608 assert(!src->is_xmm_register(), "input in xmm register not supported (no SSE instruction present)"); | |
1609 assert(src->fpu() == 0, "input must be on TOS"); | |
304 | 1610 assert(dest == FrameMap::long0_opr, "runtime stub places result in these registers"); |
0 | 1611 |
1612 // instruction sequence too long to inline it here | |
1613 { | |
1614 __ call(RuntimeAddress(Runtime1::entry_for(Runtime1::fpu2long_stub_id))); | |
1615 } | |
1616 break; | |
1617 | |
1618 default: ShouldNotReachHere(); | |
1619 } | |
1620 } | |
1621 | |
1622 void LIR_Assembler::emit_alloc_obj(LIR_OpAllocObj* op) { | |
1623 if (op->init_check()) { | |
4739
52b5d32fbfaf
7117052: instanceKlass::_init_state can be u1 type
coleenp
parents:
3960
diff
changeset
|
1624 __ cmpb(Address(op->klass()->as_register(), |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
1625 InstanceKlass::init_state_offset()), |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
1626 InstanceKlass::fully_initialized); |
0 | 1627 add_debug_info_for_null_check_here(op->stub()->info()); |
1628 __ jcc(Assembler::notEqual, *op->stub()->entry()); | |
1629 } | |
1630 __ allocate_object(op->obj()->as_register(), | |
1631 op->tmp1()->as_register(), | |
1632 op->tmp2()->as_register(), | |
1633 op->header_size(), | |
1634 op->object_size(), | |
1635 op->klass()->as_register(), | |
1636 *op->stub()->entry()); | |
1637 __ bind(*op->stub()->continuation()); | |
1638 } | |
1639 | |
1640 void LIR_Assembler::emit_alloc_array(LIR_OpAllocArray* op) { | |
2112
55f868e91c3b
7010618: C1: array length should be treated at int on 64bit during array allocation
iveresov
parents:
2089
diff
changeset
|
1641 Register len = op->len()->as_register(); |
55f868e91c3b
7010618: C1: array length should be treated at int on 64bit during array allocation
iveresov
parents:
2089
diff
changeset
|
1642 LP64_ONLY( __ movslq(len, len); ) |
55f868e91c3b
7010618: C1: array length should be treated at int on 64bit during array allocation
iveresov
parents:
2089
diff
changeset
|
1643 |
0 | 1644 if (UseSlowPath || |
1645 (!UseFastNewObjectArray && (op->type() == T_OBJECT || op->type() == T_ARRAY)) || | |
1646 (!UseFastNewTypeArray && (op->type() != T_OBJECT && op->type() != T_ARRAY))) { | |
1647 __ jmp(*op->stub()->entry()); | |
1648 } else { | |
1649 Register tmp1 = op->tmp1()->as_register(); | |
1650 Register tmp2 = op->tmp2()->as_register(); | |
1651 Register tmp3 = op->tmp3()->as_register(); | |
1652 if (len == tmp1) { | |
1653 tmp1 = tmp3; | |
1654 } else if (len == tmp2) { | |
1655 tmp2 = tmp3; | |
1656 } else if (len == tmp3) { | |
1657 // everything is ok | |
1658 } else { | |
304 | 1659 __ mov(tmp3, len); |
0 | 1660 } |
1661 __ allocate_array(op->obj()->as_register(), | |
1662 len, | |
1663 tmp1, | |
1664 tmp2, | |
1665 arrayOopDesc::header_size(op->type()), | |
1666 array_element_size(op->type()), | |
1667 op->klass()->as_register(), | |
1668 *op->stub()->entry()); | |
1669 } | |
1670 __ bind(*op->stub()->continuation()); | |
1671 } | |
1672 | |
1783 | 1673 void LIR_Assembler::type_profile_helper(Register mdo, |
1674 ciMethodData *md, ciProfileData *data, | |
1675 Register recv, Label* update_done) { | |
1808
5511edd5d719
6988779: c1_LIRAssembler_x86.cpp crashes VS2010 compiler
iveresov
parents:
1791
diff
changeset
|
1676 for (uint i = 0; i < ReceiverTypeData::row_limit(); i++) { |
1783 | 1677 Label next_test; |
1678 // See if the receiver is receiver[n]. | |
1679 __ cmpptr(recv, Address(mdo, md->byte_offset_of_slot(data, ReceiverTypeData::receiver_offset(i)))); | |
1680 __ jccb(Assembler::notEqual, next_test); | |
1681 Address data_addr(mdo, md->byte_offset_of_slot(data, ReceiverTypeData::receiver_count_offset(i))); | |
1682 __ addptr(data_addr, DataLayout::counter_increment); | |
1791
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1683 __ jmp(*update_done); |
1783 | 1684 __ bind(next_test); |
1685 } | |
1686 | |
1687 // Didn't find receiver; find next empty slot and fill it in | |
1808
5511edd5d719
6988779: c1_LIRAssembler_x86.cpp crashes VS2010 compiler
iveresov
parents:
1791
diff
changeset
|
1688 for (uint i = 0; i < ReceiverTypeData::row_limit(); i++) { |
1783 | 1689 Label next_test; |
1690 Address recv_addr(mdo, md->byte_offset_of_slot(data, ReceiverTypeData::receiver_offset(i))); | |
1691 __ cmpptr(recv_addr, (intptr_t)NULL_WORD); | |
1692 __ jccb(Assembler::notEqual, next_test); | |
1693 __ movptr(recv_addr, recv); | |
1694 __ movptr(Address(mdo, md->byte_offset_of_slot(data, ReceiverTypeData::receiver_count_offset(i))), DataLayout::counter_increment); | |
1791
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1695 __ jmp(*update_done); |
1783 | 1696 __ bind(next_test); |
1697 } | |
1698 } | |
1699 | |
1791
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1700 void LIR_Assembler::emit_typecheck_helper(LIR_OpTypeCheck *op, Label* success, Label* failure, Label* obj_is_null) { |
1783 | 1701 // we always need a stub for the failure case. |
1702 CodeStub* stub = op->stub(); | |
1703 Register obj = op->object()->as_register(); | |
1704 Register k_RInfo = op->tmp1()->as_register(); | |
1705 Register klass_RInfo = op->tmp2()->as_register(); | |
1706 Register dst = op->result_opr()->as_register(); | |
1707 ciKlass* k = op->klass(); | |
1708 Register Rtmp1 = noreg; | |
1709 | |
1710 // check if it needs to be profiled | |
1711 ciMethodData* md; | |
1712 ciProfileData* data; | |
1713 | |
1714 if (op->should_profile()) { | |
1715 ciMethod* method = op->profiled_method(); | |
1716 assert(method != NULL, "Should have method"); | |
1717 int bci = op->profiled_bci(); | |
2007
5ddfcf4b079e
7003554: (tiered) assert(is_null_object() || handle() != NULL) failed: cannot embed null pointer
iveresov
parents:
2002
diff
changeset
|
1718 md = method->method_data_or_null(); |
5ddfcf4b079e
7003554: (tiered) assert(is_null_object() || handle() != NULL) failed: cannot embed null pointer
iveresov
parents:
2002
diff
changeset
|
1719 assert(md != NULL, "Sanity"); |
1783 | 1720 data = md->bci_to_data(bci); |
1791
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1721 assert(data != NULL, "need data for type check"); |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1722 assert(data->is_ReceiverTypeData(), "need ReceiverTypeData for type check"); |
1783 | 1723 } |
1791
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1724 Label profile_cast_success, profile_cast_failure; |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1725 Label *success_target = op->should_profile() ? &profile_cast_success : success; |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1726 Label *failure_target = op->should_profile() ? &profile_cast_failure : failure; |
1783 | 1727 |
1728 if (obj == k_RInfo) { | |
1729 k_RInfo = dst; | |
1730 } else if (obj == klass_RInfo) { | |
1731 klass_RInfo = dst; | |
1732 } | |
12226
7944aba7ba41
8015107: NPG: Use consistent naming for metaspace concepts
ehelin
parents:
12160
diff
changeset
|
1733 if (k->is_loaded() && !UseCompressedClassPointers) { |
1783 | 1734 select_different_registers(obj, dst, k_RInfo, klass_RInfo); |
1735 } else { | |
1736 Rtmp1 = op->tmp3()->as_register(); | |
1737 select_different_registers(obj, dst, k_RInfo, klass_RInfo, Rtmp1); | |
1738 } | |
1739 | |
1740 assert_different_registers(obj, k_RInfo, klass_RInfo); | |
1741 | |
1742 __ cmpptr(obj, (int32_t)NULL_WORD); | |
1743 if (op->should_profile()) { | |
1791
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1744 Label not_null; |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1745 __ jccb(Assembler::notEqual, not_null); |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1746 // Object is null; update MDO and exit |
1783 | 1747 Register mdo = klass_RInfo; |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
1748 __ mov_metadata(mdo, md->constant_encoding()); |
1783 | 1749 Address data_addr(mdo, md->byte_offset_of_slot(data, DataLayout::header_offset())); |
1750 int header_bits = DataLayout::flag_mask_to_header_mask(BitData::null_seen_byte_constant()); | |
1751 __ orl(data_addr, header_bits); | |
1791
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1752 __ jmp(*obj_is_null); |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1753 __ bind(not_null); |
1783 | 1754 } else { |
1791
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1755 __ jcc(Assembler::equal, *obj_is_null); |
1783 | 1756 } |
12268
2795dff62b6c
8023542: Test java/io/File/CheckPermission.java fails due to unfinished recursion (java.lang.StackOverflowError) when JIT'ed code (-client,-server) is running
iveresov
parents:
12160
diff
changeset
|
1757 |
2795dff62b6c
8023542: Test java/io/File/CheckPermission.java fails due to unfinished recursion (java.lang.StackOverflowError) when JIT'ed code (-client,-server) is running
iveresov
parents:
12160
diff
changeset
|
1758 if (!k->is_loaded()) { |
2795dff62b6c
8023542: Test java/io/File/CheckPermission.java fails due to unfinished recursion (java.lang.StackOverflowError) when JIT'ed code (-client,-server) is running
iveresov
parents:
12160
diff
changeset
|
1759 klass2reg_with_patching(k_RInfo, op->info_for_patch()); |
2795dff62b6c
8023542: Test java/io/File/CheckPermission.java fails due to unfinished recursion (java.lang.StackOverflowError) when JIT'ed code (-client,-server) is running
iveresov
parents:
12160
diff
changeset
|
1760 } else { |
2795dff62b6c
8023542: Test java/io/File/CheckPermission.java fails due to unfinished recursion (java.lang.StackOverflowError) when JIT'ed code (-client,-server) is running
iveresov
parents:
12160
diff
changeset
|
1761 #ifdef _LP64 |
2795dff62b6c
8023542: Test java/io/File/CheckPermission.java fails due to unfinished recursion (java.lang.StackOverflowError) when JIT'ed code (-client,-server) is running
iveresov
parents:
12160
diff
changeset
|
1762 __ mov_metadata(k_RInfo, k->constant_encoding()); |
2795dff62b6c
8023542: Test java/io/File/CheckPermission.java fails due to unfinished recursion (java.lang.StackOverflowError) when JIT'ed code (-client,-server) is running
iveresov
parents:
12160
diff
changeset
|
1763 #endif // _LP64 |
2795dff62b6c
8023542: Test java/io/File/CheckPermission.java fails due to unfinished recursion (java.lang.StackOverflowError) when JIT'ed code (-client,-server) is running
iveresov
parents:
12160
diff
changeset
|
1764 } |
1783 | 1765 __ verify_oop(obj); |
1766 | |
1767 if (op->fast_check()) { | |
1791
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1768 // get object class |
1783 | 1769 // not a safepoint as obj null check happens earlier |
1770 #ifdef _LP64 | |
12226
7944aba7ba41
8015107: NPG: Use consistent naming for metaspace concepts
ehelin
parents:
12160
diff
changeset
|
1771 if (UseCompressedClassPointers) { |
2002 | 1772 __ load_klass(Rtmp1, obj); |
1773 __ cmpptr(k_RInfo, Rtmp1); | |
1783 | 1774 } else { |
1775 __ cmpptr(k_RInfo, Address(obj, oopDesc::klass_offset_in_bytes())); | |
1776 } | |
2002 | 1777 #else |
1778 if (k->is_loaded()) { | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
1779 __ cmpklass(Address(obj, oopDesc::klass_offset_in_bytes()), k->constant_encoding()); |
2002 | 1780 } else { |
1781 __ cmpptr(k_RInfo, Address(obj, oopDesc::klass_offset_in_bytes())); | |
1782 } | |
1783 #endif | |
1783 | 1784 __ jcc(Assembler::notEqual, *failure_target); |
1791
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1785 // successful cast, fall through to profile or jump |
1783 | 1786 } else { |
1787 // get object class | |
1788 // not a safepoint as obj null check happens earlier | |
2002 | 1789 __ load_klass(klass_RInfo, obj); |
1783 | 1790 if (k->is_loaded()) { |
1791 // See if we get an immediate positive hit | |
1792 #ifdef _LP64 | |
1793 __ cmpptr(k_RInfo, Address(klass_RInfo, k->super_check_offset())); | |
1794 #else | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
1795 __ cmpklass(Address(klass_RInfo, k->super_check_offset()), k->constant_encoding()); |
1783 | 1796 #endif // _LP64 |
4762
069ab3f976d3
7118863: Move sizeof(klassOopDesc) into the *Klass::*_offset_in_bytes() functions
stefank
parents:
3960
diff
changeset
|
1797 if ((juint)in_bytes(Klass::secondary_super_cache_offset()) != k->super_check_offset()) { |
1783 | 1798 __ jcc(Assembler::notEqual, *failure_target); |
1791
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1799 // successful cast, fall through to profile or jump |
1783 | 1800 } else { |
1801 // See if we get an immediate positive hit | |
1791
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1802 __ jcc(Assembler::equal, *success_target); |
1783 | 1803 // check for self |
1804 #ifdef _LP64 | |
1805 __ cmpptr(klass_RInfo, k_RInfo); | |
1806 #else | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
1807 __ cmpklass(klass_RInfo, k->constant_encoding()); |
1783 | 1808 #endif // _LP64 |
1791
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1809 __ jcc(Assembler::equal, *success_target); |
1783 | 1810 |
1811 __ push(klass_RInfo); | |
1812 #ifdef _LP64 | |
1813 __ push(k_RInfo); | |
1814 #else | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
1815 __ pushklass(k->constant_encoding()); |
1783 | 1816 #endif // _LP64 |
1817 __ call(RuntimeAddress(Runtime1::entry_for(Runtime1::slow_subtype_check_id))); | |
1818 __ pop(klass_RInfo); | |
1819 __ pop(klass_RInfo); | |
1820 // result is a boolean | |
1821 __ cmpl(klass_RInfo, 0); | |
1822 __ jcc(Assembler::equal, *failure_target); | |
1791
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1823 // successful cast, fall through to profile or jump |
1783 | 1824 } |
1825 } else { | |
1826 // perform the fast part of the checking logic | |
1791
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1827 __ check_klass_subtype_fast_path(klass_RInfo, k_RInfo, Rtmp1, success_target, failure_target, NULL); |
1783 | 1828 // call out-of-line instance of __ check_klass_subtype_slow_path(...): |
1829 __ push(klass_RInfo); | |
1830 __ push(k_RInfo); | |
1831 __ call(RuntimeAddress(Runtime1::entry_for(Runtime1::slow_subtype_check_id))); | |
1832 __ pop(klass_RInfo); | |
1833 __ pop(k_RInfo); | |
1834 // result is a boolean | |
1835 __ cmpl(k_RInfo, 0); | |
1836 __ jcc(Assembler::equal, *failure_target); | |
1791
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1837 // successful cast, fall through to profile or jump |
1783 | 1838 } |
1839 } | |
1840 if (op->should_profile()) { | |
1841 Register mdo = klass_RInfo, recv = k_RInfo; | |
1791
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1842 __ bind(profile_cast_success); |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
1843 __ mov_metadata(mdo, md->constant_encoding()); |
2002 | 1844 __ load_klass(recv, obj); |
1783 | 1845 Label update_done; |
1791
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1846 type_profile_helper(mdo, md, data, recv, success); |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1847 __ jmp(*success); |
1783 | 1848 |
1849 __ bind(profile_cast_failure); | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
1850 __ mov_metadata(mdo, md->constant_encoding()); |
1783 | 1851 Address counter_addr(mdo, md->byte_offset_of_slot(data, CounterData::count_offset())); |
1852 __ subptr(counter_addr, DataLayout::counter_increment); | |
1791
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1853 __ jmp(*failure); |
1783 | 1854 } |
1791
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1855 __ jmp(*success); |
1783 | 1856 } |
0 | 1857 |
1791
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1858 |
0 | 1859 void LIR_Assembler::emit_opTypeCheck(LIR_OpTypeCheck* op) { |
1860 LIR_Code code = op->code(); | |
1861 if (code == lir_store_check) { | |
1862 Register value = op->object()->as_register(); | |
1863 Register array = op->array()->as_register(); | |
1864 Register k_RInfo = op->tmp1()->as_register(); | |
1865 Register klass_RInfo = op->tmp2()->as_register(); | |
1866 Register Rtmp1 = op->tmp3()->as_register(); | |
1867 | |
1868 CodeStub* stub = op->stub(); | |
1791
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1869 |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1870 // check if it needs to be profiled |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1871 ciMethodData* md; |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1872 ciProfileData* data; |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1873 |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1874 if (op->should_profile()) { |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1875 ciMethod* method = op->profiled_method(); |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1876 assert(method != NULL, "Should have method"); |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1877 int bci = op->profiled_bci(); |
2007
5ddfcf4b079e
7003554: (tiered) assert(is_null_object() || handle() != NULL) failed: cannot embed null pointer
iveresov
parents:
2002
diff
changeset
|
1878 md = method->method_data_or_null(); |
5ddfcf4b079e
7003554: (tiered) assert(is_null_object() || handle() != NULL) failed: cannot embed null pointer
iveresov
parents:
2002
diff
changeset
|
1879 assert(md != NULL, "Sanity"); |
1791
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1880 data = md->bci_to_data(bci); |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1881 assert(data != NULL, "need data for type check"); |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1882 assert(data->is_ReceiverTypeData(), "need ReceiverTypeData for type check"); |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1883 } |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1884 Label profile_cast_success, profile_cast_failure, done; |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1885 Label *success_target = op->should_profile() ? &profile_cast_success : &done; |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1886 Label *failure_target = op->should_profile() ? &profile_cast_failure : stub->entry(); |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1887 |
304 | 1888 __ cmpptr(value, (int32_t)NULL_WORD); |
1791
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1889 if (op->should_profile()) { |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1890 Label not_null; |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1891 __ jccb(Assembler::notEqual, not_null); |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1892 // Object is null; update MDO and exit |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1893 Register mdo = klass_RInfo; |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
1894 __ mov_metadata(mdo, md->constant_encoding()); |
1791
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1895 Address data_addr(mdo, md->byte_offset_of_slot(data, DataLayout::header_offset())); |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1896 int header_bits = DataLayout::flag_mask_to_header_mask(BitData::null_seen_byte_constant()); |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1897 __ orl(data_addr, header_bits); |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1898 __ jmp(done); |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1899 __ bind(not_null); |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1900 } else { |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1901 __ jcc(Assembler::equal, done); |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1902 } |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1903 |
0 | 1904 add_debug_info_for_null_check_here(op->info_for_exception()); |
2002 | 1905 __ load_klass(k_RInfo, array); |
1906 __ load_klass(klass_RInfo, value); | |
1907 | |
1908 // get instance klass (it's already uncompressed) | |
6831
d8ce2825b193
8000213: NPG: Should have renamed arrayKlass and typeArrayKlass
coleenp
parents:
6795
diff
changeset
|
1909 __ movptr(k_RInfo, Address(k_RInfo, ObjArrayKlass::element_klass_offset())); |
644
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
622
diff
changeset
|
1910 // perform the fast part of the checking logic |
1791
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1911 __ check_klass_subtype_fast_path(klass_RInfo, k_RInfo, Rtmp1, success_target, failure_target, NULL); |
644
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
622
diff
changeset
|
1912 // call out-of-line instance of __ check_klass_subtype_slow_path(...): |
304 | 1913 __ push(klass_RInfo); |
1914 __ push(k_RInfo); | |
0 | 1915 __ call(RuntimeAddress(Runtime1::entry_for(Runtime1::slow_subtype_check_id))); |
304 | 1916 __ pop(klass_RInfo); |
1917 __ pop(k_RInfo); | |
1918 // result is a boolean | |
0 | 1919 __ cmpl(k_RInfo, 0); |
1791
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1920 __ jcc(Assembler::equal, *failure_target); |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1921 // fall through to the success case |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1922 |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1923 if (op->should_profile()) { |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1924 Register mdo = klass_RInfo, recv = k_RInfo; |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1925 __ bind(profile_cast_success); |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
1926 __ mov_metadata(mdo, md->constant_encoding()); |
2002 | 1927 __ load_klass(recv, value); |
1791
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1928 Label update_done; |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1929 type_profile_helper(mdo, md, data, recv, &done); |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1930 __ jmpb(done); |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1931 |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1932 __ bind(profile_cast_failure); |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
1933 __ mov_metadata(mdo, md->constant_encoding()); |
1791
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1934 Address counter_addr(mdo, md->byte_offset_of_slot(data, CounterData::count_offset())); |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1935 __ subptr(counter_addr, DataLayout::counter_increment); |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1936 __ jmp(*stub->entry()); |
0 | 1937 } |
1791
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1938 |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1939 __ bind(done); |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1940 } else |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1941 if (code == lir_checkcast) { |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1942 Register obj = op->object()->as_register(); |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1943 Register dst = op->result_opr()->as_register(); |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1944 Label success; |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1945 emit_typecheck_helper(op, &success, op->stub()->entry(), &success); |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1946 __ bind(success); |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1947 if (dst != obj) { |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1948 __ mov(dst, obj); |
0 | 1949 } |
1791
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1950 } else |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1951 if (code == lir_instanceof) { |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1952 Register obj = op->object()->as_register(); |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1953 Register dst = op->result_opr()->as_register(); |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1954 Label success, failure, done; |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1955 emit_typecheck_helper(op, &success, &failure, &failure); |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1956 __ bind(failure); |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1957 __ xorptr(dst, dst); |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1958 __ jmpb(done); |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1959 __ bind(success); |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1960 __ movptr(dst, 1); |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1961 __ bind(done); |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1962 } else { |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1963 ShouldNotReachHere(); |
644
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
622
diff
changeset
|
1964 } |
0 | 1965 |
1966 } | |
1967 | |
1968 | |
1969 void LIR_Assembler::emit_compare_and_swap(LIR_OpCompareAndSwap* op) { | |
304 | 1970 if (LP64_ONLY(false &&) op->code() == lir_cas_long && VM_Version::supports_cx8()) { |
0 | 1971 assert(op->cmp_value()->as_register_lo() == rax, "wrong register"); |
1972 assert(op->cmp_value()->as_register_hi() == rdx, "wrong register"); | |
1973 assert(op->new_value()->as_register_lo() == rbx, "wrong register"); | |
1974 assert(op->new_value()->as_register_hi() == rcx, "wrong register"); | |
1975 Register addr = op->addr()->as_register(); | |
1976 if (os::is_MP()) { | |
1977 __ lock(); | |
1978 } | |
304 | 1979 NOT_LP64(__ cmpxchg8(Address(addr, 0))); |
1980 | |
1981 } else if (op->code() == lir_cas_int || op->code() == lir_cas_obj ) { | |
1982 NOT_LP64(assert(op->addr()->is_single_cpu(), "must be single");) | |
1983 Register addr = (op->addr()->is_single_cpu() ? op->addr()->as_register() : op->addr()->as_register_lo()); | |
0 | 1984 Register newval = op->new_value()->as_register(); |
1985 Register cmpval = op->cmp_value()->as_register(); | |
1986 assert(cmpval == rax, "wrong register"); | |
1987 assert(newval != NULL, "new val must be register"); | |
1988 assert(cmpval != newval, "cmp and new values must be in different registers"); | |
1989 assert(cmpval != addr, "cmp and addr must be in different registers"); | |
1990 assert(newval != addr, "new value and addr must be in different registers"); | |
2002 | 1991 |
304 | 1992 if ( op->code() == lir_cas_obj) { |
2002 | 1993 #ifdef _LP64 |
1994 if (UseCompressedOops) { | |
1995 __ encode_heap_oop(cmpval); | |
2013
ec8c74742417
7005241: C1: SEGV in java.util.concurrent.LinkedTransferQueue.xfer() with compressed oops
iveresov
parents:
2007
diff
changeset
|
1996 __ mov(rscratch1, newval); |
ec8c74742417
7005241: C1: SEGV in java.util.concurrent.LinkedTransferQueue.xfer() with compressed oops
iveresov
parents:
2007
diff
changeset
|
1997 __ encode_heap_oop(rscratch1); |
2002 | 1998 if (os::is_MP()) { |
1999 __ lock(); | |
2000 } | |
2013
ec8c74742417
7005241: C1: SEGV in java.util.concurrent.LinkedTransferQueue.xfer() with compressed oops
iveresov
parents:
2007
diff
changeset
|
2001 // cmpval (rax) is implicitly used by this instruction |
ec8c74742417
7005241: C1: SEGV in java.util.concurrent.LinkedTransferQueue.xfer() with compressed oops
iveresov
parents:
2007
diff
changeset
|
2002 __ cmpxchgl(rscratch1, Address(addr, 0)); |
2002 | 2003 } else |
2004 #endif | |
2005 { | |
2006 if (os::is_MP()) { | |
2007 __ lock(); | |
2008 } | |
2009 __ cmpxchgptr(newval, Address(addr, 0)); | |
2010 } | |
2011 } else { | |
2012 assert(op->code() == lir_cas_int, "lir_cas_int expected"); | |
2013 if (os::is_MP()) { | |
2014 __ lock(); | |
2015 } | |
304 | 2016 __ cmpxchgl(newval, Address(addr, 0)); |
2017 } | |
2018 #ifdef _LP64 | |
2019 } else if (op->code() == lir_cas_long) { | |
2020 Register addr = (op->addr()->is_single_cpu() ? op->addr()->as_register() : op->addr()->as_register_lo()); | |
2021 Register newval = op->new_value()->as_register_lo(); | |
2022 Register cmpval = op->cmp_value()->as_register_lo(); | |
2023 assert(cmpval == rax, "wrong register"); | |
2024 assert(newval != NULL, "new val must be register"); | |
2025 assert(cmpval != newval, "cmp and new values must be in different registers"); | |
2026 assert(cmpval != addr, "cmp and addr must be in different registers"); | |
2027 assert(newval != addr, "new value and addr must be in different registers"); | |
2028 if (os::is_MP()) { | |
2029 __ lock(); | |
2030 } | |
2031 __ cmpxchgq(newval, Address(addr, 0)); | |
2032 #endif // _LP64 | |
0 | 2033 } else { |
2034 Unimplemented(); | |
2035 } | |
2036 } | |
2037 | |
2089
037c727f35fb
7009231: C1: Incorrect CAS code for longs on SPARC 32bit
iveresov
parents:
2013
diff
changeset
|
2038 void LIR_Assembler::cmove(LIR_Condition condition, LIR_Opr opr1, LIR_Opr opr2, LIR_Opr result, BasicType type) { |
0 | 2039 Assembler::Condition acond, ncond; |
2040 switch (condition) { | |
2041 case lir_cond_equal: acond = Assembler::equal; ncond = Assembler::notEqual; break; | |
2042 case lir_cond_notEqual: acond = Assembler::notEqual; ncond = Assembler::equal; break; | |
2043 case lir_cond_less: acond = Assembler::less; ncond = Assembler::greaterEqual; break; | |
2044 case lir_cond_lessEqual: acond = Assembler::lessEqual; ncond = Assembler::greater; break; | |
2045 case lir_cond_greaterEqual: acond = Assembler::greaterEqual; ncond = Assembler::less; break; | |
2046 case lir_cond_greater: acond = Assembler::greater; ncond = Assembler::lessEqual; break; | |
2047 case lir_cond_belowEqual: acond = Assembler::belowEqual; ncond = Assembler::above; break; | |
2048 case lir_cond_aboveEqual: acond = Assembler::aboveEqual; ncond = Assembler::below; break; | |
2049 default: ShouldNotReachHere(); | |
2050 } | |
2051 | |
2052 if (opr1->is_cpu_register()) { | |
2053 reg2reg(opr1, result); | |
2054 } else if (opr1->is_stack()) { | |
2055 stack2reg(opr1, result, result->type()); | |
2056 } else if (opr1->is_constant()) { | |
2057 const2reg(opr1, result, lir_patch_none, NULL); | |
2058 } else { | |
2059 ShouldNotReachHere(); | |
2060 } | |
2061 | |
2062 if (VM_Version::supports_cmov() && !opr2->is_constant()) { | |
2063 // optimized version that does not require a branch | |
2064 if (opr2->is_single_cpu()) { | |
2065 assert(opr2->cpu_regnr() != result->cpu_regnr(), "opr2 already overwritten by previous move"); | |
304 | 2066 __ cmov(ncond, result->as_register(), opr2->as_register()); |
0 | 2067 } else if (opr2->is_double_cpu()) { |
2068 assert(opr2->cpu_regnrLo() != result->cpu_regnrLo() && opr2->cpu_regnrLo() != result->cpu_regnrHi(), "opr2 already overwritten by previous move"); | |
2069 assert(opr2->cpu_regnrHi() != result->cpu_regnrLo() && opr2->cpu_regnrHi() != result->cpu_regnrHi(), "opr2 already overwritten by previous move"); | |
304 | 2070 __ cmovptr(ncond, result->as_register_lo(), opr2->as_register_lo()); |
2071 NOT_LP64(__ cmovptr(ncond, result->as_register_hi(), opr2->as_register_hi());) | |
0 | 2072 } else if (opr2->is_single_stack()) { |
2073 __ cmovl(ncond, result->as_register(), frame_map()->address_for_slot(opr2->single_stack_ix())); | |
2074 } else if (opr2->is_double_stack()) { | |
304 | 2075 __ cmovptr(ncond, result->as_register_lo(), frame_map()->address_for_slot(opr2->double_stack_ix(), lo_word_offset_in_bytes)); |
2076 NOT_LP64(__ cmovptr(ncond, result->as_register_hi(), frame_map()->address_for_slot(opr2->double_stack_ix(), hi_word_offset_in_bytes));) | |
0 | 2077 } else { |
2078 ShouldNotReachHere(); | |
2079 } | |
2080 | |
2081 } else { | |
2082 Label skip; | |
2083 __ jcc (acond, skip); | |
2084 if (opr2->is_cpu_register()) { | |
2085 reg2reg(opr2, result); | |
2086 } else if (opr2->is_stack()) { | |
2087 stack2reg(opr2, result, result->type()); | |
2088 } else if (opr2->is_constant()) { | |
2089 const2reg(opr2, result, lir_patch_none, NULL); | |
2090 } else { | |
2091 ShouldNotReachHere(); | |
2092 } | |
2093 __ bind(skip); | |
2094 } | |
2095 } | |
2096 | |
2097 | |
2098 void LIR_Assembler::arith_op(LIR_Code code, LIR_Opr left, LIR_Opr right, LIR_Opr dest, CodeEmitInfo* info, bool pop_fpu_stack) { | |
2099 assert(info == NULL, "should never be used, idiv/irem and ldiv/lrem not handled by this method"); | |
2100 | |
2101 if (left->is_single_cpu()) { | |
2102 assert(left == dest, "left and dest must be equal"); | |
2103 Register lreg = left->as_register(); | |
2104 | |
2105 if (right->is_single_cpu()) { | |
2106 // cpu register - cpu register | |
2107 Register rreg = right->as_register(); | |
2108 switch (code) { | |
2109 case lir_add: __ addl (lreg, rreg); break; | |
2110 case lir_sub: __ subl (lreg, rreg); break; | |
2111 case lir_mul: __ imull(lreg, rreg); break; | |
2112 default: ShouldNotReachHere(); | |
2113 } | |
2114 | |
2115 } else if (right->is_stack()) { | |
2116 // cpu register - stack | |
2117 Address raddr = frame_map()->address_for_slot(right->single_stack_ix()); | |
2118 switch (code) { | |
2119 case lir_add: __ addl(lreg, raddr); break; | |
2120 case lir_sub: __ subl(lreg, raddr); break; | |
2121 default: ShouldNotReachHere(); | |
2122 } | |
2123 | |
2124 } else if (right->is_constant()) { | |
2125 // cpu register - constant | |
2126 jint c = right->as_constant_ptr()->as_jint(); | |
2127 switch (code) { | |
2128 case lir_add: { | |
1790
7f9553bedfd5
6984056: C1: incorrect code for integer constant addition on x64
iveresov
parents:
1783
diff
changeset
|
2129 __ incrementl(lreg, c); |
0 | 2130 break; |
2131 } | |
2132 case lir_sub: { | |
1790
7f9553bedfd5
6984056: C1: incorrect code for integer constant addition on x64
iveresov
parents:
1783
diff
changeset
|
2133 __ decrementl(lreg, c); |
0 | 2134 break; |
2135 } | |
2136 default: ShouldNotReachHere(); | |
2137 } | |
2138 | |
2139 } else { | |
2140 ShouldNotReachHere(); | |
2141 } | |
2142 | |
2143 } else if (left->is_double_cpu()) { | |
2144 assert(left == dest, "left and dest must be equal"); | |
2145 Register lreg_lo = left->as_register_lo(); | |
2146 Register lreg_hi = left->as_register_hi(); | |
2147 | |
2148 if (right->is_double_cpu()) { | |
2149 // cpu register - cpu register | |
2150 Register rreg_lo = right->as_register_lo(); | |
2151 Register rreg_hi = right->as_register_hi(); | |
304 | 2152 NOT_LP64(assert_different_registers(lreg_lo, lreg_hi, rreg_lo, rreg_hi)); |
2153 LP64_ONLY(assert_different_registers(lreg_lo, rreg_lo)); | |
0 | 2154 switch (code) { |
2155 case lir_add: | |
304 | 2156 __ addptr(lreg_lo, rreg_lo); |
2157 NOT_LP64(__ adcl(lreg_hi, rreg_hi)); | |
0 | 2158 break; |
2159 case lir_sub: | |
304 | 2160 __ subptr(lreg_lo, rreg_lo); |
2161 NOT_LP64(__ sbbl(lreg_hi, rreg_hi)); | |
0 | 2162 break; |
2163 case lir_mul: | |
304 | 2164 #ifdef _LP64 |
2165 __ imulq(lreg_lo, rreg_lo); | |
2166 #else | |
0 | 2167 assert(lreg_lo == rax && lreg_hi == rdx, "must be"); |
2168 __ imull(lreg_hi, rreg_lo); | |
2169 __ imull(rreg_hi, lreg_lo); | |
2170 __ addl (rreg_hi, lreg_hi); | |
2171 __ mull (rreg_lo); | |
2172 __ addl (lreg_hi, rreg_hi); | |
304 | 2173 #endif // _LP64 |
0 | 2174 break; |
2175 default: | |
2176 ShouldNotReachHere(); | |
2177 } | |
2178 | |
2179 } else if (right->is_constant()) { | |
2180 // cpu register - constant | |
304 | 2181 #ifdef _LP64 |
2182 jlong c = right->as_constant_ptr()->as_jlong_bits(); | |
2183 __ movptr(r10, (intptr_t) c); | |
2184 switch (code) { | |
2185 case lir_add: | |
2186 __ addptr(lreg_lo, r10); | |
2187 break; | |
2188 case lir_sub: | |
2189 __ subptr(lreg_lo, r10); | |
2190 break; | |
2191 default: | |
2192 ShouldNotReachHere(); | |
2193 } | |
2194 #else | |
0 | 2195 jint c_lo = right->as_constant_ptr()->as_jint_lo(); |
2196 jint c_hi = right->as_constant_ptr()->as_jint_hi(); | |
2197 switch (code) { | |
2198 case lir_add: | |
304 | 2199 __ addptr(lreg_lo, c_lo); |
0 | 2200 __ adcl(lreg_hi, c_hi); |
2201 break; | |
2202 case lir_sub: | |
304 | 2203 __ subptr(lreg_lo, c_lo); |
0 | 2204 __ sbbl(lreg_hi, c_hi); |
2205 break; | |
2206 default: | |
2207 ShouldNotReachHere(); | |
2208 } | |
304 | 2209 #endif // _LP64 |
0 | 2210 |
2211 } else { | |
2212 ShouldNotReachHere(); | |
2213 } | |
2214 | |
2215 } else if (left->is_single_xmm()) { | |
2216 assert(left == dest, "left and dest must be equal"); | |
2217 XMMRegister lreg = left->as_xmm_float_reg(); | |
2218 | |
2219 if (right->is_single_xmm()) { | |
2220 XMMRegister rreg = right->as_xmm_float_reg(); | |
2221 switch (code) { | |
2222 case lir_add: __ addss(lreg, rreg); break; | |
2223 case lir_sub: __ subss(lreg, rreg); break; | |
2224 case lir_mul_strictfp: // fall through | |
2225 case lir_mul: __ mulss(lreg, rreg); break; | |
2226 case lir_div_strictfp: // fall through | |
2227 case lir_div: __ divss(lreg, rreg); break; | |
2228 default: ShouldNotReachHere(); | |
2229 } | |
2230 } else { | |
2231 Address raddr; | |
2232 if (right->is_single_stack()) { | |
2233 raddr = frame_map()->address_for_slot(right->single_stack_ix()); | |
2234 } else if (right->is_constant()) { | |
2235 // hack for now | |
2236 raddr = __ as_Address(InternalAddress(float_constant(right->as_jfloat()))); | |
2237 } else { | |
2238 ShouldNotReachHere(); | |
2239 } | |
2240 switch (code) { | |
2241 case lir_add: __ addss(lreg, raddr); break; | |
2242 case lir_sub: __ subss(lreg, raddr); break; | |
2243 case lir_mul_strictfp: // fall through | |
2244 case lir_mul: __ mulss(lreg, raddr); break; | |
2245 case lir_div_strictfp: // fall through | |
2246 case lir_div: __ divss(lreg, raddr); break; | |
2247 default: ShouldNotReachHere(); | |
2248 } | |
2249 } | |
2250 | |
2251 } else if (left->is_double_xmm()) { | |
2252 assert(left == dest, "left and dest must be equal"); | |
2253 | |
2254 XMMRegister lreg = left->as_xmm_double_reg(); | |
2255 if (right->is_double_xmm()) { | |
2256 XMMRegister rreg = right->as_xmm_double_reg(); | |
2257 switch (code) { | |
2258 case lir_add: __ addsd(lreg, rreg); break; | |
2259 case lir_sub: __ subsd(lreg, rreg); break; | |
2260 case lir_mul_strictfp: // fall through | |
2261 case lir_mul: __ mulsd(lreg, rreg); break; | |
2262 case lir_div_strictfp: // fall through | |
2263 case lir_div: __ divsd(lreg, rreg); break; | |
2264 default: ShouldNotReachHere(); | |
2265 } | |
2266 } else { | |
2267 Address raddr; | |
2268 if (right->is_double_stack()) { | |
2269 raddr = frame_map()->address_for_slot(right->double_stack_ix()); | |
2270 } else if (right->is_constant()) { | |
2271 // hack for now | |
2272 raddr = __ as_Address(InternalAddress(double_constant(right->as_jdouble()))); | |
2273 } else { | |
2274 ShouldNotReachHere(); | |
2275 } | |
2276 switch (code) { | |
2277 case lir_add: __ addsd(lreg, raddr); break; | |
2278 case lir_sub: __ subsd(lreg, raddr); break; | |
2279 case lir_mul_strictfp: // fall through | |
2280 case lir_mul: __ mulsd(lreg, raddr); break; | |
2281 case lir_div_strictfp: // fall through | |
2282 case lir_div: __ divsd(lreg, raddr); break; | |
2283 default: ShouldNotReachHere(); | |
2284 } | |
2285 } | |
2286 | |
2287 } else if (left->is_single_fpu()) { | |
2288 assert(dest->is_single_fpu(), "fpu stack allocation required"); | |
2289 | |
2290 if (right->is_single_fpu()) { | |
2291 arith_fpu_implementation(code, left->fpu_regnr(), right->fpu_regnr(), dest->fpu_regnr(), pop_fpu_stack); | |
2292 | |
2293 } else { | |
2294 assert(left->fpu_regnr() == 0, "left must be on TOS"); | |
2295 assert(dest->fpu_regnr() == 0, "dest must be on TOS"); | |
2296 | |
2297 Address raddr; | |
2298 if (right->is_single_stack()) { | |
2299 raddr = frame_map()->address_for_slot(right->single_stack_ix()); | |
2300 } else if (right->is_constant()) { | |
2301 address const_addr = float_constant(right->as_jfloat()); | |
2302 assert(const_addr != NULL, "incorrect float/double constant maintainance"); | |
2303 // hack for now | |
2304 raddr = __ as_Address(InternalAddress(const_addr)); | |
2305 } else { | |
2306 ShouldNotReachHere(); | |
2307 } | |
2308 | |
2309 switch (code) { | |
2310 case lir_add: __ fadd_s(raddr); break; | |
2311 case lir_sub: __ fsub_s(raddr); break; | |
2312 case lir_mul_strictfp: // fall through | |
2313 case lir_mul: __ fmul_s(raddr); break; | |
2314 case lir_div_strictfp: // fall through | |
2315 case lir_div: __ fdiv_s(raddr); break; | |
2316 default: ShouldNotReachHere(); | |
2317 } | |
2318 } | |
2319 | |
2320 } else if (left->is_double_fpu()) { | |
2321 assert(dest->is_double_fpu(), "fpu stack allocation required"); | |
2322 | |
2323 if (code == lir_mul_strictfp || code == lir_div_strictfp) { | |
2324 // Double values require special handling for strictfp mul/div on x86 | |
2325 __ fld_x(ExternalAddress(StubRoutines::addr_fpu_subnormal_bias1())); | |
2326 __ fmulp(left->fpu_regnrLo() + 1); | |
2327 } | |
2328 | |
2329 if (right->is_double_fpu()) { | |
2330 arith_fpu_implementation(code, left->fpu_regnrLo(), right->fpu_regnrLo(), dest->fpu_regnrLo(), pop_fpu_stack); | |
2331 | |
2332 } else { | |
2333 assert(left->fpu_regnrLo() == 0, "left must be on TOS"); | |
2334 assert(dest->fpu_regnrLo() == 0, "dest must be on TOS"); | |
2335 | |
2336 Address raddr; | |
2337 if (right->is_double_stack()) { | |
2338 raddr = frame_map()->address_for_slot(right->double_stack_ix()); | |
2339 } else if (right->is_constant()) { | |
2340 // hack for now | |
2341 raddr = __ as_Address(InternalAddress(double_constant(right->as_jdouble()))); | |
2342 } else { | |
2343 ShouldNotReachHere(); | |
2344 } | |
2345 | |
2346 switch (code) { | |
2347 case lir_add: __ fadd_d(raddr); break; | |
2348 case lir_sub: __ fsub_d(raddr); break; | |
2349 case lir_mul_strictfp: // fall through | |
2350 case lir_mul: __ fmul_d(raddr); break; | |
2351 case lir_div_strictfp: // fall through | |
2352 case lir_div: __ fdiv_d(raddr); break; | |
2353 default: ShouldNotReachHere(); | |
2354 } | |
2355 } | |
2356 | |
2357 if (code == lir_mul_strictfp || code == lir_div_strictfp) { | |
2358 // Double values require special handling for strictfp mul/div on x86 | |
2359 __ fld_x(ExternalAddress(StubRoutines::addr_fpu_subnormal_bias2())); | |
2360 __ fmulp(dest->fpu_regnrLo() + 1); | |
2361 } | |
2362 | |
2363 } else if (left->is_single_stack() || left->is_address()) { | |
2364 assert(left == dest, "left and dest must be equal"); | |
2365 | |
2366 Address laddr; | |
2367 if (left->is_single_stack()) { | |
2368 laddr = frame_map()->address_for_slot(left->single_stack_ix()); | |
2369 } else if (left->is_address()) { | |
2370 laddr = as_Address(left->as_address_ptr()); | |
2371 } else { | |
2372 ShouldNotReachHere(); | |
2373 } | |
2374 | |
2375 if (right->is_single_cpu()) { | |
2376 Register rreg = right->as_register(); | |
2377 switch (code) { | |
2378 case lir_add: __ addl(laddr, rreg); break; | |
2379 case lir_sub: __ subl(laddr, rreg); break; | |
2380 default: ShouldNotReachHere(); | |
2381 } | |
2382 } else if (right->is_constant()) { | |
2383 jint c = right->as_constant_ptr()->as_jint(); | |
2384 switch (code) { | |
2385 case lir_add: { | |
304 | 2386 __ incrementl(laddr, c); |
0 | 2387 break; |
2388 } | |
2389 case lir_sub: { | |
304 | 2390 __ decrementl(laddr, c); |
0 | 2391 break; |
2392 } | |
2393 default: ShouldNotReachHere(); | |
2394 } | |
2395 } else { | |
2396 ShouldNotReachHere(); | |
2397 } | |
2398 | |
2399 } else { | |
2400 ShouldNotReachHere(); | |
2401 } | |
2402 } | |
2403 | |
2404 void LIR_Assembler::arith_fpu_implementation(LIR_Code code, int left_index, int right_index, int dest_index, bool pop_fpu_stack) { | |
2405 assert(pop_fpu_stack || (left_index == dest_index || right_index == dest_index), "invalid LIR"); | |
2406 assert(!pop_fpu_stack || (left_index - 1 == dest_index || right_index - 1 == dest_index), "invalid LIR"); | |
2407 assert(left_index == 0 || right_index == 0, "either must be on top of stack"); | |
2408 | |
2409 bool left_is_tos = (left_index == 0); | |
2410 bool dest_is_tos = (dest_index == 0); | |
2411 int non_tos_index = (left_is_tos ? right_index : left_index); | |
2412 | |
2413 switch (code) { | |
2414 case lir_add: | |
2415 if (pop_fpu_stack) __ faddp(non_tos_index); | |
2416 else if (dest_is_tos) __ fadd (non_tos_index); | |
2417 else __ fadda(non_tos_index); | |
2418 break; | |
2419 | |
2420 case lir_sub: | |
2421 if (left_is_tos) { | |
2422 if (pop_fpu_stack) __ fsubrp(non_tos_index); | |
2423 else if (dest_is_tos) __ fsub (non_tos_index); | |
2424 else __ fsubra(non_tos_index); | |
2425 } else { | |
2426 if (pop_fpu_stack) __ fsubp (non_tos_index); | |
2427 else if (dest_is_tos) __ fsubr (non_tos_index); | |
2428 else __ fsuba (non_tos_index); | |
2429 } | |
2430 break; | |
2431 | |
2432 case lir_mul_strictfp: // fall through | |
2433 case lir_mul: | |
2434 if (pop_fpu_stack) __ fmulp(non_tos_index); | |
2435 else if (dest_is_tos) __ fmul (non_tos_index); | |
2436 else __ fmula(non_tos_index); | |
2437 break; | |
2438 | |
2439 case lir_div_strictfp: // fall through | |
2440 case lir_div: | |
2441 if (left_is_tos) { | |
2442 if (pop_fpu_stack) __ fdivrp(non_tos_index); | |
2443 else if (dest_is_tos) __ fdiv (non_tos_index); | |
2444 else __ fdivra(non_tos_index); | |
2445 } else { | |
2446 if (pop_fpu_stack) __ fdivp (non_tos_index); | |
2447 else if (dest_is_tos) __ fdivr (non_tos_index); | |
2448 else __ fdiva (non_tos_index); | |
2449 } | |
2450 break; | |
2451 | |
2452 case lir_rem: | |
2453 assert(left_is_tos && dest_is_tos && right_index == 1, "must be guaranteed by FPU stack allocation"); | |
2454 __ fremr(noreg); | |
2455 break; | |
2456 | |
2457 default: | |
2458 ShouldNotReachHere(); | |
2459 } | |
2460 } | |
2461 | |
2462 | |
2463 void LIR_Assembler::intrinsic_op(LIR_Code code, LIR_Opr value, LIR_Opr unused, LIR_Opr dest, LIR_Op* op) { | |
2464 if (value->is_double_xmm()) { | |
2465 switch(code) { | |
2466 case lir_abs : | |
2467 { | |
2468 if (dest->as_xmm_double_reg() != value->as_xmm_double_reg()) { | |
2469 __ movdbl(dest->as_xmm_double_reg(), value->as_xmm_double_reg()); | |
2470 } | |
2471 __ andpd(dest->as_xmm_double_reg(), | |
2472 ExternalAddress((address)double_signmask_pool)); | |
2473 } | |
2474 break; | |
2475 | |
2476 case lir_sqrt: __ sqrtsd(dest->as_xmm_double_reg(), value->as_xmm_double_reg()); break; | |
2477 // all other intrinsics are not available in the SSE instruction set, so FPU is used | |
2478 default : ShouldNotReachHere(); | |
2479 } | |
2480 | |
2481 } else if (value->is_double_fpu()) { | |
2482 assert(value->fpu_regnrLo() == 0 && dest->fpu_regnrLo() == 0, "both must be on TOS"); | |
2483 switch(code) { | |
2484 case lir_log : __ flog() ; break; | |
2485 case lir_log10 : __ flog10() ; break; | |
2486 case lir_abs : __ fabs() ; break; | |
2487 case lir_sqrt : __ fsqrt(); break; | |
2488 case lir_sin : | |
2489 // Should consider not saving rbx, if not necessary | |
2490 __ trigfunc('s', op->as_Op2()->fpu_stack_size()); | |
2491 break; | |
2492 case lir_cos : | |
2493 // Should consider not saving rbx, if not necessary | |
2494 assert(op->as_Op2()->fpu_stack_size() <= 6, "sin and cos need two free stack slots"); | |
2495 __ trigfunc('c', op->as_Op2()->fpu_stack_size()); | |
2496 break; | |
2497 case lir_tan : | |
2498 // Should consider not saving rbx, if not necessary | |
2499 __ trigfunc('t', op->as_Op2()->fpu_stack_size()); | |
2500 break; | |
6084
6759698e3140
7133857: exp() and pow() should use the x87 ISA on x86
roland
parents:
6057
diff
changeset
|
2501 case lir_exp : |
6759698e3140
7133857: exp() and pow() should use the x87 ISA on x86
roland
parents:
6057
diff
changeset
|
2502 __ exp_with_fallback(op->as_Op2()->fpu_stack_size()); |
6759698e3140
7133857: exp() and pow() should use the x87 ISA on x86
roland
parents:
6057
diff
changeset
|
2503 break; |
6759698e3140
7133857: exp() and pow() should use the x87 ISA on x86
roland
parents:
6057
diff
changeset
|
2504 case lir_pow : |
6759698e3140
7133857: exp() and pow() should use the x87 ISA on x86
roland
parents:
6057
diff
changeset
|
2505 __ pow_with_fallback(op->as_Op2()->fpu_stack_size()); |
6759698e3140
7133857: exp() and pow() should use the x87 ISA on x86
roland
parents:
6057
diff
changeset
|
2506 break; |
0 | 2507 default : ShouldNotReachHere(); |
2508 } | |
2509 } else { | |
2510 Unimplemented(); | |
2511 } | |
2512 } | |
2513 | |
2514 void LIR_Assembler::logic_op(LIR_Code code, LIR_Opr left, LIR_Opr right, LIR_Opr dst) { | |
2515 // assert(left->destroys_register(), "check"); | |
2516 if (left->is_single_cpu()) { | |
2517 Register reg = left->as_register(); | |
2518 if (right->is_constant()) { | |
2519 int val = right->as_constant_ptr()->as_jint(); | |
2520 switch (code) { | |
2521 case lir_logic_and: __ andl (reg, val); break; | |
2522 case lir_logic_or: __ orl (reg, val); break; | |
2523 case lir_logic_xor: __ xorl (reg, val); break; | |
2524 default: ShouldNotReachHere(); | |
2525 } | |
2526 } else if (right->is_stack()) { | |
2527 // added support for stack operands | |
2528 Address raddr = frame_map()->address_for_slot(right->single_stack_ix()); | |
2529 switch (code) { | |
2530 case lir_logic_and: __ andl (reg, raddr); break; | |
2531 case lir_logic_or: __ orl (reg, raddr); break; | |
2532 case lir_logic_xor: __ xorl (reg, raddr); break; | |
2533 default: ShouldNotReachHere(); | |
2534 } | |
2535 } else { | |
2536 Register rright = right->as_register(); | |
2537 switch (code) { | |
304 | 2538 case lir_logic_and: __ andptr (reg, rright); break; |
2539 case lir_logic_or : __ orptr (reg, rright); break; | |
2540 case lir_logic_xor: __ xorptr (reg, rright); break; | |
0 | 2541 default: ShouldNotReachHere(); |
2542 } | |
2543 } | |
2544 move_regs(reg, dst->as_register()); | |
2545 } else { | |
2546 Register l_lo = left->as_register_lo(); | |
2547 Register l_hi = left->as_register_hi(); | |
2548 if (right->is_constant()) { | |
304 | 2549 #ifdef _LP64 |
2550 __ mov64(rscratch1, right->as_constant_ptr()->as_jlong()); | |
2551 switch (code) { | |
2552 case lir_logic_and: | |
2553 __ andq(l_lo, rscratch1); | |
2554 break; | |
2555 case lir_logic_or: | |
2556 __ orq(l_lo, rscratch1); | |
2557 break; | |
2558 case lir_logic_xor: | |
2559 __ xorq(l_lo, rscratch1); | |
2560 break; | |
2561 default: ShouldNotReachHere(); | |
2562 } | |
2563 #else | |
0 | 2564 int r_lo = right->as_constant_ptr()->as_jint_lo(); |
2565 int r_hi = right->as_constant_ptr()->as_jint_hi(); | |
2566 switch (code) { | |
2567 case lir_logic_and: | |
2568 __ andl(l_lo, r_lo); | |
2569 __ andl(l_hi, r_hi); | |
2570 break; | |
2571 case lir_logic_or: | |
2572 __ orl(l_lo, r_lo); | |
2573 __ orl(l_hi, r_hi); | |
2574 break; | |
2575 case lir_logic_xor: | |
2576 __ xorl(l_lo, r_lo); | |
2577 __ xorl(l_hi, r_hi); | |
2578 break; | |
2579 default: ShouldNotReachHere(); | |
2580 } | |
304 | 2581 #endif // _LP64 |
0 | 2582 } else { |
1572 | 2583 #ifdef _LP64 |
2584 Register r_lo; | |
2585 if (right->type() == T_OBJECT || right->type() == T_ARRAY) { | |
2586 r_lo = right->as_register(); | |
2587 } else { | |
2588 r_lo = right->as_register_lo(); | |
2589 } | |
2590 #else | |
0 | 2591 Register r_lo = right->as_register_lo(); |
2592 Register r_hi = right->as_register_hi(); | |
2593 assert(l_lo != r_hi, "overwriting registers"); | |
1572 | 2594 #endif |
0 | 2595 switch (code) { |
2596 case lir_logic_and: | |
304 | 2597 __ andptr(l_lo, r_lo); |
2598 NOT_LP64(__ andptr(l_hi, r_hi);) | |
0 | 2599 break; |
2600 case lir_logic_or: | |
304 | 2601 __ orptr(l_lo, r_lo); |
2602 NOT_LP64(__ orptr(l_hi, r_hi);) | |
0 | 2603 break; |
2604 case lir_logic_xor: | |
304 | 2605 __ xorptr(l_lo, r_lo); |
2606 NOT_LP64(__ xorptr(l_hi, r_hi);) | |
0 | 2607 break; |
2608 default: ShouldNotReachHere(); | |
2609 } | |
2610 } | |
2611 | |
2612 Register dst_lo = dst->as_register_lo(); | |
2613 Register dst_hi = dst->as_register_hi(); | |
2614 | |
304 | 2615 #ifdef _LP64 |
2616 move_regs(l_lo, dst_lo); | |
2617 #else | |
0 | 2618 if (dst_lo == l_hi) { |
2619 assert(dst_hi != l_lo, "overwriting registers"); | |
2620 move_regs(l_hi, dst_hi); | |
2621 move_regs(l_lo, dst_lo); | |
2622 } else { | |
2623 assert(dst_lo != l_hi, "overwriting registers"); | |
2624 move_regs(l_lo, dst_lo); | |
2625 move_regs(l_hi, dst_hi); | |
2626 } | |
304 | 2627 #endif // _LP64 |
0 | 2628 } |
2629 } | |
2630 | |
2631 | |
2632 // we assume that rax, and rdx can be overwritten | |
2633 void LIR_Assembler::arithmetic_idiv(LIR_Code code, LIR_Opr left, LIR_Opr right, LIR_Opr temp, LIR_Opr result, CodeEmitInfo* info) { | |
2634 | |
2635 assert(left->is_single_cpu(), "left must be register"); | |
2636 assert(right->is_single_cpu() || right->is_constant(), "right must be register or constant"); | |
2637 assert(result->is_single_cpu(), "result must be register"); | |
2638 | |
2639 // assert(left->destroys_register(), "check"); | |
2640 // assert(right->destroys_register(), "check"); | |
2641 | |
2642 Register lreg = left->as_register(); | |
2643 Register dreg = result->as_register(); | |
2644 | |
2645 if (right->is_constant()) { | |
2646 int divisor = right->as_constant_ptr()->as_jint(); | |
2647 assert(divisor > 0 && is_power_of_2(divisor), "must be"); | |
2648 if (code == lir_idiv) { | |
2649 assert(lreg == rax, "must be rax,"); | |
2650 assert(temp->as_register() == rdx, "tmp register must be rdx"); | |
2651 __ cdql(); // sign extend into rdx:rax | |
2652 if (divisor == 2) { | |
2653 __ subl(lreg, rdx); | |
2654 } else { | |
2655 __ andl(rdx, divisor - 1); | |
2656 __ addl(lreg, rdx); | |
2657 } | |
2658 __ sarl(lreg, log2_intptr(divisor)); | |
2659 move_regs(lreg, dreg); | |
2660 } else if (code == lir_irem) { | |
2661 Label done; | |
304 | 2662 __ mov(dreg, lreg); |
0 | 2663 __ andl(dreg, 0x80000000 | (divisor - 1)); |
2664 __ jcc(Assembler::positive, done); | |
2665 __ decrement(dreg); | |
2666 __ orl(dreg, ~(divisor - 1)); | |
2667 __ increment(dreg); | |
2668 __ bind(done); | |
2669 } else { | |
2670 ShouldNotReachHere(); | |
2671 } | |
2672 } else { | |
2673 Register rreg = right->as_register(); | |
2674 assert(lreg == rax, "left register must be rax,"); | |
2675 assert(rreg != rdx, "right register must not be rdx"); | |
2676 assert(temp->as_register() == rdx, "tmp register must be rdx"); | |
2677 | |
2678 move_regs(lreg, rax); | |
2679 | |
2680 int idivl_offset = __ corrected_idivl(rreg); | |
2681 add_debug_info_for_div0(idivl_offset, info); | |
2682 if (code == lir_irem) { | |
2683 move_regs(rdx, dreg); // result is in rdx | |
2684 } else { | |
2685 move_regs(rax, dreg); | |
2686 } | |
2687 } | |
2688 } | |
2689 | |
2690 | |
2691 void LIR_Assembler::comp_op(LIR_Condition condition, LIR_Opr opr1, LIR_Opr opr2, LIR_Op2* op) { | |
2692 if (opr1->is_single_cpu()) { | |
2693 Register reg1 = opr1->as_register(); | |
2694 if (opr2->is_single_cpu()) { | |
2695 // cpu register - cpu register | |
304 | 2696 if (opr1->type() == T_OBJECT || opr1->type() == T_ARRAY) { |
2697 __ cmpptr(reg1, opr2->as_register()); | |
2698 } else { | |
2699 assert(opr2->type() != T_OBJECT && opr2->type() != T_ARRAY, "cmp int, oop?"); | |
2700 __ cmpl(reg1, opr2->as_register()); | |
2701 } | |
0 | 2702 } else if (opr2->is_stack()) { |
2703 // cpu register - stack | |
304 | 2704 if (opr1->type() == T_OBJECT || opr1->type() == T_ARRAY) { |
2705 __ cmpptr(reg1, frame_map()->address_for_slot(opr2->single_stack_ix())); | |
2706 } else { | |
2707 __ cmpl(reg1, frame_map()->address_for_slot(opr2->single_stack_ix())); | |
2708 } | |
0 | 2709 } else if (opr2->is_constant()) { |
2710 // cpu register - constant | |
2711 LIR_Const* c = opr2->as_constant_ptr(); | |
2712 if (c->type() == T_INT) { | |
2713 __ cmpl(reg1, c->as_jint()); | |
304 | 2714 } else if (c->type() == T_OBJECT || c->type() == T_ARRAY) { |
2715 // In 64bit oops are single register | |
0 | 2716 jobject o = c->as_jobject(); |
2717 if (o == NULL) { | |
304 | 2718 __ cmpptr(reg1, (int32_t)NULL_WORD); |
0 | 2719 } else { |
304 | 2720 #ifdef _LP64 |
2721 __ movoop(rscratch1, o); | |
2722 __ cmpptr(reg1, rscratch1); | |
2723 #else | |
0 | 2724 __ cmpoop(reg1, c->as_jobject()); |
304 | 2725 #endif // _LP64 |
0 | 2726 } |
2727 } else { | |
6145
e2fe93124108
7174928: JSR 292: unresolved invokedynamic call sites deopt and osr infinitely
twisti
parents:
6084
diff
changeset
|
2728 fatal(err_msg("unexpected type: %s", basictype_to_str(c->type()))); |
0 | 2729 } |
2730 // cpu register - address | |
2731 } else if (opr2->is_address()) { | |
2732 if (op->info() != NULL) { | |
2733 add_debug_info_for_null_check_here(op->info()); | |
2734 } | |
2735 __ cmpl(reg1, as_Address(opr2->as_address_ptr())); | |
2736 } else { | |
2737 ShouldNotReachHere(); | |
2738 } | |
2739 | |
2740 } else if(opr1->is_double_cpu()) { | |
2741 Register xlo = opr1->as_register_lo(); | |
2742 Register xhi = opr1->as_register_hi(); | |
2743 if (opr2->is_double_cpu()) { | |
304 | 2744 #ifdef _LP64 |
2745 __ cmpptr(xlo, opr2->as_register_lo()); | |
2746 #else | |
0 | 2747 // cpu register - cpu register |
2748 Register ylo = opr2->as_register_lo(); | |
2749 Register yhi = opr2->as_register_hi(); | |
2750 __ subl(xlo, ylo); | |
2751 __ sbbl(xhi, yhi); | |
2752 if (condition == lir_cond_equal || condition == lir_cond_notEqual) { | |
2753 __ orl(xhi, xlo); | |
2754 } | |
304 | 2755 #endif // _LP64 |
0 | 2756 } else if (opr2->is_constant()) { |
2757 // cpu register - constant 0 | |
2758 assert(opr2->as_jlong() == (jlong)0, "only handles zero"); | |
304 | 2759 #ifdef _LP64 |
2760 __ cmpptr(xlo, (int32_t)opr2->as_jlong()); | |
2761 #else | |
0 | 2762 assert(condition == lir_cond_equal || condition == lir_cond_notEqual, "only handles equals case"); |
2763 __ orl(xhi, xlo); | |
304 | 2764 #endif // _LP64 |
0 | 2765 } else { |
2766 ShouldNotReachHere(); | |
2767 } | |
2768 | |
2769 } else if (opr1->is_single_xmm()) { | |
2770 XMMRegister reg1 = opr1->as_xmm_float_reg(); | |
2771 if (opr2->is_single_xmm()) { | |
2772 // xmm register - xmm register | |
2773 __ ucomiss(reg1, opr2->as_xmm_float_reg()); | |
2774 } else if (opr2->is_stack()) { | |
2775 // xmm register - stack | |
2776 __ ucomiss(reg1, frame_map()->address_for_slot(opr2->single_stack_ix())); | |
2777 } else if (opr2->is_constant()) { | |
2778 // xmm register - constant | |
2779 __ ucomiss(reg1, InternalAddress(float_constant(opr2->as_jfloat()))); | |
2780 } else if (opr2->is_address()) { | |
2781 // xmm register - address | |
2782 if (op->info() != NULL) { | |
2783 add_debug_info_for_null_check_here(op->info()); | |
2784 } | |
2785 __ ucomiss(reg1, as_Address(opr2->as_address_ptr())); | |
2786 } else { | |
2787 ShouldNotReachHere(); | |
2788 } | |
2789 | |
2790 } else if (opr1->is_double_xmm()) { | |
2791 XMMRegister reg1 = opr1->as_xmm_double_reg(); | |
2792 if (opr2->is_double_xmm()) { | |
2793 // xmm register - xmm register | |
2794 __ ucomisd(reg1, opr2->as_xmm_double_reg()); | |
2795 } else if (opr2->is_stack()) { | |
2796 // xmm register - stack | |
2797 __ ucomisd(reg1, frame_map()->address_for_slot(opr2->double_stack_ix())); | |
2798 } else if (opr2->is_constant()) { | |
2799 // xmm register - constant | |
2800 __ ucomisd(reg1, InternalAddress(double_constant(opr2->as_jdouble()))); | |
2801 } else if (opr2->is_address()) { | |
2802 // xmm register - address | |
2803 if (op->info() != NULL) { | |
2804 add_debug_info_for_null_check_here(op->info()); | |
2805 } | |
2806 __ ucomisd(reg1, as_Address(opr2->pointer()->as_address())); | |
2807 } else { | |
2808 ShouldNotReachHere(); | |
2809 } | |
2810 | |
2811 } else if(opr1->is_single_fpu() || opr1->is_double_fpu()) { | |
2812 assert(opr1->is_fpu_register() && opr1->fpu() == 0, "currently left-hand side must be on TOS (relax this restriction)"); | |
2813 assert(opr2->is_fpu_register(), "both must be registers"); | |
2814 __ fcmp(noreg, opr2->fpu(), op->fpu_pop_count() > 0, op->fpu_pop_count() > 1); | |
2815 | |
2816 } else if (opr1->is_address() && opr2->is_constant()) { | |
304 | 2817 LIR_Const* c = opr2->as_constant_ptr(); |
2818 #ifdef _LP64 | |
2819 if (c->type() == T_OBJECT || c->type() == T_ARRAY) { | |
2820 assert(condition == lir_cond_equal || condition == lir_cond_notEqual, "need to reverse"); | |
2821 __ movoop(rscratch1, c->as_jobject()); | |
2822 } | |
2823 #endif // LP64 | |
0 | 2824 if (op->info() != NULL) { |
2825 add_debug_info_for_null_check_here(op->info()); | |
2826 } | |
2827 // special case: address - constant | |
2828 LIR_Address* addr = opr1->as_address_ptr(); | |
2829 if (c->type() == T_INT) { | |
2830 __ cmpl(as_Address(addr), c->as_jint()); | |
304 | 2831 } else if (c->type() == T_OBJECT || c->type() == T_ARRAY) { |
2832 #ifdef _LP64 | |
2833 // %%% Make this explode if addr isn't reachable until we figure out a | |
2834 // better strategy by giving noreg as the temp for as_Address | |
2835 __ cmpptr(rscratch1, as_Address(addr, noreg)); | |
2836 #else | |
0 | 2837 __ cmpoop(as_Address(addr), c->as_jobject()); |
304 | 2838 #endif // _LP64 |
0 | 2839 } else { |
2840 ShouldNotReachHere(); | |
2841 } | |
2842 | |
2843 } else { | |
2844 ShouldNotReachHere(); | |
2845 } | |
2846 } | |
2847 | |
2848 void LIR_Assembler::comp_fl2i(LIR_Code code, LIR_Opr left, LIR_Opr right, LIR_Opr dst, LIR_Op2* op) { | |
2849 if (code == lir_cmp_fd2i || code == lir_ucmp_fd2i) { | |
2850 if (left->is_single_xmm()) { | |
2851 assert(right->is_single_xmm(), "must match"); | |
2852 __ cmpss2int(left->as_xmm_float_reg(), right->as_xmm_float_reg(), dst->as_register(), code == lir_ucmp_fd2i); | |
2853 } else if (left->is_double_xmm()) { | |
2854 assert(right->is_double_xmm(), "must match"); | |
2855 __ cmpsd2int(left->as_xmm_double_reg(), right->as_xmm_double_reg(), dst->as_register(), code == lir_ucmp_fd2i); | |
2856 | |
2857 } else { | |
2858 assert(left->is_single_fpu() || left->is_double_fpu(), "must be"); | |
2859 assert(right->is_single_fpu() || right->is_double_fpu(), "must match"); | |
2860 | |
2861 assert(left->fpu() == 0, "left must be on TOS"); | |
2862 __ fcmp2int(dst->as_register(), code == lir_ucmp_fd2i, right->fpu(), | |
2863 op->fpu_pop_count() > 0, op->fpu_pop_count() > 1); | |
2864 } | |
2865 } else { | |
2866 assert(code == lir_cmp_l2i, "check"); | |
304 | 2867 #ifdef _LP64 |
1369 | 2868 Label done; |
2869 Register dest = dst->as_register(); | |
2870 __ cmpptr(left->as_register_lo(), right->as_register_lo()); | |
2871 __ movl(dest, -1); | |
2872 __ jccb(Assembler::less, done); | |
2873 __ set_byte_if_not_zero(dest); | |
2874 __ movzbl(dest, dest); | |
2875 __ bind(done); | |
304 | 2876 #else |
0 | 2877 __ lcmp2int(left->as_register_hi(), |
2878 left->as_register_lo(), | |
2879 right->as_register_hi(), | |
2880 right->as_register_lo()); | |
2881 move_regs(left->as_register_hi(), dst->as_register()); | |
304 | 2882 #endif // _LP64 |
0 | 2883 } |
2884 } | |
2885 | |
2886 | |
2887 void LIR_Assembler::align_call(LIR_Code code) { | |
2888 if (os::is_MP()) { | |
2889 // make sure that the displacement word of the call ends up word aligned | |
2890 int offset = __ offset(); | |
2891 switch (code) { | |
2892 case lir_static_call: | |
2893 case lir_optvirtual_call: | |
1295 | 2894 case lir_dynamic_call: |
0 | 2895 offset += NativeCall::displacement_offset; |
2896 break; | |
2897 case lir_icvirtual_call: | |
2898 offset += NativeCall::displacement_offset + NativeMovConstReg::instruction_size; | |
2899 break; | |
2900 case lir_virtual_call: // currently, sparc-specific for niagara | |
2901 default: ShouldNotReachHere(); | |
2902 } | |
2903 while (offset++ % BytesPerWord != 0) { | |
2904 __ nop(); | |
2905 } | |
2906 } | |
2907 } | |
2908 | |
2909 | |
1295 | 2910 void LIR_Assembler::call(LIR_OpJavaCall* op, relocInfo::relocType rtype) { |
0 | 2911 assert(!os::is_MP() || (__ offset() + NativeCall::displacement_offset) % BytesPerWord == 0, |
2912 "must be aligned"); | |
1295 | 2913 __ call(AddressLiteral(op->addr(), rtype)); |
1564 | 2914 add_call_info(code_offset(), op->info()); |
0 | 2915 } |
2916 | |
2917 | |
1295 | 2918 void LIR_Assembler::ic_call(LIR_OpJavaCall* op) { |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
2919 __ ic_call(op->addr()); |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
2920 add_call_info(code_offset(), op->info()); |
0 | 2921 assert(!os::is_MP() || |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
2922 (__ offset() - NativeCall::instruction_size + NativeCall::displacement_offset) % BytesPerWord == 0, |
0 | 2923 "must be aligned"); |
2924 } | |
2925 | |
2926 | |
2927 /* Currently, vtable-dispatch is only enabled for sparc platforms */ | |
1295 | 2928 void LIR_Assembler::vtable_call(LIR_OpJavaCall* op) { |
0 | 2929 ShouldNotReachHere(); |
2930 } | |
2931 | |
1295 | 2932 |
0 | 2933 void LIR_Assembler::emit_static_call_stub() { |
2934 address call_pc = __ pc(); | |
2935 address stub = __ start_a_stub(call_stub_size); | |
2936 if (stub == NULL) { | |
2937 bailout("static call stub overflow"); | |
2938 return; | |
2939 } | |
2940 | |
2941 int start = __ offset(); | |
2942 if (os::is_MP()) { | |
2943 // make sure that the displacement word of the call ends up word aligned | |
2944 int offset = __ offset() + NativeMovConstReg::instruction_size + NativeCall::displacement_offset; | |
2945 while (offset++ % BytesPerWord != 0) { | |
2946 __ nop(); | |
2947 } | |
2948 } | |
2949 __ relocate(static_stub_Relocation::spec(call_pc)); | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
2950 __ mov_metadata(rbx, (Metadata*)NULL); |
0 | 2951 // must be set to -1 at code generation time |
2952 assert(!os::is_MP() || ((__ offset() + 1) % BytesPerWord) == 0, "must be aligned on MP"); | |
304 | 2953 // On 64bit this will die since it will take a movq & jmp, must be only a jmp |
2954 __ jump(RuntimeAddress(__ pc())); | |
0 | 2955 |
1489
cff162798819
6888953: some calls to function-like macros are missing semicolons
jcoomes
parents:
1378
diff
changeset
|
2956 assert(__ offset() - start <= call_stub_size, "stub too big"); |
0 | 2957 __ end_a_stub(); |
2958 } | |
2959 | |
2960 | |
1378
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
2961 void LIR_Assembler::throw_op(LIR_Opr exceptionPC, LIR_Opr exceptionOop, CodeEmitInfo* info) { |
0 | 2962 assert(exceptionOop->as_register() == rax, "must match"); |
1378
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
2963 assert(exceptionPC->as_register() == rdx, "must match"); |
0 | 2964 |
2965 // exception object is not added to oop map by LinearScan | |
2966 // (LinearScan assumes that no oops are in fixed registers) | |
2967 info->add_register_oop(exceptionOop); | |
2968 Runtime1::StubID unwind_id; | |
2969 | |
1378
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
2970 // get current pc information |
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
2971 // pc is only needed if the method has an exception handler, the unwind code does not need it. |
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
2972 int pc_for_athrow_offset = __ offset(); |
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
2973 InternalAddress pc_for_athrow(__ pc()); |
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
2974 __ lea(exceptionPC->as_register(), pc_for_athrow); |
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
2975 add_call_info(pc_for_athrow_offset, info); // for exception handler |
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
2976 |
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
2977 __ verify_not_null_oop(rax); |
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
2978 // search an exception handler (rax: exception oop, rdx: throwing pc) |
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
2979 if (compilation()->has_fpu_code()) { |
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
2980 unwind_id = Runtime1::handle_exception_id; |
0 | 2981 } else { |
1378
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
2982 unwind_id = Runtime1::handle_exception_nofpu_id; |
0 | 2983 } |
1378
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
2984 __ call(RuntimeAddress(Runtime1::entry_for(unwind_id))); |
0 | 2985 |
2986 // enough room for two byte trap | |
2987 __ nop(); | |
2988 } | |
2989 | |
2990 | |
1378
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
2991 void LIR_Assembler::unwind_op(LIR_Opr exceptionOop) { |
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
2992 assert(exceptionOop->as_register() == rax, "must match"); |
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
2993 |
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
2994 __ jmp(_unwind_handler_entry); |
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
2995 } |
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
2996 |
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
2997 |
0 | 2998 void LIR_Assembler::shift_op(LIR_Code code, LIR_Opr left, LIR_Opr count, LIR_Opr dest, LIR_Opr tmp) { |
2999 | |
3000 // optimized version for linear scan: | |
3001 // * count must be already in ECX (guaranteed by LinearScan) | |
3002 // * left and dest must be equal | |
3003 // * tmp must be unused | |
3004 assert(count->as_register() == SHIFT_count, "count must be in ECX"); | |
3005 assert(left == dest, "left and dest must be equal"); | |
3006 assert(tmp->is_illegal(), "wasting a register if tmp is allocated"); | |
3007 | |
3008 if (left->is_single_cpu()) { | |
3009 Register value = left->as_register(); | |
3010 assert(value != SHIFT_count, "left cannot be ECX"); | |
3011 | |
3012 switch (code) { | |
3013 case lir_shl: __ shll(value); break; | |
3014 case lir_shr: __ sarl(value); break; | |
3015 case lir_ushr: __ shrl(value); break; | |
3016 default: ShouldNotReachHere(); | |
3017 } | |
3018 } else if (left->is_double_cpu()) { | |
3019 Register lo = left->as_register_lo(); | |
3020 Register hi = left->as_register_hi(); | |
3021 assert(lo != SHIFT_count && hi != SHIFT_count, "left cannot be ECX"); | |
304 | 3022 #ifdef _LP64 |
3023 switch (code) { | |
3024 case lir_shl: __ shlptr(lo); break; | |
3025 case lir_shr: __ sarptr(lo); break; | |
3026 case lir_ushr: __ shrptr(lo); break; | |
3027 default: ShouldNotReachHere(); | |
3028 } | |
3029 #else | |
0 | 3030 |
3031 switch (code) { | |
3032 case lir_shl: __ lshl(hi, lo); break; | |
3033 case lir_shr: __ lshr(hi, lo, true); break; | |
3034 case lir_ushr: __ lshr(hi, lo, false); break; | |
3035 default: ShouldNotReachHere(); | |
3036 } | |
304 | 3037 #endif // LP64 |
0 | 3038 } else { |
3039 ShouldNotReachHere(); | |
3040 } | |
3041 } | |
3042 | |
3043 | |
3044 void LIR_Assembler::shift_op(LIR_Code code, LIR_Opr left, jint count, LIR_Opr dest) { | |
3045 if (dest->is_single_cpu()) { | |
3046 // first move left into dest so that left is not destroyed by the shift | |
3047 Register value = dest->as_register(); | |
3048 count = count & 0x1F; // Java spec | |
3049 | |
3050 move_regs(left->as_register(), value); | |
3051 switch (code) { | |
3052 case lir_shl: __ shll(value, count); break; | |
3053 case lir_shr: __ sarl(value, count); break; | |
3054 case lir_ushr: __ shrl(value, count); break; | |
3055 default: ShouldNotReachHere(); | |
3056 } | |
3057 } else if (dest->is_double_cpu()) { | |
304 | 3058 #ifndef _LP64 |
0 | 3059 Unimplemented(); |
304 | 3060 #else |
3061 // first move left into dest so that left is not destroyed by the shift | |
3062 Register value = dest->as_register_lo(); | |
3063 count = count & 0x1F; // Java spec | |
3064 | |
3065 move_regs(left->as_register_lo(), value); | |
3066 switch (code) { | |
3067 case lir_shl: __ shlptr(value, count); break; | |
3068 case lir_shr: __ sarptr(value, count); break; | |
3069 case lir_ushr: __ shrptr(value, count); break; | |
3070 default: ShouldNotReachHere(); | |
3071 } | |
3072 #endif // _LP64 | |
0 | 3073 } else { |
3074 ShouldNotReachHere(); | |
3075 } | |
3076 } | |
3077 | |
3078 | |
3079 void LIR_Assembler::store_parameter(Register r, int offset_from_rsp_in_words) { | |
3080 assert(offset_from_rsp_in_words >= 0, "invalid offset from rsp"); | |
3081 int offset_from_rsp_in_bytes = offset_from_rsp_in_words * BytesPerWord; | |
3082 assert(offset_from_rsp_in_bytes < frame_map()->reserved_argument_area_size(), "invalid offset"); | |
304 | 3083 __ movptr (Address(rsp, offset_from_rsp_in_bytes), r); |
0 | 3084 } |
3085 | |
3086 | |
3087 void LIR_Assembler::store_parameter(jint c, int offset_from_rsp_in_words) { | |
3088 assert(offset_from_rsp_in_words >= 0, "invalid offset from rsp"); | |
3089 int offset_from_rsp_in_bytes = offset_from_rsp_in_words * BytesPerWord; | |
3090 assert(offset_from_rsp_in_bytes < frame_map()->reserved_argument_area_size(), "invalid offset"); | |
304 | 3091 __ movptr (Address(rsp, offset_from_rsp_in_bytes), c); |
0 | 3092 } |
3093 | |
3094 | |
3095 void LIR_Assembler::store_parameter(jobject o, int offset_from_rsp_in_words) { | |
3096 assert(offset_from_rsp_in_words >= 0, "invalid offset from rsp"); | |
3097 int offset_from_rsp_in_bytes = offset_from_rsp_in_words * BytesPerWord; | |
3098 assert(offset_from_rsp_in_bytes < frame_map()->reserved_argument_area_size(), "invalid offset"); | |
3099 __ movoop (Address(rsp, offset_from_rsp_in_bytes), o); | |
3100 } | |
3101 | |
3102 | |
3103 // This code replaces a call to arraycopy; no exception may | |
3104 // be thrown in this code, they must be thrown in the System.arraycopy | |
3105 // activation frame; we could save some checks if this would not be the case | |
3106 void LIR_Assembler::emit_arraycopy(LIR_OpArrayCopy* op) { | |
3107 ciArrayKlass* default_type = op->expected_type(); | |
3108 Register src = op->src()->as_register(); | |
3109 Register dst = op->dst()->as_register(); | |
3110 Register src_pos = op->src_pos()->as_register(); | |
3111 Register dst_pos = op->dst_pos()->as_register(); | |
3112 Register length = op->length()->as_register(); | |
3113 Register tmp = op->tmp()->as_register(); | |
3114 | |
3115 CodeStub* stub = op->stub(); | |
3116 int flags = op->flags(); | |
3117 BasicType basic_type = default_type != NULL ? default_type->element_type()->basic_type() : T_ILLEGAL; | |
3118 if (basic_type == T_ARRAY) basic_type = T_OBJECT; | |
3119 | |
2446 | 3120 // if we don't know anything, just go through the generic arraycopy |
0 | 3121 if (default_type == NULL) { |
3122 Label done; | |
3123 // save outgoing arguments on stack in case call to System.arraycopy is needed | |
3124 // HACK ALERT. This code used to push the parameters in a hardwired fashion | |
3125 // for interpreter calling conventions. Now we have to do it in new style conventions. | |
3126 // For the moment until C1 gets the new register allocator I just force all the | |
3127 // args to the right place (except the register args) and then on the back side | |
3128 // reload the register args properly if we go slow path. Yuck | |
3129 | |
3130 // These are proper for the calling convention | |
3131 store_parameter(length, 2); | |
3132 store_parameter(dst_pos, 1); | |
3133 store_parameter(dst, 0); | |
3134 | |
3135 // these are just temporary placements until we need to reload | |
3136 store_parameter(src_pos, 3); | |
3137 store_parameter(src, 4); | |
304 | 3138 NOT_LP64(assert(src == rcx && src_pos == rdx, "mismatch in calling convention");) |
3139 | |
2446 | 3140 address C_entry = CAST_FROM_FN_PTR(address, Runtime1::arraycopy); |
3141 | |
3142 address copyfunc_addr = StubRoutines::generic_arraycopy(); | |
0 | 3143 |
3144 // pass arguments: may push as this is not a safepoint; SP must be fix at each safepoint | |
304 | 3145 #ifdef _LP64 |
3146 // The arguments are in java calling convention so we can trivially shift them to C | |
3147 // convention | |
3148 assert_different_registers(c_rarg0, j_rarg1, j_rarg2, j_rarg3, j_rarg4); | |
3149 __ mov(c_rarg0, j_rarg0); | |
3150 assert_different_registers(c_rarg1, j_rarg2, j_rarg3, j_rarg4); | |
3151 __ mov(c_rarg1, j_rarg1); | |
3152 assert_different_registers(c_rarg2, j_rarg3, j_rarg4); | |
3153 __ mov(c_rarg2, j_rarg2); | |
3154 assert_different_registers(c_rarg3, j_rarg4); | |
3155 __ mov(c_rarg3, j_rarg3); | |
3156 #ifdef _WIN64 | |
3157 // Allocate abi space for args but be sure to keep stack aligned | |
3158 __ subptr(rsp, 6*wordSize); | |
3159 store_parameter(j_rarg4, 4); | |
2446 | 3160 if (copyfunc_addr == NULL) { // Use C version if stub was not generated |
3161 __ call(RuntimeAddress(C_entry)); | |
3162 } else { | |
3163 #ifndef PRODUCT | |
3164 if (PrintC1Statistics) { | |
3165 __ incrementl(ExternalAddress((address)&Runtime1::_generic_arraycopystub_cnt)); | |
3166 } | |
3167 #endif | |
3168 __ call(RuntimeAddress(copyfunc_addr)); | |
3169 } | |
304 | 3170 __ addptr(rsp, 6*wordSize); |
3171 #else | |
3172 __ mov(c_rarg4, j_rarg4); | |
2446 | 3173 if (copyfunc_addr == NULL) { // Use C version if stub was not generated |
3174 __ call(RuntimeAddress(C_entry)); | |
3175 } else { | |
3176 #ifndef PRODUCT | |
3177 if (PrintC1Statistics) { | |
3178 __ incrementl(ExternalAddress((address)&Runtime1::_generic_arraycopystub_cnt)); | |
3179 } | |
3180 #endif | |
3181 __ call(RuntimeAddress(copyfunc_addr)); | |
3182 } | |
304 | 3183 #endif // _WIN64 |
3184 #else | |
3185 __ push(length); | |
3186 __ push(dst_pos); | |
3187 __ push(dst); | |
3188 __ push(src_pos); | |
3189 __ push(src); | |
2446 | 3190 |
3191 if (copyfunc_addr == NULL) { // Use C version if stub was not generated | |
3192 __ call_VM_leaf(C_entry, 5); // removes pushed parameter from the stack | |
3193 } else { | |
3194 #ifndef PRODUCT | |
3195 if (PrintC1Statistics) { | |
3196 __ incrementl(ExternalAddress((address)&Runtime1::_generic_arraycopystub_cnt)); | |
3197 } | |
3198 #endif | |
3199 __ call_VM_leaf(copyfunc_addr, 5); // removes pushed parameter from the stack | |
3200 } | |
0 | 3201 |
304 | 3202 #endif // _LP64 |
3203 | |
0 | 3204 __ cmpl(rax, 0); |
3205 __ jcc(Assembler::equal, *stub->continuation()); | |
3206 | |
2446 | 3207 if (copyfunc_addr != NULL) { |
3208 __ mov(tmp, rax); | |
3209 __ xorl(tmp, -1); | |
3210 } | |
3211 | |
0 | 3212 // Reload values from the stack so they are where the stub |
3213 // expects them. | |
304 | 3214 __ movptr (dst, Address(rsp, 0*BytesPerWord)); |
3215 __ movptr (dst_pos, Address(rsp, 1*BytesPerWord)); | |
3216 __ movptr (length, Address(rsp, 2*BytesPerWord)); | |
3217 __ movptr (src_pos, Address(rsp, 3*BytesPerWord)); | |
3218 __ movptr (src, Address(rsp, 4*BytesPerWord)); | |
2446 | 3219 |
3220 if (copyfunc_addr != NULL) { | |
3221 __ subl(length, tmp); | |
3222 __ addl(src_pos, tmp); | |
3223 __ addl(dst_pos, tmp); | |
3224 } | |
0 | 3225 __ jmp(*stub->entry()); |
3226 | |
3227 __ bind(*stub->continuation()); | |
3228 return; | |
3229 } | |
3230 | |
3231 assert(default_type != NULL && default_type->is_array_klass() && default_type->is_loaded(), "must be true at this point"); | |
3232 | |
29
d5fc211aea19
6633953: type2aelembytes{T_ADDRESS} should be 8 bytes in 64 bit VM
kvn
parents:
0
diff
changeset
|
3233 int elem_size = type2aelembytes(basic_type); |
0 | 3234 int shift_amount; |
3235 Address::ScaleFactor scale; | |
3236 | |
3237 switch (elem_size) { | |
3238 case 1 : | |
3239 shift_amount = 0; | |
3240 scale = Address::times_1; | |
3241 break; | |
3242 case 2 : | |
3243 shift_amount = 1; | |
3244 scale = Address::times_2; | |
3245 break; | |
3246 case 4 : | |
3247 shift_amount = 2; | |
3248 scale = Address::times_4; | |
3249 break; | |
3250 case 8 : | |
3251 shift_amount = 3; | |
3252 scale = Address::times_8; | |
3253 break; | |
3254 default: | |
3255 ShouldNotReachHere(); | |
3256 } | |
3257 | |
3258 Address src_length_addr = Address(src, arrayOopDesc::length_offset_in_bytes()); | |
3259 Address dst_length_addr = Address(dst, arrayOopDesc::length_offset_in_bytes()); | |
3260 Address src_klass_addr = Address(src, oopDesc::klass_offset_in_bytes()); | |
3261 Address dst_klass_addr = Address(dst, oopDesc::klass_offset_in_bytes()); | |
3262 | |
304 | 3263 // length and pos's are all sign extended at this point on 64bit |
3264 | |
0 | 3265 // test for NULL |
3266 if (flags & LIR_OpArrayCopy::src_null_check) { | |
304 | 3267 __ testptr(src, src); |
0 | 3268 __ jcc(Assembler::zero, *stub->entry()); |
3269 } | |
3270 if (flags & LIR_OpArrayCopy::dst_null_check) { | |
304 | 3271 __ testptr(dst, dst); |
0 | 3272 __ jcc(Assembler::zero, *stub->entry()); |
3273 } | |
3274 | |
3275 // check if negative | |
3276 if (flags & LIR_OpArrayCopy::src_pos_positive_check) { | |
3277 __ testl(src_pos, src_pos); | |
3278 __ jcc(Assembler::less, *stub->entry()); | |
3279 } | |
3280 if (flags & LIR_OpArrayCopy::dst_pos_positive_check) { | |
3281 __ testl(dst_pos, dst_pos); | |
3282 __ jcc(Assembler::less, *stub->entry()); | |
3283 } | |
3284 | |
3285 if (flags & LIR_OpArrayCopy::src_range_check) { | |
304 | 3286 __ lea(tmp, Address(src_pos, length, Address::times_1, 0)); |
0 | 3287 __ cmpl(tmp, src_length_addr); |
3288 __ jcc(Assembler::above, *stub->entry()); | |
3289 } | |
3290 if (flags & LIR_OpArrayCopy::dst_range_check) { | |
304 | 3291 __ lea(tmp, Address(dst_pos, length, Address::times_1, 0)); |
0 | 3292 __ cmpl(tmp, dst_length_addr); |
3293 __ jcc(Assembler::above, *stub->entry()); | |
3294 } | |
3295 | |
2446 | 3296 if (flags & LIR_OpArrayCopy::length_positive_check) { |
3297 __ testl(length, length); | |
3298 __ jcc(Assembler::less, *stub->entry()); | |
3299 __ jcc(Assembler::zero, *stub->continuation()); | |
3300 } | |
3301 | |
3302 #ifdef _LP64 | |
3303 __ movl2ptr(src_pos, src_pos); //higher 32bits must be null | |
3304 __ movl2ptr(dst_pos, dst_pos); //higher 32bits must be null | |
3305 #endif | |
3306 | |
0 | 3307 if (flags & LIR_OpArrayCopy::type_check) { |
2446 | 3308 // We don't know the array types are compatible |
3309 if (basic_type != T_OBJECT) { | |
3310 // Simple test for basic type arrays | |
12226
7944aba7ba41
8015107: NPG: Use consistent naming for metaspace concepts
ehelin
parents:
12160
diff
changeset
|
3311 if (UseCompressedClassPointers) { |
2446 | 3312 __ movl(tmp, src_klass_addr); |
3313 __ cmpl(tmp, dst_klass_addr); | |
3314 } else { | |
3315 __ movptr(tmp, src_klass_addr); | |
3316 __ cmpptr(tmp, dst_klass_addr); | |
3317 } | |
3318 __ jcc(Assembler::notEqual, *stub->entry()); | |
2002 | 3319 } else { |
2446 | 3320 // For object arrays, if src is a sub class of dst then we can |
3321 // safely do the copy. | |
3322 Label cont, slow; | |
3323 | |
3324 __ push(src); | |
3325 __ push(dst); | |
3326 | |
3327 __ load_klass(src, src); | |
3328 __ load_klass(dst, dst); | |
3329 | |
3330 __ check_klass_subtype_fast_path(src, dst, tmp, &cont, &slow, NULL); | |
3331 | |
3332 __ push(src); | |
3333 __ push(dst); | |
3334 __ call(RuntimeAddress(Runtime1::entry_for(Runtime1::slow_subtype_check_id))); | |
3335 __ pop(dst); | |
3336 __ pop(src); | |
3337 | |
3338 __ cmpl(src, 0); | |
3339 __ jcc(Assembler::notEqual, cont); | |
3340 | |
3341 __ bind(slow); | |
3342 __ pop(dst); | |
3343 __ pop(src); | |
3344 | |
3345 address copyfunc_addr = StubRoutines::checkcast_arraycopy(); | |
3346 if (copyfunc_addr != NULL) { // use stub if available | |
3347 // src is not a sub class of dst so we have to do a | |
3348 // per-element check. | |
3349 | |
3350 int mask = LIR_OpArrayCopy::src_objarray|LIR_OpArrayCopy::dst_objarray; | |
3351 if ((flags & mask) != mask) { | |
3352 // Check that at least both of them object arrays. | |
3353 assert(flags & mask, "one of the two should be known to be an object array"); | |
3354 | |
3355 if (!(flags & LIR_OpArrayCopy::src_objarray)) { | |
3356 __ load_klass(tmp, src); | |
3357 } else if (!(flags & LIR_OpArrayCopy::dst_objarray)) { | |
3358 __ load_klass(tmp, dst); | |
3359 } | |
4762
069ab3f976d3
7118863: Move sizeof(klassOopDesc) into the *Klass::*_offset_in_bytes() functions
stefank
parents:
3960
diff
changeset
|
3360 int lh_offset = in_bytes(Klass::layout_helper_offset()); |
2446 | 3361 Address klass_lh_addr(tmp, lh_offset); |
3362 jint objArray_lh = Klass::array_layout_helper(T_OBJECT); | |
3363 __ cmpl(klass_lh_addr, objArray_lh); | |
3364 __ jcc(Assembler::notEqual, *stub->entry()); | |
3365 } | |
3366 | |
3739
28263a73ebfb
7047491: C1: registers saved incorrectly when calling checkcast_arraycopy stub
iveresov
parents:
3401
diff
changeset
|
3367 // Spill because stubs can use any register they like and it's |
28263a73ebfb
7047491: C1: registers saved incorrectly when calling checkcast_arraycopy stub
iveresov
parents:
3401
diff
changeset
|
3368 // easier to restore just those that we care about. |
28263a73ebfb
7047491: C1: registers saved incorrectly when calling checkcast_arraycopy stub
iveresov
parents:
3401
diff
changeset
|
3369 store_parameter(dst, 0); |
28263a73ebfb
7047491: C1: registers saved incorrectly when calling checkcast_arraycopy stub
iveresov
parents:
3401
diff
changeset
|
3370 store_parameter(dst_pos, 1); |
28263a73ebfb
7047491: C1: registers saved incorrectly when calling checkcast_arraycopy stub
iveresov
parents:
3401
diff
changeset
|
3371 store_parameter(length, 2); |
28263a73ebfb
7047491: C1: registers saved incorrectly when calling checkcast_arraycopy stub
iveresov
parents:
3401
diff
changeset
|
3372 store_parameter(src_pos, 3); |
28263a73ebfb
7047491: C1: registers saved incorrectly when calling checkcast_arraycopy stub
iveresov
parents:
3401
diff
changeset
|
3373 store_parameter(src, 4); |
28263a73ebfb
7047491: C1: registers saved incorrectly when calling checkcast_arraycopy stub
iveresov
parents:
3401
diff
changeset
|
3374 |
2446 | 3375 #ifndef _LP64 |
3376 __ movptr(tmp, dst_klass_addr); | |
6831
d8ce2825b193
8000213: NPG: Should have renamed arrayKlass and typeArrayKlass
coleenp
parents:
6795
diff
changeset
|
3377 __ movptr(tmp, Address(tmp, ObjArrayKlass::element_klass_offset())); |
2446 | 3378 __ push(tmp); |
4762
069ab3f976d3
7118863: Move sizeof(klassOopDesc) into the *Klass::*_offset_in_bytes() functions
stefank
parents:
3960
diff
changeset
|
3379 __ movl(tmp, Address(tmp, Klass::super_check_offset_offset())); |
2446 | 3380 __ push(tmp); |
3381 __ push(length); | |
3382 __ lea(tmp, Address(dst, dst_pos, scale, arrayOopDesc::base_offset_in_bytes(basic_type))); | |
3383 __ push(tmp); | |
3384 __ lea(tmp, Address(src, src_pos, scale, arrayOopDesc::base_offset_in_bytes(basic_type))); | |
3385 __ push(tmp); | |
3386 | |
3387 __ call_VM_leaf(copyfunc_addr, 5); | |
3388 #else | |
3389 __ movl2ptr(length, length); //higher 32bits must be null | |
3390 | |
3391 __ lea(c_rarg0, Address(src, src_pos, scale, arrayOopDesc::base_offset_in_bytes(basic_type))); | |
3392 assert_different_registers(c_rarg0, dst, dst_pos, length); | |
3393 __ lea(c_rarg1, Address(dst, dst_pos, scale, arrayOopDesc::base_offset_in_bytes(basic_type))); | |
3394 assert_different_registers(c_rarg1, dst, length); | |
3395 | |
3396 __ mov(c_rarg2, length); | |
3397 assert_different_registers(c_rarg2, dst); | |
3398 | |
3399 #ifdef _WIN64 | |
3400 // Allocate abi space for args but be sure to keep stack aligned | |
3401 __ subptr(rsp, 6*wordSize); | |
3402 __ load_klass(c_rarg3, dst); | |
6831
d8ce2825b193
8000213: NPG: Should have renamed arrayKlass and typeArrayKlass
coleenp
parents:
6795
diff
changeset
|
3403 __ movptr(c_rarg3, Address(c_rarg3, ObjArrayKlass::element_klass_offset())); |
2446 | 3404 store_parameter(c_rarg3, 4); |
4762
069ab3f976d3
7118863: Move sizeof(klassOopDesc) into the *Klass::*_offset_in_bytes() functions
stefank
parents:
3960
diff
changeset
|
3405 __ movl(c_rarg3, Address(c_rarg3, Klass::super_check_offset_offset())); |
2446 | 3406 __ call(RuntimeAddress(copyfunc_addr)); |
3407 __ addptr(rsp, 6*wordSize); | |
3408 #else | |
3409 __ load_klass(c_rarg4, dst); | |
6831
d8ce2825b193
8000213: NPG: Should have renamed arrayKlass and typeArrayKlass
coleenp
parents:
6795
diff
changeset
|
3410 __ movptr(c_rarg4, Address(c_rarg4, ObjArrayKlass::element_klass_offset())); |
4762
069ab3f976d3
7118863: Move sizeof(klassOopDesc) into the *Klass::*_offset_in_bytes() functions
stefank
parents:
3960
diff
changeset
|
3411 __ movl(c_rarg3, Address(c_rarg4, Klass::super_check_offset_offset())); |
2446 | 3412 __ call(RuntimeAddress(copyfunc_addr)); |
3413 #endif | |
3414 | |
3415 #endif | |
3416 | |
3417 #ifndef PRODUCT | |
3418 if (PrintC1Statistics) { | |
3419 Label failed; | |
3420 __ testl(rax, rax); | |
3421 __ jcc(Assembler::notZero, failed); | |
3422 __ incrementl(ExternalAddress((address)&Runtime1::_arraycopy_checkcast_cnt)); | |
3423 __ bind(failed); | |
3424 } | |
3425 #endif | |
3426 | |
3427 __ testl(rax, rax); | |
3428 __ jcc(Assembler::zero, *stub->continuation()); | |
3429 | |
3430 #ifndef PRODUCT | |
3431 if (PrintC1Statistics) { | |
3432 __ incrementl(ExternalAddress((address)&Runtime1::_arraycopy_checkcast_attempt_cnt)); | |
3433 } | |
3434 #endif | |
3435 | |
3436 __ mov(tmp, rax); | |
3437 | |
3438 __ xorl(tmp, -1); | |
3439 | |
3739
28263a73ebfb
7047491: C1: registers saved incorrectly when calling checkcast_arraycopy stub
iveresov
parents:
3401
diff
changeset
|
3440 // Restore previously spilled arguments |
28263a73ebfb
7047491: C1: registers saved incorrectly when calling checkcast_arraycopy stub
iveresov
parents:
3401
diff
changeset
|
3441 __ movptr (dst, Address(rsp, 0*BytesPerWord)); |
28263a73ebfb
7047491: C1: registers saved incorrectly when calling checkcast_arraycopy stub
iveresov
parents:
3401
diff
changeset
|
3442 __ movptr (dst_pos, Address(rsp, 1*BytesPerWord)); |
28263a73ebfb
7047491: C1: registers saved incorrectly when calling checkcast_arraycopy stub
iveresov
parents:
3401
diff
changeset
|
3443 __ movptr (length, Address(rsp, 2*BytesPerWord)); |
28263a73ebfb
7047491: C1: registers saved incorrectly when calling checkcast_arraycopy stub
iveresov
parents:
3401
diff
changeset
|
3444 __ movptr (src_pos, Address(rsp, 3*BytesPerWord)); |
28263a73ebfb
7047491: C1: registers saved incorrectly when calling checkcast_arraycopy stub
iveresov
parents:
3401
diff
changeset
|
3445 __ movptr (src, Address(rsp, 4*BytesPerWord)); |
28263a73ebfb
7047491: C1: registers saved incorrectly when calling checkcast_arraycopy stub
iveresov
parents:
3401
diff
changeset
|
3446 |
2446 | 3447 |
3448 __ subl(length, tmp); | |
3449 __ addl(src_pos, tmp); | |
3450 __ addl(dst_pos, tmp); | |
3451 } | |
3452 | |
3453 __ jmp(*stub->entry()); | |
3454 | |
3455 __ bind(cont); | |
3456 __ pop(dst); | |
3457 __ pop(src); | |
2002 | 3458 } |
0 | 3459 } |
3460 | |
3461 #ifdef ASSERT | |
3462 if (basic_type != T_OBJECT || !(flags & LIR_OpArrayCopy::type_check)) { | |
3463 // Sanity check the known type with the incoming class. For the | |
3464 // primitive case the types must match exactly with src.klass and | |
3465 // dst.klass each exactly matching the default type. For the | |
3466 // object array case, if no type check is needed then either the | |
3467 // dst type is exactly the expected type and the src type is a | |
3468 // subtype which we can't check or src is the same array as dst | |
3469 // but not necessarily exactly of type default_type. | |
3470 Label known_ok, halt; | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
3471 __ mov_metadata(tmp, default_type->constant_encoding()); |
2002 | 3472 #ifdef _LP64 |
12226
7944aba7ba41
8015107: NPG: Use consistent naming for metaspace concepts
ehelin
parents:
12160
diff
changeset
|
3473 if (UseCompressedClassPointers) { |
6848
8e47bac5643a
7054512: Compress class pointers after perm gen removal
roland
parents:
6795
diff
changeset
|
3474 __ encode_klass_not_null(tmp); |
2002 | 3475 } |
3476 #endif | |
3477 | |
0 | 3478 if (basic_type != T_OBJECT) { |
2002 | 3479 |
12226
7944aba7ba41
8015107: NPG: Use consistent naming for metaspace concepts
ehelin
parents:
12160
diff
changeset
|
3480 if (UseCompressedClassPointers) __ cmpl(tmp, dst_klass_addr); |
2002 | 3481 else __ cmpptr(tmp, dst_klass_addr); |
0 | 3482 __ jcc(Assembler::notEqual, halt); |
12226
7944aba7ba41
8015107: NPG: Use consistent naming for metaspace concepts
ehelin
parents:
12160
diff
changeset
|
3483 if (UseCompressedClassPointers) __ cmpl(tmp, src_klass_addr); |
2002 | 3484 else __ cmpptr(tmp, src_klass_addr); |
0 | 3485 __ jcc(Assembler::equal, known_ok); |
3486 } else { | |
12226
7944aba7ba41
8015107: NPG: Use consistent naming for metaspace concepts
ehelin
parents:
12160
diff
changeset
|
3487 if (UseCompressedClassPointers) __ cmpl(tmp, dst_klass_addr); |
2002 | 3488 else __ cmpptr(tmp, dst_klass_addr); |
0 | 3489 __ jcc(Assembler::equal, known_ok); |
304 | 3490 __ cmpptr(src, dst); |
0 | 3491 __ jcc(Assembler::equal, known_ok); |
3492 } | |
3493 __ bind(halt); | |
3494 __ stop("incorrect type information in arraycopy"); | |
3495 __ bind(known_ok); | |
3496 } | |
3497 #endif | |
3498 | |
2446 | 3499 #ifndef PRODUCT |
3500 if (PrintC1Statistics) { | |
3501 __ incrementl(ExternalAddress(Runtime1::arraycopy_count_address(basic_type))); | |
304 | 3502 } |
2446 | 3503 #endif |
304 | 3504 |
3505 #ifdef _LP64 | |
3506 assert_different_registers(c_rarg0, dst, dst_pos, length); | |
3507 __ lea(c_rarg0, Address(src, src_pos, scale, arrayOopDesc::base_offset_in_bytes(basic_type))); | |
3508 assert_different_registers(c_rarg1, length); | |
3509 __ lea(c_rarg1, Address(dst, dst_pos, scale, arrayOopDesc::base_offset_in_bytes(basic_type))); | |
3510 __ mov(c_rarg2, length); | |
3511 | |
3512 #else | |
3513 __ lea(tmp, Address(src, src_pos, scale, arrayOopDesc::base_offset_in_bytes(basic_type))); | |
0 | 3514 store_parameter(tmp, 0); |
304 | 3515 __ lea(tmp, Address(dst, dst_pos, scale, arrayOopDesc::base_offset_in_bytes(basic_type))); |
0 | 3516 store_parameter(tmp, 1); |
3517 store_parameter(length, 2); | |
304 | 3518 #endif // _LP64 |
2446 | 3519 |
3520 bool disjoint = (flags & LIR_OpArrayCopy::overlapping) == 0; | |
3521 bool aligned = (flags & LIR_OpArrayCopy::unaligned) == 0; | |
3522 const char *name; | |
3523 address entry = StubRoutines::select_arraycopy_function(basic_type, aligned, disjoint, name, false); | |
3524 __ call_VM_leaf(entry, 0); | |
0 | 3525 |
3526 __ bind(*stub->continuation()); | |
3527 } | |
3528 | |
11080
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
8860
diff
changeset
|
3529 void LIR_Assembler::emit_updatecrc32(LIR_OpUpdateCRC32* op) { |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
8860
diff
changeset
|
3530 assert(op->crc()->is_single_cpu(), "crc must be register"); |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
8860
diff
changeset
|
3531 assert(op->val()->is_single_cpu(), "byte value must be register"); |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
8860
diff
changeset
|
3532 assert(op->result_opr()->is_single_cpu(), "result must be register"); |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
8860
diff
changeset
|
3533 Register crc = op->crc()->as_register(); |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
8860
diff
changeset
|
3534 Register val = op->val()->as_register(); |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
8860
diff
changeset
|
3535 Register res = op->result_opr()->as_register(); |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
8860
diff
changeset
|
3536 |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
8860
diff
changeset
|
3537 assert_different_registers(val, crc, res); |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
8860
diff
changeset
|
3538 |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
8860
diff
changeset
|
3539 __ lea(res, ExternalAddress(StubRoutines::crc_table_addr())); |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
8860
diff
changeset
|
3540 __ notl(crc); // ~crc |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
8860
diff
changeset
|
3541 __ update_byte_crc32(crc, val, res); |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
8860
diff
changeset
|
3542 __ notl(crc); // ~crc |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
8860
diff
changeset
|
3543 __ mov(res, crc); |
b800986664f4
7088419: Use x86 Hardware CRC32 Instruction with java.util.zip.CRC32
drchase
parents:
8860
diff
changeset
|
3544 } |
0 | 3545 |
3546 void LIR_Assembler::emit_lock(LIR_OpLock* op) { | |
3547 Register obj = op->obj_opr()->as_register(); // may not be an oop | |
3548 Register hdr = op->hdr_opr()->as_register(); | |
3549 Register lock = op->lock_opr()->as_register(); | |
3550 if (!UseFastLocking) { | |
3551 __ jmp(*op->stub()->entry()); | |
3552 } else if (op->code() == lir_lock) { | |
3553 Register scratch = noreg; | |
3554 if (UseBiasedLocking) { | |
3555 scratch = op->scratch_opr()->as_register(); | |
3556 } | |
3557 assert(BasicLock::displaced_header_offset_in_bytes() == 0, "lock_reg must point to the displaced header"); | |
3558 // add debug info for NullPointerException only if one is possible | |
3559 int null_check_offset = __ lock_object(hdr, obj, lock, scratch, *op->stub()->entry()); | |
3560 if (op->info() != NULL) { | |
3561 add_debug_info_for_null_check(null_check_offset, op->info()); | |
3562 } | |
3563 // done | |
3564 } else if (op->code() == lir_unlock) { | |
3565 assert(BasicLock::displaced_header_offset_in_bytes() == 0, "lock_reg must point to the displaced header"); | |
3566 __ unlock_object(hdr, obj, lock, *op->stub()->entry()); | |
3567 } else { | |
3568 Unimplemented(); | |
3569 } | |
3570 __ bind(*op->stub()->continuation()); | |
3571 } | |
3572 | |
3573 | |
3574 void LIR_Assembler::emit_profile_call(LIR_OpProfileCall* op) { | |
3575 ciMethod* method = op->profiled_method(); | |
3576 int bci = op->profiled_bci(); | |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6145
diff
changeset
|
3577 ciMethod* callee = op->profiled_callee(); |
0 | 3578 |
3579 // Update counter for all call types | |
2007
5ddfcf4b079e
7003554: (tiered) assert(is_null_object() || handle() != NULL) failed: cannot embed null pointer
iveresov
parents:
2002
diff
changeset
|
3580 ciMethodData* md = method->method_data_or_null(); |
5ddfcf4b079e
7003554: (tiered) assert(is_null_object() || handle() != NULL) failed: cannot embed null pointer
iveresov
parents:
2002
diff
changeset
|
3581 assert(md != NULL, "Sanity"); |
0 | 3582 ciProfileData* data = md->bci_to_data(bci); |
3583 assert(data->is_CounterData(), "need CounterData for calls"); | |
3584 assert(op->mdo()->is_single_cpu(), "mdo must be allocated"); | |
3585 Register mdo = op->mdo()->as_register(); | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
3586 __ mov_metadata(mdo, md->constant_encoding()); |
0 | 3587 Address counter_addr(mdo, md->byte_offset_of_slot(data, CounterData::count_offset())); |
3588 Bytecodes::Code bc = method->java_code_at_bci(bci); | |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6145
diff
changeset
|
3589 const bool callee_is_static = callee->is_loaded() && callee->is_static(); |
0 | 3590 // Perform additional virtual call profiling for invokevirtual and |
3591 // invokeinterface bytecodes | |
3592 if ((bc == Bytecodes::_invokevirtual || bc == Bytecodes::_invokeinterface) && | |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6145
diff
changeset
|
3593 !callee_is_static && // required for optimized MH invokes |
1783 | 3594 C1ProfileVirtualCalls) { |
0 | 3595 assert(op->recv()->is_single_cpu(), "recv must be allocated"); |
3596 Register recv = op->recv()->as_register(); | |
3597 assert_different_registers(mdo, recv); | |
3598 assert(data->is_VirtualCallData(), "need VirtualCallData for virtual calls"); | |
3599 ciKlass* known_klass = op->known_holder(); | |
1783 | 3600 if (C1OptimizeVirtualCallProfiling && known_klass != NULL) { |
0 | 3601 // We know the type that will be seen at this call site; we can |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
3602 // statically update the MethodData* rather than needing to do |
0 | 3603 // dynamic tests on the receiver type |
3604 | |
3605 // NOTE: we should probably put a lock around this search to | |
3606 // avoid collisions by concurrent compilations | |
3607 ciVirtualCallData* vc_data = (ciVirtualCallData*) data; | |
3608 uint i; | |
3609 for (i = 0; i < VirtualCallData::row_limit(); i++) { | |
3610 ciKlass* receiver = vc_data->receiver(i); | |
3611 if (known_klass->equals(receiver)) { | |
3612 Address data_addr(mdo, md->byte_offset_of_slot(data, VirtualCallData::receiver_count_offset(i))); | |
1783 | 3613 __ addptr(data_addr, DataLayout::counter_increment); |
0 | 3614 return; |
3615 } | |
3616 } | |
3617 | |
3618 // Receiver type not found in profile data; select an empty slot | |
3619 | |
3620 // Note that this is less efficient than it should be because it | |
3621 // always does a write to the receiver part of the | |
3622 // VirtualCallData rather than just the first time | |
3623 for (i = 0; i < VirtualCallData::row_limit(); i++) { | |
3624 ciKlass* receiver = vc_data->receiver(i); | |
3625 if (receiver == NULL) { | |
3626 Address recv_addr(mdo, md->byte_offset_of_slot(data, VirtualCallData::receiver_offset(i))); | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
3627 __ mov_metadata(recv_addr, known_klass->constant_encoding()); |
0 | 3628 Address data_addr(mdo, md->byte_offset_of_slot(data, VirtualCallData::receiver_count_offset(i))); |
1783 | 3629 __ addptr(data_addr, DataLayout::counter_increment); |
0 | 3630 return; |
3631 } | |
3632 } | |
3633 } else { | |
2002 | 3634 __ load_klass(recv, recv); |
0 | 3635 Label update_done; |
1783 | 3636 type_profile_helper(mdo, md, data, recv, &update_done); |
1206
87684f1a88b5
6614597: Performance variability in jvm2008 xml.validation
kvn
parents:
1204
diff
changeset
|
3637 // 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
|
3638 // Increment total counter to indicate polymorphic case. |
1783 | 3639 __ addptr(counter_addr, DataLayout::counter_increment); |
0 | 3640 |
3641 __ bind(update_done); | |
3642 } | |
1206
87684f1a88b5
6614597: Performance variability in jvm2008 xml.validation
kvn
parents:
1204
diff
changeset
|
3643 } else { |
87684f1a88b5
6614597: Performance variability in jvm2008 xml.validation
kvn
parents:
1204
diff
changeset
|
3644 // Static call |
1783 | 3645 __ addptr(counter_addr, DataLayout::counter_increment); |
0 | 3646 } |
3647 } | |
3648 | |
12875
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3649 void LIR_Assembler::emit_profile_type(LIR_OpProfileType* op) { |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3650 Register obj = op->obj()->as_register(); |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3651 Register tmp = op->tmp()->as_pointer_register(); |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3652 Address mdo_addr = as_Address(op->mdp()->as_address_ptr()); |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3653 ciKlass* exact_klass = op->exact_klass(); |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3654 intptr_t current_klass = op->current_klass(); |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3655 bool not_null = op->not_null(); |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3656 bool no_conflict = op->no_conflict(); |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3657 |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3658 Label update, next, none; |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3659 |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3660 bool do_null = !not_null; |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3661 bool exact_klass_set = exact_klass != NULL && ciTypeEntries::valid_ciklass(current_klass) == exact_klass; |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3662 bool do_update = !TypeEntries::is_type_unknown(current_klass) && !exact_klass_set; |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3663 |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3664 assert(do_null || do_update, "why are we here?"); |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3665 assert(!TypeEntries::was_null_seen(current_klass) || do_update, "why are we here?"); |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3666 |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3667 __ verify_oop(obj); |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3668 |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3669 if (tmp != obj) { |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3670 __ mov(tmp, obj); |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3671 } |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3672 if (do_null) { |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3673 __ testptr(tmp, tmp); |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3674 __ jccb(Assembler::notZero, update); |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3675 if (!TypeEntries::was_null_seen(current_klass)) { |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3676 __ orptr(mdo_addr, TypeEntries::null_seen); |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3677 } |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3678 if (do_update) { |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3679 #ifndef ASSERT |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3680 __ jmpb(next); |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3681 } |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3682 #else |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3683 __ jmp(next); |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3684 } |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3685 } else { |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3686 __ testptr(tmp, tmp); |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3687 __ jccb(Assembler::notZero, update); |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3688 __ stop("unexpect null obj"); |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3689 #endif |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3690 } |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3691 |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3692 __ bind(update); |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3693 |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3694 if (do_update) { |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3695 #ifdef ASSERT |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3696 if (exact_klass != NULL) { |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3697 Label ok; |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3698 __ load_klass(tmp, tmp); |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3699 __ push(tmp); |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3700 __ mov_metadata(tmp, exact_klass->constant_encoding()); |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3701 __ cmpptr(tmp, Address(rsp, 0)); |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3702 __ jccb(Assembler::equal, ok); |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3703 __ stop("exact klass and actual klass differ"); |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3704 __ bind(ok); |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3705 __ pop(tmp); |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3706 } |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3707 #endif |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3708 if (!no_conflict) { |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3709 if (exact_klass == NULL || TypeEntries::is_type_none(current_klass)) { |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3710 if (exact_klass != NULL) { |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3711 __ mov_metadata(tmp, exact_klass->constant_encoding()); |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3712 } else { |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3713 __ load_klass(tmp, tmp); |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3714 } |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3715 |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3716 __ xorptr(tmp, mdo_addr); |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3717 __ testptr(tmp, TypeEntries::type_klass_mask); |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3718 // klass seen before, nothing to do. The unknown bit may have been |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3719 // set already but no need to check. |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3720 __ jccb(Assembler::zero, next); |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3721 |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3722 __ testptr(tmp, TypeEntries::type_unknown); |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3723 __ jccb(Assembler::notZero, next); // already unknown. Nothing to do anymore. |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3724 |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3725 if (TypeEntries::is_type_none(current_klass)) { |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3726 __ cmpptr(mdo_addr, 0); |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3727 __ jccb(Assembler::equal, none); |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3728 __ cmpptr(mdo_addr, TypeEntries::null_seen); |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3729 __ jccb(Assembler::equal, none); |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3730 // There is a chance that the checks above (re-reading profiling |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3731 // data from memory) fail if another thread has just set the |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3732 // profiling to this obj's klass |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3733 __ xorptr(tmp, mdo_addr); |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3734 __ testptr(tmp, TypeEntries::type_klass_mask); |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3735 __ jccb(Assembler::zero, next); |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3736 } |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3737 } else { |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3738 assert(ciTypeEntries::valid_ciklass(current_klass) != NULL && |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3739 ciTypeEntries::valid_ciklass(current_klass) != exact_klass, "conflict only"); |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3740 |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3741 __ movptr(tmp, mdo_addr); |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3742 __ testptr(tmp, TypeEntries::type_unknown); |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3743 __ jccb(Assembler::notZero, next); // already unknown. Nothing to do anymore. |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3744 } |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3745 |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3746 // different than before. Cannot keep accurate profile. |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3747 __ orptr(mdo_addr, TypeEntries::type_unknown); |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3748 |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3749 if (TypeEntries::is_type_none(current_klass)) { |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3750 __ jmpb(next); |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3751 |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3752 __ bind(none); |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3753 // first time here. Set profile type. |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3754 __ movptr(mdo_addr, tmp); |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3755 } |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3756 } else { |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3757 // There's a single possible klass at this profile point |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3758 assert(exact_klass != NULL, "should be"); |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3759 if (TypeEntries::is_type_none(current_klass)) { |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3760 __ mov_metadata(tmp, exact_klass->constant_encoding()); |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3761 __ xorptr(tmp, mdo_addr); |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3762 __ testptr(tmp, TypeEntries::type_klass_mask); |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3763 #ifdef ASSERT |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3764 __ jcc(Assembler::zero, next); |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3765 |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3766 { |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3767 Label ok; |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3768 __ push(tmp); |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3769 __ cmpptr(mdo_addr, 0); |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3770 __ jcc(Assembler::equal, ok); |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3771 __ cmpptr(mdo_addr, TypeEntries::null_seen); |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3772 __ jcc(Assembler::equal, ok); |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3773 // may have been set by another thread |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3774 __ mov_metadata(tmp, exact_klass->constant_encoding()); |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3775 __ xorptr(tmp, mdo_addr); |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3776 __ testptr(tmp, TypeEntries::type_mask); |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3777 __ jcc(Assembler::zero, ok); |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3778 |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3779 __ stop("unexpected profiling mismatch"); |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3780 __ bind(ok); |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3781 __ pop(tmp); |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3782 } |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3783 #else |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3784 __ jccb(Assembler::zero, next); |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3785 #endif |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3786 // first time here. Set profile type. |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3787 __ movptr(mdo_addr, tmp); |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3788 } else { |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3789 assert(ciTypeEntries::valid_ciklass(current_klass) != NULL && |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3790 ciTypeEntries::valid_ciklass(current_klass) != exact_klass, "inconsistent"); |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3791 |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3792 __ movptr(tmp, mdo_addr); |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3793 __ testptr(tmp, TypeEntries::type_unknown); |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3794 __ jccb(Assembler::notZero, next); // already unknown. Nothing to do anymore. |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3795 |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3796 __ orptr(mdo_addr, TypeEntries::type_unknown); |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3797 } |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3798 } |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3799 |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3800 __ bind(next); |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3801 } |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3802 } |
d13d7aba8c12
8023657: New type profiling points: arguments to call
roland
parents:
12269
diff
changeset
|
3803 |
0 | 3804 void LIR_Assembler::emit_delay(LIR_OpDelay*) { |
3805 Unimplemented(); | |
3806 } | |
3807 | |
3808 | |
3809 void LIR_Assembler::monitor_address(int monitor_no, LIR_Opr dst) { | |
304 | 3810 __ lea(dst->as_register(), frame_map()->address_for_monitor_lock(monitor_no)); |
0 | 3811 } |
3812 | |
3813 | |
3814 void LIR_Assembler::align_backward_branch_target() { | |
3815 __ align(BytesPerWord); | |
3816 } | |
3817 | |
3818 | |
3819 void LIR_Assembler::negate(LIR_Opr left, LIR_Opr dest) { | |
3820 if (left->is_single_cpu()) { | |
3821 __ negl(left->as_register()); | |
3822 move_regs(left->as_register(), dest->as_register()); | |
3823 | |
3824 } else if (left->is_double_cpu()) { | |
3825 Register lo = left->as_register_lo(); | |
304 | 3826 #ifdef _LP64 |
3827 Register dst = dest->as_register_lo(); | |
3828 __ movptr(dst, lo); | |
3829 __ negptr(dst); | |
3830 #else | |
0 | 3831 Register hi = left->as_register_hi(); |
3832 __ lneg(hi, lo); | |
3833 if (dest->as_register_lo() == hi) { | |
3834 assert(dest->as_register_hi() != lo, "destroying register"); | |
3835 move_regs(hi, dest->as_register_hi()); | |
3836 move_regs(lo, dest->as_register_lo()); | |
3837 } else { | |
3838 move_regs(lo, dest->as_register_lo()); | |
3839 move_regs(hi, dest->as_register_hi()); | |
3840 } | |
304 | 3841 #endif // _LP64 |
0 | 3842 |
3843 } else if (dest->is_single_xmm()) { | |
3844 if (left->as_xmm_float_reg() != dest->as_xmm_float_reg()) { | |
3845 __ movflt(dest->as_xmm_float_reg(), left->as_xmm_float_reg()); | |
3846 } | |
3847 __ xorps(dest->as_xmm_float_reg(), | |
3848 ExternalAddress((address)float_signflip_pool)); | |
3849 | |
3850 } else if (dest->is_double_xmm()) { | |
3851 if (left->as_xmm_double_reg() != dest->as_xmm_double_reg()) { | |
3852 __ movdbl(dest->as_xmm_double_reg(), left->as_xmm_double_reg()); | |
3853 } | |
3854 __ xorpd(dest->as_xmm_double_reg(), | |
3855 ExternalAddress((address)double_signflip_pool)); | |
3856 | |
3857 } else if (left->is_single_fpu() || left->is_double_fpu()) { | |
3858 assert(left->fpu() == 0, "arg must be on TOS"); | |
3859 assert(dest->fpu() == 0, "dest must be TOS"); | |
3860 __ fchs(); | |
3861 | |
3862 } else { | |
3863 ShouldNotReachHere(); | |
3864 } | |
3865 } | |
3866 | |
3867 | |
3868 void LIR_Assembler::leal(LIR_Opr addr, LIR_Opr dest) { | |
3869 assert(addr->is_address() && dest->is_register(), "check"); | |
304 | 3870 Register reg; |
3871 reg = dest->as_pointer_register(); | |
3872 __ lea(reg, as_Address(addr->as_address_ptr())); | |
0 | 3873 } |
3874 | |
3875 | |
3876 | |
3877 void LIR_Assembler::rt_call(LIR_Opr result, address dest, const LIR_OprList* args, LIR_Opr tmp, CodeEmitInfo* info) { | |
3878 assert(!tmp->is_valid(), "don't need temporary"); | |
3879 __ call(RuntimeAddress(dest)); | |
3880 if (info != NULL) { | |
3881 add_call_info_here(info); | |
3882 } | |
3883 } | |
3884 | |
3885 | |
3886 void LIR_Assembler::volatile_move_op(LIR_Opr src, LIR_Opr dest, BasicType type, CodeEmitInfo* info) { | |
3887 assert(type == T_LONG, "only for volatile long fields"); | |
3888 | |
3889 if (info != NULL) { | |
3890 add_debug_info_for_null_check_here(info); | |
3891 } | |
3892 | |
3893 if (src->is_double_xmm()) { | |
3894 if (dest->is_double_cpu()) { | |
304 | 3895 #ifdef _LP64 |
3896 __ movdq(dest->as_register_lo(), src->as_xmm_double_reg()); | |
3897 #else | |
3898 __ movdl(dest->as_register_lo(), src->as_xmm_double_reg()); | |
0 | 3899 __ psrlq(src->as_xmm_double_reg(), 32); |
304 | 3900 __ movdl(dest->as_register_hi(), src->as_xmm_double_reg()); |
3901 #endif // _LP64 | |
0 | 3902 } else if (dest->is_double_stack()) { |
3903 __ movdbl(frame_map()->address_for_slot(dest->double_stack_ix()), src->as_xmm_double_reg()); | |
3904 } else if (dest->is_address()) { | |
3905 __ movdbl(as_Address(dest->as_address_ptr()), src->as_xmm_double_reg()); | |
3906 } else { | |
3907 ShouldNotReachHere(); | |
3908 } | |
3909 | |
3910 } else if (dest->is_double_xmm()) { | |
3911 if (src->is_double_stack()) { | |
3912 __ movdbl(dest->as_xmm_double_reg(), frame_map()->address_for_slot(src->double_stack_ix())); | |
3913 } else if (src->is_address()) { | |
3914 __ movdbl(dest->as_xmm_double_reg(), as_Address(src->as_address_ptr())); | |
3915 } else { | |
3916 ShouldNotReachHere(); | |
3917 } | |
3918 | |
3919 } else if (src->is_double_fpu()) { | |
3920 assert(src->fpu_regnrLo() == 0, "must be TOS"); | |
3921 if (dest->is_double_stack()) { | |
3922 __ fistp_d(frame_map()->address_for_slot(dest->double_stack_ix())); | |
3923 } else if (dest->is_address()) { | |
3924 __ fistp_d(as_Address(dest->as_address_ptr())); | |
3925 } else { | |
3926 ShouldNotReachHere(); | |
3927 } | |
3928 | |
3929 } else if (dest->is_double_fpu()) { | |
3930 assert(dest->fpu_regnrLo() == 0, "must be TOS"); | |
3931 if (src->is_double_stack()) { | |
3932 __ fild_d(frame_map()->address_for_slot(src->double_stack_ix())); | |
3933 } else if (src->is_address()) { | |
3934 __ fild_d(as_Address(src->as_address_ptr())); | |
3935 } else { | |
3936 ShouldNotReachHere(); | |
3937 } | |
3938 } else { | |
3939 ShouldNotReachHere(); | |
3940 } | |
3941 } | |
3942 | |
8860 | 3943 #ifdef ASSERT |
3944 // emit run-time assertion | |
3945 void LIR_Assembler::emit_assert(LIR_OpAssert* op) { | |
3946 assert(op->code() == lir_assert, "must be"); | |
3947 | |
3948 if (op->in_opr1()->is_valid()) { | |
3949 assert(op->in_opr2()->is_valid(), "both operands must be valid"); | |
3950 comp_op(op->condition(), op->in_opr1(), op->in_opr2(), op); | |
3951 } else { | |
3952 assert(op->in_opr2()->is_illegal(), "both operands must be illegal"); | |
3953 assert(op->condition() == lir_cond_always, "no other conditions allowed"); | |
3954 } | |
3955 | |
3956 Label ok; | |
3957 if (op->condition() != lir_cond_always) { | |
3958 Assembler::Condition acond = Assembler::zero; | |
3959 switch (op->condition()) { | |
3960 case lir_cond_equal: acond = Assembler::equal; break; | |
3961 case lir_cond_notEqual: acond = Assembler::notEqual; break; | |
3962 case lir_cond_less: acond = Assembler::less; break; | |
3963 case lir_cond_lessEqual: acond = Assembler::lessEqual; break; | |
3964 case lir_cond_greaterEqual: acond = Assembler::greaterEqual;break; | |
3965 case lir_cond_greater: acond = Assembler::greater; break; | |
3966 case lir_cond_belowEqual: acond = Assembler::belowEqual; break; | |
3967 case lir_cond_aboveEqual: acond = Assembler::aboveEqual; break; | |
3968 default: ShouldNotReachHere(); | |
3969 } | |
3970 __ jcc(acond, ok); | |
3971 } | |
3972 if (op->halt()) { | |
3973 const char* str = __ code_string(op->msg()); | |
3974 __ stop(str); | |
3975 } else { | |
3976 breakpoint(); | |
3977 } | |
3978 __ bind(ok); | |
3979 } | |
3980 #endif | |
0 | 3981 |
3982 void LIR_Assembler::membar() { | |
304 | 3983 // QQQ sparc TSO uses this, |
3984 __ membar( Assembler::Membar_mask_bits(Assembler::StoreLoad)); | |
0 | 3985 } |
3986 | |
3987 void LIR_Assembler::membar_acquire() { | |
3988 // No x86 machines currently require load fences | |
3989 // __ load_fence(); | |
3990 } | |
3991 | |
3992 void LIR_Assembler::membar_release() { | |
3993 // No x86 machines currently require store fences | |
3994 // __ store_fence(); | |
3995 } | |
3996 | |
4966
701a83c86f28
7120481: storeStore barrier in constructor with final field
jiangli
parents:
4808
diff
changeset
|
3997 void LIR_Assembler::membar_loadload() { |
701a83c86f28
7120481: storeStore barrier in constructor with final field
jiangli
parents:
4808
diff
changeset
|
3998 // no-op |
701a83c86f28
7120481: storeStore barrier in constructor with final field
jiangli
parents:
4808
diff
changeset
|
3999 //__ membar(Assembler::Membar_mask_bits(Assembler::loadload)); |
701a83c86f28
7120481: storeStore barrier in constructor with final field
jiangli
parents:
4808
diff
changeset
|
4000 } |
701a83c86f28
7120481: storeStore barrier in constructor with final field
jiangli
parents:
4808
diff
changeset
|
4001 |
701a83c86f28
7120481: storeStore barrier in constructor with final field
jiangli
parents:
4808
diff
changeset
|
4002 void LIR_Assembler::membar_storestore() { |
701a83c86f28
7120481: storeStore barrier in constructor with final field
jiangli
parents:
4808
diff
changeset
|
4003 // no-op |
701a83c86f28
7120481: storeStore barrier in constructor with final field
jiangli
parents:
4808
diff
changeset
|
4004 //__ membar(Assembler::Membar_mask_bits(Assembler::storestore)); |
701a83c86f28
7120481: storeStore barrier in constructor with final field
jiangli
parents:
4808
diff
changeset
|
4005 } |
701a83c86f28
7120481: storeStore barrier in constructor with final field
jiangli
parents:
4808
diff
changeset
|
4006 |
701a83c86f28
7120481: storeStore barrier in constructor with final field
jiangli
parents:
4808
diff
changeset
|
4007 void LIR_Assembler::membar_loadstore() { |
701a83c86f28
7120481: storeStore barrier in constructor with final field
jiangli
parents:
4808
diff
changeset
|
4008 // no-op |
701a83c86f28
7120481: storeStore barrier in constructor with final field
jiangli
parents:
4808
diff
changeset
|
4009 //__ membar(Assembler::Membar_mask_bits(Assembler::loadstore)); |
701a83c86f28
7120481: storeStore barrier in constructor with final field
jiangli
parents:
4808
diff
changeset
|
4010 } |
701a83c86f28
7120481: storeStore barrier in constructor with final field
jiangli
parents:
4808
diff
changeset
|
4011 |
701a83c86f28
7120481: storeStore barrier in constructor with final field
jiangli
parents:
4808
diff
changeset
|
4012 void LIR_Assembler::membar_storeload() { |
701a83c86f28
7120481: storeStore barrier in constructor with final field
jiangli
parents:
4808
diff
changeset
|
4013 __ membar(Assembler::Membar_mask_bits(Assembler::StoreLoad)); |
701a83c86f28
7120481: storeStore barrier in constructor with final field
jiangli
parents:
4808
diff
changeset
|
4014 } |
701a83c86f28
7120481: storeStore barrier in constructor with final field
jiangli
parents:
4808
diff
changeset
|
4015 |
0 | 4016 void LIR_Assembler::get_thread(LIR_Opr result_reg) { |
4017 assert(result_reg->is_register(), "check"); | |
304 | 4018 #ifdef _LP64 |
4019 // __ get_thread(result_reg->as_register_lo()); | |
4020 __ mov(result_reg->as_register(), r15_thread); | |
4021 #else | |
0 | 4022 __ get_thread(result_reg->as_register()); |
304 | 4023 #endif // _LP64 |
0 | 4024 } |
4025 | |
4026 | |
4027 void LIR_Assembler::peephole(LIR_List*) { | |
4028 // do nothing for now | |
4029 } | |
4030 | |
6795
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6739
diff
changeset
|
4031 void LIR_Assembler::atomic_op(LIR_Code code, LIR_Opr src, LIR_Opr data, LIR_Opr dest, LIR_Opr tmp) { |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6739
diff
changeset
|
4032 assert(data == dest, "xchg/xadd uses only 2 operands"); |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6739
diff
changeset
|
4033 |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6739
diff
changeset
|
4034 if (data->type() == T_INT) { |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6739
diff
changeset
|
4035 if (code == lir_xadd) { |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6739
diff
changeset
|
4036 if (os::is_MP()) { |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6739
diff
changeset
|
4037 __ lock(); |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6739
diff
changeset
|
4038 } |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6739
diff
changeset
|
4039 __ xaddl(as_Address(src->as_address_ptr()), data->as_register()); |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6739
diff
changeset
|
4040 } else { |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6739
diff
changeset
|
4041 __ xchgl(data->as_register(), as_Address(src->as_address_ptr())); |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6739
diff
changeset
|
4042 } |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6739
diff
changeset
|
4043 } else if (data->is_oop()) { |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6739
diff
changeset
|
4044 assert (code == lir_xchg, "xadd for oops"); |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6739
diff
changeset
|
4045 Register obj = data->as_register(); |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6739
diff
changeset
|
4046 #ifdef _LP64 |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6739
diff
changeset
|
4047 if (UseCompressedOops) { |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6739
diff
changeset
|
4048 __ encode_heap_oop(obj); |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6739
diff
changeset
|
4049 __ xchgl(obj, as_Address(src->as_address_ptr())); |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6739
diff
changeset
|
4050 __ decode_heap_oop(obj); |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6739
diff
changeset
|
4051 } else { |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6739
diff
changeset
|
4052 __ xchgptr(obj, as_Address(src->as_address_ptr())); |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6739
diff
changeset
|
4053 } |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6739
diff
changeset
|
4054 #else |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6739
diff
changeset
|
4055 __ xchgl(obj, as_Address(src->as_address_ptr())); |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6739
diff
changeset
|
4056 #endif |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6739
diff
changeset
|
4057 } else if (data->type() == T_LONG) { |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6739
diff
changeset
|
4058 #ifdef _LP64 |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6739
diff
changeset
|
4059 assert(data->as_register_lo() == data->as_register_hi(), "should be a single register"); |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6739
diff
changeset
|
4060 if (code == lir_xadd) { |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6739
diff
changeset
|
4061 if (os::is_MP()) { |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6739
diff
changeset
|
4062 __ lock(); |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6739
diff
changeset
|
4063 } |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6739
diff
changeset
|
4064 __ xaddq(as_Address(src->as_address_ptr()), data->as_register_lo()); |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6739
diff
changeset
|
4065 } else { |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6739
diff
changeset
|
4066 __ xchgq(data->as_register_lo(), as_Address(src->as_address_ptr())); |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6739
diff
changeset
|
4067 } |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6739
diff
changeset
|
4068 #else |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6739
diff
changeset
|
4069 ShouldNotReachHere(); |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6739
diff
changeset
|
4070 #endif |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6739
diff
changeset
|
4071 } else { |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6739
diff
changeset
|
4072 ShouldNotReachHere(); |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6739
diff
changeset
|
4073 } |
7eca5de9e0b6
7023898: Intrinsify AtomicLongFieldUpdater.getAndIncrement()
roland
parents:
6739
diff
changeset
|
4074 } |
0 | 4075 |
4076 #undef __ |