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