Mercurial > hg > truffle
annotate src/cpu/x86/vm/c1_LIRAssembler_x86.cpp @ 2007:5ddfcf4b079e
7003554: (tiered) assert(is_null_object() || handle() != NULL) failed: cannot embed null pointer
Summary: C1 with profiling doesn't check whether the MDO has been really allocated, which can silently fail if the perm gen is full. The solution is to check if the allocation failed and bailout out of inlining or compilation.
Reviewed-by: kvn, never
author | iveresov |
---|---|
date | Thu, 02 Dec 2010 17:21:12 -0800 |
parents | ac637b7220d1 |
children | ec8c74742417 |
rev | line source |
---|---|
0 | 1 /* |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1491
diff
changeset
|
2 * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. |
0 | 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * | |
5 * This code is free software; you can redistribute it and/or modify it | |
6 * under the terms of the GNU General Public License version 2 only, as | |
7 * published by the Free Software Foundation. | |
8 * | |
9 * This code is distributed in the hope that it will be useful, but WITHOUT | |
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
12 * version 2 for more details (a copy is included in the LICENSE file that | |
13 * accompanied this code). | |
14 * | |
15 * You should have received a copy of the GNU General Public License version | |
16 * 2 along with this work; if not, write to the Free Software Foundation, | |
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
18 * | |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
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" |
26 #include "c1/c1_Compilation.hpp" | |
27 #include "c1/c1_LIRAssembler.hpp" | |
28 #include "c1/c1_MacroAssembler.hpp" | |
29 #include "c1/c1_Runtime1.hpp" | |
30 #include "c1/c1_ValueStack.hpp" | |
31 #include "ci/ciArrayKlass.hpp" | |
32 #include "ci/ciInstance.hpp" | |
33 #include "gc_interface/collectedHeap.hpp" | |
34 #include "memory/barrierSet.hpp" | |
35 #include "memory/cardTableModRefBS.hpp" | |
36 #include "nativeInst_x86.hpp" | |
37 #include "oops/objArrayKlass.hpp" | |
38 #include "runtime/sharedRuntime.hpp" | |
0 | 39 |
40 | |
41 // These masks are used to provide 128-bit aligned bitmasks to the XMM | |
42 // instructions, to allow sign-masking or sign-bit flipping. They allow | |
43 // fast versions of NegF/NegD and AbsF/AbsD. | |
44 | |
45 // Note: 'double' and 'long long' have 32-bits alignment on x86. | |
46 static jlong* double_quadword(jlong *adr, jlong lo, jlong hi) { | |
47 // Use the expression (adr)&(~0xF) to provide 128-bits aligned address | |
48 // of 128-bits operands for SSE instructions. | |
49 jlong *operand = (jlong*)(((long)adr)&((long)(~0xF))); | |
50 // Store the value to a 128-bits operand. | |
51 operand[0] = lo; | |
52 operand[1] = hi; | |
53 return operand; | |
54 } | |
55 | |
56 // Buffer for 128-bits masks used by SSE instructions. | |
57 static jlong fp_signmask_pool[(4+1)*2]; // 4*128bits(data) + 128bits(alignment) | |
58 | |
59 // Static initialization during VM startup. | |
60 static jlong *float_signmask_pool = double_quadword(&fp_signmask_pool[1*2], CONST64(0x7FFFFFFF7FFFFFFF), CONST64(0x7FFFFFFF7FFFFFFF)); | |
61 static jlong *double_signmask_pool = double_quadword(&fp_signmask_pool[2*2], CONST64(0x7FFFFFFFFFFFFFFF), CONST64(0x7FFFFFFFFFFFFFFF)); | |
62 static jlong *float_signflip_pool = double_quadword(&fp_signmask_pool[3*2], CONST64(0x8000000080000000), CONST64(0x8000000080000000)); | |
63 static jlong *double_signflip_pool = double_quadword(&fp_signmask_pool[4*2], CONST64(0x8000000000000000), CONST64(0x8000000000000000)); | |
64 | |
65 | |
66 | |
67 NEEDS_CLEANUP // remove this definitions ? | |
68 const Register IC_Klass = rax; // where the IC klass is cached | |
69 const Register SYNC_header = rax; // synchronization header | |
70 const Register SHIFT_count = rcx; // where count for shift operations must be | |
71 | |
72 #define __ _masm-> | |
73 | |
74 | |
75 static void select_different_registers(Register preserve, | |
76 Register extra, | |
77 Register &tmp1, | |
78 Register &tmp2) { | |
79 if (tmp1 == preserve) { | |
80 assert_different_registers(tmp1, tmp2, extra); | |
81 tmp1 = extra; | |
82 } else if (tmp2 == preserve) { | |
83 assert_different_registers(tmp1, tmp2, extra); | |
84 tmp2 = extra; | |
85 } | |
86 assert_different_registers(preserve, tmp1, tmp2); | |
87 } | |
88 | |
89 | |
90 | |
91 static void select_different_registers(Register preserve, | |
92 Register extra, | |
93 Register &tmp1, | |
94 Register &tmp2, | |
95 Register &tmp3) { | |
96 if (tmp1 == preserve) { | |
97 assert_different_registers(tmp1, tmp2, tmp3, extra); | |
98 tmp1 = extra; | |
99 } else if (tmp2 == preserve) { | |
100 assert_different_registers(tmp1, tmp2, tmp3, extra); | |
101 tmp2 = extra; | |
102 } else if (tmp3 == preserve) { | |
103 assert_different_registers(tmp1, tmp2, tmp3, extra); | |
104 tmp3 = extra; | |
105 } | |
106 assert_different_registers(preserve, tmp1, tmp2, tmp3); | |
107 } | |
108 | |
109 | |
110 | |
111 bool LIR_Assembler::is_small_constant(LIR_Opr opr) { | |
112 if (opr->is_constant()) { | |
113 LIR_Const* constant = opr->as_constant_ptr(); | |
114 switch (constant->type()) { | |
115 case T_INT: { | |
116 return true; | |
117 } | |
118 | |
119 default: | |
120 return false; | |
121 } | |
122 } | |
123 return false; | |
124 } | |
125 | |
126 | |
127 LIR_Opr LIR_Assembler::receiverOpr() { | |
304 | 128 return FrameMap::receiver_opr; |
0 | 129 } |
130 | |
131 LIR_Opr LIR_Assembler::incomingReceiverOpr() { | |
132 return receiverOpr(); | |
133 } | |
134 | |
135 LIR_Opr LIR_Assembler::osrBufferPointer() { | |
304 | 136 return FrameMap::as_pointer_opr(receiverOpr()->as_register()); |
0 | 137 } |
138 | |
139 //--------------fpu register translations----------------------- | |
140 | |
141 | |
142 address LIR_Assembler::float_constant(float f) { | |
143 address const_addr = __ float_constant(f); | |
144 if (const_addr == NULL) { | |
145 bailout("const section overflow"); | |
146 return __ code()->consts()->start(); | |
147 } else { | |
148 return const_addr; | |
149 } | |
150 } | |
151 | |
152 | |
153 address LIR_Assembler::double_constant(double d) { | |
154 address const_addr = __ double_constant(d); | |
155 if (const_addr == NULL) { | |
156 bailout("const section overflow"); | |
157 return __ code()->consts()->start(); | |
158 } else { | |
159 return const_addr; | |
160 } | |
161 } | |
162 | |
163 | |
164 void LIR_Assembler::set_24bit_FPU() { | |
165 __ fldcw(ExternalAddress(StubRoutines::addr_fpu_cntrl_wrd_24())); | |
166 } | |
167 | |
168 void LIR_Assembler::reset_FPU() { | |
169 __ fldcw(ExternalAddress(StubRoutines::addr_fpu_cntrl_wrd_std())); | |
170 } | |
171 | |
172 void LIR_Assembler::fpop() { | |
173 __ fpop(); | |
174 } | |
175 | |
176 void LIR_Assembler::fxch(int i) { | |
177 __ fxch(i); | |
178 } | |
179 | |
180 void LIR_Assembler::fld(int i) { | |
181 __ fld_s(i); | |
182 } | |
183 | |
184 void LIR_Assembler::ffree(int i) { | |
185 __ ffree(i); | |
186 } | |
187 | |
188 void LIR_Assembler::breakpoint() { | |
189 __ int3(); | |
190 } | |
191 | |
192 void LIR_Assembler::push(LIR_Opr opr) { | |
193 if (opr->is_single_cpu()) { | |
194 __ push_reg(opr->as_register()); | |
195 } else if (opr->is_double_cpu()) { | |
304 | 196 NOT_LP64(__ push_reg(opr->as_register_hi())); |
0 | 197 __ push_reg(opr->as_register_lo()); |
198 } else if (opr->is_stack()) { | |
199 __ push_addr(frame_map()->address_for_slot(opr->single_stack_ix())); | |
200 } else if (opr->is_constant()) { | |
201 LIR_Const* const_opr = opr->as_constant_ptr(); | |
202 if (const_opr->type() == T_OBJECT) { | |
203 __ push_oop(const_opr->as_jobject()); | |
204 } else if (const_opr->type() == T_INT) { | |
205 __ push_jint(const_opr->as_jint()); | |
206 } else { | |
207 ShouldNotReachHere(); | |
208 } | |
209 | |
210 } else { | |
211 ShouldNotReachHere(); | |
212 } | |
213 } | |
214 | |
215 void LIR_Assembler::pop(LIR_Opr opr) { | |
216 if (opr->is_single_cpu()) { | |
304 | 217 __ pop_reg(opr->as_register()); |
0 | 218 } else { |
219 ShouldNotReachHere(); | |
220 } | |
221 } | |
222 | |
304 | 223 bool LIR_Assembler::is_literal_address(LIR_Address* addr) { |
224 return addr->base()->is_illegal() && addr->index()->is_illegal(); | |
225 } | |
226 | |
0 | 227 //------------------------------------------- |
304 | 228 |
0 | 229 Address LIR_Assembler::as_Address(LIR_Address* addr) { |
304 | 230 return as_Address(addr, rscratch1); |
231 } | |
232 | |
233 Address LIR_Assembler::as_Address(LIR_Address* addr, Register tmp) { | |
0 | 234 if (addr->base()->is_illegal()) { |
235 assert(addr->index()->is_illegal(), "must be illegal too"); | |
304 | 236 AddressLiteral laddr((address)addr->disp(), relocInfo::none); |
237 if (! __ reachable(laddr)) { | |
238 __ movptr(tmp, laddr.addr()); | |
239 Address res(tmp, 0); | |
240 return res; | |
241 } else { | |
242 return __ as_Address(laddr); | |
243 } | |
0 | 244 } |
245 | |
304 | 246 Register base = addr->base()->as_pointer_register(); |
0 | 247 |
248 if (addr->index()->is_illegal()) { | |
249 return Address( base, addr->disp()); | |
304 | 250 } else if (addr->index()->is_cpu_register()) { |
251 Register index = addr->index()->as_pointer_register(); | |
0 | 252 return Address(base, index, (Address::ScaleFactor) addr->scale(), addr->disp()); |
253 } else if (addr->index()->is_constant()) { | |
304 | 254 intptr_t addr_offset = (addr->index()->as_constant_ptr()->as_jint() << addr->scale()) + addr->disp(); |
255 assert(Assembler::is_simm32(addr_offset), "must be"); | |
0 | 256 |
257 return Address(base, addr_offset); | |
258 } else { | |
259 Unimplemented(); | |
260 return Address(); | |
261 } | |
262 } | |
263 | |
264 | |
265 Address LIR_Assembler::as_Address_hi(LIR_Address* addr) { | |
266 Address base = as_Address(addr); | |
267 return Address(base._base, base._index, base._scale, base._disp + BytesPerWord); | |
268 } | |
269 | |
270 | |
271 Address LIR_Assembler::as_Address_lo(LIR_Address* addr) { | |
272 return as_Address(addr); | |
273 } | |
274 | |
275 | |
276 void LIR_Assembler::osr_entry() { | |
277 offsets()->set_value(CodeOffsets::OSR_Entry, code_offset()); | |
278 BlockBegin* osr_entry = compilation()->hir()->osr_entry(); | |
279 ValueStack* entry_state = osr_entry->state(); | |
280 int number_of_locks = entry_state->locks_size(); | |
281 | |
282 // we jump here if osr happens with the interpreter | |
283 // state set up to continue at the beginning of the | |
284 // loop that triggered osr - in particular, we have | |
285 // the following registers setup: | |
286 // | |
287 // rcx: osr buffer | |
288 // | |
289 | |
290 // build frame | |
291 ciMethod* m = compilation()->method(); | |
292 __ build_frame(initial_frame_size_in_bytes()); | |
293 | |
294 // OSR buffer is | |
295 // | |
296 // locals[nlocals-1..0] | |
297 // monitors[0..number_of_locks] | |
298 // | |
299 // locals is a direct copy of the interpreter frame so in the osr buffer | |
300 // so first slot in the local array is the last local from the interpreter | |
301 // and last slot is local[0] (receiver) from the interpreter | |
302 // | |
303 // Similarly with locks. The first lock slot in the osr buffer is the nth lock | |
304 // from the interpreter frame, the nth lock slot in the osr buffer is 0th lock | |
305 // in the interpreter frame (the method lock if a sync method) | |
306 | |
307 // Initialize monitors in the compiled activation. | |
308 // rcx: pointer to osr buffer | |
309 // | |
310 // All other registers are dead at this point and the locals will be | |
311 // copied into place by code emitted in the IR. | |
312 | |
304 | 313 Register OSR_buf = osrBufferPointer()->as_pointer_register(); |
0 | 314 { assert(frame::interpreter_frame_monitor_size() == BasicObjectLock::size(), "adjust code below"); |
315 int monitor_offset = BytesPerWord * method()->max_locals() + | |
1060 | 316 (2 * BytesPerWord) * (number_of_locks - 1); |
317 // SharedRuntime::OSR_migration_begin() packs BasicObjectLocks in | |
318 // the OSR buffer using 2 word entries: first the lock and then | |
319 // the oop. | |
0 | 320 for (int i = 0; i < number_of_locks; i++) { |
1060 | 321 int slot_offset = monitor_offset - ((i * 2) * BytesPerWord); |
0 | 322 #ifdef ASSERT |
323 // verify the interpreter's monitor has a non-null object | |
324 { | |
325 Label L; | |
1060 | 326 __ cmpptr(Address(OSR_buf, slot_offset + 1*BytesPerWord), (int32_t)NULL_WORD); |
0 | 327 __ jcc(Assembler::notZero, L); |
328 __ stop("locked object is NULL"); | |
329 __ bind(L); | |
330 } | |
331 #endif | |
1060 | 332 __ movptr(rbx, Address(OSR_buf, slot_offset + 0)); |
304 | 333 __ movptr(frame_map()->address_for_monitor_lock(i), rbx); |
1060 | 334 __ movptr(rbx, Address(OSR_buf, slot_offset + 1*BytesPerWord)); |
304 | 335 __ movptr(frame_map()->address_for_monitor_object(i), rbx); |
0 | 336 } |
337 } | |
338 } | |
339 | |
340 | |
341 // inline cache check; done before the frame is built. | |
342 int LIR_Assembler::check_icache() { | |
343 Register receiver = FrameMap::receiver_opr->as_register(); | |
344 Register ic_klass = IC_Klass; | |
304 | 345 const int ic_cmp_size = LP64_ONLY(10) NOT_LP64(9); |
2002 | 346 const bool do_post_padding = VerifyOops || UseCompressedOops; |
347 if (!do_post_padding) { | |
0 | 348 // insert some nops so that the verified entry point is aligned on CodeEntryAlignment |
304 | 349 while ((__ offset() + ic_cmp_size) % CodeEntryAlignment != 0) { |
0 | 350 __ nop(); |
351 } | |
352 } | |
353 int offset = __ offset(); | |
354 __ inline_cache_check(receiver, IC_Klass); | |
2002 | 355 assert(__ offset() % CodeEntryAlignment == 0 || do_post_padding, "alignment must be correct"); |
356 if (do_post_padding) { | |
0 | 357 // force alignment after the cache check. |
358 // It's been verified to be aligned if !VerifyOops | |
359 __ align(CodeEntryAlignment); | |
360 } | |
361 return offset; | |
362 } | |
363 | |
364 | |
365 void LIR_Assembler::jobject2reg_with_patching(Register reg, CodeEmitInfo* info) { | |
366 jobject o = NULL; | |
367 PatchingStub* patch = new PatchingStub(_masm, PatchingStub::load_klass_id); | |
368 __ movoop(reg, o); | |
369 patching_epilog(patch, lir_patch_normal, reg, info); | |
370 } | |
371 | |
372 | |
373 void LIR_Assembler::monitorexit(LIR_Opr obj_opr, LIR_Opr lock_opr, Register new_hdr, int monitor_no, Register exception) { | |
374 if (exception->is_valid()) { | |
375 // preserve exception | |
376 // note: the monitor_exit runtime call is a leaf routine | |
377 // and cannot block => no GC can happen | |
378 // The slow case (MonitorAccessStub) uses the first two stack slots | |
379 // ([esp+0] and [esp+4]), therefore we store the exception at [esp+8] | |
304 | 380 __ movptr (Address(rsp, 2*wordSize), exception); |
0 | 381 } |
382 | |
383 Register obj_reg = obj_opr->as_register(); | |
384 Register lock_reg = lock_opr->as_register(); | |
385 | |
386 // setup registers (lock_reg must be rax, for lock_object) | |
387 assert(obj_reg != SYNC_header && lock_reg != SYNC_header, "rax, must be available here"); | |
388 Register hdr = lock_reg; | |
389 assert(new_hdr == SYNC_header, "wrong register"); | |
390 lock_reg = new_hdr; | |
391 // compute pointer to BasicLock | |
392 Address lock_addr = frame_map()->address_for_monitor_lock(monitor_no); | |
304 | 393 __ lea(lock_reg, lock_addr); |
0 | 394 // unlock object |
395 MonitorAccessStub* slow_case = new MonitorExitStub(lock_opr, true, monitor_no); | |
396 // _slow_case_stubs->append(slow_case); | |
397 // temporary fix: must be created after exceptionhandler, therefore as call stub | |
398 _slow_case_stubs->append(slow_case); | |
399 if (UseFastLocking) { | |
400 // try inlined fast unlocking first, revert to slow locking if it fails | |
401 // note: lock_reg points to the displaced header since the displaced header offset is 0! | |
402 assert(BasicLock::displaced_header_offset_in_bytes() == 0, "lock_reg must point to the displaced header"); | |
403 __ unlock_object(hdr, obj_reg, lock_reg, *slow_case->entry()); | |
404 } else { | |
405 // always do slow unlocking | |
406 // note: the slow unlocking code could be inlined here, however if we use | |
407 // slow unlocking, speed doesn't matter anyway and this solution is | |
408 // simpler and requires less duplicated code - additionally, the | |
409 // slow unlocking code is the same in either case which simplifies | |
410 // debugging | |
411 __ jmp(*slow_case->entry()); | |
412 } | |
413 // done | |
414 __ bind(*slow_case->continuation()); | |
415 | |
416 if (exception->is_valid()) { | |
417 // restore exception | |
304 | 418 __ movptr (exception, Address(rsp, 2 * wordSize)); |
0 | 419 } |
420 } | |
421 | |
422 // This specifies the rsp decrement needed to build the frame | |
423 int LIR_Assembler::initial_frame_size_in_bytes() { | |
424 // if rounding, must let FrameMap know! | |
304 | 425 |
426 // The frame_map records size in slots (32bit word) | |
427 | |
428 // subtract two words to account for return address and link | |
429 return (frame_map()->framesize() - (2*VMRegImpl::slots_per_word)) * VMRegImpl::stack_slot_size; | |
0 | 430 } |
431 | |
432 | |
1204 | 433 int LIR_Assembler::emit_exception_handler() { |
0 | 434 // if the last instruction is a call (typically to do a throw which |
435 // is coming at the end after block reordering) the return address | |
436 // must still point into the code area in order to avoid assertion | |
437 // failures when searching for the corresponding bci => add a nop | |
438 // (was bug 5/14/1999 - gri) | |
439 __ nop(); | |
440 | |
441 // generate code for exception handler | |
442 address handler_base = __ start_a_stub(exception_handler_size); | |
443 if (handler_base == NULL) { | |
444 // not enough space left for the handler | |
445 bailout("exception handler overflow"); | |
1204 | 446 return -1; |
0 | 447 } |
1204 | 448 |
0 | 449 int offset = code_offset(); |
450 | |
1295 | 451 // the exception oop and pc are in rax, and rdx |
0 | 452 // no other registers need to be preserved, so invalidate them |
1295 | 453 __ invalidate_registers(false, true, true, false, true, true); |
0 | 454 |
455 // check that there is really an exception | |
456 __ verify_not_null_oop(rax); | |
457 | |
1295 | 458 // search an exception handler (rax: exception oop, rdx: throwing pc) |
459 __ call(RuntimeAddress(Runtime1::entry_for(Runtime1::handle_exception_nofpu_id))); | |
460 | |
461 __ stop("should not reach here"); | |
462 | |
0 | 463 assert(code_offset() - offset <= exception_handler_size, "overflow"); |
464 __ end_a_stub(); | |
1204 | 465 |
466 return offset; | |
0 | 467 } |
468 | |
1204 | 469 |
1378
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
470 // 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
|
471 // unwind path. |
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
472 int LIR_Assembler::emit_unwind_handler() { |
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
473 #ifndef PRODUCT |
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
474 if (CommentedAssembly) { |
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
475 _masm->block_comment("Unwind handler"); |
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
476 } |
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
477 #endif |
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
478 |
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
479 int offset = code_offset(); |
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 // Fetch the exception from TLS and clear out exception related thread state |
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
482 __ get_thread(rsi); |
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
483 __ movptr(rax, Address(rsi, JavaThread::exception_oop_offset())); |
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
484 __ movptr(Address(rsi, JavaThread::exception_oop_offset()), (int32_t)NULL_WORD); |
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
485 __ movptr(Address(rsi, JavaThread::exception_pc_offset()), (int32_t)NULL_WORD); |
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
486 |
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
487 __ bind(_unwind_handler_entry); |
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
488 __ verify_not_null_oop(rax); |
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
489 if (method()->is_synchronized() || compilation()->env()->dtrace_method_probes()) { |
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
490 __ mov(rsi, rax); // Preserve the exception |
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
491 } |
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
492 |
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
493 // Preform needed unlocking |
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
494 MonitorExitStub* stub = NULL; |
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
495 if (method()->is_synchronized()) { |
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
496 monitor_address(0, FrameMap::rax_opr); |
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
497 stub = new MonitorExitStub(FrameMap::rax_opr, true, 0); |
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
498 __ unlock_object(rdi, rbx, rax, *stub->entry()); |
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
499 __ bind(*stub->continuation()); |
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
500 } |
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
501 |
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
502 if (compilation()->env()->dtrace_method_probes()) { |
1830
a3f7f95b0165
6988018: dtrace/hotspot/MethodInvocation/MethodInvocation002 crashes with client compiler
never
parents:
1791
diff
changeset
|
503 __ get_thread(rax); |
a3f7f95b0165
6988018: dtrace/hotspot/MethodInvocation/MethodInvocation002 crashes with client compiler
never
parents:
1791
diff
changeset
|
504 __ movptr(Address(rsp, 0), rax); |
a3f7f95b0165
6988018: dtrace/hotspot/MethodInvocation/MethodInvocation002 crashes with client compiler
never
parents:
1791
diff
changeset
|
505 __ movoop(Address(rsp, sizeof(void*)), method()->constant_encoding()); |
1378
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
506 __ 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
|
507 } |
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
508 |
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
509 if (method()->is_synchronized() || compilation()->env()->dtrace_method_probes()) { |
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
510 __ mov(rax, rsi); // Restore the exception |
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
511 } |
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
512 |
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
513 // remove the activation and dispatch to the unwind handler |
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
514 __ remove_frame(initial_frame_size_in_bytes()); |
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
515 __ jump(RuntimeAddress(Runtime1::entry_for(Runtime1::unwind_exception_id))); |
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
516 |
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
517 // Emit the slow path assembly |
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
518 if (stub != NULL) { |
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
519 stub->emit_code(this); |
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
520 } |
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
521 |
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
522 return offset; |
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
523 } |
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
524 |
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
525 |
1204 | 526 int LIR_Assembler::emit_deopt_handler() { |
0 | 527 // if the last instruction is a call (typically to do a throw which |
528 // is coming at the end after block reordering) the return address | |
529 // must still point into the code area in order to avoid assertion | |
530 // failures when searching for the corresponding bci => add a nop | |
531 // (was bug 5/14/1999 - gri) | |
532 __ nop(); | |
533 | |
534 // generate code for exception handler | |
535 address handler_base = __ start_a_stub(deopt_handler_size); | |
536 if (handler_base == NULL) { | |
537 // not enough space left for the handler | |
538 bailout("deopt handler overflow"); | |
1204 | 539 return -1; |
0 | 540 } |
1204 | 541 |
0 | 542 int offset = code_offset(); |
543 InternalAddress here(__ pc()); | |
1295 | 544 |
0 | 545 __ pushptr(here.addr()); |
546 __ jump(RuntimeAddress(SharedRuntime::deopt_blob()->unpack())); | |
1295 | 547 |
0 | 548 assert(code_offset() - offset <= deopt_handler_size, "overflow"); |
549 __ end_a_stub(); | |
550 | |
1204 | 551 return offset; |
0 | 552 } |
553 | |
554 | |
555 // This is the fast version of java.lang.String.compare; it has not | |
556 // OSR-entry and therefore, we generate a slow version for OSR's | |
557 void LIR_Assembler::emit_string_compare(LIR_Opr arg0, LIR_Opr arg1, LIR_Opr dst, CodeEmitInfo* info) { | |
304 | 558 __ movptr (rbx, rcx); // receiver is in rcx |
559 __ movptr (rax, arg1->as_register()); | |
0 | 560 |
561 // Get addresses of first characters from both Strings | |
2002 | 562 __ load_heap_oop(rsi, Address(rax, java_lang_String::value_offset_in_bytes())); |
563 __ movptr (rcx, Address(rax, java_lang_String::offset_offset_in_bytes())); | |
564 __ lea (rsi, Address(rsi, rcx, Address::times_2, arrayOopDesc::base_offset_in_bytes(T_CHAR))); | |
0 | 565 |
566 | |
567 // rbx, may be NULL | |
568 add_debug_info_for_null_check_here(info); | |
2002 | 569 __ load_heap_oop(rdi, Address(rbx, java_lang_String::value_offset_in_bytes())); |
570 __ movptr (rcx, Address(rbx, java_lang_String::offset_offset_in_bytes())); | |
571 __ lea (rdi, Address(rdi, rcx, Address::times_2, arrayOopDesc::base_offset_in_bytes(T_CHAR))); | |
0 | 572 |
573 // compute minimum length (in rax) and difference of lengths (on top of stack) | |
574 if (VM_Version::supports_cmov()) { | |
304 | 575 __ movl (rbx, Address(rbx, java_lang_String::count_offset_in_bytes())); |
576 __ movl (rax, Address(rax, java_lang_String::count_offset_in_bytes())); | |
577 __ mov (rcx, rbx); | |
578 __ subptr (rbx, rax); // subtract lengths | |
579 __ push (rbx); // result | |
580 __ cmov (Assembler::lessEqual, rax, rcx); | |
0 | 581 } else { |
582 Label L; | |
304 | 583 __ movl (rbx, Address(rbx, java_lang_String::count_offset_in_bytes())); |
584 __ movl (rcx, Address(rax, java_lang_String::count_offset_in_bytes())); | |
585 __ mov (rax, rbx); | |
586 __ subptr (rbx, rcx); | |
587 __ push (rbx); | |
588 __ jcc (Assembler::lessEqual, L); | |
589 __ mov (rax, rcx); | |
0 | 590 __ bind (L); |
591 } | |
592 // is minimum length 0? | |
593 Label noLoop, haveResult; | |
304 | 594 __ testptr (rax, rax); |
0 | 595 __ jcc (Assembler::zero, noLoop); |
596 | |
597 // compare first characters | |
622
56aae7be60d4
6812678: macro assembler needs delayed binding of a few constants (for 6655638)
jrose
parents:
512
diff
changeset
|
598 __ 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
|
599 __ load_unsigned_short(rbx, Address(rsi, 0)); |
0 | 600 __ subl(rcx, rbx); |
601 __ jcc(Assembler::notZero, haveResult); | |
602 // starting loop | |
603 __ decrement(rax); // we already tested index: skip one | |
604 __ jcc(Assembler::zero, noLoop); | |
605 | |
606 // set rsi.edi to the end of the arrays (arrays have same length) | |
607 // negate the index | |
608 | |
304 | 609 __ lea(rsi, Address(rsi, rax, Address::times_2, type2aelembytes(T_CHAR))); |
610 __ lea(rdi, Address(rdi, rax, Address::times_2, type2aelembytes(T_CHAR))); | |
611 __ negptr(rax); | |
0 | 612 |
613 // compare the strings in a loop | |
614 | |
615 Label loop; | |
616 __ align(wordSize); | |
617 __ bind(loop); | |
622
56aae7be60d4
6812678: macro assembler needs delayed binding of a few constants (for 6655638)
jrose
parents:
512
diff
changeset
|
618 __ 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
|
619 __ load_unsigned_short(rbx, Address(rsi, rax, Address::times_2, 0)); |
0 | 620 __ subl(rcx, rbx); |
621 __ jcc(Assembler::notZero, haveResult); | |
622 __ increment(rax); | |
623 __ jcc(Assembler::notZero, loop); | |
624 | |
625 // strings are equal up to min length | |
626 | |
627 __ bind(noLoop); | |
304 | 628 __ pop(rax); |
0 | 629 return_op(LIR_OprFact::illegalOpr); |
630 | |
631 __ bind(haveResult); | |
632 // leave instruction is going to discard the TOS value | |
304 | 633 __ mov (rax, rcx); // result of call is in rax, |
0 | 634 } |
635 | |
636 | |
637 void LIR_Assembler::return_op(LIR_Opr result) { | |
638 assert(result->is_illegal() || !result->is_single_cpu() || result->as_register() == rax, "word returns are in rax,"); | |
639 if (!result->is_illegal() && result->is_float_kind() && !result->is_xmm_register()) { | |
640 assert(result->fpu() == 0, "result must already be on TOS"); | |
641 } | |
642 | |
643 // Pop the stack before the safepoint code | |
1295 | 644 __ remove_frame(initial_frame_size_in_bytes()); |
0 | 645 |
646 bool result_is_oop = result->is_valid() ? result->is_oop() : false; | |
647 | |
648 // Note: we do not need to round double result; float result has the right precision | |
649 // the poll sets the condition code, but no data registers | |
650 AddressLiteral polling_page(os::get_polling_page() + (SafepointPollOffset % os::vm_page_size()), | |
651 relocInfo::poll_return_type); | |
304 | 652 |
653 // NOTE: the requires that the polling page be reachable else the reloc | |
654 // goes to the movq that loads the address and not the faulting instruction | |
655 // which breaks the signal handler code | |
656 | |
0 | 657 __ test32(rax, polling_page); |
658 | |
659 __ ret(0); | |
660 } | |
661 | |
662 | |
663 int LIR_Assembler::safepoint_poll(LIR_Opr tmp, CodeEmitInfo* info) { | |
664 AddressLiteral polling_page(os::get_polling_page() + (SafepointPollOffset % os::vm_page_size()), | |
665 relocInfo::poll_type); | |
666 | |
667 if (info != NULL) { | |
668 add_debug_info_for_branch(info); | |
669 } else { | |
670 ShouldNotReachHere(); | |
671 } | |
672 | |
673 int offset = __ offset(); | |
304 | 674 |
675 // NOTE: the requires that the polling page be reachable else the reloc | |
676 // goes to the movq that loads the address and not the faulting instruction | |
677 // which breaks the signal handler code | |
678 | |
0 | 679 __ test32(rax, polling_page); |
680 return offset; | |
681 } | |
682 | |
683 | |
684 void LIR_Assembler::move_regs(Register from_reg, Register to_reg) { | |
304 | 685 if (from_reg != to_reg) __ mov(to_reg, from_reg); |
0 | 686 } |
687 | |
688 void LIR_Assembler::swap_reg(Register a, Register b) { | |
304 | 689 __ xchgptr(a, b); |
0 | 690 } |
691 | |
692 | |
693 void LIR_Assembler::const2reg(LIR_Opr src, LIR_Opr dest, LIR_PatchCode patch_code, CodeEmitInfo* info) { | |
694 assert(src->is_constant(), "should not call otherwise"); | |
695 assert(dest->is_register(), "should not call otherwise"); | |
696 LIR_Const* c = src->as_constant_ptr(); | |
697 | |
698 switch (c->type()) { | |
2002 | 699 case T_INT: { |
700 assert(patch_code == lir_patch_none, "no patching handled here"); | |
701 __ movl(dest->as_register(), c->as_jint()); | |
702 break; | |
703 } | |
704 | |
1297
c466efa608d5
6932496: c1: deoptimization of jsr subroutine fails on sparcv9
roland
parents:
1295
diff
changeset
|
705 case T_ADDRESS: { |
0 | 706 assert(patch_code == lir_patch_none, "no patching handled here"); |
2002 | 707 __ movptr(dest->as_register(), c->as_jint()); |
0 | 708 break; |
709 } | |
710 | |
711 case T_LONG: { | |
712 assert(patch_code == lir_patch_none, "no patching handled here"); | |
304 | 713 #ifdef _LP64 |
714 __ movptr(dest->as_register_lo(), (intptr_t)c->as_jlong()); | |
715 #else | |
716 __ movptr(dest->as_register_lo(), c->as_jint_lo()); | |
717 __ movptr(dest->as_register_hi(), c->as_jint_hi()); | |
718 #endif // _LP64 | |
0 | 719 break; |
720 } | |
721 | |
722 case T_OBJECT: { | |
723 if (patch_code != lir_patch_none) { | |
724 jobject2reg_with_patching(dest->as_register(), info); | |
725 } else { | |
726 __ movoop(dest->as_register(), c->as_jobject()); | |
727 } | |
728 break; | |
729 } | |
730 | |
731 case T_FLOAT: { | |
732 if (dest->is_single_xmm()) { | |
733 if (c->is_zero_float()) { | |
734 __ xorps(dest->as_xmm_float_reg(), dest->as_xmm_float_reg()); | |
735 } else { | |
736 __ movflt(dest->as_xmm_float_reg(), | |
737 InternalAddress(float_constant(c->as_jfloat()))); | |
738 } | |
739 } else { | |
740 assert(dest->is_single_fpu(), "must be"); | |
741 assert(dest->fpu_regnr() == 0, "dest must be TOS"); | |
742 if (c->is_zero_float()) { | |
743 __ fldz(); | |
744 } else if (c->is_one_float()) { | |
745 __ fld1(); | |
746 } else { | |
747 __ fld_s (InternalAddress(float_constant(c->as_jfloat()))); | |
748 } | |
749 } | |
750 break; | |
751 } | |
752 | |
753 case T_DOUBLE: { | |
754 if (dest->is_double_xmm()) { | |
755 if (c->is_zero_double()) { | |
756 __ xorpd(dest->as_xmm_double_reg(), dest->as_xmm_double_reg()); | |
757 } else { | |
758 __ movdbl(dest->as_xmm_double_reg(), | |
759 InternalAddress(double_constant(c->as_jdouble()))); | |
760 } | |
761 } else { | |
762 assert(dest->is_double_fpu(), "must be"); | |
763 assert(dest->fpu_regnrLo() == 0, "dest must be TOS"); | |
764 if (c->is_zero_double()) { | |
765 __ fldz(); | |
766 } else if (c->is_one_double()) { | |
767 __ fld1(); | |
768 } else { | |
769 __ fld_d (InternalAddress(double_constant(c->as_jdouble()))); | |
770 } | |
771 } | |
772 break; | |
773 } | |
774 | |
775 default: | |
776 ShouldNotReachHere(); | |
777 } | |
778 } | |
779 | |
780 void LIR_Assembler::const2stack(LIR_Opr src, LIR_Opr dest) { | |
781 assert(src->is_constant(), "should not call otherwise"); | |
782 assert(dest->is_stack(), "should not call otherwise"); | |
783 LIR_Const* c = src->as_constant_ptr(); | |
784 | |
785 switch (c->type()) { | |
786 case T_INT: // fall through | |
787 case T_FLOAT: | |
2002 | 788 __ movl(frame_map()->address_for_slot(dest->single_stack_ix()), c->as_jint_bits()); |
789 break; | |
790 | |
1297
c466efa608d5
6932496: c1: deoptimization of jsr subroutine fails on sparcv9
roland
parents:
1295
diff
changeset
|
791 case T_ADDRESS: |
2002 | 792 __ movptr(frame_map()->address_for_slot(dest->single_stack_ix()), c->as_jint_bits()); |
0 | 793 break; |
794 | |
795 case T_OBJECT: | |
796 __ movoop(frame_map()->address_for_slot(dest->single_stack_ix()), c->as_jobject()); | |
797 break; | |
798 | |
799 case T_LONG: // fall through | |
800 case T_DOUBLE: | |
304 | 801 #ifdef _LP64 |
802 __ movptr(frame_map()->address_for_slot(dest->double_stack_ix(), | |
803 lo_word_offset_in_bytes), (intptr_t)c->as_jlong_bits()); | |
804 #else | |
805 __ movptr(frame_map()->address_for_slot(dest->double_stack_ix(), | |
806 lo_word_offset_in_bytes), c->as_jint_lo_bits()); | |
807 __ movptr(frame_map()->address_for_slot(dest->double_stack_ix(), | |
808 hi_word_offset_in_bytes), c->as_jint_hi_bits()); | |
809 #endif // _LP64 | |
0 | 810 break; |
811 | |
812 default: | |
813 ShouldNotReachHere(); | |
814 } | |
815 } | |
816 | |
2002 | 817 void LIR_Assembler::const2mem(LIR_Opr src, LIR_Opr dest, BasicType type, CodeEmitInfo* info, bool wide) { |
0 | 818 assert(src->is_constant(), "should not call otherwise"); |
819 assert(dest->is_address(), "should not call otherwise"); | |
820 LIR_Const* c = src->as_constant_ptr(); | |
821 LIR_Address* addr = dest->as_address_ptr(); | |
822 | |
304 | 823 int null_check_here = code_offset(); |
0 | 824 switch (type) { |
825 case T_INT: // fall through | |
826 case T_FLOAT: | |
2002 | 827 __ movl(as_Address(addr), c->as_jint_bits()); |
828 break; | |
829 | |
1297
c466efa608d5
6932496: c1: deoptimization of jsr subroutine fails on sparcv9
roland
parents:
1295
diff
changeset
|
830 case T_ADDRESS: |
2002 | 831 __ movptr(as_Address(addr), c->as_jint_bits()); |
0 | 832 break; |
833 | |
834 case T_OBJECT: // fall through | |
835 case T_ARRAY: | |
836 if (c->as_jobject() == NULL) { | |
2002 | 837 if (UseCompressedOops && !wide) { |
838 __ movl(as_Address(addr), (int32_t)NULL_WORD); | |
839 } else { | |
840 __ movptr(as_Address(addr), NULL_WORD); | |
841 } | |
0 | 842 } else { |
304 | 843 if (is_literal_address(addr)) { |
844 ShouldNotReachHere(); | |
845 __ movoop(as_Address(addr, noreg), c->as_jobject()); | |
846 } else { | |
1060 | 847 #ifdef _LP64 |
848 __ movoop(rscratch1, c->as_jobject()); | |
2002 | 849 if (UseCompressedOops && !wide) { |
850 __ encode_heap_oop(rscratch1); | |
851 null_check_here = code_offset(); | |
852 __ movl(as_Address_lo(addr), rscratch1); | |
853 } else { | |
854 null_check_here = code_offset(); | |
855 __ movptr(as_Address_lo(addr), rscratch1); | |
856 } | |
1060 | 857 #else |
304 | 858 __ movoop(as_Address(addr), c->as_jobject()); |
1060 | 859 #endif |
304 | 860 } |
0 | 861 } |
862 break; | |
863 | |
864 case T_LONG: // fall through | |
865 case T_DOUBLE: | |
304 | 866 #ifdef _LP64 |
867 if (is_literal_address(addr)) { | |
868 ShouldNotReachHere(); | |
869 __ movptr(as_Address(addr, r15_thread), (intptr_t)c->as_jlong_bits()); | |
870 } else { | |
871 __ movptr(r10, (intptr_t)c->as_jlong_bits()); | |
872 null_check_here = code_offset(); | |
873 __ movptr(as_Address_lo(addr), r10); | |
874 } | |
875 #else | |
876 // Always reachable in 32bit so this doesn't produce useless move literal | |
877 __ movptr(as_Address_hi(addr), c->as_jint_hi_bits()); | |
878 __ movptr(as_Address_lo(addr), c->as_jint_lo_bits()); | |
879 #endif // _LP64 | |
0 | 880 break; |
881 | |
882 case T_BOOLEAN: // fall through | |
883 case T_BYTE: | |
884 __ movb(as_Address(addr), c->as_jint() & 0xFF); | |
885 break; | |
886 | |
887 case T_CHAR: // fall through | |
888 case T_SHORT: | |
889 __ movw(as_Address(addr), c->as_jint() & 0xFFFF); | |
890 break; | |
891 | |
892 default: | |
893 ShouldNotReachHere(); | |
894 }; | |
304 | 895 |
896 if (info != NULL) { | |
897 add_debug_info_for_null_check(null_check_here, info); | |
898 } | |
0 | 899 } |
900 | |
901 | |
902 void LIR_Assembler::reg2reg(LIR_Opr src, LIR_Opr dest) { | |
903 assert(src->is_register(), "should not call otherwise"); | |
904 assert(dest->is_register(), "should not call otherwise"); | |
905 | |
906 // move between cpu-registers | |
907 if (dest->is_single_cpu()) { | |
304 | 908 #ifdef _LP64 |
909 if (src->type() == T_LONG) { | |
910 // Can do LONG -> OBJECT | |
911 move_regs(src->as_register_lo(), dest->as_register()); | |
912 return; | |
913 } | |
914 #endif | |
0 | 915 assert(src->is_single_cpu(), "must match"); |
916 if (src->type() == T_OBJECT) { | |
917 __ verify_oop(src->as_register()); | |
918 } | |
919 move_regs(src->as_register(), dest->as_register()); | |
920 | |
921 } else if (dest->is_double_cpu()) { | |
304 | 922 #ifdef _LP64 |
923 if (src->type() == T_OBJECT || src->type() == T_ARRAY) { | |
924 // Surprising to me but we can see move of a long to t_object | |
925 __ verify_oop(src->as_register()); | |
926 move_regs(src->as_register(), dest->as_register_lo()); | |
927 return; | |
928 } | |
929 #endif | |
0 | 930 assert(src->is_double_cpu(), "must match"); |
931 Register f_lo = src->as_register_lo(); | |
932 Register f_hi = src->as_register_hi(); | |
933 Register t_lo = dest->as_register_lo(); | |
934 Register t_hi = dest->as_register_hi(); | |
304 | 935 #ifdef _LP64 |
936 assert(f_hi == f_lo, "must be same"); | |
937 assert(t_hi == t_lo, "must be same"); | |
938 move_regs(f_lo, t_lo); | |
939 #else | |
0 | 940 assert(f_lo != f_hi && t_lo != t_hi, "invalid register allocation"); |
941 | |
304 | 942 |
0 | 943 if (f_lo == t_hi && f_hi == t_lo) { |
944 swap_reg(f_lo, f_hi); | |
945 } else if (f_hi == t_lo) { | |
946 assert(f_lo != t_hi, "overwriting register"); | |
947 move_regs(f_hi, t_hi); | |
948 move_regs(f_lo, t_lo); | |
949 } else { | |
950 assert(f_hi != t_lo, "overwriting register"); | |
951 move_regs(f_lo, t_lo); | |
952 move_regs(f_hi, t_hi); | |
953 } | |
304 | 954 #endif // LP64 |
0 | 955 |
956 // special moves from fpu-register to xmm-register | |
957 // necessary for method results | |
958 } else if (src->is_single_xmm() && !dest->is_single_xmm()) { | |
959 __ movflt(Address(rsp, 0), src->as_xmm_float_reg()); | |
960 __ fld_s(Address(rsp, 0)); | |
961 } else if (src->is_double_xmm() && !dest->is_double_xmm()) { | |
962 __ movdbl(Address(rsp, 0), src->as_xmm_double_reg()); | |
963 __ fld_d(Address(rsp, 0)); | |
964 } else if (dest->is_single_xmm() && !src->is_single_xmm()) { | |
965 __ fstp_s(Address(rsp, 0)); | |
966 __ movflt(dest->as_xmm_float_reg(), Address(rsp, 0)); | |
967 } else if (dest->is_double_xmm() && !src->is_double_xmm()) { | |
968 __ fstp_d(Address(rsp, 0)); | |
969 __ movdbl(dest->as_xmm_double_reg(), Address(rsp, 0)); | |
970 | |
971 // move between xmm-registers | |
972 } else if (dest->is_single_xmm()) { | |
973 assert(src->is_single_xmm(), "must match"); | |
974 __ movflt(dest->as_xmm_float_reg(), src->as_xmm_float_reg()); | |
975 } else if (dest->is_double_xmm()) { | |
976 assert(src->is_double_xmm(), "must match"); | |
977 __ movdbl(dest->as_xmm_double_reg(), src->as_xmm_double_reg()); | |
978 | |
979 // move between fpu-registers (no instruction necessary because of fpu-stack) | |
980 } else if (dest->is_single_fpu() || dest->is_double_fpu()) { | |
981 assert(src->is_single_fpu() || src->is_double_fpu(), "must match"); | |
982 assert(src->fpu() == dest->fpu(), "currently should be nothing to do"); | |
983 } else { | |
984 ShouldNotReachHere(); | |
985 } | |
986 } | |
987 | |
988 void LIR_Assembler::reg2stack(LIR_Opr src, LIR_Opr dest, BasicType type, bool pop_fpu_stack) { | |
989 assert(src->is_register(), "should not call otherwise"); | |
990 assert(dest->is_stack(), "should not call otherwise"); | |
991 | |
992 if (src->is_single_cpu()) { | |
993 Address dst = frame_map()->address_for_slot(dest->single_stack_ix()); | |
994 if (type == T_OBJECT || type == T_ARRAY) { | |
995 __ verify_oop(src->as_register()); | |
304 | 996 __ movptr (dst, src->as_register()); |
997 } else { | |
998 __ movl (dst, src->as_register()); | |
0 | 999 } |
1000 | |
1001 } else if (src->is_double_cpu()) { | |
1002 Address dstLO = frame_map()->address_for_slot(dest->double_stack_ix(), lo_word_offset_in_bytes); | |
1003 Address dstHI = frame_map()->address_for_slot(dest->double_stack_ix(), hi_word_offset_in_bytes); | |
304 | 1004 __ movptr (dstLO, src->as_register_lo()); |
1005 NOT_LP64(__ movptr (dstHI, src->as_register_hi())); | |
0 | 1006 |
1007 } else if (src->is_single_xmm()) { | |
1008 Address dst_addr = frame_map()->address_for_slot(dest->single_stack_ix()); | |
1009 __ movflt(dst_addr, src->as_xmm_float_reg()); | |
1010 | |
1011 } else if (src->is_double_xmm()) { | |
1012 Address dst_addr = frame_map()->address_for_slot(dest->double_stack_ix()); | |
1013 __ movdbl(dst_addr, src->as_xmm_double_reg()); | |
1014 | |
1015 } else if (src->is_single_fpu()) { | |
1016 assert(src->fpu_regnr() == 0, "argument must be on TOS"); | |
1017 Address dst_addr = frame_map()->address_for_slot(dest->single_stack_ix()); | |
1018 if (pop_fpu_stack) __ fstp_s (dst_addr); | |
1019 else __ fst_s (dst_addr); | |
1020 | |
1021 } else if (src->is_double_fpu()) { | |
1022 assert(src->fpu_regnrLo() == 0, "argument must be on TOS"); | |
1023 Address dst_addr = frame_map()->address_for_slot(dest->double_stack_ix()); | |
1024 if (pop_fpu_stack) __ fstp_d (dst_addr); | |
1025 else __ fst_d (dst_addr); | |
1026 | |
1027 } else { | |
1028 ShouldNotReachHere(); | |
1029 } | |
1030 } | |
1031 | |
1032 | |
2002 | 1033 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 | 1034 LIR_Address* to_addr = dest->as_address_ptr(); |
1035 PatchingStub* patch = NULL; | |
2002 | 1036 Register compressed_src = rscratch1; |
0 | 1037 |
1038 if (type == T_ARRAY || type == T_OBJECT) { | |
1039 __ verify_oop(src->as_register()); | |
2002 | 1040 #ifdef _LP64 |
1041 if (UseCompressedOops && !wide) { | |
1042 __ movptr(compressed_src, src->as_register()); | |
1043 __ encode_heap_oop(compressed_src); | |
1044 } | |
1045 #endif | |
0 | 1046 } |
2002 | 1047 |
0 | 1048 if (patch_code != lir_patch_none) { |
1049 patch = new PatchingStub(_masm, PatchingStub::access_field_id); | |
304 | 1050 Address toa = as_Address(to_addr); |
1051 assert(toa.disp() != 0, "must have"); | |
0 | 1052 } |
2002 | 1053 |
1054 int null_check_here = code_offset(); | |
0 | 1055 switch (type) { |
1056 case T_FLOAT: { | |
1057 if (src->is_single_xmm()) { | |
1058 __ movflt(as_Address(to_addr), src->as_xmm_float_reg()); | |
1059 } else { | |
1060 assert(src->is_single_fpu(), "must be"); | |
1061 assert(src->fpu_regnr() == 0, "argument must be on TOS"); | |
1062 if (pop_fpu_stack) __ fstp_s(as_Address(to_addr)); | |
1063 else __ fst_s (as_Address(to_addr)); | |
1064 } | |
1065 break; | |
1066 } | |
1067 | |
1068 case T_DOUBLE: { | |
1069 if (src->is_double_xmm()) { | |
1070 __ movdbl(as_Address(to_addr), src->as_xmm_double_reg()); | |
1071 } else { | |
1072 assert(src->is_double_fpu(), "must be"); | |
1073 assert(src->fpu_regnrLo() == 0, "argument must be on TOS"); | |
1074 if (pop_fpu_stack) __ fstp_d(as_Address(to_addr)); | |
1075 else __ fst_d (as_Address(to_addr)); | |
1076 } | |
1077 break; | |
1078 } | |
1079 | |
1080 case T_ARRAY: // fall through | |
1081 case T_OBJECT: // fall through | |
2002 | 1082 if (UseCompressedOops && !wide) { |
1083 __ movl(as_Address(to_addr), compressed_src); | |
1084 } else { | |
1085 __ movptr(as_Address(to_addr), src->as_register()); | |
1086 } | |
1087 break; | |
1088 case T_ADDRESS: | |
304 | 1089 __ movptr(as_Address(to_addr), src->as_register()); |
1090 break; | |
0 | 1091 case T_INT: |
1092 __ movl(as_Address(to_addr), src->as_register()); | |
1093 break; | |
1094 | |
1095 case T_LONG: { | |
1096 Register from_lo = src->as_register_lo(); | |
1097 Register from_hi = src->as_register_hi(); | |
304 | 1098 #ifdef _LP64 |
1099 __ movptr(as_Address_lo(to_addr), from_lo); | |
1100 #else | |
0 | 1101 Register base = to_addr->base()->as_register(); |
1102 Register index = noreg; | |
1103 if (to_addr->index()->is_register()) { | |
1104 index = to_addr->index()->as_register(); | |
1105 } | |
1106 if (base == from_lo || index == from_lo) { | |
1107 assert(base != from_hi, "can't be"); | |
1108 assert(index == noreg || (index != base && index != from_hi), "can't handle this"); | |
1109 __ movl(as_Address_hi(to_addr), from_hi); | |
1110 if (patch != NULL) { | |
1111 patching_epilog(patch, lir_patch_high, base, info); | |
1112 patch = new PatchingStub(_masm, PatchingStub::access_field_id); | |
1113 patch_code = lir_patch_low; | |
1114 } | |
1115 __ movl(as_Address_lo(to_addr), from_lo); | |
1116 } else { | |
1117 assert(index == noreg || (index != base && index != from_lo), "can't handle this"); | |
1118 __ movl(as_Address_lo(to_addr), from_lo); | |
1119 if (patch != NULL) { | |
1120 patching_epilog(patch, lir_patch_low, base, info); | |
1121 patch = new PatchingStub(_masm, PatchingStub::access_field_id); | |
1122 patch_code = lir_patch_high; | |
1123 } | |
1124 __ movl(as_Address_hi(to_addr), from_hi); | |
1125 } | |
304 | 1126 #endif // _LP64 |
0 | 1127 break; |
1128 } | |
1129 | |
1130 case T_BYTE: // fall through | |
1131 case T_BOOLEAN: { | |
1132 Register src_reg = src->as_register(); | |
1133 Address dst_addr = as_Address(to_addr); | |
1134 assert(VM_Version::is_P6() || src_reg->has_byte_register(), "must use byte registers if not P6"); | |
1135 __ movb(dst_addr, src_reg); | |
1136 break; | |
1137 } | |
1138 | |
1139 case T_CHAR: // fall through | |
1140 case T_SHORT: | |
1141 __ movw(as_Address(to_addr), src->as_register()); | |
1142 break; | |
1143 | |
1144 default: | |
1145 ShouldNotReachHere(); | |
1146 } | |
2002 | 1147 if (info != NULL) { |
1148 add_debug_info_for_null_check(null_check_here, info); | |
1149 } | |
0 | 1150 |
1151 if (patch_code != lir_patch_none) { | |
1152 patching_epilog(patch, patch_code, to_addr->base()->as_register(), info); | |
1153 } | |
1154 } | |
1155 | |
1156 | |
1157 void LIR_Assembler::stack2reg(LIR_Opr src, LIR_Opr dest, BasicType type) { | |
1158 assert(src->is_stack(), "should not call otherwise"); | |
1159 assert(dest->is_register(), "should not call otherwise"); | |
1160 | |
1161 if (dest->is_single_cpu()) { | |
1162 if (type == T_ARRAY || type == T_OBJECT) { | |
304 | 1163 __ movptr(dest->as_register(), frame_map()->address_for_slot(src->single_stack_ix())); |
0 | 1164 __ verify_oop(dest->as_register()); |
304 | 1165 } else { |
1166 __ movl(dest->as_register(), frame_map()->address_for_slot(src->single_stack_ix())); | |
0 | 1167 } |
1168 | |
1169 } else if (dest->is_double_cpu()) { | |
1170 Address src_addr_LO = frame_map()->address_for_slot(src->double_stack_ix(), lo_word_offset_in_bytes); | |
1171 Address src_addr_HI = frame_map()->address_for_slot(src->double_stack_ix(), hi_word_offset_in_bytes); | |
304 | 1172 __ movptr(dest->as_register_lo(), src_addr_LO); |
1173 NOT_LP64(__ movptr(dest->as_register_hi(), src_addr_HI)); | |
0 | 1174 |
1175 } else if (dest->is_single_xmm()) { | |
1176 Address src_addr = frame_map()->address_for_slot(src->single_stack_ix()); | |
1177 __ movflt(dest->as_xmm_float_reg(), src_addr); | |
1178 | |
1179 } else if (dest->is_double_xmm()) { | |
1180 Address src_addr = frame_map()->address_for_slot(src->double_stack_ix()); | |
1181 __ movdbl(dest->as_xmm_double_reg(), src_addr); | |
1182 | |
1183 } else if (dest->is_single_fpu()) { | |
1184 assert(dest->fpu_regnr() == 0, "dest must be TOS"); | |
1185 Address src_addr = frame_map()->address_for_slot(src->single_stack_ix()); | |
1186 __ fld_s(src_addr); | |
1187 | |
1188 } else if (dest->is_double_fpu()) { | |
1189 assert(dest->fpu_regnrLo() == 0, "dest must be TOS"); | |
1190 Address src_addr = frame_map()->address_for_slot(src->double_stack_ix()); | |
1191 __ fld_d(src_addr); | |
1192 | |
1193 } else { | |
1194 ShouldNotReachHere(); | |
1195 } | |
1196 } | |
1197 | |
1198 | |
1199 void LIR_Assembler::stack2stack(LIR_Opr src, LIR_Opr dest, BasicType type) { | |
1200 if (src->is_single_stack()) { | |
304 | 1201 if (type == T_OBJECT || type == T_ARRAY) { |
1202 __ pushptr(frame_map()->address_for_slot(src ->single_stack_ix())); | |
1203 __ popptr (frame_map()->address_for_slot(dest->single_stack_ix())); | |
1204 } else { | |
1060 | 1205 #ifndef _LP64 |
304 | 1206 __ pushl(frame_map()->address_for_slot(src ->single_stack_ix())); |
1207 __ popl (frame_map()->address_for_slot(dest->single_stack_ix())); | |
1060 | 1208 #else |
1209 //no pushl on 64bits | |
1210 __ movl(rscratch1, frame_map()->address_for_slot(src ->single_stack_ix())); | |
1211 __ movl(frame_map()->address_for_slot(dest->single_stack_ix()), rscratch1); | |
1212 #endif | |
304 | 1213 } |
0 | 1214 |
1215 } else if (src->is_double_stack()) { | |
304 | 1216 #ifdef _LP64 |
1217 __ pushptr(frame_map()->address_for_slot(src ->double_stack_ix())); | |
1218 __ popptr (frame_map()->address_for_slot(dest->double_stack_ix())); | |
1219 #else | |
0 | 1220 __ pushl(frame_map()->address_for_slot(src ->double_stack_ix(), 0)); |
304 | 1221 // 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
|
1222 __ 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
|
1223 __ popl (frame_map()->address_for_slot(dest->double_stack_ix(), 2 * wordSize)); |
0 | 1224 __ popl (frame_map()->address_for_slot(dest->double_stack_ix(), 0)); |
304 | 1225 #endif // _LP64 |
0 | 1226 |
1227 } else { | |
1228 ShouldNotReachHere(); | |
1229 } | |
1230 } | |
1231 | |
1232 | |
2002 | 1233 void LIR_Assembler::mem2reg(LIR_Opr src, LIR_Opr dest, BasicType type, LIR_PatchCode patch_code, CodeEmitInfo* info, bool wide, bool /* unaligned */) { |
0 | 1234 assert(src->is_address(), "should not call otherwise"); |
1235 assert(dest->is_register(), "should not call otherwise"); | |
1236 | |
1237 LIR_Address* addr = src->as_address_ptr(); | |
1238 Address from_addr = as_Address(addr); | |
1239 | |
1240 switch (type) { | |
1241 case T_BOOLEAN: // fall through | |
1242 case T_BYTE: // fall through | |
1243 case T_CHAR: // fall through | |
1244 case T_SHORT: | |
1245 if (!VM_Version::is_P6() && !from_addr.uses(dest->as_register())) { | |
1246 // on pre P6 processors we may get partial register stalls | |
1247 // so blow away the value of to_rinfo before loading a | |
1248 // partial word into it. Do it here so that it precedes | |
1249 // the potential patch point below. | |
304 | 1250 __ xorptr(dest->as_register(), dest->as_register()); |
0 | 1251 } |
1252 break; | |
1253 } | |
1254 | |
1255 PatchingStub* patch = NULL; | |
1256 if (patch_code != lir_patch_none) { | |
1257 patch = new PatchingStub(_masm, PatchingStub::access_field_id); | |
304 | 1258 assert(from_addr.disp() != 0, "must have"); |
0 | 1259 } |
1260 if (info != NULL) { | |
1261 add_debug_info_for_null_check_here(info); | |
1262 } | |
1263 | |
1264 switch (type) { | |
1265 case T_FLOAT: { | |
1266 if (dest->is_single_xmm()) { | |
1267 __ movflt(dest->as_xmm_float_reg(), from_addr); | |
1268 } else { | |
1269 assert(dest->is_single_fpu(), "must be"); | |
1270 assert(dest->fpu_regnr() == 0, "dest must be TOS"); | |
1271 __ fld_s(from_addr); | |
1272 } | |
1273 break; | |
1274 } | |
1275 | |
1276 case T_DOUBLE: { | |
1277 if (dest->is_double_xmm()) { | |
1278 __ movdbl(dest->as_xmm_double_reg(), from_addr); | |
1279 } else { | |
1280 assert(dest->is_double_fpu(), "must be"); | |
1281 assert(dest->fpu_regnrLo() == 0, "dest must be TOS"); | |
1282 __ fld_d(from_addr); | |
1283 } | |
1284 break; | |
1285 } | |
1286 | |
1287 case T_OBJECT: // fall through | |
1288 case T_ARRAY: // fall through | |
2002 | 1289 if (UseCompressedOops && !wide) { |
1290 __ movl(dest->as_register(), from_addr); | |
1291 } else { | |
1292 __ movptr(dest->as_register(), from_addr); | |
1293 } | |
1294 break; | |
1295 | |
1296 case T_ADDRESS: | |
304 | 1297 __ movptr(dest->as_register(), from_addr); |
1298 break; | |
0 | 1299 case T_INT: |
1398
314e17ca2c23
6946892: c1 shouldn't sign-extend to upper 32bits on x64
iveresov
parents:
1378
diff
changeset
|
1300 __ movl(dest->as_register(), from_addr); |
0 | 1301 break; |
1302 | |
1303 case T_LONG: { | |
1304 Register to_lo = dest->as_register_lo(); | |
1305 Register to_hi = dest->as_register_hi(); | |
304 | 1306 #ifdef _LP64 |
1307 __ movptr(to_lo, as_Address_lo(addr)); | |
1308 #else | |
0 | 1309 Register base = addr->base()->as_register(); |
1310 Register index = noreg; | |
1311 if (addr->index()->is_register()) { | |
1312 index = addr->index()->as_register(); | |
1313 } | |
1314 if ((base == to_lo && index == to_hi) || | |
1315 (base == to_hi && index == to_lo)) { | |
1316 // addresses with 2 registers are only formed as a result of | |
1317 // array access so this code will never have to deal with | |
1318 // patches or null checks. | |
1319 assert(info == NULL && patch == NULL, "must be"); | |
304 | 1320 __ lea(to_hi, as_Address(addr)); |
0 | 1321 __ movl(to_lo, Address(to_hi, 0)); |
1322 __ movl(to_hi, Address(to_hi, BytesPerWord)); | |
1323 } else if (base == to_lo || index == to_lo) { | |
1324 assert(base != to_hi, "can't be"); | |
1325 assert(index == noreg || (index != base && index != to_hi), "can't handle this"); | |
1326 __ movl(to_hi, as_Address_hi(addr)); | |
1327 if (patch != NULL) { | |
1328 patching_epilog(patch, lir_patch_high, base, info); | |
1329 patch = new PatchingStub(_masm, PatchingStub::access_field_id); | |
1330 patch_code = lir_patch_low; | |
1331 } | |
1332 __ movl(to_lo, as_Address_lo(addr)); | |
1333 } else { | |
1334 assert(index == noreg || (index != base && index != to_lo), "can't handle this"); | |
1335 __ movl(to_lo, as_Address_lo(addr)); | |
1336 if (patch != NULL) { | |
1337 patching_epilog(patch, lir_patch_low, base, info); | |
1338 patch = new PatchingStub(_masm, PatchingStub::access_field_id); | |
1339 patch_code = lir_patch_high; | |
1340 } | |
1341 __ movl(to_hi, as_Address_hi(addr)); | |
1342 } | |
304 | 1343 #endif // _LP64 |
0 | 1344 break; |
1345 } | |
1346 | |
1347 case T_BOOLEAN: // fall through | |
1348 case T_BYTE: { | |
1349 Register dest_reg = dest->as_register(); | |
1350 assert(VM_Version::is_P6() || dest_reg->has_byte_register(), "must use byte registers if not P6"); | |
1351 if (VM_Version::is_P6() || from_addr.uses(dest_reg)) { | |
304 | 1352 __ movsbl(dest_reg, from_addr); |
0 | 1353 } else { |
1354 __ movb(dest_reg, from_addr); | |
1355 __ shll(dest_reg, 24); | |
1356 __ sarl(dest_reg, 24); | |
1357 } | |
1358 break; | |
1359 } | |
1360 | |
1361 case T_CHAR: { | |
1362 Register dest_reg = dest->as_register(); | |
1363 assert(VM_Version::is_P6() || dest_reg->has_byte_register(), "must use byte registers if not P6"); | |
1364 if (VM_Version::is_P6() || from_addr.uses(dest_reg)) { | |
304 | 1365 __ movzwl(dest_reg, from_addr); |
0 | 1366 } else { |
1367 __ movw(dest_reg, from_addr); | |
1368 } | |
1369 break; | |
1370 } | |
1371 | |
1372 case T_SHORT: { | |
1373 Register dest_reg = dest->as_register(); | |
1374 if (VM_Version::is_P6() || from_addr.uses(dest_reg)) { | |
304 | 1375 __ movswl(dest_reg, from_addr); |
0 | 1376 } else { |
1377 __ movw(dest_reg, from_addr); | |
1378 __ shll(dest_reg, 16); | |
1379 __ sarl(dest_reg, 16); | |
1380 } | |
1381 break; | |
1382 } | |
1383 | |
1384 default: | |
1385 ShouldNotReachHere(); | |
1386 } | |
1387 | |
1388 if (patch != NULL) { | |
1389 patching_epilog(patch, patch_code, addr->base()->as_register(), info); | |
1390 } | |
1391 | |
1392 if (type == T_ARRAY || type == T_OBJECT) { | |
2002 | 1393 #ifdef _LP64 |
1394 if (UseCompressedOops && !wide) { | |
1395 __ decode_heap_oop(dest->as_register()); | |
1396 } | |
1397 #endif | |
0 | 1398 __ verify_oop(dest->as_register()); |
1399 } | |
1400 } | |
1401 | |
1402 | |
1403 void LIR_Assembler::prefetchr(LIR_Opr src) { | |
1404 LIR_Address* addr = src->as_address_ptr(); | |
1405 Address from_addr = as_Address(addr); | |
1406 | |
1407 if (VM_Version::supports_sse()) { | |
1408 switch (ReadPrefetchInstr) { | |
1409 case 0: | |
1410 __ prefetchnta(from_addr); break; | |
1411 case 1: | |
1412 __ prefetcht0(from_addr); break; | |
1413 case 2: | |
1414 __ prefetcht2(from_addr); break; | |
1415 default: | |
1416 ShouldNotReachHere(); break; | |
1417 } | |
1418 } else if (VM_Version::supports_3dnow()) { | |
1419 __ prefetchr(from_addr); | |
1420 } | |
1421 } | |
1422 | |
1423 | |
1424 void LIR_Assembler::prefetchw(LIR_Opr src) { | |
1425 LIR_Address* addr = src->as_address_ptr(); | |
1426 Address from_addr = as_Address(addr); | |
1427 | |
1428 if (VM_Version::supports_sse()) { | |
1429 switch (AllocatePrefetchInstr) { | |
1430 case 0: | |
1431 __ prefetchnta(from_addr); break; | |
1432 case 1: | |
1433 __ prefetcht0(from_addr); break; | |
1434 case 2: | |
1435 __ prefetcht2(from_addr); break; | |
1436 case 3: | |
1437 __ prefetchw(from_addr); break; | |
1438 default: | |
1439 ShouldNotReachHere(); break; | |
1440 } | |
1441 } else if (VM_Version::supports_3dnow()) { | |
1442 __ prefetchw(from_addr); | |
1443 } | |
1444 } | |
1445 | |
1446 | |
1447 NEEDS_CLEANUP; // This could be static? | |
1448 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
|
1449 int elem_size = type2aelembytes(type); |
0 | 1450 switch (elem_size) { |
1451 case 1: return Address::times_1; | |
1452 case 2: return Address::times_2; | |
1453 case 4: return Address::times_4; | |
1454 case 8: return Address::times_8; | |
1455 } | |
1456 ShouldNotReachHere(); | |
1457 return Address::no_scale; | |
1458 } | |
1459 | |
1460 | |
1461 void LIR_Assembler::emit_op3(LIR_Op3* op) { | |
1462 switch (op->code()) { | |
1463 case lir_idiv: | |
1464 case lir_irem: | |
1465 arithmetic_idiv(op->code(), | |
1466 op->in_opr1(), | |
1467 op->in_opr2(), | |
1468 op->in_opr3(), | |
1469 op->result_opr(), | |
1470 op->info()); | |
1471 break; | |
1472 default: ShouldNotReachHere(); break; | |
1473 } | |
1474 } | |
1475 | |
1476 void LIR_Assembler::emit_opBranch(LIR_OpBranch* op) { | |
1477 #ifdef ASSERT | |
1478 assert(op->block() == NULL || op->block()->label() == op->label(), "wrong label"); | |
1479 if (op->block() != NULL) _branch_target_blocks.append(op->block()); | |
1480 if (op->ublock() != NULL) _branch_target_blocks.append(op->ublock()); | |
1481 #endif | |
1482 | |
1483 if (op->cond() == lir_cond_always) { | |
1484 if (op->info() != NULL) add_debug_info_for_branch(op->info()); | |
1485 __ jmp (*(op->label())); | |
1486 } else { | |
1487 Assembler::Condition acond = Assembler::zero; | |
1488 if (op->code() == lir_cond_float_branch) { | |
1489 assert(op->ublock() != NULL, "must have unordered successor"); | |
1490 __ jcc(Assembler::parity, *(op->ublock()->label())); | |
1491 switch(op->cond()) { | |
1492 case lir_cond_equal: acond = Assembler::equal; break; | |
1493 case lir_cond_notEqual: acond = Assembler::notEqual; break; | |
1494 case lir_cond_less: acond = Assembler::below; break; | |
1495 case lir_cond_lessEqual: acond = Assembler::belowEqual; break; | |
1496 case lir_cond_greaterEqual: acond = Assembler::aboveEqual; break; | |
1497 case lir_cond_greater: acond = Assembler::above; break; | |
1498 default: ShouldNotReachHere(); | |
1499 } | |
1500 } else { | |
1501 switch (op->cond()) { | |
1502 case lir_cond_equal: acond = Assembler::equal; break; | |
1503 case lir_cond_notEqual: acond = Assembler::notEqual; break; | |
1504 case lir_cond_less: acond = Assembler::less; break; | |
1505 case lir_cond_lessEqual: acond = Assembler::lessEqual; break; | |
1506 case lir_cond_greaterEqual: acond = Assembler::greaterEqual;break; | |
1507 case lir_cond_greater: acond = Assembler::greater; break; | |
1508 case lir_cond_belowEqual: acond = Assembler::belowEqual; break; | |
1509 case lir_cond_aboveEqual: acond = Assembler::aboveEqual; break; | |
1510 default: ShouldNotReachHere(); | |
1511 } | |
1512 } | |
1513 __ jcc(acond,*(op->label())); | |
1514 } | |
1515 } | |
1516 | |
1517 void LIR_Assembler::emit_opConvert(LIR_OpConvert* op) { | |
1518 LIR_Opr src = op->in_opr(); | |
1519 LIR_Opr dest = op->result_opr(); | |
1520 | |
1521 switch (op->bytecode()) { | |
1522 case Bytecodes::_i2l: | |
304 | 1523 #ifdef _LP64 |
1524 __ movl2ptr(dest->as_register_lo(), src->as_register()); | |
1525 #else | |
0 | 1526 move_regs(src->as_register(), dest->as_register_lo()); |
1527 move_regs(src->as_register(), dest->as_register_hi()); | |
1528 __ sarl(dest->as_register_hi(), 31); | |
304 | 1529 #endif // LP64 |
0 | 1530 break; |
1531 | |
1532 case Bytecodes::_l2i: | |
1533 move_regs(src->as_register_lo(), dest->as_register()); | |
1534 break; | |
1535 | |
1536 case Bytecodes::_i2b: | |
1537 move_regs(src->as_register(), dest->as_register()); | |
1538 __ sign_extend_byte(dest->as_register()); | |
1539 break; | |
1540 | |
1541 case Bytecodes::_i2c: | |
1542 move_regs(src->as_register(), dest->as_register()); | |
1543 __ andl(dest->as_register(), 0xFFFF); | |
1544 break; | |
1545 | |
1546 case Bytecodes::_i2s: | |
1547 move_regs(src->as_register(), dest->as_register()); | |
1548 __ sign_extend_short(dest->as_register()); | |
1549 break; | |
1550 | |
1551 | |
1552 case Bytecodes::_f2d: | |
1553 case Bytecodes::_d2f: | |
1554 if (dest->is_single_xmm()) { | |
1555 __ cvtsd2ss(dest->as_xmm_float_reg(), src->as_xmm_double_reg()); | |
1556 } else if (dest->is_double_xmm()) { | |
1557 __ cvtss2sd(dest->as_xmm_double_reg(), src->as_xmm_float_reg()); | |
1558 } else { | |
1559 assert(src->fpu() == dest->fpu(), "register must be equal"); | |
1560 // do nothing (float result is rounded later through spilling) | |
1561 } | |
1562 break; | |
1563 | |
1564 case Bytecodes::_i2f: | |
1565 case Bytecodes::_i2d: | |
1566 if (dest->is_single_xmm()) { | |
304 | 1567 __ cvtsi2ssl(dest->as_xmm_float_reg(), src->as_register()); |
0 | 1568 } else if (dest->is_double_xmm()) { |
304 | 1569 __ cvtsi2sdl(dest->as_xmm_double_reg(), src->as_register()); |
0 | 1570 } else { |
1571 assert(dest->fpu() == 0, "result must be on TOS"); | |
1572 __ movl(Address(rsp, 0), src->as_register()); | |
1573 __ fild_s(Address(rsp, 0)); | |
1574 } | |
1575 break; | |
1576 | |
1577 case Bytecodes::_f2i: | |
1578 case Bytecodes::_d2i: | |
1579 if (src->is_single_xmm()) { | |
304 | 1580 __ cvttss2sil(dest->as_register(), src->as_xmm_float_reg()); |
0 | 1581 } else if (src->is_double_xmm()) { |
304 | 1582 __ cvttsd2sil(dest->as_register(), src->as_xmm_double_reg()); |
0 | 1583 } else { |
1584 assert(src->fpu() == 0, "input must be on TOS"); | |
1585 __ fldcw(ExternalAddress(StubRoutines::addr_fpu_cntrl_wrd_trunc())); | |
1586 __ fist_s(Address(rsp, 0)); | |
1587 __ movl(dest->as_register(), Address(rsp, 0)); | |
1588 __ fldcw(ExternalAddress(StubRoutines::addr_fpu_cntrl_wrd_std())); | |
1589 } | |
1590 | |
1591 // IA32 conversion instructions do not match JLS for overflow, underflow and NaN -> fixup in stub | |
1592 assert(op->stub() != NULL, "stub required"); | |
1593 __ cmpl(dest->as_register(), 0x80000000); | |
1594 __ jcc(Assembler::equal, *op->stub()->entry()); | |
1595 __ bind(*op->stub()->continuation()); | |
1596 break; | |
1597 | |
1598 case Bytecodes::_l2f: | |
1599 case Bytecodes::_l2d: | |
1600 assert(!dest->is_xmm_register(), "result in xmm register not supported (no SSE instruction present)"); | |
1601 assert(dest->fpu() == 0, "result must be on TOS"); | |
1602 | |
304 | 1603 __ movptr(Address(rsp, 0), src->as_register_lo()); |
1604 NOT_LP64(__ movl(Address(rsp, BytesPerWord), src->as_register_hi())); | |
0 | 1605 __ fild_d(Address(rsp, 0)); |
1606 // float result is rounded later through spilling | |
1607 break; | |
1608 | |
1609 case Bytecodes::_f2l: | |
1610 case Bytecodes::_d2l: | |
1611 assert(!src->is_xmm_register(), "input in xmm register not supported (no SSE instruction present)"); | |
1612 assert(src->fpu() == 0, "input must be on TOS"); | |
304 | 1613 assert(dest == FrameMap::long0_opr, "runtime stub places result in these registers"); |
0 | 1614 |
1615 // instruction sequence too long to inline it here | |
1616 { | |
1617 __ call(RuntimeAddress(Runtime1::entry_for(Runtime1::fpu2long_stub_id))); | |
1618 } | |
1619 break; | |
1620 | |
1621 default: ShouldNotReachHere(); | |
1622 } | |
1623 } | |
1624 | |
1625 void LIR_Assembler::emit_alloc_obj(LIR_OpAllocObj* op) { | |
1626 if (op->init_check()) { | |
1627 __ cmpl(Address(op->klass()->as_register(), | |
1628 instanceKlass::init_state_offset_in_bytes() + sizeof(oopDesc)), | |
1629 instanceKlass::fully_initialized); | |
1630 add_debug_info_for_null_check_here(op->stub()->info()); | |
1631 __ jcc(Assembler::notEqual, *op->stub()->entry()); | |
1632 } | |
1633 __ allocate_object(op->obj()->as_register(), | |
1634 op->tmp1()->as_register(), | |
1635 op->tmp2()->as_register(), | |
1636 op->header_size(), | |
1637 op->object_size(), | |
1638 op->klass()->as_register(), | |
1639 *op->stub()->entry()); | |
1640 __ bind(*op->stub()->continuation()); | |
1641 } | |
1642 | |
1643 void LIR_Assembler::emit_alloc_array(LIR_OpAllocArray* op) { | |
1644 if (UseSlowPath || | |
1645 (!UseFastNewObjectArray && (op->type() == T_OBJECT || op->type() == T_ARRAY)) || | |
1646 (!UseFastNewTypeArray && (op->type() != T_OBJECT && op->type() != T_ARRAY))) { | |
1647 __ jmp(*op->stub()->entry()); | |
1648 } else { | |
1649 Register len = op->len()->as_register(); | |
1650 Register tmp1 = op->tmp1()->as_register(); | |
1651 Register tmp2 = op->tmp2()->as_register(); | |
1652 Register tmp3 = op->tmp3()->as_register(); | |
1653 if (len == tmp1) { | |
1654 tmp1 = tmp3; | |
1655 } else if (len == tmp2) { | |
1656 tmp2 = tmp3; | |
1657 } else if (len == tmp3) { | |
1658 // everything is ok | |
1659 } else { | |
304 | 1660 __ mov(tmp3, len); |
0 | 1661 } |
1662 __ allocate_array(op->obj()->as_register(), | |
1663 len, | |
1664 tmp1, | |
1665 tmp2, | |
1666 arrayOopDesc::header_size(op->type()), | |
1667 array_element_size(op->type()), | |
1668 op->klass()->as_register(), | |
1669 *op->stub()->entry()); | |
1670 } | |
1671 __ bind(*op->stub()->continuation()); | |
1672 } | |
1673 | |
1783 | 1674 void LIR_Assembler::type_profile_helper(Register mdo, |
1675 ciMethodData *md, ciProfileData *data, | |
1676 Register recv, Label* update_done) { | |
1808
5511edd5d719
6988779: c1_LIRAssembler_x86.cpp crashes VS2010 compiler
iveresov
parents:
1791
diff
changeset
|
1677 for (uint i = 0; i < ReceiverTypeData::row_limit(); i++) { |
1783 | 1678 Label next_test; |
1679 // See if the receiver is receiver[n]. | |
1680 __ cmpptr(recv, Address(mdo, md->byte_offset_of_slot(data, ReceiverTypeData::receiver_offset(i)))); | |
1681 __ jccb(Assembler::notEqual, next_test); | |
1682 Address data_addr(mdo, md->byte_offset_of_slot(data, ReceiverTypeData::receiver_count_offset(i))); | |
1683 __ 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
|
1684 __ jmp(*update_done); |
1783 | 1685 __ bind(next_test); |
1686 } | |
1687 | |
1688 // 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
|
1689 for (uint i = 0; i < ReceiverTypeData::row_limit(); i++) { |
1783 | 1690 Label next_test; |
1691 Address recv_addr(mdo, md->byte_offset_of_slot(data, ReceiverTypeData::receiver_offset(i))); | |
1692 __ cmpptr(recv_addr, (intptr_t)NULL_WORD); | |
1693 __ jccb(Assembler::notEqual, next_test); | |
1694 __ movptr(recv_addr, recv); | |
1695 __ 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
|
1696 __ jmp(*update_done); |
1783 | 1697 __ bind(next_test); |
1698 } | |
1699 } | |
1700 | |
1791
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1701 void LIR_Assembler::emit_typecheck_helper(LIR_OpTypeCheck *op, Label* success, Label* failure, Label* obj_is_null) { |
1783 | 1702 // we always need a stub for the failure case. |
1703 CodeStub* stub = op->stub(); | |
1704 Register obj = op->object()->as_register(); | |
1705 Register k_RInfo = op->tmp1()->as_register(); | |
1706 Register klass_RInfo = op->tmp2()->as_register(); | |
1707 Register dst = op->result_opr()->as_register(); | |
1708 ciKlass* k = op->klass(); | |
1709 Register Rtmp1 = noreg; | |
1710 | |
1711 // check if it needs to be profiled | |
1712 ciMethodData* md; | |
1713 ciProfileData* data; | |
1714 | |
1715 if (op->should_profile()) { | |
1716 ciMethod* method = op->profiled_method(); | |
1717 assert(method != NULL, "Should have method"); | |
1718 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
|
1719 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
|
1720 assert(md != NULL, "Sanity"); |
1783 | 1721 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
|
1722 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
|
1723 assert(data->is_ReceiverTypeData(), "need ReceiverTypeData for type check"); |
1783 | 1724 } |
1791
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1725 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
|
1726 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
|
1727 Label *failure_target = op->should_profile() ? &profile_cast_failure : failure; |
1783 | 1728 |
1729 if (obj == k_RInfo) { | |
1730 k_RInfo = dst; | |
1731 } else if (obj == klass_RInfo) { | |
1732 klass_RInfo = dst; | |
1733 } | |
2002 | 1734 if (k->is_loaded() && !UseCompressedOops) { |
1783 | 1735 select_different_registers(obj, dst, k_RInfo, klass_RInfo); |
1736 } else { | |
1737 Rtmp1 = op->tmp3()->as_register(); | |
1738 select_different_registers(obj, dst, k_RInfo, klass_RInfo, Rtmp1); | |
1739 } | |
1740 | |
1741 assert_different_registers(obj, k_RInfo, klass_RInfo); | |
1742 if (!k->is_loaded()) { | |
1743 jobject2reg_with_patching(k_RInfo, op->info_for_patch()); | |
1744 } else { | |
1745 #ifdef _LP64 | |
1746 __ movoop(k_RInfo, k->constant_encoding()); | |
1747 #endif // _LP64 | |
1748 } | |
1749 assert(obj != k_RInfo, "must be different"); | |
1750 | |
1751 __ cmpptr(obj, (int32_t)NULL_WORD); | |
1752 if (op->should_profile()) { | |
1791
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1753 Label not_null; |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1754 __ jccb(Assembler::notEqual, not_null); |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1755 // Object is null; update MDO and exit |
1783 | 1756 Register mdo = klass_RInfo; |
1757 __ movoop(mdo, md->constant_encoding()); | |
1758 Address data_addr(mdo, md->byte_offset_of_slot(data, DataLayout::header_offset())); | |
1759 int header_bits = DataLayout::flag_mask_to_header_mask(BitData::null_seen_byte_constant()); | |
1760 __ orl(data_addr, header_bits); | |
1791
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1761 __ jmp(*obj_is_null); |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1762 __ bind(not_null); |
1783 | 1763 } else { |
1791
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1764 __ jcc(Assembler::equal, *obj_is_null); |
1783 | 1765 } |
1766 __ verify_oop(obj); | |
1767 | |
1768 if (op->fast_check()) { | |
1791
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1769 // get object class |
1783 | 1770 // not a safepoint as obj null check happens earlier |
1771 #ifdef _LP64 | |
2002 | 1772 if (UseCompressedOops) { |
1773 __ load_klass(Rtmp1, obj); | |
1774 __ cmpptr(k_RInfo, Rtmp1); | |
1783 | 1775 } else { |
1776 __ cmpptr(k_RInfo, Address(obj, oopDesc::klass_offset_in_bytes())); | |
1777 } | |
2002 | 1778 #else |
1779 if (k->is_loaded()) { | |
1780 __ cmpoop(Address(obj, oopDesc::klass_offset_in_bytes()), k->constant_encoding()); | |
1781 } else { | |
1782 __ cmpptr(k_RInfo, Address(obj, oopDesc::klass_offset_in_bytes())); | |
1783 } | |
1784 #endif | |
1783 | 1785 __ jcc(Assembler::notEqual, *failure_target); |
1791
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1786 // successful cast, fall through to profile or jump |
1783 | 1787 } else { |
1788 // get object class | |
1789 // not a safepoint as obj null check happens earlier | |
2002 | 1790 __ load_klass(klass_RInfo, obj); |
1783 | 1791 if (k->is_loaded()) { |
1792 // See if we get an immediate positive hit | |
1793 #ifdef _LP64 | |
1794 __ cmpptr(k_RInfo, Address(klass_RInfo, k->super_check_offset())); | |
1795 #else | |
1796 __ cmpoop(Address(klass_RInfo, k->super_check_offset()), k->constant_encoding()); | |
1797 #endif // _LP64 | |
1798 if (sizeof(oopDesc) + Klass::secondary_super_cache_offset_in_bytes() != k->super_check_offset()) { | |
1799 __ jcc(Assembler::notEqual, *failure_target); | |
1791
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1800 // successful cast, fall through to profile or jump |
1783 | 1801 } else { |
1802 // 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
|
1803 __ jcc(Assembler::equal, *success_target); |
1783 | 1804 // check for self |
1805 #ifdef _LP64 | |
1806 __ cmpptr(klass_RInfo, k_RInfo); | |
1807 #else | |
1808 __ cmpoop(klass_RInfo, k->constant_encoding()); | |
1809 #endif // _LP64 | |
1791
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1810 __ jcc(Assembler::equal, *success_target); |
1783 | 1811 |
1812 __ push(klass_RInfo); | |
1813 #ifdef _LP64 | |
1814 __ push(k_RInfo); | |
1815 #else | |
1816 __ pushoop(k->constant_encoding()); | |
1817 #endif // _LP64 | |
1818 __ call(RuntimeAddress(Runtime1::entry_for(Runtime1::slow_subtype_check_id))); | |
1819 __ pop(klass_RInfo); | |
1820 __ pop(klass_RInfo); | |
1821 // result is a boolean | |
1822 __ cmpl(klass_RInfo, 0); | |
1823 __ jcc(Assembler::equal, *failure_target); | |
1791
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1824 // successful cast, fall through to profile or jump |
1783 | 1825 } |
1826 } else { | |
1827 // 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
|
1828 __ check_klass_subtype_fast_path(klass_RInfo, k_RInfo, Rtmp1, success_target, failure_target, NULL); |
1783 | 1829 // call out-of-line instance of __ check_klass_subtype_slow_path(...): |
1830 __ push(klass_RInfo); | |
1831 __ push(k_RInfo); | |
1832 __ call(RuntimeAddress(Runtime1::entry_for(Runtime1::slow_subtype_check_id))); | |
1833 __ pop(klass_RInfo); | |
1834 __ pop(k_RInfo); | |
1835 // result is a boolean | |
1836 __ cmpl(k_RInfo, 0); | |
1837 __ jcc(Assembler::equal, *failure_target); | |
1791
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1838 // successful cast, fall through to profile or jump |
1783 | 1839 } |
1840 } | |
1841 if (op->should_profile()) { | |
1842 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
|
1843 __ bind(profile_cast_success); |
1783 | 1844 __ movoop(mdo, md->constant_encoding()); |
2002 | 1845 __ load_klass(recv, obj); |
1783 | 1846 Label update_done; |
1791
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1847 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
|
1848 __ jmp(*success); |
1783 | 1849 |
1850 __ bind(profile_cast_failure); | |
1851 __ movoop(mdo, md->constant_encoding()); | |
1852 Address counter_addr(mdo, md->byte_offset_of_slot(data, CounterData::count_offset())); | |
1853 __ 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
|
1854 __ jmp(*failure); |
1783 | 1855 } |
1791
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1856 __ jmp(*success); |
1783 | 1857 } |
0 | 1858 |
1791
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1859 |
0 | 1860 void LIR_Assembler::emit_opTypeCheck(LIR_OpTypeCheck* op) { |
1861 LIR_Code code = op->code(); | |
1862 if (code == lir_store_check) { | |
1863 Register value = op->object()->as_register(); | |
1864 Register array = op->array()->as_register(); | |
1865 Register k_RInfo = op->tmp1()->as_register(); | |
1866 Register klass_RInfo = op->tmp2()->as_register(); | |
1867 Register Rtmp1 = op->tmp3()->as_register(); | |
1868 | |
1869 CodeStub* stub = op->stub(); | |
1791
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1870 |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1871 // 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
|
1872 ciMethodData* md; |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1873 ciProfileData* data; |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1874 |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1875 if (op->should_profile()) { |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1876 ciMethod* method = op->profiled_method(); |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1877 assert(method != NULL, "Should have method"); |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1878 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
|
1879 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
|
1880 assert(md != NULL, "Sanity"); |
1791
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1881 data = md->bci_to_data(bci); |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1882 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
|
1883 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
|
1884 } |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1885 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
|
1886 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
|
1887 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
|
1888 |
304 | 1889 __ 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
|
1890 if (op->should_profile()) { |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1891 Label not_null; |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1892 __ jccb(Assembler::notEqual, not_null); |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1893 // 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
|
1894 Register mdo = klass_RInfo; |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1895 __ movoop(mdo, md->constant_encoding()); |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1896 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
|
1897 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
|
1898 __ orl(data_addr, header_bits); |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1899 __ jmp(done); |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1900 __ bind(not_null); |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1901 } else { |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1902 __ jcc(Assembler::equal, done); |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1903 } |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1904 |
0 | 1905 add_debug_info_for_null_check_here(op->info_for_exception()); |
2002 | 1906 __ load_klass(k_RInfo, array); |
1907 __ load_klass(klass_RInfo, value); | |
1908 | |
1909 // get instance klass (it's already uncompressed) | |
304 | 1910 __ movptr(k_RInfo, Address(k_RInfo, objArrayKlass::element_klass_offset_in_bytes() + sizeof(oopDesc))); |
644
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
622
diff
changeset
|
1911 // 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
|
1912 __ 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
|
1913 // call out-of-line instance of __ check_klass_subtype_slow_path(...): |
304 | 1914 __ push(klass_RInfo); |
1915 __ push(k_RInfo); | |
0 | 1916 __ call(RuntimeAddress(Runtime1::entry_for(Runtime1::slow_subtype_check_id))); |
304 | 1917 __ pop(klass_RInfo); |
1918 __ pop(k_RInfo); | |
1919 // result is a boolean | |
0 | 1920 __ cmpl(k_RInfo, 0); |
1791
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1921 __ jcc(Assembler::equal, *failure_target); |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1922 // fall through to the success case |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1923 |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1924 if (op->should_profile()) { |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1925 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
|
1926 __ bind(profile_cast_success); |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1927 __ movoop(mdo, md->constant_encoding()); |
2002 | 1928 __ load_klass(recv, value); |
1791
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1929 Label update_done; |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1930 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
|
1931 __ jmpb(done); |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1932 |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1933 __ bind(profile_cast_failure); |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1934 __ movoop(mdo, md->constant_encoding()); |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1935 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
|
1936 __ subptr(counter_addr, DataLayout::counter_increment); |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1937 __ jmp(*stub->entry()); |
0 | 1938 } |
1791
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1939 |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1940 __ bind(done); |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1941 } else |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1942 if (code == lir_checkcast) { |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1943 Register obj = op->object()->as_register(); |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1944 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
|
1945 Label success; |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1946 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
|
1947 __ bind(success); |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1948 if (dst != obj) { |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1949 __ mov(dst, obj); |
0 | 1950 } |
1791
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1951 } else |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1952 if (code == lir_instanceof) { |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1953 Register obj = op->object()->as_register(); |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1954 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
|
1955 Label success, failure, done; |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1956 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
|
1957 __ bind(failure); |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1958 __ xorptr(dst, dst); |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1959 __ jmpb(done); |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1960 __ bind(success); |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1961 __ movptr(dst, 1); |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1962 __ bind(done); |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1963 } else { |
3a294e483abc
6919069: client compiler needs to capture more profile information for tiered work
iveresov
parents:
1790
diff
changeset
|
1964 ShouldNotReachHere(); |
644
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
622
diff
changeset
|
1965 } |
0 | 1966 |
1967 } | |
1968 | |
1969 | |
1970 void LIR_Assembler::emit_compare_and_swap(LIR_OpCompareAndSwap* op) { | |
304 | 1971 if (LP64_ONLY(false &&) op->code() == lir_cas_long && VM_Version::supports_cx8()) { |
0 | 1972 assert(op->cmp_value()->as_register_lo() == rax, "wrong register"); |
1973 assert(op->cmp_value()->as_register_hi() == rdx, "wrong register"); | |
1974 assert(op->new_value()->as_register_lo() == rbx, "wrong register"); | |
1975 assert(op->new_value()->as_register_hi() == rcx, "wrong register"); | |
1976 Register addr = op->addr()->as_register(); | |
1977 if (os::is_MP()) { | |
1978 __ lock(); | |
1979 } | |
304 | 1980 NOT_LP64(__ cmpxchg8(Address(addr, 0))); |
1981 | |
1982 } else if (op->code() == lir_cas_int || op->code() == lir_cas_obj ) { | |
1983 NOT_LP64(assert(op->addr()->is_single_cpu(), "must be single");) | |
1984 Register addr = (op->addr()->is_single_cpu() ? op->addr()->as_register() : op->addr()->as_register_lo()); | |
0 | 1985 Register newval = op->new_value()->as_register(); |
1986 Register cmpval = op->cmp_value()->as_register(); | |
1987 assert(cmpval == rax, "wrong register"); | |
1988 assert(newval != NULL, "new val must be register"); | |
1989 assert(cmpval != newval, "cmp and new values must be in different registers"); | |
1990 assert(cmpval != addr, "cmp and addr must be in different registers"); | |
1991 assert(newval != addr, "new value and addr must be in different registers"); | |
2002 | 1992 |
304 | 1993 if ( op->code() == lir_cas_obj) { |
2002 | 1994 #ifdef _LP64 |
1995 if (UseCompressedOops) { | |
1996 __ mov(rscratch1, cmpval); | |
1997 __ encode_heap_oop(cmpval); | |
1998 __ mov(rscratch2, newval); | |
1999 __ encode_heap_oop(rscratch2); | |
2000 if (os::is_MP()) { | |
2001 __ lock(); | |
2002 } | |
2003 __ cmpxchgl(rscratch2, Address(addr, 0)); | |
2004 __ mov(cmpval, rscratch1); | |
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 | |
2040 void LIR_Assembler::cmove(LIR_Condition condition, LIR_Opr opr1, LIR_Opr opr2, LIR_Opr result) { | |
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; | |
2503 default : ShouldNotReachHere(); | |
2504 } | |
2505 } else { | |
2506 Unimplemented(); | |
2507 } | |
2508 } | |
2509 | |
2510 void LIR_Assembler::logic_op(LIR_Code code, LIR_Opr left, LIR_Opr right, LIR_Opr dst) { | |
2511 // assert(left->destroys_register(), "check"); | |
2512 if (left->is_single_cpu()) { | |
2513 Register reg = left->as_register(); | |
2514 if (right->is_constant()) { | |
2515 int val = right->as_constant_ptr()->as_jint(); | |
2516 switch (code) { | |
2517 case lir_logic_and: __ andl (reg, val); break; | |
2518 case lir_logic_or: __ orl (reg, val); break; | |
2519 case lir_logic_xor: __ xorl (reg, val); break; | |
2520 default: ShouldNotReachHere(); | |
2521 } | |
2522 } else if (right->is_stack()) { | |
2523 // added support for stack operands | |
2524 Address raddr = frame_map()->address_for_slot(right->single_stack_ix()); | |
2525 switch (code) { | |
2526 case lir_logic_and: __ andl (reg, raddr); break; | |
2527 case lir_logic_or: __ orl (reg, raddr); break; | |
2528 case lir_logic_xor: __ xorl (reg, raddr); break; | |
2529 default: ShouldNotReachHere(); | |
2530 } | |
2531 } else { | |
2532 Register rright = right->as_register(); | |
2533 switch (code) { | |
304 | 2534 case lir_logic_and: __ andptr (reg, rright); break; |
2535 case lir_logic_or : __ orptr (reg, rright); break; | |
2536 case lir_logic_xor: __ xorptr (reg, rright); break; | |
0 | 2537 default: ShouldNotReachHere(); |
2538 } | |
2539 } | |
2540 move_regs(reg, dst->as_register()); | |
2541 } else { | |
2542 Register l_lo = left->as_register_lo(); | |
2543 Register l_hi = left->as_register_hi(); | |
2544 if (right->is_constant()) { | |
304 | 2545 #ifdef _LP64 |
2546 __ mov64(rscratch1, right->as_constant_ptr()->as_jlong()); | |
2547 switch (code) { | |
2548 case lir_logic_and: | |
2549 __ andq(l_lo, rscratch1); | |
2550 break; | |
2551 case lir_logic_or: | |
2552 __ orq(l_lo, rscratch1); | |
2553 break; | |
2554 case lir_logic_xor: | |
2555 __ xorq(l_lo, rscratch1); | |
2556 break; | |
2557 default: ShouldNotReachHere(); | |
2558 } | |
2559 #else | |
0 | 2560 int r_lo = right->as_constant_ptr()->as_jint_lo(); |
2561 int r_hi = right->as_constant_ptr()->as_jint_hi(); | |
2562 switch (code) { | |
2563 case lir_logic_and: | |
2564 __ andl(l_lo, r_lo); | |
2565 __ andl(l_hi, r_hi); | |
2566 break; | |
2567 case lir_logic_or: | |
2568 __ orl(l_lo, r_lo); | |
2569 __ orl(l_hi, r_hi); | |
2570 break; | |
2571 case lir_logic_xor: | |
2572 __ xorl(l_lo, r_lo); | |
2573 __ xorl(l_hi, r_hi); | |
2574 break; | |
2575 default: ShouldNotReachHere(); | |
2576 } | |
304 | 2577 #endif // _LP64 |
0 | 2578 } else { |
1572 | 2579 #ifdef _LP64 |
2580 Register r_lo; | |
2581 if (right->type() == T_OBJECT || right->type() == T_ARRAY) { | |
2582 r_lo = right->as_register(); | |
2583 } else { | |
2584 r_lo = right->as_register_lo(); | |
2585 } | |
2586 #else | |
0 | 2587 Register r_lo = right->as_register_lo(); |
2588 Register r_hi = right->as_register_hi(); | |
2589 assert(l_lo != r_hi, "overwriting registers"); | |
1572 | 2590 #endif |
0 | 2591 switch (code) { |
2592 case lir_logic_and: | |
304 | 2593 __ andptr(l_lo, r_lo); |
2594 NOT_LP64(__ andptr(l_hi, r_hi);) | |
0 | 2595 break; |
2596 case lir_logic_or: | |
304 | 2597 __ orptr(l_lo, r_lo); |
2598 NOT_LP64(__ orptr(l_hi, r_hi);) | |
0 | 2599 break; |
2600 case lir_logic_xor: | |
304 | 2601 __ xorptr(l_lo, r_lo); |
2602 NOT_LP64(__ xorptr(l_hi, r_hi);) | |
0 | 2603 break; |
2604 default: ShouldNotReachHere(); | |
2605 } | |
2606 } | |
2607 | |
2608 Register dst_lo = dst->as_register_lo(); | |
2609 Register dst_hi = dst->as_register_hi(); | |
2610 | |
304 | 2611 #ifdef _LP64 |
2612 move_regs(l_lo, dst_lo); | |
2613 #else | |
0 | 2614 if (dst_lo == l_hi) { |
2615 assert(dst_hi != l_lo, "overwriting registers"); | |
2616 move_regs(l_hi, dst_hi); | |
2617 move_regs(l_lo, dst_lo); | |
2618 } else { | |
2619 assert(dst_lo != l_hi, "overwriting registers"); | |
2620 move_regs(l_lo, dst_lo); | |
2621 move_regs(l_hi, dst_hi); | |
2622 } | |
304 | 2623 #endif // _LP64 |
0 | 2624 } |
2625 } | |
2626 | |
2627 | |
2628 // we assume that rax, and rdx can be overwritten | |
2629 void LIR_Assembler::arithmetic_idiv(LIR_Code code, LIR_Opr left, LIR_Opr right, LIR_Opr temp, LIR_Opr result, CodeEmitInfo* info) { | |
2630 | |
2631 assert(left->is_single_cpu(), "left must be register"); | |
2632 assert(right->is_single_cpu() || right->is_constant(), "right must be register or constant"); | |
2633 assert(result->is_single_cpu(), "result must be register"); | |
2634 | |
2635 // assert(left->destroys_register(), "check"); | |
2636 // assert(right->destroys_register(), "check"); | |
2637 | |
2638 Register lreg = left->as_register(); | |
2639 Register dreg = result->as_register(); | |
2640 | |
2641 if (right->is_constant()) { | |
2642 int divisor = right->as_constant_ptr()->as_jint(); | |
2643 assert(divisor > 0 && is_power_of_2(divisor), "must be"); | |
2644 if (code == lir_idiv) { | |
2645 assert(lreg == rax, "must be rax,"); | |
2646 assert(temp->as_register() == rdx, "tmp register must be rdx"); | |
2647 __ cdql(); // sign extend into rdx:rax | |
2648 if (divisor == 2) { | |
2649 __ subl(lreg, rdx); | |
2650 } else { | |
2651 __ andl(rdx, divisor - 1); | |
2652 __ addl(lreg, rdx); | |
2653 } | |
2654 __ sarl(lreg, log2_intptr(divisor)); | |
2655 move_regs(lreg, dreg); | |
2656 } else if (code == lir_irem) { | |
2657 Label done; | |
304 | 2658 __ mov(dreg, lreg); |
0 | 2659 __ andl(dreg, 0x80000000 | (divisor - 1)); |
2660 __ jcc(Assembler::positive, done); | |
2661 __ decrement(dreg); | |
2662 __ orl(dreg, ~(divisor - 1)); | |
2663 __ increment(dreg); | |
2664 __ bind(done); | |
2665 } else { | |
2666 ShouldNotReachHere(); | |
2667 } | |
2668 } else { | |
2669 Register rreg = right->as_register(); | |
2670 assert(lreg == rax, "left register must be rax,"); | |
2671 assert(rreg != rdx, "right register must not be rdx"); | |
2672 assert(temp->as_register() == rdx, "tmp register must be rdx"); | |
2673 | |
2674 move_regs(lreg, rax); | |
2675 | |
2676 int idivl_offset = __ corrected_idivl(rreg); | |
2677 add_debug_info_for_div0(idivl_offset, info); | |
2678 if (code == lir_irem) { | |
2679 move_regs(rdx, dreg); // result is in rdx | |
2680 } else { | |
2681 move_regs(rax, dreg); | |
2682 } | |
2683 } | |
2684 } | |
2685 | |
2686 | |
2687 void LIR_Assembler::comp_op(LIR_Condition condition, LIR_Opr opr1, LIR_Opr opr2, LIR_Op2* op) { | |
2688 if (opr1->is_single_cpu()) { | |
2689 Register reg1 = opr1->as_register(); | |
2690 if (opr2->is_single_cpu()) { | |
2691 // cpu register - cpu register | |
304 | 2692 if (opr1->type() == T_OBJECT || opr1->type() == T_ARRAY) { |
2693 __ cmpptr(reg1, opr2->as_register()); | |
2694 } else { | |
2695 assert(opr2->type() != T_OBJECT && opr2->type() != T_ARRAY, "cmp int, oop?"); | |
2696 __ cmpl(reg1, opr2->as_register()); | |
2697 } | |
0 | 2698 } else if (opr2->is_stack()) { |
2699 // cpu register - stack | |
304 | 2700 if (opr1->type() == T_OBJECT || opr1->type() == T_ARRAY) { |
2701 __ cmpptr(reg1, frame_map()->address_for_slot(opr2->single_stack_ix())); | |
2702 } else { | |
2703 __ cmpl(reg1, frame_map()->address_for_slot(opr2->single_stack_ix())); | |
2704 } | |
0 | 2705 } else if (opr2->is_constant()) { |
2706 // cpu register - constant | |
2707 LIR_Const* c = opr2->as_constant_ptr(); | |
2708 if (c->type() == T_INT) { | |
2709 __ cmpl(reg1, c->as_jint()); | |
304 | 2710 } else if (c->type() == T_OBJECT || c->type() == T_ARRAY) { |
2711 // In 64bit oops are single register | |
0 | 2712 jobject o = c->as_jobject(); |
2713 if (o == NULL) { | |
304 | 2714 __ cmpptr(reg1, (int32_t)NULL_WORD); |
0 | 2715 } else { |
304 | 2716 #ifdef _LP64 |
2717 __ movoop(rscratch1, o); | |
2718 __ cmpptr(reg1, rscratch1); | |
2719 #else | |
0 | 2720 __ cmpoop(reg1, c->as_jobject()); |
304 | 2721 #endif // _LP64 |
0 | 2722 } |
2723 } else { | |
2724 ShouldNotReachHere(); | |
2725 } | |
2726 // cpu register - address | |
2727 } else if (opr2->is_address()) { | |
2728 if (op->info() != NULL) { | |
2729 add_debug_info_for_null_check_here(op->info()); | |
2730 } | |
2731 __ cmpl(reg1, as_Address(opr2->as_address_ptr())); | |
2732 } else { | |
2733 ShouldNotReachHere(); | |
2734 } | |
2735 | |
2736 } else if(opr1->is_double_cpu()) { | |
2737 Register xlo = opr1->as_register_lo(); | |
2738 Register xhi = opr1->as_register_hi(); | |
2739 if (opr2->is_double_cpu()) { | |
304 | 2740 #ifdef _LP64 |
2741 __ cmpptr(xlo, opr2->as_register_lo()); | |
2742 #else | |
0 | 2743 // cpu register - cpu register |
2744 Register ylo = opr2->as_register_lo(); | |
2745 Register yhi = opr2->as_register_hi(); | |
2746 __ subl(xlo, ylo); | |
2747 __ sbbl(xhi, yhi); | |
2748 if (condition == lir_cond_equal || condition == lir_cond_notEqual) { | |
2749 __ orl(xhi, xlo); | |
2750 } | |
304 | 2751 #endif // _LP64 |
0 | 2752 } else if (opr2->is_constant()) { |
2753 // cpu register - constant 0 | |
2754 assert(opr2->as_jlong() == (jlong)0, "only handles zero"); | |
304 | 2755 #ifdef _LP64 |
2756 __ cmpptr(xlo, (int32_t)opr2->as_jlong()); | |
2757 #else | |
0 | 2758 assert(condition == lir_cond_equal || condition == lir_cond_notEqual, "only handles equals case"); |
2759 __ orl(xhi, xlo); | |
304 | 2760 #endif // _LP64 |
0 | 2761 } else { |
2762 ShouldNotReachHere(); | |
2763 } | |
2764 | |
2765 } else if (opr1->is_single_xmm()) { | |
2766 XMMRegister reg1 = opr1->as_xmm_float_reg(); | |
2767 if (opr2->is_single_xmm()) { | |
2768 // xmm register - xmm register | |
2769 __ ucomiss(reg1, opr2->as_xmm_float_reg()); | |
2770 } else if (opr2->is_stack()) { | |
2771 // xmm register - stack | |
2772 __ ucomiss(reg1, frame_map()->address_for_slot(opr2->single_stack_ix())); | |
2773 } else if (opr2->is_constant()) { | |
2774 // xmm register - constant | |
2775 __ ucomiss(reg1, InternalAddress(float_constant(opr2->as_jfloat()))); | |
2776 } else if (opr2->is_address()) { | |
2777 // xmm register - address | |
2778 if (op->info() != NULL) { | |
2779 add_debug_info_for_null_check_here(op->info()); | |
2780 } | |
2781 __ ucomiss(reg1, as_Address(opr2->as_address_ptr())); | |
2782 } else { | |
2783 ShouldNotReachHere(); | |
2784 } | |
2785 | |
2786 } else if (opr1->is_double_xmm()) { | |
2787 XMMRegister reg1 = opr1->as_xmm_double_reg(); | |
2788 if (opr2->is_double_xmm()) { | |
2789 // xmm register - xmm register | |
2790 __ ucomisd(reg1, opr2->as_xmm_double_reg()); | |
2791 } else if (opr2->is_stack()) { | |
2792 // xmm register - stack | |
2793 __ ucomisd(reg1, frame_map()->address_for_slot(opr2->double_stack_ix())); | |
2794 } else if (opr2->is_constant()) { | |
2795 // xmm register - constant | |
2796 __ ucomisd(reg1, InternalAddress(double_constant(opr2->as_jdouble()))); | |
2797 } else if (opr2->is_address()) { | |
2798 // xmm register - address | |
2799 if (op->info() != NULL) { | |
2800 add_debug_info_for_null_check_here(op->info()); | |
2801 } | |
2802 __ ucomisd(reg1, as_Address(opr2->pointer()->as_address())); | |
2803 } else { | |
2804 ShouldNotReachHere(); | |
2805 } | |
2806 | |
2807 } else if(opr1->is_single_fpu() || opr1->is_double_fpu()) { | |
2808 assert(opr1->is_fpu_register() && opr1->fpu() == 0, "currently left-hand side must be on TOS (relax this restriction)"); | |
2809 assert(opr2->is_fpu_register(), "both must be registers"); | |
2810 __ fcmp(noreg, opr2->fpu(), op->fpu_pop_count() > 0, op->fpu_pop_count() > 1); | |
2811 | |
2812 } else if (opr1->is_address() && opr2->is_constant()) { | |
304 | 2813 LIR_Const* c = opr2->as_constant_ptr(); |
2814 #ifdef _LP64 | |
2815 if (c->type() == T_OBJECT || c->type() == T_ARRAY) { | |
2816 assert(condition == lir_cond_equal || condition == lir_cond_notEqual, "need to reverse"); | |
2817 __ movoop(rscratch1, c->as_jobject()); | |
2818 } | |
2819 #endif // LP64 | |
0 | 2820 if (op->info() != NULL) { |
2821 add_debug_info_for_null_check_here(op->info()); | |
2822 } | |
2823 // special case: address - constant | |
2824 LIR_Address* addr = opr1->as_address_ptr(); | |
2825 if (c->type() == T_INT) { | |
2826 __ cmpl(as_Address(addr), c->as_jint()); | |
304 | 2827 } else if (c->type() == T_OBJECT || c->type() == T_ARRAY) { |
2828 #ifdef _LP64 | |
2829 // %%% Make this explode if addr isn't reachable until we figure out a | |
2830 // better strategy by giving noreg as the temp for as_Address | |
2831 __ cmpptr(rscratch1, as_Address(addr, noreg)); | |
2832 #else | |
0 | 2833 __ cmpoop(as_Address(addr), c->as_jobject()); |
304 | 2834 #endif // _LP64 |
0 | 2835 } else { |
2836 ShouldNotReachHere(); | |
2837 } | |
2838 | |
2839 } else { | |
2840 ShouldNotReachHere(); | |
2841 } | |
2842 } | |
2843 | |
2844 void LIR_Assembler::comp_fl2i(LIR_Code code, LIR_Opr left, LIR_Opr right, LIR_Opr dst, LIR_Op2* op) { | |
2845 if (code == lir_cmp_fd2i || code == lir_ucmp_fd2i) { | |
2846 if (left->is_single_xmm()) { | |
2847 assert(right->is_single_xmm(), "must match"); | |
2848 __ cmpss2int(left->as_xmm_float_reg(), right->as_xmm_float_reg(), dst->as_register(), code == lir_ucmp_fd2i); | |
2849 } else if (left->is_double_xmm()) { | |
2850 assert(right->is_double_xmm(), "must match"); | |
2851 __ cmpsd2int(left->as_xmm_double_reg(), right->as_xmm_double_reg(), dst->as_register(), code == lir_ucmp_fd2i); | |
2852 | |
2853 } else { | |
2854 assert(left->is_single_fpu() || left->is_double_fpu(), "must be"); | |
2855 assert(right->is_single_fpu() || right->is_double_fpu(), "must match"); | |
2856 | |
2857 assert(left->fpu() == 0, "left must be on TOS"); | |
2858 __ fcmp2int(dst->as_register(), code == lir_ucmp_fd2i, right->fpu(), | |
2859 op->fpu_pop_count() > 0, op->fpu_pop_count() > 1); | |
2860 } | |
2861 } else { | |
2862 assert(code == lir_cmp_l2i, "check"); | |
304 | 2863 #ifdef _LP64 |
1369 | 2864 Label done; |
2865 Register dest = dst->as_register(); | |
2866 __ cmpptr(left->as_register_lo(), right->as_register_lo()); | |
2867 __ movl(dest, -1); | |
2868 __ jccb(Assembler::less, done); | |
2869 __ set_byte_if_not_zero(dest); | |
2870 __ movzbl(dest, dest); | |
2871 __ bind(done); | |
304 | 2872 #else |
0 | 2873 __ lcmp2int(left->as_register_hi(), |
2874 left->as_register_lo(), | |
2875 right->as_register_hi(), | |
2876 right->as_register_lo()); | |
2877 move_regs(left->as_register_hi(), dst->as_register()); | |
304 | 2878 #endif // _LP64 |
0 | 2879 } |
2880 } | |
2881 | |
2882 | |
2883 void LIR_Assembler::align_call(LIR_Code code) { | |
2884 if (os::is_MP()) { | |
2885 // make sure that the displacement word of the call ends up word aligned | |
2886 int offset = __ offset(); | |
2887 switch (code) { | |
2888 case lir_static_call: | |
2889 case lir_optvirtual_call: | |
1295 | 2890 case lir_dynamic_call: |
0 | 2891 offset += NativeCall::displacement_offset; |
2892 break; | |
2893 case lir_icvirtual_call: | |
2894 offset += NativeCall::displacement_offset + NativeMovConstReg::instruction_size; | |
2895 break; | |
2896 case lir_virtual_call: // currently, sparc-specific for niagara | |
2897 default: ShouldNotReachHere(); | |
2898 } | |
2899 while (offset++ % BytesPerWord != 0) { | |
2900 __ nop(); | |
2901 } | |
2902 } | |
2903 } | |
2904 | |
2905 | |
1295 | 2906 void LIR_Assembler::call(LIR_OpJavaCall* op, relocInfo::relocType rtype) { |
0 | 2907 assert(!os::is_MP() || (__ offset() + NativeCall::displacement_offset) % BytesPerWord == 0, |
2908 "must be aligned"); | |
1295 | 2909 __ call(AddressLiteral(op->addr(), rtype)); |
1564 | 2910 add_call_info(code_offset(), op->info()); |
0 | 2911 } |
2912 | |
2913 | |
1295 | 2914 void LIR_Assembler::ic_call(LIR_OpJavaCall* op) { |
0 | 2915 RelocationHolder rh = virtual_call_Relocation::spec(pc()); |
2916 __ movoop(IC_Klass, (jobject)Universe::non_oop_word()); | |
2917 assert(!os::is_MP() || | |
2918 (__ offset() + NativeCall::displacement_offset) % BytesPerWord == 0, | |
2919 "must be aligned"); | |
1295 | 2920 __ call(AddressLiteral(op->addr(), rh)); |
1564 | 2921 add_call_info(code_offset(), op->info()); |
0 | 2922 } |
2923 | |
2924 | |
2925 /* Currently, vtable-dispatch is only enabled for sparc platforms */ | |
1295 | 2926 void LIR_Assembler::vtable_call(LIR_OpJavaCall* op) { |
0 | 2927 ShouldNotReachHere(); |
2928 } | |
2929 | |
1295 | 2930 |
0 | 2931 void LIR_Assembler::emit_static_call_stub() { |
2932 address call_pc = __ pc(); | |
2933 address stub = __ start_a_stub(call_stub_size); | |
2934 if (stub == NULL) { | |
2935 bailout("static call stub overflow"); | |
2936 return; | |
2937 } | |
2938 | |
2939 int start = __ offset(); | |
2940 if (os::is_MP()) { | |
2941 // make sure that the displacement word of the call ends up word aligned | |
2942 int offset = __ offset() + NativeMovConstReg::instruction_size + NativeCall::displacement_offset; | |
2943 while (offset++ % BytesPerWord != 0) { | |
2944 __ nop(); | |
2945 } | |
2946 } | |
2947 __ relocate(static_stub_Relocation::spec(call_pc)); | |
2948 __ movoop(rbx, (jobject)NULL); | |
2949 // must be set to -1 at code generation time | |
2950 assert(!os::is_MP() || ((__ offset() + 1) % BytesPerWord) == 0, "must be aligned on MP"); | |
304 | 2951 // On 64bit this will die since it will take a movq & jmp, must be only a jmp |
2952 __ jump(RuntimeAddress(__ pc())); | |
0 | 2953 |
1489
cff162798819
6888953: some calls to function-like macros are missing semicolons
jcoomes
parents:
1378
diff
changeset
|
2954 assert(__ offset() - start <= call_stub_size, "stub too big"); |
0 | 2955 __ end_a_stub(); |
2956 } | |
2957 | |
2958 | |
1378
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
2959 void LIR_Assembler::throw_op(LIR_Opr exceptionPC, LIR_Opr exceptionOop, CodeEmitInfo* info) { |
0 | 2960 assert(exceptionOop->as_register() == rax, "must match"); |
1378
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
2961 assert(exceptionPC->as_register() == rdx, "must match"); |
0 | 2962 |
2963 // exception object is not added to oop map by LinearScan | |
2964 // (LinearScan assumes that no oops are in fixed registers) | |
2965 info->add_register_oop(exceptionOop); | |
2966 Runtime1::StubID unwind_id; | |
2967 | |
1378
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
2968 // get current pc information |
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
2969 // 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
|
2970 int pc_for_athrow_offset = __ offset(); |
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
2971 InternalAddress pc_for_athrow(__ pc()); |
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
2972 __ lea(exceptionPC->as_register(), pc_for_athrow); |
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
2973 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
|
2974 |
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
2975 __ verify_not_null_oop(rax); |
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
2976 // 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
|
2977 if (compilation()->has_fpu_code()) { |
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
2978 unwind_id = Runtime1::handle_exception_id; |
0 | 2979 } else { |
1378
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
2980 unwind_id = Runtime1::handle_exception_nofpu_id; |
0 | 2981 } |
1378
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
2982 __ call(RuntimeAddress(Runtime1::entry_for(unwind_id))); |
0 | 2983 |
2984 // enough room for two byte trap | |
2985 __ nop(); | |
2986 } | |
2987 | |
2988 | |
1378
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
2989 void LIR_Assembler::unwind_op(LIR_Opr exceptionOop) { |
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
2990 assert(exceptionOop->as_register() == rax, "must match"); |
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
2991 |
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
2992 __ jmp(_unwind_handler_entry); |
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
2993 } |
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
2994 |
9f5b60a14736
6939930: exception unwind changes in 6919934 hurts compilation speed
never
parents:
1369
diff
changeset
|
2995 |
0 | 2996 void LIR_Assembler::shift_op(LIR_Code code, LIR_Opr left, LIR_Opr count, LIR_Opr dest, LIR_Opr tmp) { |
2997 | |
2998 // optimized version for linear scan: | |
2999 // * count must be already in ECX (guaranteed by LinearScan) | |
3000 // * left and dest must be equal | |
3001 // * tmp must be unused | |
3002 assert(count->as_register() == SHIFT_count, "count must be in ECX"); | |
3003 assert(left == dest, "left and dest must be equal"); | |
3004 assert(tmp->is_illegal(), "wasting a register if tmp is allocated"); | |
3005 | |
3006 if (left->is_single_cpu()) { | |
3007 Register value = left->as_register(); | |
3008 assert(value != SHIFT_count, "left cannot be ECX"); | |
3009 | |
3010 switch (code) { | |
3011 case lir_shl: __ shll(value); break; | |
3012 case lir_shr: __ sarl(value); break; | |
3013 case lir_ushr: __ shrl(value); break; | |
3014 default: ShouldNotReachHere(); | |
3015 } | |
3016 } else if (left->is_double_cpu()) { | |
3017 Register lo = left->as_register_lo(); | |
3018 Register hi = left->as_register_hi(); | |
3019 assert(lo != SHIFT_count && hi != SHIFT_count, "left cannot be ECX"); | |
304 | 3020 #ifdef _LP64 |
3021 switch (code) { | |
3022 case lir_shl: __ shlptr(lo); break; | |
3023 case lir_shr: __ sarptr(lo); break; | |
3024 case lir_ushr: __ shrptr(lo); break; | |
3025 default: ShouldNotReachHere(); | |
3026 } | |
3027 #else | |
0 | 3028 |
3029 switch (code) { | |
3030 case lir_shl: __ lshl(hi, lo); break; | |
3031 case lir_shr: __ lshr(hi, lo, true); break; | |
3032 case lir_ushr: __ lshr(hi, lo, false); break; | |
3033 default: ShouldNotReachHere(); | |
3034 } | |
304 | 3035 #endif // LP64 |
0 | 3036 } else { |
3037 ShouldNotReachHere(); | |
3038 } | |
3039 } | |
3040 | |
3041 | |
3042 void LIR_Assembler::shift_op(LIR_Code code, LIR_Opr left, jint count, LIR_Opr dest) { | |
3043 if (dest->is_single_cpu()) { | |
3044 // first move left into dest so that left is not destroyed by the shift | |
3045 Register value = dest->as_register(); | |
3046 count = count & 0x1F; // Java spec | |
3047 | |
3048 move_regs(left->as_register(), value); | |
3049 switch (code) { | |
3050 case lir_shl: __ shll(value, count); break; | |
3051 case lir_shr: __ sarl(value, count); break; | |
3052 case lir_ushr: __ shrl(value, count); break; | |
3053 default: ShouldNotReachHere(); | |
3054 } | |
3055 } else if (dest->is_double_cpu()) { | |
304 | 3056 #ifndef _LP64 |
0 | 3057 Unimplemented(); |
304 | 3058 #else |
3059 // first move left into dest so that left is not destroyed by the shift | |
3060 Register value = dest->as_register_lo(); | |
3061 count = count & 0x1F; // Java spec | |
3062 | |
3063 move_regs(left->as_register_lo(), value); | |
3064 switch (code) { | |
3065 case lir_shl: __ shlptr(value, count); break; | |
3066 case lir_shr: __ sarptr(value, count); break; | |
3067 case lir_ushr: __ shrptr(value, count); break; | |
3068 default: ShouldNotReachHere(); | |
3069 } | |
3070 #endif // _LP64 | |
0 | 3071 } else { |
3072 ShouldNotReachHere(); | |
3073 } | |
3074 } | |
3075 | |
3076 | |
3077 void LIR_Assembler::store_parameter(Register r, int offset_from_rsp_in_words) { | |
3078 assert(offset_from_rsp_in_words >= 0, "invalid offset from rsp"); | |
3079 int offset_from_rsp_in_bytes = offset_from_rsp_in_words * BytesPerWord; | |
3080 assert(offset_from_rsp_in_bytes < frame_map()->reserved_argument_area_size(), "invalid offset"); | |
304 | 3081 __ movptr (Address(rsp, offset_from_rsp_in_bytes), r); |
0 | 3082 } |
3083 | |
3084 | |
3085 void LIR_Assembler::store_parameter(jint c, int offset_from_rsp_in_words) { | |
3086 assert(offset_from_rsp_in_words >= 0, "invalid offset from rsp"); | |
3087 int offset_from_rsp_in_bytes = offset_from_rsp_in_words * BytesPerWord; | |
3088 assert(offset_from_rsp_in_bytes < frame_map()->reserved_argument_area_size(), "invalid offset"); | |
304 | 3089 __ movptr (Address(rsp, offset_from_rsp_in_bytes), c); |
0 | 3090 } |
3091 | |
3092 | |
3093 void LIR_Assembler::store_parameter(jobject o, int offset_from_rsp_in_words) { | |
3094 assert(offset_from_rsp_in_words >= 0, "invalid offset from rsp"); | |
3095 int offset_from_rsp_in_bytes = offset_from_rsp_in_words * BytesPerWord; | |
3096 assert(offset_from_rsp_in_bytes < frame_map()->reserved_argument_area_size(), "invalid offset"); | |
3097 __ movoop (Address(rsp, offset_from_rsp_in_bytes), o); | |
3098 } | |
3099 | |
3100 | |
3101 // This code replaces a call to arraycopy; no exception may | |
3102 // be thrown in this code, they must be thrown in the System.arraycopy | |
3103 // activation frame; we could save some checks if this would not be the case | |
3104 void LIR_Assembler::emit_arraycopy(LIR_OpArrayCopy* op) { | |
3105 ciArrayKlass* default_type = op->expected_type(); | |
3106 Register src = op->src()->as_register(); | |
3107 Register dst = op->dst()->as_register(); | |
3108 Register src_pos = op->src_pos()->as_register(); | |
3109 Register dst_pos = op->dst_pos()->as_register(); | |
3110 Register length = op->length()->as_register(); | |
3111 Register tmp = op->tmp()->as_register(); | |
3112 | |
3113 CodeStub* stub = op->stub(); | |
3114 int flags = op->flags(); | |
3115 BasicType basic_type = default_type != NULL ? default_type->element_type()->basic_type() : T_ILLEGAL; | |
3116 if (basic_type == T_ARRAY) basic_type = T_OBJECT; | |
3117 | |
3118 // if we don't know anything or it's an object array, just go through the generic arraycopy | |
3119 if (default_type == NULL) { | |
3120 Label done; | |
3121 // save outgoing arguments on stack in case call to System.arraycopy is needed | |
3122 // HACK ALERT. This code used to push the parameters in a hardwired fashion | |
3123 // for interpreter calling conventions. Now we have to do it in new style conventions. | |
3124 // For the moment until C1 gets the new register allocator I just force all the | |
3125 // args to the right place (except the register args) and then on the back side | |
3126 // reload the register args properly if we go slow path. Yuck | |
3127 | |
3128 // These are proper for the calling convention | |
3129 | |
3130 store_parameter(length, 2); | |
3131 store_parameter(dst_pos, 1); | |
3132 store_parameter(dst, 0); | |
3133 | |
3134 // these are just temporary placements until we need to reload | |
3135 store_parameter(src_pos, 3); | |
3136 store_parameter(src, 4); | |
304 | 3137 NOT_LP64(assert(src == rcx && src_pos == rdx, "mismatch in calling convention");) |
3138 | |
3139 address entry = CAST_FROM_FN_PTR(address, Runtime1::arraycopy); | |
0 | 3140 |
3141 // pass arguments: may push as this is not a safepoint; SP must be fix at each safepoint | |
304 | 3142 #ifdef _LP64 |
3143 // The arguments are in java calling convention so we can trivially shift them to C | |
3144 // convention | |
3145 assert_different_registers(c_rarg0, j_rarg1, j_rarg2, j_rarg3, j_rarg4); | |
3146 __ mov(c_rarg0, j_rarg0); | |
3147 assert_different_registers(c_rarg1, j_rarg2, j_rarg3, j_rarg4); | |
3148 __ mov(c_rarg1, j_rarg1); | |
3149 assert_different_registers(c_rarg2, j_rarg3, j_rarg4); | |
3150 __ mov(c_rarg2, j_rarg2); | |
3151 assert_different_registers(c_rarg3, j_rarg4); | |
3152 __ mov(c_rarg3, j_rarg3); | |
3153 #ifdef _WIN64 | |
3154 // Allocate abi space for args but be sure to keep stack aligned | |
3155 __ subptr(rsp, 6*wordSize); | |
3156 store_parameter(j_rarg4, 4); | |
3157 __ call(RuntimeAddress(entry)); | |
3158 __ addptr(rsp, 6*wordSize); | |
3159 #else | |
3160 __ mov(c_rarg4, j_rarg4); | |
3161 __ call(RuntimeAddress(entry)); | |
3162 #endif // _WIN64 | |
3163 #else | |
3164 __ push(length); | |
3165 __ push(dst_pos); | |
3166 __ push(dst); | |
3167 __ push(src_pos); | |
3168 __ push(src); | |
0 | 3169 __ call_VM_leaf(entry, 5); // removes pushed parameter from the stack |
3170 | |
304 | 3171 #endif // _LP64 |
3172 | |
0 | 3173 __ cmpl(rax, 0); |
3174 __ jcc(Assembler::equal, *stub->continuation()); | |
3175 | |
3176 // Reload values from the stack so they are where the stub | |
3177 // expects them. | |
304 | 3178 __ movptr (dst, Address(rsp, 0*BytesPerWord)); |
3179 __ movptr (dst_pos, Address(rsp, 1*BytesPerWord)); | |
3180 __ movptr (length, Address(rsp, 2*BytesPerWord)); | |
3181 __ movptr (src_pos, Address(rsp, 3*BytesPerWord)); | |
3182 __ movptr (src, Address(rsp, 4*BytesPerWord)); | |
0 | 3183 __ jmp(*stub->entry()); |
3184 | |
3185 __ bind(*stub->continuation()); | |
3186 return; | |
3187 } | |
3188 | |
3189 assert(default_type != NULL && default_type->is_array_klass() && default_type->is_loaded(), "must be true at this point"); | |
3190 | |
29
d5fc211aea19
6633953: type2aelembytes{T_ADDRESS} should be 8 bytes in 64 bit VM
kvn
parents:
0
diff
changeset
|
3191 int elem_size = type2aelembytes(basic_type); |
0 | 3192 int shift_amount; |
3193 Address::ScaleFactor scale; | |
3194 | |
3195 switch (elem_size) { | |
3196 case 1 : | |
3197 shift_amount = 0; | |
3198 scale = Address::times_1; | |
3199 break; | |
3200 case 2 : | |
3201 shift_amount = 1; | |
3202 scale = Address::times_2; | |
3203 break; | |
3204 case 4 : | |
3205 shift_amount = 2; | |
3206 scale = Address::times_4; | |
3207 break; | |
3208 case 8 : | |
3209 shift_amount = 3; | |
3210 scale = Address::times_8; | |
3211 break; | |
3212 default: | |
3213 ShouldNotReachHere(); | |
3214 } | |
3215 | |
3216 Address src_length_addr = Address(src, arrayOopDesc::length_offset_in_bytes()); | |
3217 Address dst_length_addr = Address(dst, arrayOopDesc::length_offset_in_bytes()); | |
3218 Address src_klass_addr = Address(src, oopDesc::klass_offset_in_bytes()); | |
3219 Address dst_klass_addr = Address(dst, oopDesc::klass_offset_in_bytes()); | |
3220 | |
304 | 3221 // length and pos's are all sign extended at this point on 64bit |
3222 | |
0 | 3223 // test for NULL |
3224 if (flags & LIR_OpArrayCopy::src_null_check) { | |
304 | 3225 __ testptr(src, src); |
0 | 3226 __ jcc(Assembler::zero, *stub->entry()); |
3227 } | |
3228 if (flags & LIR_OpArrayCopy::dst_null_check) { | |
304 | 3229 __ testptr(dst, dst); |
0 | 3230 __ jcc(Assembler::zero, *stub->entry()); |
3231 } | |
3232 | |
3233 // check if negative | |
3234 if (flags & LIR_OpArrayCopy::src_pos_positive_check) { | |
3235 __ testl(src_pos, src_pos); | |
3236 __ jcc(Assembler::less, *stub->entry()); | |
3237 } | |
3238 if (flags & LIR_OpArrayCopy::dst_pos_positive_check) { | |
3239 __ testl(dst_pos, dst_pos); | |
3240 __ jcc(Assembler::less, *stub->entry()); | |
3241 } | |
3242 if (flags & LIR_OpArrayCopy::length_positive_check) { | |
3243 __ testl(length, length); | |
3244 __ jcc(Assembler::less, *stub->entry()); | |
3245 } | |
3246 | |
3247 if (flags & LIR_OpArrayCopy::src_range_check) { | |
304 | 3248 __ lea(tmp, Address(src_pos, length, Address::times_1, 0)); |
0 | 3249 __ cmpl(tmp, src_length_addr); |
3250 __ jcc(Assembler::above, *stub->entry()); | |
3251 } | |
3252 if (flags & LIR_OpArrayCopy::dst_range_check) { | |
304 | 3253 __ lea(tmp, Address(dst_pos, length, Address::times_1, 0)); |
0 | 3254 __ cmpl(tmp, dst_length_addr); |
3255 __ jcc(Assembler::above, *stub->entry()); | |
3256 } | |
3257 | |
3258 if (flags & LIR_OpArrayCopy::type_check) { | |
2002 | 3259 if (UseCompressedOops) { |
3260 __ movl(tmp, src_klass_addr); | |
3261 __ cmpl(tmp, dst_klass_addr); | |
3262 } else { | |
3263 __ movptr(tmp, src_klass_addr); | |
3264 __ cmpptr(tmp, dst_klass_addr); | |
3265 } | |
0 | 3266 __ jcc(Assembler::notEqual, *stub->entry()); |
3267 } | |
3268 | |
3269 #ifdef ASSERT | |
3270 if (basic_type != T_OBJECT || !(flags & LIR_OpArrayCopy::type_check)) { | |
3271 // Sanity check the known type with the incoming class. For the | |
3272 // primitive case the types must match exactly with src.klass and | |
3273 // dst.klass each exactly matching the default type. For the | |
3274 // object array case, if no type check is needed then either the | |
3275 // dst type is exactly the expected type and the src type is a | |
3276 // subtype which we can't check or src is the same array as dst | |
3277 // but not necessarily exactly of type default_type. | |
3278 Label known_ok, halt; | |
989
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
780
diff
changeset
|
3279 __ movoop(tmp, default_type->constant_encoding()); |
2002 | 3280 #ifdef _LP64 |
3281 if (UseCompressedOops) { | |
3282 __ encode_heap_oop(tmp); | |
3283 } | |
3284 #endif | |
3285 | |
0 | 3286 if (basic_type != T_OBJECT) { |
2002 | 3287 |
3288 if (UseCompressedOops) __ cmpl(tmp, dst_klass_addr); | |
3289 else __ cmpptr(tmp, dst_klass_addr); | |
0 | 3290 __ jcc(Assembler::notEqual, halt); |
2002 | 3291 if (UseCompressedOops) __ cmpl(tmp, src_klass_addr); |
3292 else __ cmpptr(tmp, src_klass_addr); | |
0 | 3293 __ jcc(Assembler::equal, known_ok); |
3294 } else { | |
2002 | 3295 if (UseCompressedOops) __ cmpl(tmp, dst_klass_addr); |
3296 else __ cmpptr(tmp, dst_klass_addr); | |
0 | 3297 __ jcc(Assembler::equal, known_ok); |
304 | 3298 __ cmpptr(src, dst); |
0 | 3299 __ jcc(Assembler::equal, known_ok); |
3300 } | |
3301 __ bind(halt); | |
3302 __ stop("incorrect type information in arraycopy"); | |
3303 __ bind(known_ok); | |
3304 } | |
3305 #endif | |
3306 | |
304 | 3307 if (shift_amount > 0 && basic_type != T_OBJECT) { |
3308 __ shlptr(length, shift_amount); | |
3309 } | |
3310 | |
3311 #ifdef _LP64 | |
3312 assert_different_registers(c_rarg0, dst, dst_pos, length); | |
1060 | 3313 __ movl2ptr(src_pos, src_pos); //higher 32bits must be null |
304 | 3314 __ lea(c_rarg0, Address(src, src_pos, scale, arrayOopDesc::base_offset_in_bytes(basic_type))); |
3315 assert_different_registers(c_rarg1, length); | |
1060 | 3316 __ movl2ptr(dst_pos, dst_pos); //higher 32bits must be null |
304 | 3317 __ lea(c_rarg1, Address(dst, dst_pos, scale, arrayOopDesc::base_offset_in_bytes(basic_type))); |
3318 __ mov(c_rarg2, length); | |
3319 | |
3320 #else | |
3321 __ lea(tmp, Address(src, src_pos, scale, arrayOopDesc::base_offset_in_bytes(basic_type))); | |
0 | 3322 store_parameter(tmp, 0); |
304 | 3323 __ lea(tmp, Address(dst, dst_pos, scale, arrayOopDesc::base_offset_in_bytes(basic_type))); |
0 | 3324 store_parameter(tmp, 1); |
3325 store_parameter(length, 2); | |
304 | 3326 #endif // _LP64 |
0 | 3327 if (basic_type == T_OBJECT) { |
3328 __ call_VM_leaf(CAST_FROM_FN_PTR(address, Runtime1::oop_arraycopy), 0); | |
3329 } else { | |
3330 __ call_VM_leaf(CAST_FROM_FN_PTR(address, Runtime1::primitive_arraycopy), 0); | |
3331 } | |
3332 | |
3333 __ bind(*stub->continuation()); | |
3334 } | |
3335 | |
3336 | |
3337 void LIR_Assembler::emit_lock(LIR_OpLock* op) { | |
3338 Register obj = op->obj_opr()->as_register(); // may not be an oop | |
3339 Register hdr = op->hdr_opr()->as_register(); | |
3340 Register lock = op->lock_opr()->as_register(); | |
3341 if (!UseFastLocking) { | |
3342 __ jmp(*op->stub()->entry()); | |
3343 } else if (op->code() == lir_lock) { | |
3344 Register scratch = noreg; | |
3345 if (UseBiasedLocking) { | |
3346 scratch = op->scratch_opr()->as_register(); | |
3347 } | |
3348 assert(BasicLock::displaced_header_offset_in_bytes() == 0, "lock_reg must point to the displaced header"); | |
3349 // add debug info for NullPointerException only if one is possible | |
3350 int null_check_offset = __ lock_object(hdr, obj, lock, scratch, *op->stub()->entry()); | |
3351 if (op->info() != NULL) { | |
3352 add_debug_info_for_null_check(null_check_offset, op->info()); | |
3353 } | |
3354 // done | |
3355 } else if (op->code() == lir_unlock) { | |
3356 assert(BasicLock::displaced_header_offset_in_bytes() == 0, "lock_reg must point to the displaced header"); | |
3357 __ unlock_object(hdr, obj, lock, *op->stub()->entry()); | |
3358 } else { | |
3359 Unimplemented(); | |
3360 } | |
3361 __ bind(*op->stub()->continuation()); | |
3362 } | |
3363 | |
3364 | |
3365 void LIR_Assembler::emit_profile_call(LIR_OpProfileCall* op) { | |
3366 ciMethod* method = op->profiled_method(); | |
3367 int bci = op->profiled_bci(); | |
3368 | |
3369 // 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
|
3370 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
|
3371 assert(md != NULL, "Sanity"); |
0 | 3372 ciProfileData* data = md->bci_to_data(bci); |
3373 assert(data->is_CounterData(), "need CounterData for calls"); | |
3374 assert(op->mdo()->is_single_cpu(), "mdo must be allocated"); | |
3375 Register mdo = op->mdo()->as_register(); | |
989
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
780
diff
changeset
|
3376 __ movoop(mdo, md->constant_encoding()); |
0 | 3377 Address counter_addr(mdo, md->byte_offset_of_slot(data, CounterData::count_offset())); |
3378 Bytecodes::Code bc = method->java_code_at_bci(bci); | |
3379 // Perform additional virtual call profiling for invokevirtual and | |
3380 // invokeinterface bytecodes | |
3381 if ((bc == Bytecodes::_invokevirtual || bc == Bytecodes::_invokeinterface) && | |
1783 | 3382 C1ProfileVirtualCalls) { |
0 | 3383 assert(op->recv()->is_single_cpu(), "recv must be allocated"); |
3384 Register recv = op->recv()->as_register(); | |
3385 assert_different_registers(mdo, recv); | |
3386 assert(data->is_VirtualCallData(), "need VirtualCallData for virtual calls"); | |
3387 ciKlass* known_klass = op->known_holder(); | |
1783 | 3388 if (C1OptimizeVirtualCallProfiling && known_klass != NULL) { |
0 | 3389 // We know the type that will be seen at this call site; we can |
3390 // statically update the methodDataOop rather than needing to do | |
3391 // dynamic tests on the receiver type | |
3392 | |
3393 // NOTE: we should probably put a lock around this search to | |
3394 // avoid collisions by concurrent compilations | |
3395 ciVirtualCallData* vc_data = (ciVirtualCallData*) data; | |
3396 uint i; | |
3397 for (i = 0; i < VirtualCallData::row_limit(); i++) { | |
3398 ciKlass* receiver = vc_data->receiver(i); | |
3399 if (known_klass->equals(receiver)) { | |
3400 Address data_addr(mdo, md->byte_offset_of_slot(data, VirtualCallData::receiver_count_offset(i))); | |
1783 | 3401 __ addptr(data_addr, DataLayout::counter_increment); |
0 | 3402 return; |
3403 } | |
3404 } | |
3405 | |
3406 // Receiver type not found in profile data; select an empty slot | |
3407 | |
3408 // Note that this is less efficient than it should be because it | |
3409 // always does a write to the receiver part of the | |
3410 // VirtualCallData rather than just the first time | |
3411 for (i = 0; i < VirtualCallData::row_limit(); i++) { | |
3412 ciKlass* receiver = vc_data->receiver(i); | |
3413 if (receiver == NULL) { | |
3414 Address recv_addr(mdo, md->byte_offset_of_slot(data, VirtualCallData::receiver_offset(i))); | |
989
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
780
diff
changeset
|
3415 __ movoop(recv_addr, known_klass->constant_encoding()); |
0 | 3416 Address data_addr(mdo, md->byte_offset_of_slot(data, VirtualCallData::receiver_count_offset(i))); |
1783 | 3417 __ addptr(data_addr, DataLayout::counter_increment); |
0 | 3418 return; |
3419 } | |
3420 } | |
3421 } else { | |
2002 | 3422 __ load_klass(recv, recv); |
0 | 3423 Label update_done; |
1783 | 3424 type_profile_helper(mdo, md, data, recv, &update_done); |
1206
87684f1a88b5
6614597: Performance variability in jvm2008 xml.validation
kvn
parents:
1204
diff
changeset
|
3425 // 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
|
3426 // Increment total counter to indicate polymorphic case. |
1783 | 3427 __ addptr(counter_addr, DataLayout::counter_increment); |
0 | 3428 |
3429 __ bind(update_done); | |
3430 } | |
1206
87684f1a88b5
6614597: Performance variability in jvm2008 xml.validation
kvn
parents:
1204
diff
changeset
|
3431 } else { |
87684f1a88b5
6614597: Performance variability in jvm2008 xml.validation
kvn
parents:
1204
diff
changeset
|
3432 // Static call |
1783 | 3433 __ addptr(counter_addr, DataLayout::counter_increment); |
0 | 3434 } |
3435 } | |
3436 | |
3437 void LIR_Assembler::emit_delay(LIR_OpDelay*) { | |
3438 Unimplemented(); | |
3439 } | |
3440 | |
3441 | |
3442 void LIR_Assembler::monitor_address(int monitor_no, LIR_Opr dst) { | |
304 | 3443 __ lea(dst->as_register(), frame_map()->address_for_monitor_lock(monitor_no)); |
0 | 3444 } |
3445 | |
3446 | |
3447 void LIR_Assembler::align_backward_branch_target() { | |
3448 __ align(BytesPerWord); | |
3449 } | |
3450 | |
3451 | |
3452 void LIR_Assembler::negate(LIR_Opr left, LIR_Opr dest) { | |
3453 if (left->is_single_cpu()) { | |
3454 __ negl(left->as_register()); | |
3455 move_regs(left->as_register(), dest->as_register()); | |
3456 | |
3457 } else if (left->is_double_cpu()) { | |
3458 Register lo = left->as_register_lo(); | |
304 | 3459 #ifdef _LP64 |
3460 Register dst = dest->as_register_lo(); | |
3461 __ movptr(dst, lo); | |
3462 __ negptr(dst); | |
3463 #else | |
0 | 3464 Register hi = left->as_register_hi(); |
3465 __ lneg(hi, lo); | |
3466 if (dest->as_register_lo() == hi) { | |
3467 assert(dest->as_register_hi() != lo, "destroying register"); | |
3468 move_regs(hi, dest->as_register_hi()); | |
3469 move_regs(lo, dest->as_register_lo()); | |
3470 } else { | |
3471 move_regs(lo, dest->as_register_lo()); | |
3472 move_regs(hi, dest->as_register_hi()); | |
3473 } | |
304 | 3474 #endif // _LP64 |
0 | 3475 |
3476 } else if (dest->is_single_xmm()) { | |
3477 if (left->as_xmm_float_reg() != dest->as_xmm_float_reg()) { | |
3478 __ movflt(dest->as_xmm_float_reg(), left->as_xmm_float_reg()); | |
3479 } | |
3480 __ xorps(dest->as_xmm_float_reg(), | |
3481 ExternalAddress((address)float_signflip_pool)); | |
3482 | |
3483 } else if (dest->is_double_xmm()) { | |
3484 if (left->as_xmm_double_reg() != dest->as_xmm_double_reg()) { | |
3485 __ movdbl(dest->as_xmm_double_reg(), left->as_xmm_double_reg()); | |
3486 } | |
3487 __ xorpd(dest->as_xmm_double_reg(), | |
3488 ExternalAddress((address)double_signflip_pool)); | |
3489 | |
3490 } else if (left->is_single_fpu() || left->is_double_fpu()) { | |
3491 assert(left->fpu() == 0, "arg must be on TOS"); | |
3492 assert(dest->fpu() == 0, "dest must be TOS"); | |
3493 __ fchs(); | |
3494 | |
3495 } else { | |
3496 ShouldNotReachHere(); | |
3497 } | |
3498 } | |
3499 | |
3500 | |
3501 void LIR_Assembler::leal(LIR_Opr addr, LIR_Opr dest) { | |
3502 assert(addr->is_address() && dest->is_register(), "check"); | |
304 | 3503 Register reg; |
3504 reg = dest->as_pointer_register(); | |
3505 __ lea(reg, as_Address(addr->as_address_ptr())); | |
0 | 3506 } |
3507 | |
3508 | |
3509 | |
3510 void LIR_Assembler::rt_call(LIR_Opr result, address dest, const LIR_OprList* args, LIR_Opr tmp, CodeEmitInfo* info) { | |
3511 assert(!tmp->is_valid(), "don't need temporary"); | |
3512 __ call(RuntimeAddress(dest)); | |
3513 if (info != NULL) { | |
3514 add_call_info_here(info); | |
3515 } | |
3516 } | |
3517 | |
3518 | |
3519 void LIR_Assembler::volatile_move_op(LIR_Opr src, LIR_Opr dest, BasicType type, CodeEmitInfo* info) { | |
3520 assert(type == T_LONG, "only for volatile long fields"); | |
3521 | |
3522 if (info != NULL) { | |
3523 add_debug_info_for_null_check_here(info); | |
3524 } | |
3525 | |
3526 if (src->is_double_xmm()) { | |
3527 if (dest->is_double_cpu()) { | |
304 | 3528 #ifdef _LP64 |
3529 __ movdq(dest->as_register_lo(), src->as_xmm_double_reg()); | |
3530 #else | |
3531 __ movdl(dest->as_register_lo(), src->as_xmm_double_reg()); | |
0 | 3532 __ psrlq(src->as_xmm_double_reg(), 32); |
304 | 3533 __ movdl(dest->as_register_hi(), src->as_xmm_double_reg()); |
3534 #endif // _LP64 | |
0 | 3535 } else if (dest->is_double_stack()) { |
3536 __ movdbl(frame_map()->address_for_slot(dest->double_stack_ix()), src->as_xmm_double_reg()); | |
3537 } else if (dest->is_address()) { | |
3538 __ movdbl(as_Address(dest->as_address_ptr()), src->as_xmm_double_reg()); | |
3539 } else { | |
3540 ShouldNotReachHere(); | |
3541 } | |
3542 | |
3543 } else if (dest->is_double_xmm()) { | |
3544 if (src->is_double_stack()) { | |
3545 __ movdbl(dest->as_xmm_double_reg(), frame_map()->address_for_slot(src->double_stack_ix())); | |
3546 } else if (src->is_address()) { | |
3547 __ movdbl(dest->as_xmm_double_reg(), as_Address(src->as_address_ptr())); | |
3548 } else { | |
3549 ShouldNotReachHere(); | |
3550 } | |
3551 | |
3552 } else if (src->is_double_fpu()) { | |
3553 assert(src->fpu_regnrLo() == 0, "must be TOS"); | |
3554 if (dest->is_double_stack()) { | |
3555 __ fistp_d(frame_map()->address_for_slot(dest->double_stack_ix())); | |
3556 } else if (dest->is_address()) { | |
3557 __ fistp_d(as_Address(dest->as_address_ptr())); | |
3558 } else { | |
3559 ShouldNotReachHere(); | |
3560 } | |
3561 | |
3562 } else if (dest->is_double_fpu()) { | |
3563 assert(dest->fpu_regnrLo() == 0, "must be TOS"); | |
3564 if (src->is_double_stack()) { | |
3565 __ fild_d(frame_map()->address_for_slot(src->double_stack_ix())); | |
3566 } else if (src->is_address()) { | |
3567 __ fild_d(as_Address(src->as_address_ptr())); | |
3568 } else { | |
3569 ShouldNotReachHere(); | |
3570 } | |
3571 } else { | |
3572 ShouldNotReachHere(); | |
3573 } | |
3574 } | |
3575 | |
3576 | |
3577 void LIR_Assembler::membar() { | |
304 | 3578 // QQQ sparc TSO uses this, |
3579 __ membar( Assembler::Membar_mask_bits(Assembler::StoreLoad)); | |
0 | 3580 } |
3581 | |
3582 void LIR_Assembler::membar_acquire() { | |
3583 // No x86 machines currently require load fences | |
3584 // __ load_fence(); | |
3585 } | |
3586 | |
3587 void LIR_Assembler::membar_release() { | |
3588 // No x86 machines currently require store fences | |
3589 // __ store_fence(); | |
3590 } | |
3591 | |
3592 void LIR_Assembler::get_thread(LIR_Opr result_reg) { | |
3593 assert(result_reg->is_register(), "check"); | |
304 | 3594 #ifdef _LP64 |
3595 // __ get_thread(result_reg->as_register_lo()); | |
3596 __ mov(result_reg->as_register(), r15_thread); | |
3597 #else | |
0 | 3598 __ get_thread(result_reg->as_register()); |
304 | 3599 #endif // _LP64 |
0 | 3600 } |
3601 | |
3602 | |
3603 void LIR_Assembler::peephole(LIR_List*) { | |
3604 // do nothing for now | |
3605 } | |
3606 | |
3607 | |
3608 #undef __ |