Mercurial > hg > truffle
annotate src/cpu/x86/vm/stubGenerator_x86_64.cpp @ 4582:b24386206122
Made all vm builds go into subdirectories, even product builds to simplify building the various types of VMs (server, client and graal).
Made HotSpot build jobs use the number of CPUs on the host machine.
author | Doug Simon <doug.simon@oracle.com> |
---|---|
date | Mon, 13 Feb 2012 23:13:37 +0100 |
parents | 82af018d61db |
children | 33df1aeaebbf |
rev | line source |
---|---|
0 | 1 /* |
2313
d89a22843c62
7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents:
2006
diff
changeset
|
2 * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. |
0 | 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * | |
5 * This code is free software; you can redistribute it and/or modify it | |
6 * under the terms of the GNU General Public License version 2 only, as | |
7 * published by the Free Software Foundation. | |
8 * | |
9 * This code is distributed in the hope that it will be useful, but WITHOUT | |
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
12 * version 2 for more details (a copy is included in the LICENSE file that | |
13 * accompanied this code). | |
14 * | |
15 * You should have received a copy of the GNU General Public License version | |
16 * 2 along with this work; if not, write to the Free Software Foundation, | |
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
18 * | |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1506
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1506
diff
changeset
|
20 * or visit www.oracle.com if you need additional information or have any |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1506
diff
changeset
|
21 * questions. |
0 | 22 * |
23 */ | |
24 | |
1972 | 25 #include "precompiled.hpp" |
26 #include "asm/assembler.hpp" | |
27 #include "assembler_x86.inline.hpp" | |
28 #include "interpreter/interpreter.hpp" | |
29 #include "nativeInst_x86.hpp" | |
30 #include "oops/instanceOop.hpp" | |
31 #include "oops/methodOop.hpp" | |
32 #include "oops/objArrayKlass.hpp" | |
33 #include "oops/oop.inline.hpp" | |
34 #include "prims/methodHandles.hpp" | |
35 #include "runtime/frame.inline.hpp" | |
36 #include "runtime/handles.inline.hpp" | |
37 #include "runtime/sharedRuntime.hpp" | |
38 #include "runtime/stubCodeGenerator.hpp" | |
39 #include "runtime/stubRoutines.hpp" | |
40 #include "utilities/top.hpp" | |
41 #ifdef TARGET_OS_FAMILY_linux | |
42 # include "thread_linux.inline.hpp" | |
43 #endif | |
44 #ifdef TARGET_OS_FAMILY_solaris | |
45 # include "thread_solaris.inline.hpp" | |
46 #endif | |
47 #ifdef TARGET_OS_FAMILY_windows | |
48 # include "thread_windows.inline.hpp" | |
49 #endif | |
3960 | 50 #ifdef TARGET_OS_FAMILY_bsd |
51 # include "thread_bsd.inline.hpp" | |
52 #endif | |
1972 | 53 #ifdef COMPILER2 |
54 #include "opto/runtime.hpp" | |
55 #endif | |
0 | 56 |
57 // Declaration and definition of StubGenerator (no .hpp file). | |
58 // For a more detailed description of the stub routine structure | |
59 // see the comment in stubRoutines.hpp | |
60 | |
61 #define __ _masm-> | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
16
diff
changeset
|
62 #define TIMES_OOP (UseCompressedOops ? Address::times_4 : Address::times_8) |
304 | 63 #define a__ ((Assembler*)_masm)-> |
0 | 64 |
65 #ifdef PRODUCT | |
66 #define BLOCK_COMMENT(str) /* nothing */ | |
67 #else | |
68 #define BLOCK_COMMENT(str) __ block_comment(str) | |
69 #endif | |
70 | |
71 #define BIND(label) bind(label); BLOCK_COMMENT(#label ":") | |
72 const int MXCSR_MASK = 0xFFC0; // Mask out any pending exceptions | |
73 | |
74 // Stub Code definitions | |
75 | |
76 static address handle_unsafe_access() { | |
77 JavaThread* thread = JavaThread::current(); | |
78 address pc = thread->saved_exception_pc(); | |
79 // pc is the instruction which we must emulate | |
80 // doing a no-op is fine: return garbage from the load | |
81 // therefore, compute npc | |
82 address npc = Assembler::locate_next_instruction(pc); | |
83 | |
84 // request an async exception | |
85 thread->set_pending_unsafe_access_error(); | |
86 | |
87 // return address of next instruction to execute | |
88 return npc; | |
89 } | |
90 | |
91 class StubGenerator: public StubCodeGenerator { | |
92 private: | |
93 | |
94 #ifdef PRODUCT | |
95 #define inc_counter_np(counter) (0) | |
96 #else | |
97 void inc_counter_np_(int& counter) { | |
4118
59bc0d4d9ea3
7110489: C1: 64-bit tiered with ForceUnreachable: assert(reachable(src)) failed: Address should be reachable
never
parents:
4114
diff
changeset
|
98 // This can destroy rscratch1 if counter is far from the code cache |
0 | 99 __ incrementl(ExternalAddress((address)&counter)); |
100 } | |
101 #define inc_counter_np(counter) \ | |
102 BLOCK_COMMENT("inc_counter " #counter); \ | |
103 inc_counter_np_(counter); | |
104 #endif | |
105 | |
106 // Call stubs are used to call Java from C | |
107 // | |
108 // Linux Arguments: | |
109 // c_rarg0: call wrapper address address | |
110 // c_rarg1: result address | |
111 // c_rarg2: result type BasicType | |
112 // c_rarg3: method methodOop | |
113 // c_rarg4: (interpreter) entry point address | |
114 // c_rarg5: parameters intptr_t* | |
115 // 16(rbp): parameter size (in words) int | |
116 // 24(rbp): thread Thread* | |
117 // | |
118 // [ return_from_Java ] <--- rsp | |
119 // [ argument word n ] | |
120 // ... | |
121 // -12 [ argument word 1 ] | |
122 // -11 [ saved r15 ] <--- rsp_after_call | |
123 // -10 [ saved r14 ] | |
124 // -9 [ saved r13 ] | |
125 // -8 [ saved r12 ] | |
126 // -7 [ saved rbx ] | |
127 // -6 [ call wrapper ] | |
128 // -5 [ result ] | |
129 // -4 [ result type ] | |
130 // -3 [ method ] | |
131 // -2 [ entry point ] | |
132 // -1 [ parameters ] | |
133 // 0 [ saved rbp ] <--- rbp | |
134 // 1 [ return address ] | |
135 // 2 [ parameter size ] | |
136 // 3 [ thread ] | |
137 // | |
138 // Windows Arguments: | |
139 // c_rarg0: call wrapper address address | |
140 // c_rarg1: result address | |
141 // c_rarg2: result type BasicType | |
142 // c_rarg3: method methodOop | |
143 // 48(rbp): (interpreter) entry point address | |
144 // 56(rbp): parameters intptr_t* | |
145 // 64(rbp): parameter size (in words) int | |
146 // 72(rbp): thread Thread* | |
147 // | |
148 // [ return_from_Java ] <--- rsp | |
149 // [ argument word n ] | |
150 // ... | |
2407
b1c22848507b
6741940: Nonvolatile XMM registers not preserved across JNI calls
iveresov
parents:
2324
diff
changeset
|
151 // -28 [ argument word 1 ] |
b1c22848507b
6741940: Nonvolatile XMM registers not preserved across JNI calls
iveresov
parents:
2324
diff
changeset
|
152 // -27 [ saved xmm15 ] <--- rsp_after_call |
b1c22848507b
6741940: Nonvolatile XMM registers not preserved across JNI calls
iveresov
parents:
2324
diff
changeset
|
153 // [ saved xmm7-xmm14 ] |
b1c22848507b
6741940: Nonvolatile XMM registers not preserved across JNI calls
iveresov
parents:
2324
diff
changeset
|
154 // -9 [ saved xmm6 ] (each xmm register takes 2 slots) |
b1c22848507b
6741940: Nonvolatile XMM registers not preserved across JNI calls
iveresov
parents:
2324
diff
changeset
|
155 // -7 [ saved r15 ] |
0 | 156 // -6 [ saved r14 ] |
157 // -5 [ saved r13 ] | |
158 // -4 [ saved r12 ] | |
159 // -3 [ saved rdi ] | |
160 // -2 [ saved rsi ] | |
161 // -1 [ saved rbx ] | |
162 // 0 [ saved rbp ] <--- rbp | |
163 // 1 [ return address ] | |
164 // 2 [ call wrapper ] | |
165 // 3 [ result ] | |
166 // 4 [ result type ] | |
167 // 5 [ method ] | |
168 // 6 [ entry point ] | |
169 // 7 [ parameters ] | |
170 // 8 [ parameter size ] | |
171 // 9 [ thread ] | |
172 // | |
173 // Windows reserves the callers stack space for arguments 1-4. | |
174 // We spill c_rarg0-c_rarg3 to this space. | |
175 | |
176 // Call stub stack layout word offsets from rbp | |
177 enum call_stub_layout { | |
178 #ifdef _WIN64 | |
2407
b1c22848507b
6741940: Nonvolatile XMM registers not preserved across JNI calls
iveresov
parents:
2324
diff
changeset
|
179 xmm_save_first = 6, // save from xmm6 |
b1c22848507b
6741940: Nonvolatile XMM registers not preserved across JNI calls
iveresov
parents:
2324
diff
changeset
|
180 xmm_save_last = 15, // to xmm15 |
b1c22848507b
6741940: Nonvolatile XMM registers not preserved across JNI calls
iveresov
parents:
2324
diff
changeset
|
181 xmm_save_base = -9, |
b1c22848507b
6741940: Nonvolatile XMM registers not preserved across JNI calls
iveresov
parents:
2324
diff
changeset
|
182 rsp_after_call_off = xmm_save_base - 2 * (xmm_save_last - xmm_save_first), // -27 |
b1c22848507b
6741940: Nonvolatile XMM registers not preserved across JNI calls
iveresov
parents:
2324
diff
changeset
|
183 r15_off = -7, |
0 | 184 r14_off = -6, |
185 r13_off = -5, | |
186 r12_off = -4, | |
187 rdi_off = -3, | |
188 rsi_off = -2, | |
189 rbx_off = -1, | |
190 rbp_off = 0, | |
191 retaddr_off = 1, | |
192 call_wrapper_off = 2, | |
193 result_off = 3, | |
194 result_type_off = 4, | |
195 method_off = 5, | |
196 entry_point_off = 6, | |
197 parameters_off = 7, | |
198 parameter_size_off = 8, | |
199 thread_off = 9 | |
200 #else | |
201 rsp_after_call_off = -12, | |
202 mxcsr_off = rsp_after_call_off, | |
203 r15_off = -11, | |
204 r14_off = -10, | |
205 r13_off = -9, | |
206 r12_off = -8, | |
207 rbx_off = -7, | |
208 call_wrapper_off = -6, | |
209 result_off = -5, | |
210 result_type_off = -4, | |
211 method_off = -3, | |
212 entry_point_off = -2, | |
213 parameters_off = -1, | |
214 rbp_off = 0, | |
215 retaddr_off = 1, | |
216 parameter_size_off = 2, | |
217 thread_off = 3 | |
218 #endif | |
219 }; | |
220 | |
2407
b1c22848507b
6741940: Nonvolatile XMM registers not preserved across JNI calls
iveresov
parents:
2324
diff
changeset
|
221 #ifdef _WIN64 |
b1c22848507b
6741940: Nonvolatile XMM registers not preserved across JNI calls
iveresov
parents:
2324
diff
changeset
|
222 Address xmm_save(int reg) { |
b1c22848507b
6741940: Nonvolatile XMM registers not preserved across JNI calls
iveresov
parents:
2324
diff
changeset
|
223 assert(reg >= xmm_save_first && reg <= xmm_save_last, "XMM register number out of range"); |
b1c22848507b
6741940: Nonvolatile XMM registers not preserved across JNI calls
iveresov
parents:
2324
diff
changeset
|
224 return Address(rbp, (xmm_save_base - (reg - xmm_save_first) * 2) * wordSize); |
b1c22848507b
6741940: Nonvolatile XMM registers not preserved across JNI calls
iveresov
parents:
2324
diff
changeset
|
225 } |
b1c22848507b
6741940: Nonvolatile XMM registers not preserved across JNI calls
iveresov
parents:
2324
diff
changeset
|
226 #endif |
b1c22848507b
6741940: Nonvolatile XMM registers not preserved across JNI calls
iveresov
parents:
2324
diff
changeset
|
227 |
0 | 228 address generate_call_stub(address& return_address) { |
229 assert((int)frame::entry_frame_after_call_words == -(int)rsp_after_call_off + 1 && | |
230 (int)frame::entry_frame_call_wrapper_offset == (int)call_wrapper_off, | |
231 "adjust this code"); | |
232 StubCodeMark mark(this, "StubRoutines", "call_stub"); | |
233 address start = __ pc(); | |
234 | |
235 // same as in generate_catch_exception()! | |
236 const Address rsp_after_call(rbp, rsp_after_call_off * wordSize); | |
237 | |
238 const Address call_wrapper (rbp, call_wrapper_off * wordSize); | |
239 const Address result (rbp, result_off * wordSize); | |
240 const Address result_type (rbp, result_type_off * wordSize); | |
241 const Address method (rbp, method_off * wordSize); | |
242 const Address entry_point (rbp, entry_point_off * wordSize); | |
243 const Address parameters (rbp, parameters_off * wordSize); | |
244 const Address parameter_size(rbp, parameter_size_off * wordSize); | |
245 | |
246 // same as in generate_catch_exception()! | |
247 const Address thread (rbp, thread_off * wordSize); | |
248 | |
249 const Address r15_save(rbp, r15_off * wordSize); | |
250 const Address r14_save(rbp, r14_off * wordSize); | |
251 const Address r13_save(rbp, r13_off * wordSize); | |
252 const Address r12_save(rbp, r12_off * wordSize); | |
253 const Address rbx_save(rbp, rbx_off * wordSize); | |
254 | |
255 // stub code | |
256 __ enter(); | |
304 | 257 __ subptr(rsp, -rsp_after_call_off * wordSize); |
0 | 258 |
259 // save register parameters | |
260 #ifndef _WIN64 | |
304 | 261 __ movptr(parameters, c_rarg5); // parameters |
262 __ movptr(entry_point, c_rarg4); // entry_point | |
0 | 263 #endif |
264 | |
304 | 265 __ movptr(method, c_rarg3); // method |
266 __ movl(result_type, c_rarg2); // result type | |
267 __ movptr(result, c_rarg1); // result | |
268 __ movptr(call_wrapper, c_rarg0); // call wrapper | |
0 | 269 |
270 // save regs belonging to calling function | |
304 | 271 __ movptr(rbx_save, rbx); |
272 __ movptr(r12_save, r12); | |
273 __ movptr(r13_save, r13); | |
274 __ movptr(r14_save, r14); | |
275 __ movptr(r15_save, r15); | |
0 | 276 #ifdef _WIN64 |
2407
b1c22848507b
6741940: Nonvolatile XMM registers not preserved across JNI calls
iveresov
parents:
2324
diff
changeset
|
277 for (int i = 6; i <= 15; i++) { |
b1c22848507b
6741940: Nonvolatile XMM registers not preserved across JNI calls
iveresov
parents:
2324
diff
changeset
|
278 __ movdqu(xmm_save(i), as_XMMRegister(i)); |
b1c22848507b
6741940: Nonvolatile XMM registers not preserved across JNI calls
iveresov
parents:
2324
diff
changeset
|
279 } |
b1c22848507b
6741940: Nonvolatile XMM registers not preserved across JNI calls
iveresov
parents:
2324
diff
changeset
|
280 |
0 | 281 const Address rdi_save(rbp, rdi_off * wordSize); |
282 const Address rsi_save(rbp, rsi_off * wordSize); | |
283 | |
304 | 284 __ movptr(rsi_save, rsi); |
285 __ movptr(rdi_save, rdi); | |
0 | 286 #else |
287 const Address mxcsr_save(rbp, mxcsr_off * wordSize); | |
288 { | |
289 Label skip_ldmx; | |
290 __ stmxcsr(mxcsr_save); | |
291 __ movl(rax, mxcsr_save); | |
292 __ andl(rax, MXCSR_MASK); // Only check control and mask bits | |
304 | 293 ExternalAddress mxcsr_std(StubRoutines::x86::mxcsr_std()); |
0 | 294 __ cmp32(rax, mxcsr_std); |
295 __ jcc(Assembler::equal, skip_ldmx); | |
296 __ ldmxcsr(mxcsr_std); | |
297 __ bind(skip_ldmx); | |
298 } | |
299 #endif | |
300 | |
301 // Load up thread register | |
304 | 302 __ movptr(r15_thread, thread); |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
16
diff
changeset
|
303 __ reinit_heapbase(); |
0 | 304 |
305 #ifdef ASSERT | |
306 // make sure we have no pending exceptions | |
307 { | |
308 Label L; | |
304 | 309 __ cmpptr(Address(r15_thread, Thread::pending_exception_offset()), (int32_t)NULL_WORD); |
0 | 310 __ jcc(Assembler::equal, L); |
311 __ stop("StubRoutines::call_stub: entered with pending exception"); | |
312 __ bind(L); | |
313 } | |
314 #endif | |
315 | |
316 // pass parameters if any | |
317 BLOCK_COMMENT("pass parameters if any"); | |
318 Label parameters_done; | |
319 __ movl(c_rarg3, parameter_size); | |
320 __ testl(c_rarg3, c_rarg3); | |
321 __ jcc(Assembler::zero, parameters_done); | |
322 | |
323 Label loop; | |
304 | 324 __ movptr(c_rarg2, parameters); // parameter pointer |
325 __ movl(c_rarg1, c_rarg3); // parameter counter is in c_rarg1 | |
0 | 326 __ BIND(loop); |
304 | 327 __ movptr(rax, Address(c_rarg2, 0));// get parameter |
328 __ addptr(c_rarg2, wordSize); // advance to next parameter | |
329 __ decrementl(c_rarg1); // decrement counter | |
330 __ push(rax); // pass parameter | |
0 | 331 __ jcc(Assembler::notZero, loop); |
332 | |
333 // call Java function | |
334 __ BIND(parameters_done); | |
304 | 335 __ movptr(rbx, method); // get methodOop |
336 __ movptr(c_rarg1, entry_point); // get entry_point | |
337 __ mov(r13, rsp); // set sender sp | |
0 | 338 BLOCK_COMMENT("call Java function"); |
339 __ call(c_rarg1); | |
340 | |
341 BLOCK_COMMENT("call_stub_return_address:"); | |
342 return_address = __ pc(); | |
343 | |
344 // store result depending on type (everything that is not | |
345 // T_OBJECT, T_LONG, T_FLOAT or T_DOUBLE is treated as T_INT) | |
304 | 346 __ movptr(c_rarg0, result); |
0 | 347 Label is_long, is_float, is_double, exit; |
348 __ movl(c_rarg1, result_type); | |
349 __ cmpl(c_rarg1, T_OBJECT); | |
350 __ jcc(Assembler::equal, is_long); | |
351 __ cmpl(c_rarg1, T_LONG); | |
352 __ jcc(Assembler::equal, is_long); | |
353 __ cmpl(c_rarg1, T_FLOAT); | |
354 __ jcc(Assembler::equal, is_float); | |
355 __ cmpl(c_rarg1, T_DOUBLE); | |
356 __ jcc(Assembler::equal, is_double); | |
357 | |
358 // handle T_INT case | |
359 __ movl(Address(c_rarg0, 0), rax); | |
360 | |
361 __ BIND(exit); | |
362 | |
363 // pop parameters | |
304 | 364 __ lea(rsp, rsp_after_call); |
0 | 365 |
366 #ifdef ASSERT | |
367 // verify that threads correspond | |
368 { | |
369 Label L, S; | |
304 | 370 __ cmpptr(r15_thread, thread); |
0 | 371 __ jcc(Assembler::notEqual, S); |
372 __ get_thread(rbx); | |
304 | 373 __ cmpptr(r15_thread, rbx); |
0 | 374 __ jcc(Assembler::equal, L); |
375 __ bind(S); | |
376 __ jcc(Assembler::equal, L); | |
377 __ stop("StubRoutines::call_stub: threads must correspond"); | |
378 __ bind(L); | |
379 } | |
380 #endif | |
381 | |
382 // restore regs belonging to calling function | |
2407
b1c22848507b
6741940: Nonvolatile XMM registers not preserved across JNI calls
iveresov
parents:
2324
diff
changeset
|
383 #ifdef _WIN64 |
b1c22848507b
6741940: Nonvolatile XMM registers not preserved across JNI calls
iveresov
parents:
2324
diff
changeset
|
384 for (int i = 15; i >= 6; i--) { |
b1c22848507b
6741940: Nonvolatile XMM registers not preserved across JNI calls
iveresov
parents:
2324
diff
changeset
|
385 __ movdqu(as_XMMRegister(i), xmm_save(i)); |
b1c22848507b
6741940: Nonvolatile XMM registers not preserved across JNI calls
iveresov
parents:
2324
diff
changeset
|
386 } |
b1c22848507b
6741940: Nonvolatile XMM registers not preserved across JNI calls
iveresov
parents:
2324
diff
changeset
|
387 #endif |
304 | 388 __ movptr(r15, r15_save); |
389 __ movptr(r14, r14_save); | |
390 __ movptr(r13, r13_save); | |
391 __ movptr(r12, r12_save); | |
392 __ movptr(rbx, rbx_save); | |
0 | 393 |
394 #ifdef _WIN64 | |
304 | 395 __ movptr(rdi, rdi_save); |
396 __ movptr(rsi, rsi_save); | |
0 | 397 #else |
398 __ ldmxcsr(mxcsr_save); | |
399 #endif | |
400 | |
401 // restore rsp | |
304 | 402 __ addptr(rsp, -rsp_after_call_off * wordSize); |
0 | 403 |
404 // return | |
304 | 405 __ pop(rbp); |
0 | 406 __ ret(0); |
407 | |
408 // handle return types different from T_INT | |
409 __ BIND(is_long); | |
410 __ movq(Address(c_rarg0, 0), rax); | |
411 __ jmp(exit); | |
412 | |
413 __ BIND(is_float); | |
414 __ movflt(Address(c_rarg0, 0), xmm0); | |
415 __ jmp(exit); | |
416 | |
417 __ BIND(is_double); | |
418 __ movdbl(Address(c_rarg0, 0), xmm0); | |
419 __ jmp(exit); | |
420 | |
421 return start; | |
422 } | |
423 | |
424 // Return point for a Java call if there's an exception thrown in | |
425 // Java code. The exception is caught and transformed into a | |
426 // pending exception stored in JavaThread that can be tested from | |
427 // within the VM. | |
428 // | |
429 // Note: Usually the parameters are removed by the callee. In case | |
430 // of an exception crossing an activation frame boundary, that is | |
431 // not the case if the callee is compiled code => need to setup the | |
432 // rsp. | |
433 // | |
434 // rax: exception oop | |
435 | |
436 address generate_catch_exception() { | |
437 StubCodeMark mark(this, "StubRoutines", "catch_exception"); | |
438 address start = __ pc(); | |
439 | |
440 // same as in generate_call_stub(): | |
441 const Address rsp_after_call(rbp, rsp_after_call_off * wordSize); | |
442 const Address thread (rbp, thread_off * wordSize); | |
443 | |
444 #ifdef ASSERT | |
445 // verify that threads correspond | |
446 { | |
447 Label L, S; | |
304 | 448 __ cmpptr(r15_thread, thread); |
0 | 449 __ jcc(Assembler::notEqual, S); |
450 __ get_thread(rbx); | |
304 | 451 __ cmpptr(r15_thread, rbx); |
0 | 452 __ jcc(Assembler::equal, L); |
453 __ bind(S); | |
454 __ stop("StubRoutines::catch_exception: threads must correspond"); | |
455 __ bind(L); | |
456 } | |
457 #endif | |
458 | |
459 // set pending exception | |
460 __ verify_oop(rax); | |
461 | |
304 | 462 __ movptr(Address(r15_thread, Thread::pending_exception_offset()), rax); |
0 | 463 __ lea(rscratch1, ExternalAddress((address)__FILE__)); |
304 | 464 __ movptr(Address(r15_thread, Thread::exception_file_offset()), rscratch1); |
0 | 465 __ movl(Address(r15_thread, Thread::exception_line_offset()), (int) __LINE__); |
466 | |
467 // complete return to VM | |
468 assert(StubRoutines::_call_stub_return_address != NULL, | |
469 "_call_stub_return_address must have been generated before"); | |
470 __ jump(RuntimeAddress(StubRoutines::_call_stub_return_address)); | |
471 | |
472 return start; | |
473 } | |
474 | |
475 // Continuation point for runtime calls returning with a pending | |
476 // exception. The pending exception check happened in the runtime | |
477 // or native call stub. The pending exception in Thread is | |
478 // converted into a Java-level exception. | |
479 // | |
480 // Contract with Java-level exception handlers: | |
481 // rax: exception | |
482 // rdx: throwing pc | |
483 // | |
484 // NOTE: At entry of this stub, exception-pc must be on stack !! | |
485 | |
486 address generate_forward_exception() { | |
487 StubCodeMark mark(this, "StubRoutines", "forward exception"); | |
488 address start = __ pc(); | |
489 | |
490 // Upon entry, the sp points to the return address returning into | |
491 // Java (interpreted or compiled) code; i.e., the return address | |
492 // becomes the throwing pc. | |
493 // | |
494 // Arguments pushed before the runtime call are still on the stack | |
495 // but the exception handler will reset the stack pointer -> | |
496 // ignore them. A potential result in registers can be ignored as | |
497 // well. | |
498 | |
499 #ifdef ASSERT | |
500 // make sure this code is only executed if there is a pending exception | |
501 { | |
502 Label L; | |
304 | 503 __ cmpptr(Address(r15_thread, Thread::pending_exception_offset()), (int32_t) NULL); |
0 | 504 __ jcc(Assembler::notEqual, L); |
505 __ stop("StubRoutines::forward exception: no pending exception (1)"); | |
506 __ bind(L); | |
507 } | |
508 #endif | |
509 | |
510 // compute exception handler into rbx | |
304 | 511 __ movptr(c_rarg0, Address(rsp, 0)); |
0 | 512 BLOCK_COMMENT("call exception_handler_for_return_address"); |
513 __ call_VM_leaf(CAST_FROM_FN_PTR(address, | |
514 SharedRuntime::exception_handler_for_return_address), | |
1295 | 515 r15_thread, c_rarg0); |
304 | 516 __ mov(rbx, rax); |
0 | 517 |
518 // setup rax & rdx, remove return address & clear pending exception | |
304 | 519 __ pop(rdx); |
520 __ movptr(rax, Address(r15_thread, Thread::pending_exception_offset())); | |
512
db4caa99ef11
6787106: Hotspot 32 bit build fails on platforms having different definitions for intptr_t & int32_t
xlu
parents:
405
diff
changeset
|
521 __ movptr(Address(r15_thread, Thread::pending_exception_offset()), (int32_t)NULL_WORD); |
0 | 522 |
523 #ifdef ASSERT | |
524 // make sure exception is set | |
525 { | |
526 Label L; | |
304 | 527 __ testptr(rax, rax); |
0 | 528 __ jcc(Assembler::notEqual, L); |
529 __ stop("StubRoutines::forward exception: no pending exception (2)"); | |
530 __ bind(L); | |
531 } | |
532 #endif | |
533 | |
534 // continue at exception handler (return address removed) | |
535 // rax: exception | |
536 // rbx: exception handler | |
537 // rdx: throwing pc | |
538 __ verify_oop(rax); | |
539 __ jmp(rbx); | |
540 | |
541 return start; | |
542 } | |
543 | |
544 // Support for jint atomic::xchg(jint exchange_value, volatile jint* dest) | |
545 // | |
546 // Arguments : | |
547 // c_rarg0: exchange_value | |
548 // c_rarg0: dest | |
549 // | |
550 // Result: | |
551 // *dest <- ex, return (orig *dest) | |
552 address generate_atomic_xchg() { | |
553 StubCodeMark mark(this, "StubRoutines", "atomic_xchg"); | |
554 address start = __ pc(); | |
555 | |
556 __ movl(rax, c_rarg0); // Copy to eax we need a return value anyhow | |
557 __ xchgl(rax, Address(c_rarg1, 0)); // automatic LOCK | |
558 __ ret(0); | |
559 | |
560 return start; | |
561 } | |
562 | |
563 // Support for intptr_t atomic::xchg_ptr(intptr_t exchange_value, volatile intptr_t* dest) | |
564 // | |
565 // Arguments : | |
566 // c_rarg0: exchange_value | |
567 // c_rarg1: dest | |
568 // | |
569 // Result: | |
570 // *dest <- ex, return (orig *dest) | |
571 address generate_atomic_xchg_ptr() { | |
572 StubCodeMark mark(this, "StubRoutines", "atomic_xchg_ptr"); | |
573 address start = __ pc(); | |
574 | |
304 | 575 __ movptr(rax, c_rarg0); // Copy to eax we need a return value anyhow |
576 __ xchgptr(rax, Address(c_rarg1, 0)); // automatic LOCK | |
0 | 577 __ ret(0); |
578 | |
579 return start; | |
580 } | |
581 | |
582 // Support for jint atomic::atomic_cmpxchg(jint exchange_value, volatile jint* dest, | |
583 // jint compare_value) | |
584 // | |
585 // Arguments : | |
586 // c_rarg0: exchange_value | |
587 // c_rarg1: dest | |
588 // c_rarg2: compare_value | |
589 // | |
590 // Result: | |
591 // if ( compare_value == *dest ) { | |
592 // *dest = exchange_value | |
593 // return compare_value; | |
594 // else | |
595 // return *dest; | |
596 address generate_atomic_cmpxchg() { | |
597 StubCodeMark mark(this, "StubRoutines", "atomic_cmpxchg"); | |
598 address start = __ pc(); | |
599 | |
600 __ movl(rax, c_rarg2); | |
601 if ( os::is_MP() ) __ lock(); | |
602 __ cmpxchgl(c_rarg0, Address(c_rarg1, 0)); | |
603 __ ret(0); | |
604 | |
605 return start; | |
606 } | |
607 | |
608 // Support for jint atomic::atomic_cmpxchg_long(jlong exchange_value, | |
609 // volatile jlong* dest, | |
610 // jlong compare_value) | |
611 // Arguments : | |
612 // c_rarg0: exchange_value | |
613 // c_rarg1: dest | |
614 // c_rarg2: compare_value | |
615 // | |
616 // Result: | |
617 // if ( compare_value == *dest ) { | |
618 // *dest = exchange_value | |
619 // return compare_value; | |
620 // else | |
621 // return *dest; | |
622 address generate_atomic_cmpxchg_long() { | |
623 StubCodeMark mark(this, "StubRoutines", "atomic_cmpxchg_long"); | |
624 address start = __ pc(); | |
625 | |
626 __ movq(rax, c_rarg2); | |
627 if ( os::is_MP() ) __ lock(); | |
628 __ cmpxchgq(c_rarg0, Address(c_rarg1, 0)); | |
629 __ ret(0); | |
630 | |
631 return start; | |
632 } | |
633 | |
634 // Support for jint atomic::add(jint add_value, volatile jint* dest) | |
635 // | |
636 // Arguments : | |
637 // c_rarg0: add_value | |
638 // c_rarg1: dest | |
639 // | |
640 // Result: | |
641 // *dest += add_value | |
642 // return *dest; | |
643 address generate_atomic_add() { | |
644 StubCodeMark mark(this, "StubRoutines", "atomic_add"); | |
645 address start = __ pc(); | |
646 | |
647 __ movl(rax, c_rarg0); | |
648 if ( os::is_MP() ) __ lock(); | |
649 __ xaddl(Address(c_rarg1, 0), c_rarg0); | |
650 __ addl(rax, c_rarg0); | |
651 __ ret(0); | |
652 | |
653 return start; | |
654 } | |
655 | |
656 // Support for intptr_t atomic::add_ptr(intptr_t add_value, volatile intptr_t* dest) | |
657 // | |
658 // Arguments : | |
659 // c_rarg0: add_value | |
660 // c_rarg1: dest | |
661 // | |
662 // Result: | |
663 // *dest += add_value | |
664 // return *dest; | |
665 address generate_atomic_add_ptr() { | |
666 StubCodeMark mark(this, "StubRoutines", "atomic_add_ptr"); | |
667 address start = __ pc(); | |
668 | |
304 | 669 __ movptr(rax, c_rarg0); // Copy to eax we need a return value anyhow |
0 | 670 if ( os::is_MP() ) __ lock(); |
304 | 671 __ xaddptr(Address(c_rarg1, 0), c_rarg0); |
672 __ addptr(rax, c_rarg0); | |
0 | 673 __ ret(0); |
674 | |
675 return start; | |
676 } | |
677 | |
678 // Support for intptr_t OrderAccess::fence() | |
679 // | |
680 // Arguments : | |
681 // | |
682 // Result: | |
683 address generate_orderaccess_fence() { | |
684 StubCodeMark mark(this, "StubRoutines", "orderaccess_fence"); | |
685 address start = __ pc(); | |
671
d0994e5bebce
6822204: volatile fences should prefer lock:addl to actual mfence instructions
never
parents:
647
diff
changeset
|
686 __ membar(Assembler::StoreLoad); |
0 | 687 __ ret(0); |
688 | |
689 return start; | |
690 } | |
691 | |
692 // Support for intptr_t get_previous_fp() | |
693 // | |
694 // This routine is used to find the previous frame pointer for the | |
695 // caller (current_frame_guess). This is used as part of debugging | |
696 // ps() is seemingly lost trying to find frames. | |
697 // This code assumes that caller current_frame_guess) has a frame. | |
698 address generate_get_previous_fp() { | |
699 StubCodeMark mark(this, "StubRoutines", "get_previous_fp"); | |
700 const Address old_fp(rbp, 0); | |
701 const Address older_fp(rax, 0); | |
702 address start = __ pc(); | |
703 | |
704 __ enter(); | |
304 | 705 __ movptr(rax, old_fp); // callers fp |
706 __ movptr(rax, older_fp); // the frame for ps() | |
707 __ pop(rbp); | |
0 | 708 __ ret(0); |
709 | |
710 return start; | |
711 } | |
712 | |
713 //---------------------------------------------------------------------------------------------------- | |
714 // Support for void verify_mxcsr() | |
715 // | |
716 // This routine is used with -Xcheck:jni to verify that native | |
717 // JNI code does not return to Java code without restoring the | |
718 // MXCSR register to our expected state. | |
719 | |
720 address generate_verify_mxcsr() { | |
721 StubCodeMark mark(this, "StubRoutines", "verify_mxcsr"); | |
722 address start = __ pc(); | |
723 | |
724 const Address mxcsr_save(rsp, 0); | |
725 | |
726 if (CheckJNICalls) { | |
727 Label ok_ret; | |
304 | 728 __ push(rax); |
729 __ subptr(rsp, wordSize); // allocate a temp location | |
0 | 730 __ stmxcsr(mxcsr_save); |
731 __ movl(rax, mxcsr_save); | |
732 __ andl(rax, MXCSR_MASK); // Only check control and mask bits | |
304 | 733 __ cmpl(rax, *(int *)(StubRoutines::x86::mxcsr_std())); |
0 | 734 __ jcc(Assembler::equal, ok_ret); |
735 | |
736 __ warn("MXCSR changed by native JNI code, use -XX:+RestoreMXCSROnJNICall"); | |
737 | |
304 | 738 __ ldmxcsr(ExternalAddress(StubRoutines::x86::mxcsr_std())); |
0 | 739 |
740 __ bind(ok_ret); | |
304 | 741 __ addptr(rsp, wordSize); |
742 __ pop(rax); | |
0 | 743 } |
744 | |
745 __ ret(0); | |
746 | |
747 return start; | |
748 } | |
749 | |
750 address generate_f2i_fixup() { | |
751 StubCodeMark mark(this, "StubRoutines", "f2i_fixup"); | |
752 Address inout(rsp, 5 * wordSize); // return address + 4 saves | |
753 | |
754 address start = __ pc(); | |
755 | |
756 Label L; | |
757 | |
304 | 758 __ push(rax); |
759 __ push(c_rarg3); | |
760 __ push(c_rarg2); | |
761 __ push(c_rarg1); | |
0 | 762 |
763 __ movl(rax, 0x7f800000); | |
764 __ xorl(c_rarg3, c_rarg3); | |
765 __ movl(c_rarg2, inout); | |
766 __ movl(c_rarg1, c_rarg2); | |
767 __ andl(c_rarg1, 0x7fffffff); | |
768 __ cmpl(rax, c_rarg1); // NaN? -> 0 | |
769 __ jcc(Assembler::negative, L); | |
770 __ testl(c_rarg2, c_rarg2); // signed ? min_jint : max_jint | |
771 __ movl(c_rarg3, 0x80000000); | |
772 __ movl(rax, 0x7fffffff); | |
773 __ cmovl(Assembler::positive, c_rarg3, rax); | |
774 | |
775 __ bind(L); | |
304 | 776 __ movptr(inout, c_rarg3); |
777 | |
778 __ pop(c_rarg1); | |
779 __ pop(c_rarg2); | |
780 __ pop(c_rarg3); | |
781 __ pop(rax); | |
0 | 782 |
783 __ ret(0); | |
784 | |
785 return start; | |
786 } | |
787 | |
788 address generate_f2l_fixup() { | |
789 StubCodeMark mark(this, "StubRoutines", "f2l_fixup"); | |
790 Address inout(rsp, 5 * wordSize); // return address + 4 saves | |
791 address start = __ pc(); | |
792 | |
793 Label L; | |
794 | |
304 | 795 __ push(rax); |
796 __ push(c_rarg3); | |
797 __ push(c_rarg2); | |
798 __ push(c_rarg1); | |
0 | 799 |
800 __ movl(rax, 0x7f800000); | |
801 __ xorl(c_rarg3, c_rarg3); | |
802 __ movl(c_rarg2, inout); | |
803 __ movl(c_rarg1, c_rarg2); | |
804 __ andl(c_rarg1, 0x7fffffff); | |
805 __ cmpl(rax, c_rarg1); // NaN? -> 0 | |
806 __ jcc(Assembler::negative, L); | |
807 __ testl(c_rarg2, c_rarg2); // signed ? min_jlong : max_jlong | |
808 __ mov64(c_rarg3, 0x8000000000000000); | |
809 __ mov64(rax, 0x7fffffffffffffff); | |
304 | 810 __ cmov(Assembler::positive, c_rarg3, rax); |
0 | 811 |
812 __ bind(L); | |
304 | 813 __ movptr(inout, c_rarg3); |
814 | |
815 __ pop(c_rarg1); | |
816 __ pop(c_rarg2); | |
817 __ pop(c_rarg3); | |
818 __ pop(rax); | |
0 | 819 |
820 __ ret(0); | |
821 | |
822 return start; | |
823 } | |
824 | |
825 address generate_d2i_fixup() { | |
826 StubCodeMark mark(this, "StubRoutines", "d2i_fixup"); | |
827 Address inout(rsp, 6 * wordSize); // return address + 5 saves | |
828 | |
829 address start = __ pc(); | |
830 | |
831 Label L; | |
832 | |
304 | 833 __ push(rax); |
834 __ push(c_rarg3); | |
835 __ push(c_rarg2); | |
836 __ push(c_rarg1); | |
837 __ push(c_rarg0); | |
0 | 838 |
839 __ movl(rax, 0x7ff00000); | |
840 __ movq(c_rarg2, inout); | |
841 __ movl(c_rarg3, c_rarg2); | |
304 | 842 __ mov(c_rarg1, c_rarg2); |
843 __ mov(c_rarg0, c_rarg2); | |
0 | 844 __ negl(c_rarg3); |
304 | 845 __ shrptr(c_rarg1, 0x20); |
0 | 846 __ orl(c_rarg3, c_rarg2); |
847 __ andl(c_rarg1, 0x7fffffff); | |
848 __ xorl(c_rarg2, c_rarg2); | |
849 __ shrl(c_rarg3, 0x1f); | |
850 __ orl(c_rarg1, c_rarg3); | |
851 __ cmpl(rax, c_rarg1); | |
852 __ jcc(Assembler::negative, L); // NaN -> 0 | |
304 | 853 __ testptr(c_rarg0, c_rarg0); // signed ? min_jint : max_jint |
0 | 854 __ movl(c_rarg2, 0x80000000); |
855 __ movl(rax, 0x7fffffff); | |
304 | 856 __ cmov(Assembler::positive, c_rarg2, rax); |
0 | 857 |
858 __ bind(L); | |
304 | 859 __ movptr(inout, c_rarg2); |
860 | |
861 __ pop(c_rarg0); | |
862 __ pop(c_rarg1); | |
863 __ pop(c_rarg2); | |
864 __ pop(c_rarg3); | |
865 __ pop(rax); | |
0 | 866 |
867 __ ret(0); | |
868 | |
869 return start; | |
870 } | |
871 | |
872 address generate_d2l_fixup() { | |
873 StubCodeMark mark(this, "StubRoutines", "d2l_fixup"); | |
874 Address inout(rsp, 6 * wordSize); // return address + 5 saves | |
875 | |
876 address start = __ pc(); | |
877 | |
878 Label L; | |
879 | |
304 | 880 __ push(rax); |
881 __ push(c_rarg3); | |
882 __ push(c_rarg2); | |
883 __ push(c_rarg1); | |
884 __ push(c_rarg0); | |
0 | 885 |
886 __ movl(rax, 0x7ff00000); | |
887 __ movq(c_rarg2, inout); | |
888 __ movl(c_rarg3, c_rarg2); | |
304 | 889 __ mov(c_rarg1, c_rarg2); |
890 __ mov(c_rarg0, c_rarg2); | |
0 | 891 __ negl(c_rarg3); |
304 | 892 __ shrptr(c_rarg1, 0x20); |
0 | 893 __ orl(c_rarg3, c_rarg2); |
894 __ andl(c_rarg1, 0x7fffffff); | |
895 __ xorl(c_rarg2, c_rarg2); | |
896 __ shrl(c_rarg3, 0x1f); | |
897 __ orl(c_rarg1, c_rarg3); | |
898 __ cmpl(rax, c_rarg1); | |
899 __ jcc(Assembler::negative, L); // NaN -> 0 | |
900 __ testq(c_rarg0, c_rarg0); // signed ? min_jlong : max_jlong | |
901 __ mov64(c_rarg2, 0x8000000000000000); | |
902 __ mov64(rax, 0x7fffffffffffffff); | |
903 __ cmovq(Assembler::positive, c_rarg2, rax); | |
904 | |
905 __ bind(L); | |
906 __ movq(inout, c_rarg2); | |
907 | |
304 | 908 __ pop(c_rarg0); |
909 __ pop(c_rarg1); | |
910 __ pop(c_rarg2); | |
911 __ pop(c_rarg3); | |
912 __ pop(rax); | |
0 | 913 |
914 __ ret(0); | |
915 | |
916 return start; | |
917 } | |
918 | |
919 address generate_fp_mask(const char *stub_name, int64_t mask) { | |
1365 | 920 __ align(CodeEntryAlignment); |
0 | 921 StubCodeMark mark(this, "StubRoutines", stub_name); |
922 address start = __ pc(); | |
923 | |
924 __ emit_data64( mask, relocInfo::none ); | |
925 __ emit_data64( mask, relocInfo::none ); | |
926 | |
927 return start; | |
928 } | |
929 | |
930 // The following routine generates a subroutine to throw an | |
931 // asynchronous UnknownError when an unsafe access gets a fault that | |
932 // could not be reasonably prevented by the programmer. (Example: | |
933 // SIGBUS/OBJERR.) | |
934 address generate_handler_for_unsafe_access() { | |
935 StubCodeMark mark(this, "StubRoutines", "handler_for_unsafe_access"); | |
936 address start = __ pc(); | |
937 | |
304 | 938 __ push(0); // hole for return address-to-be |
939 __ pusha(); // push registers | |
0 | 940 Address next_pc(rsp, RegisterImpl::number_of_registers * BytesPerWord); |
941 | |
3937 | 942 // FIXME: this probably needs alignment logic |
943 | |
304 | 944 __ subptr(rsp, frame::arg_reg_save_area_bytes); |
0 | 945 BLOCK_COMMENT("call handle_unsafe_access"); |
946 __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, handle_unsafe_access))); | |
304 | 947 __ addptr(rsp, frame::arg_reg_save_area_bytes); |
948 | |
949 __ movptr(next_pc, rax); // stuff next address | |
950 __ popa(); | |
0 | 951 __ ret(0); // jump to next address |
952 | |
953 return start; | |
954 } | |
955 | |
956 // Non-destructive plausibility checks for oops | |
957 // | |
958 // Arguments: | |
959 // all args on stack! | |
960 // | |
961 // Stack after saving c_rarg3: | |
962 // [tos + 0]: saved c_rarg3 | |
963 // [tos + 1]: saved c_rarg2 | |
124
b130b98db9cf
6689060: Escape Analysis does not work with Compressed Oops
kvn
parents:
113
diff
changeset
|
964 // [tos + 2]: saved r12 (several TemplateTable methods use it) |
b130b98db9cf
6689060: Escape Analysis does not work with Compressed Oops
kvn
parents:
113
diff
changeset
|
965 // [tos + 3]: saved flags |
b130b98db9cf
6689060: Escape Analysis does not work with Compressed Oops
kvn
parents:
113
diff
changeset
|
966 // [tos + 4]: return address |
b130b98db9cf
6689060: Escape Analysis does not work with Compressed Oops
kvn
parents:
113
diff
changeset
|
967 // * [tos + 5]: error message (char*) |
b130b98db9cf
6689060: Escape Analysis does not work with Compressed Oops
kvn
parents:
113
diff
changeset
|
968 // * [tos + 6]: object to verify (oop) |
b130b98db9cf
6689060: Escape Analysis does not work with Compressed Oops
kvn
parents:
113
diff
changeset
|
969 // * [tos + 7]: saved rax - saved by caller and bashed |
1583 | 970 // * [tos + 8]: saved r10 (rscratch1) - saved by caller |
0 | 971 // * = popped on exit |
972 address generate_verify_oop() { | |
973 StubCodeMark mark(this, "StubRoutines", "verify_oop"); | |
974 address start = __ pc(); | |
975 | |
976 Label exit, error; | |
977 | |
304 | 978 __ pushf(); |
0 | 979 __ incrementl(ExternalAddress((address) StubRoutines::verify_oop_count_addr())); |
980 | |
304 | 981 __ push(r12); |
124
b130b98db9cf
6689060: Escape Analysis does not work with Compressed Oops
kvn
parents:
113
diff
changeset
|
982 |
0 | 983 // save c_rarg2 and c_rarg3 |
304 | 984 __ push(c_rarg2); |
985 __ push(c_rarg3); | |
0 | 986 |
124
b130b98db9cf
6689060: Escape Analysis does not work with Compressed Oops
kvn
parents:
113
diff
changeset
|
987 enum { |
b130b98db9cf
6689060: Escape Analysis does not work with Compressed Oops
kvn
parents:
113
diff
changeset
|
988 // After previous pushes. |
b130b98db9cf
6689060: Escape Analysis does not work with Compressed Oops
kvn
parents:
113
diff
changeset
|
989 oop_to_verify = 6 * wordSize, |
b130b98db9cf
6689060: Escape Analysis does not work with Compressed Oops
kvn
parents:
113
diff
changeset
|
990 saved_rax = 7 * wordSize, |
1583 | 991 saved_r10 = 8 * wordSize, |
124
b130b98db9cf
6689060: Escape Analysis does not work with Compressed Oops
kvn
parents:
113
diff
changeset
|
992 |
b130b98db9cf
6689060: Escape Analysis does not work with Compressed Oops
kvn
parents:
113
diff
changeset
|
993 // Before the call to MacroAssembler::debug(), see below. |
b130b98db9cf
6689060: Escape Analysis does not work with Compressed Oops
kvn
parents:
113
diff
changeset
|
994 return_addr = 16 * wordSize, |
b130b98db9cf
6689060: Escape Analysis does not work with Compressed Oops
kvn
parents:
113
diff
changeset
|
995 error_msg = 17 * wordSize |
b130b98db9cf
6689060: Escape Analysis does not work with Compressed Oops
kvn
parents:
113
diff
changeset
|
996 }; |
b130b98db9cf
6689060: Escape Analysis does not work with Compressed Oops
kvn
parents:
113
diff
changeset
|
997 |
0 | 998 // get object |
304 | 999 __ movptr(rax, Address(rsp, oop_to_verify)); |
0 | 1000 |
1001 // make sure object is 'reasonable' | |
304 | 1002 __ testptr(rax, rax); |
0 | 1003 __ jcc(Assembler::zero, exit); // if obj is NULL it is OK |
1004 // Check if the oop is in the right area of memory | |
304 | 1005 __ movptr(c_rarg2, rax); |
512
db4caa99ef11
6787106: Hotspot 32 bit build fails on platforms having different definitions for intptr_t & int32_t
xlu
parents:
405
diff
changeset
|
1006 __ movptr(c_rarg3, (intptr_t) Universe::verify_oop_mask()); |
304 | 1007 __ andptr(c_rarg2, c_rarg3); |
512
db4caa99ef11
6787106: Hotspot 32 bit build fails on platforms having different definitions for intptr_t & int32_t
xlu
parents:
405
diff
changeset
|
1008 __ movptr(c_rarg3, (intptr_t) Universe::verify_oop_bits()); |
304 | 1009 __ cmpptr(c_rarg2, c_rarg3); |
0 | 1010 __ jcc(Assembler::notZero, error); |
1011 | |
124
b130b98db9cf
6689060: Escape Analysis does not work with Compressed Oops
kvn
parents:
113
diff
changeset
|
1012 // set r12 to heapbase for load_klass() |
b130b98db9cf
6689060: Escape Analysis does not work with Compressed Oops
kvn
parents:
113
diff
changeset
|
1013 __ reinit_heapbase(); |
b130b98db9cf
6689060: Escape Analysis does not work with Compressed Oops
kvn
parents:
113
diff
changeset
|
1014 |
0 | 1015 // make sure klass is 'reasonable' |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
16
diff
changeset
|
1016 __ load_klass(rax, rax); // get klass |
304 | 1017 __ testptr(rax, rax); |
0 | 1018 __ jcc(Assembler::zero, error); // if klass is NULL it is broken |
1019 // Check if the klass is in the right area of memory | |
304 | 1020 __ mov(c_rarg2, rax); |
512
db4caa99ef11
6787106: Hotspot 32 bit build fails on platforms having different definitions for intptr_t & int32_t
xlu
parents:
405
diff
changeset
|
1021 __ movptr(c_rarg3, (intptr_t) Universe::verify_klass_mask()); |
304 | 1022 __ andptr(c_rarg2, c_rarg3); |
512
db4caa99ef11
6787106: Hotspot 32 bit build fails on platforms having different definitions for intptr_t & int32_t
xlu
parents:
405
diff
changeset
|
1023 __ movptr(c_rarg3, (intptr_t) Universe::verify_klass_bits()); |
304 | 1024 __ cmpptr(c_rarg2, c_rarg3); |
0 | 1025 __ jcc(Assembler::notZero, error); |
1026 | |
1027 // make sure klass' klass is 'reasonable' | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
16
diff
changeset
|
1028 __ load_klass(rax, rax); |
304 | 1029 __ testptr(rax, rax); |
0 | 1030 __ jcc(Assembler::zero, error); // if klass' klass is NULL it is broken |
1031 // Check if the klass' klass is in the right area of memory | |
512
db4caa99ef11
6787106: Hotspot 32 bit build fails on platforms having different definitions for intptr_t & int32_t
xlu
parents:
405
diff
changeset
|
1032 __ movptr(c_rarg3, (intptr_t) Universe::verify_klass_mask()); |
304 | 1033 __ andptr(rax, c_rarg3); |
512
db4caa99ef11
6787106: Hotspot 32 bit build fails on platforms having different definitions for intptr_t & int32_t
xlu
parents:
405
diff
changeset
|
1034 __ movptr(c_rarg3, (intptr_t) Universe::verify_klass_bits()); |
304 | 1035 __ cmpptr(rax, c_rarg3); |
0 | 1036 __ jcc(Assembler::notZero, error); |
1037 | |
1038 // return if everything seems ok | |
1039 __ bind(exit); | |
304 | 1040 __ movptr(rax, Address(rsp, saved_rax)); // get saved rax back |
1583 | 1041 __ movptr(rscratch1, Address(rsp, saved_r10)); // get saved r10 back |
304 | 1042 __ pop(c_rarg3); // restore c_rarg3 |
1043 __ pop(c_rarg2); // restore c_rarg2 | |
1044 __ pop(r12); // restore r12 | |
1045 __ popf(); // restore flags | |
1583 | 1046 __ ret(4 * wordSize); // pop caller saved stuff |
0 | 1047 |
1048 // handle errors | |
1049 __ bind(error); | |
304 | 1050 __ movptr(rax, Address(rsp, saved_rax)); // get saved rax back |
1583 | 1051 __ movptr(rscratch1, Address(rsp, saved_r10)); // get saved r10 back |
304 | 1052 __ pop(c_rarg3); // get saved c_rarg3 back |
1053 __ pop(c_rarg2); // get saved c_rarg2 back | |
1054 __ pop(r12); // get saved r12 back | |
1055 __ popf(); // get saved flags off stack -- | |
0 | 1056 // will be ignored |
1057 | |
304 | 1058 __ pusha(); // push registers |
0 | 1059 // (rip is already |
1060 // already pushed) | |
124
b130b98db9cf
6689060: Escape Analysis does not work with Compressed Oops
kvn
parents:
113
diff
changeset
|
1061 // debug(char* msg, int64_t pc, int64_t regs[]) |
0 | 1062 // We've popped the registers we'd saved (c_rarg3, c_rarg2 and flags), and |
1063 // pushed all the registers, so now the stack looks like: | |
1064 // [tos + 0] 16 saved registers | |
1065 // [tos + 16] return address | |
124
b130b98db9cf
6689060: Escape Analysis does not work with Compressed Oops
kvn
parents:
113
diff
changeset
|
1066 // * [tos + 17] error message (char*) |
b130b98db9cf
6689060: Escape Analysis does not work with Compressed Oops
kvn
parents:
113
diff
changeset
|
1067 // * [tos + 18] object to verify (oop) |
b130b98db9cf
6689060: Escape Analysis does not work with Compressed Oops
kvn
parents:
113
diff
changeset
|
1068 // * [tos + 19] saved rax - saved by caller and bashed |
1583 | 1069 // * [tos + 20] saved r10 (rscratch1) - saved by caller |
124
b130b98db9cf
6689060: Escape Analysis does not work with Compressed Oops
kvn
parents:
113
diff
changeset
|
1070 // * = popped on exit |
b130b98db9cf
6689060: Escape Analysis does not work with Compressed Oops
kvn
parents:
113
diff
changeset
|
1071 |
304 | 1072 __ movptr(c_rarg0, Address(rsp, error_msg)); // pass address of error message |
1073 __ movptr(c_rarg1, Address(rsp, return_addr)); // pass return address | |
1074 __ movq(c_rarg2, rsp); // pass address of regs on stack | |
1075 __ mov(r12, rsp); // remember rsp | |
1076 __ subptr(rsp, frame::arg_reg_save_area_bytes); // windows | |
1077 __ andptr(rsp, -16); // align stack as required by ABI | |
0 | 1078 BLOCK_COMMENT("call MacroAssembler::debug"); |
304 | 1079 __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, MacroAssembler::debug64))); |
1080 __ mov(rsp, r12); // restore rsp | |
1081 __ popa(); // pop registers (includes r12) | |
1583 | 1082 __ ret(4 * wordSize); // pop caller saved stuff |
0 | 1083 |
1084 return start; | |
1085 } | |
1086 | |
1087 // | |
1088 // Verify that a register contains clean 32-bits positive value | |
1089 // (high 32-bits are 0) so it could be used in 64-bits shifts. | |
1090 // | |
1091 // Input: | |
1092 // Rint - 32-bits value | |
1093 // Rtmp - scratch | |
1094 // | |
1095 void assert_clean_int(Register Rint, Register Rtmp) { | |
1096 #ifdef ASSERT | |
1097 Label L; | |
1098 assert_different_registers(Rtmp, Rint); | |
1099 __ movslq(Rtmp, Rint); | |
1100 __ cmpq(Rtmp, Rint); | |
124
b130b98db9cf
6689060: Escape Analysis does not work with Compressed Oops
kvn
parents:
113
diff
changeset
|
1101 __ jcc(Assembler::equal, L); |
0 | 1102 __ stop("high 32-bits of int value are not 0"); |
1103 __ bind(L); | |
1104 #endif | |
1105 } | |
1106 | |
1107 // Generate overlap test for array copy stubs | |
1108 // | |
1109 // Input: | |
1110 // c_rarg0 - from | |
1111 // c_rarg1 - to | |
1112 // c_rarg2 - element count | |
1113 // | |
1114 // Output: | |
1115 // rax - &from[element count - 1] | |
1116 // | |
1117 void array_overlap_test(address no_overlap_target, Address::ScaleFactor sf) { | |
1118 assert(no_overlap_target != NULL, "must be generated"); | |
1119 array_overlap_test(no_overlap_target, NULL, sf); | |
1120 } | |
1121 void array_overlap_test(Label& L_no_overlap, Address::ScaleFactor sf) { | |
1122 array_overlap_test(NULL, &L_no_overlap, sf); | |
1123 } | |
1124 void array_overlap_test(address no_overlap_target, Label* NOLp, Address::ScaleFactor sf) { | |
1125 const Register from = c_rarg0; | |
1126 const Register to = c_rarg1; | |
1127 const Register count = c_rarg2; | |
1128 const Register end_from = rax; | |
1129 | |
304 | 1130 __ cmpptr(to, from); |
1131 __ lea(end_from, Address(from, count, sf, 0)); | |
0 | 1132 if (NOLp == NULL) { |
1133 ExternalAddress no_overlap(no_overlap_target); | |
1134 __ jump_cc(Assembler::belowEqual, no_overlap); | |
304 | 1135 __ cmpptr(to, end_from); |
0 | 1136 __ jump_cc(Assembler::aboveEqual, no_overlap); |
1137 } else { | |
1138 __ jcc(Assembler::belowEqual, (*NOLp)); | |
304 | 1139 __ cmpptr(to, end_from); |
0 | 1140 __ jcc(Assembler::aboveEqual, (*NOLp)); |
1141 } | |
1142 } | |
1143 | |
1144 // Shuffle first three arg regs on Windows into Linux/Solaris locations. | |
1145 // | |
1146 // Outputs: | |
1147 // rdi - rcx | |
1148 // rsi - rdx | |
1149 // rdx - r8 | |
1150 // rcx - r9 | |
1151 // | |
1152 // Registers r9 and r10 are used to save rdi and rsi on Windows, which latter | |
1153 // are non-volatile. r9 and r10 should not be used by the caller. | |
1154 // | |
1155 void setup_arg_regs(int nargs = 3) { | |
1156 const Register saved_rdi = r9; | |
1157 const Register saved_rsi = r10; | |
1158 assert(nargs == 3 || nargs == 4, "else fix"); | |
1159 #ifdef _WIN64 | |
1160 assert(c_rarg0 == rcx && c_rarg1 == rdx && c_rarg2 == r8 && c_rarg3 == r9, | |
1161 "unexpected argument registers"); | |
1162 if (nargs >= 4) | |
304 | 1163 __ mov(rax, r9); // r9 is also saved_rdi |
1164 __ movptr(saved_rdi, rdi); | |
1165 __ movptr(saved_rsi, rsi); | |
1166 __ mov(rdi, rcx); // c_rarg0 | |
1167 __ mov(rsi, rdx); // c_rarg1 | |
1168 __ mov(rdx, r8); // c_rarg2 | |
0 | 1169 if (nargs >= 4) |
304 | 1170 __ mov(rcx, rax); // c_rarg3 (via rax) |
0 | 1171 #else |
1172 assert(c_rarg0 == rdi && c_rarg1 == rsi && c_rarg2 == rdx && c_rarg3 == rcx, | |
1173 "unexpected argument registers"); | |
1174 #endif | |
1175 } | |
1176 | |
1177 void restore_arg_regs() { | |
1178 const Register saved_rdi = r9; | |
1179 const Register saved_rsi = r10; | |
1180 #ifdef _WIN64 | |
304 | 1181 __ movptr(rdi, saved_rdi); |
1182 __ movptr(rsi, saved_rsi); | |
0 | 1183 #endif |
1184 } | |
1185 | |
1186 // Generate code for an array write pre barrier | |
1187 // | |
1188 // addr - starting address | |
2324 | 1189 // count - element count |
1190 // tmp - scratch register | |
0 | 1191 // |
1192 // Destroy no registers! | |
1193 // | |
2324 | 1194 void gen_write_ref_array_pre_barrier(Register addr, Register count, bool dest_uninitialized) { |
0 | 1195 BarrierSet* bs = Universe::heap()->barrier_set(); |
1196 switch (bs->kind()) { | |
1197 case BarrierSet::G1SATBCT: | |
1198 case BarrierSet::G1SATBCTLogging: | |
2324 | 1199 // With G1, don't generate the call if we statically know that the target in uninitialized |
1200 if (!dest_uninitialized) { | |
1201 __ pusha(); // push registers | |
1202 if (count == c_rarg0) { | |
1203 if (addr == c_rarg1) { | |
1204 // exactly backwards!! | |
1205 __ xchgptr(c_rarg1, c_rarg0); | |
1206 } else { | |
1207 __ movptr(c_rarg1, count); | |
1208 __ movptr(c_rarg0, addr); | |
1209 } | |
1210 } else { | |
1211 __ movptr(c_rarg0, addr); | |
1212 __ movptr(c_rarg1, count); | |
1213 } | |
1214 __ call_VM_leaf(CAST_FROM_FN_PTR(address, BarrierSet::static_write_ref_array_pre), 2); | |
1215 __ popa(); | |
0 | 1216 } |
2324 | 1217 break; |
0 | 1218 case BarrierSet::CardTableModRef: |
1219 case BarrierSet::CardTableExtension: | |
1220 case BarrierSet::ModRef: | |
1221 break; | |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
1222 default: |
0 | 1223 ShouldNotReachHere(); |
1224 | |
1225 } | |
1226 } | |
1227 | |
1228 // | |
1229 // Generate code for an array write post barrier | |
1230 // | |
1231 // Input: | |
1232 // start - register containing starting address of destination array | |
1233 // end - register containing ending address of destination array | |
1234 // scratch - scratch register | |
1235 // | |
1236 // The input registers are overwritten. | |
1237 // The ending address is inclusive. | |
1238 void gen_write_ref_array_post_barrier(Register start, Register end, Register scratch) { | |
1239 assert_different_registers(start, end, scratch); | |
1240 BarrierSet* bs = Universe::heap()->barrier_set(); | |
1241 switch (bs->kind()) { | |
1242 case BarrierSet::G1SATBCT: | |
1243 case BarrierSet::G1SATBCTLogging: | |
1244 | |
1245 { | |
304 | 1246 __ pusha(); // push registers (overkill) |
0 | 1247 // must compute element count unless barrier set interface is changed (other platforms supply count) |
1248 assert_different_registers(start, end, scratch); | |
845
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
671
diff
changeset
|
1249 __ lea(scratch, Address(end, BytesPerHeapOop)); |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
671
diff
changeset
|
1250 __ subptr(scratch, start); // subtract start to get #bytes |
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
671
diff
changeset
|
1251 __ shrptr(scratch, LogBytesPerHeapOop); // convert to element count |
304 | 1252 __ mov(c_rarg0, start); |
1253 __ mov(c_rarg1, scratch); | |
1192
776fb94f33cc
6918006: G1: spill space must be reserved on the stack for barrier calls on Windows x64
apetrusenko
parents:
1174
diff
changeset
|
1254 __ call_VM_leaf(CAST_FROM_FN_PTR(address, BarrierSet::static_write_ref_array_post), 2); |
304 | 1255 __ popa(); |
0 | 1256 } |
1257 break; | |
1258 case BarrierSet::CardTableModRef: | |
1259 case BarrierSet::CardTableExtension: | |
1260 { | |
1261 CardTableModRefBS* ct = (CardTableModRefBS*)bs; | |
1262 assert(sizeof(*ct->byte_map_base) == sizeof(jbyte), "adjust this code"); | |
1263 | |
1264 Label L_loop; | |
1265 | |
304 | 1266 __ shrptr(start, CardTableModRefBS::card_shift); |
845
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
671
diff
changeset
|
1267 __ addptr(end, BytesPerHeapOop); |
304 | 1268 __ shrptr(end, CardTableModRefBS::card_shift); |
1269 __ subptr(end, start); // number of bytes to copy | |
0 | 1270 |
249
910a4cb98e9e
6717457: Internal Error (src/share/vm/code/relocInfo.hpp:1089)
never
parents:
196
diff
changeset
|
1271 intptr_t disp = (intptr_t) ct->byte_map_base; |
4114
6729bbc1fcd6
7003454: order constants in constant table by number of references in code
twisti
parents:
3960
diff
changeset
|
1272 if (Assembler::is_simm32(disp)) { |
249
910a4cb98e9e
6717457: Internal Error (src/share/vm/code/relocInfo.hpp:1089)
never
parents:
196
diff
changeset
|
1273 Address cardtable(noreg, noreg, Address::no_scale, disp); |
910a4cb98e9e
6717457: Internal Error (src/share/vm/code/relocInfo.hpp:1089)
never
parents:
196
diff
changeset
|
1274 __ lea(scratch, cardtable); |
910a4cb98e9e
6717457: Internal Error (src/share/vm/code/relocInfo.hpp:1089)
never
parents:
196
diff
changeset
|
1275 } else { |
910a4cb98e9e
6717457: Internal Error (src/share/vm/code/relocInfo.hpp:1089)
never
parents:
196
diff
changeset
|
1276 ExternalAddress cardtable((address)disp); |
910a4cb98e9e
6717457: Internal Error (src/share/vm/code/relocInfo.hpp:1089)
never
parents:
196
diff
changeset
|
1277 __ lea(scratch, cardtable); |
910a4cb98e9e
6717457: Internal Error (src/share/vm/code/relocInfo.hpp:1089)
never
parents:
196
diff
changeset
|
1278 } |
910a4cb98e9e
6717457: Internal Error (src/share/vm/code/relocInfo.hpp:1089)
never
parents:
196
diff
changeset
|
1279 |
0 | 1280 const Register count = end; // 'end' register contains bytes count now |
304 | 1281 __ addptr(start, scratch); |
0 | 1282 __ BIND(L_loop); |
1283 __ movb(Address(start, count, Address::times_1), 0); | |
304 | 1284 __ decrement(count); |
0 | 1285 __ jcc(Assembler::greaterEqual, L_loop); |
1286 } | |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
1287 break; |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
1288 default: |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
1289 ShouldNotReachHere(); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
1290 |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
1291 } |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
1292 } |
0 | 1293 |
405 | 1294 |
0 | 1295 // Copy big chunks forward |
1296 // | |
1297 // Inputs: | |
1298 // end_from - source arrays end address | |
1299 // end_to - destination array end address | |
1300 // qword_count - 64-bits element count, negative | |
1301 // to - scratch | |
1302 // L_copy_32_bytes - entry label | |
1303 // L_copy_8_bytes - exit label | |
1304 // | |
1305 void copy_32_bytes_forward(Register end_from, Register end_to, | |
1306 Register qword_count, Register to, | |
1307 Label& L_copy_32_bytes, Label& L_copy_8_bytes) { | |
1308 DEBUG_ONLY(__ stop("enter at entry label, not here")); | |
1309 Label L_loop; | |
1365 | 1310 __ align(OptoLoopAlignment); |
0 | 1311 __ BIND(L_loop); |
405 | 1312 if(UseUnalignedLoadStores) { |
1313 __ movdqu(xmm0, Address(end_from, qword_count, Address::times_8, -24)); | |
1314 __ movdqu(Address(end_to, qword_count, Address::times_8, -24), xmm0); | |
1315 __ movdqu(xmm1, Address(end_from, qword_count, Address::times_8, - 8)); | |
1316 __ movdqu(Address(end_to, qword_count, Address::times_8, - 8), xmm1); | |
1317 | |
1318 } else { | |
1319 __ movq(to, Address(end_from, qword_count, Address::times_8, -24)); | |
1320 __ movq(Address(end_to, qword_count, Address::times_8, -24), to); | |
1321 __ movq(to, Address(end_from, qword_count, Address::times_8, -16)); | |
1322 __ movq(Address(end_to, qword_count, Address::times_8, -16), to); | |
1323 __ movq(to, Address(end_from, qword_count, Address::times_8, - 8)); | |
1324 __ movq(Address(end_to, qword_count, Address::times_8, - 8), to); | |
1325 __ movq(to, Address(end_from, qword_count, Address::times_8, - 0)); | |
1326 __ movq(Address(end_to, qword_count, Address::times_8, - 0), to); | |
1327 } | |
0 | 1328 __ BIND(L_copy_32_bytes); |
304 | 1329 __ addptr(qword_count, 4); |
0 | 1330 __ jcc(Assembler::lessEqual, L_loop); |
304 | 1331 __ subptr(qword_count, 4); |
0 | 1332 __ jcc(Assembler::less, L_copy_8_bytes); // Copy trailing qwords |
1333 } | |
1334 | |
1335 | |
1336 // Copy big chunks backward | |
1337 // | |
1338 // Inputs: | |
1339 // from - source arrays address | |
1340 // dest - destination array address | |
1341 // qword_count - 64-bits element count | |
1342 // to - scratch | |
1343 // L_copy_32_bytes - entry label | |
1344 // L_copy_8_bytes - exit label | |
1345 // | |
1346 void copy_32_bytes_backward(Register from, Register dest, | |
1347 Register qword_count, Register to, | |
1348 Label& L_copy_32_bytes, Label& L_copy_8_bytes) { | |
1349 DEBUG_ONLY(__ stop("enter at entry label, not here")); | |
1350 Label L_loop; | |
1365 | 1351 __ align(OptoLoopAlignment); |
0 | 1352 __ BIND(L_loop); |
405 | 1353 if(UseUnalignedLoadStores) { |
1354 __ movdqu(xmm0, Address(from, qword_count, Address::times_8, 16)); | |
1355 __ movdqu(Address(dest, qword_count, Address::times_8, 16), xmm0); | |
1356 __ movdqu(xmm1, Address(from, qword_count, Address::times_8, 0)); | |
1357 __ movdqu(Address(dest, qword_count, Address::times_8, 0), xmm1); | |
1358 | |
1359 } else { | |
1360 __ movq(to, Address(from, qword_count, Address::times_8, 24)); | |
1361 __ movq(Address(dest, qword_count, Address::times_8, 24), to); | |
1362 __ movq(to, Address(from, qword_count, Address::times_8, 16)); | |
1363 __ movq(Address(dest, qword_count, Address::times_8, 16), to); | |
1364 __ movq(to, Address(from, qword_count, Address::times_8, 8)); | |
1365 __ movq(Address(dest, qword_count, Address::times_8, 8), to); | |
1366 __ movq(to, Address(from, qword_count, Address::times_8, 0)); | |
1367 __ movq(Address(dest, qword_count, Address::times_8, 0), to); | |
1368 } | |
0 | 1369 __ BIND(L_copy_32_bytes); |
304 | 1370 __ subptr(qword_count, 4); |
0 | 1371 __ jcc(Assembler::greaterEqual, L_loop); |
304 | 1372 __ addptr(qword_count, 4); |
0 | 1373 __ jcc(Assembler::greater, L_copy_8_bytes); // Copy trailing qwords |
1374 } | |
1375 | |
1376 | |
1377 // Arguments: | |
1378 // aligned - true => Input and output aligned on a HeapWord == 8-byte boundary | |
1379 // ignored | |
1380 // name - stub name string | |
1381 // | |
1382 // Inputs: | |
1383 // c_rarg0 - source array address | |
1384 // c_rarg1 - destination array address | |
1385 // c_rarg2 - element count, treated as ssize_t, can be zero | |
1386 // | |
1387 // If 'from' and/or 'to' are aligned on 4-, 2-, or 1-byte boundaries, | |
1388 // we let the hardware handle it. The one to eight bytes within words, | |
1389 // dwords or qwords that span cache line boundaries will still be loaded | |
1390 // and stored atomically. | |
1391 // | |
1392 // Side Effects: | |
1393 // disjoint_byte_copy_entry is set to the no-overlap entry point | |
1394 // used by generate_conjoint_byte_copy(). | |
1395 // | |
2313
d89a22843c62
7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents:
2006
diff
changeset
|
1396 address generate_disjoint_byte_copy(bool aligned, address* entry, const char *name) { |
0 | 1397 __ align(CodeEntryAlignment); |
1398 StubCodeMark mark(this, "StubRoutines", name); | |
1399 address start = __ pc(); | |
1400 | |
1401 Label L_copy_32_bytes, L_copy_8_bytes, L_copy_4_bytes, L_copy_2_bytes; | |
1402 Label L_copy_byte, L_exit; | |
1403 const Register from = rdi; // source array address | |
1404 const Register to = rsi; // destination array address | |
1405 const Register count = rdx; // elements count | |
1406 const Register byte_count = rcx; | |
1407 const Register qword_count = count; | |
1408 const Register end_from = from; // source array end address | |
1409 const Register end_to = to; // destination array end address | |
1410 // End pointers are inclusive, and if count is not zero they point | |
1411 // to the last unit copied: end_to[0] := end_from[0] | |
1412 | |
1413 __ enter(); // required for proper stackwalking of RuntimeStub frame | |
1414 assert_clean_int(c_rarg2, rax); // Make sure 'count' is clean int. | |
1415 | |
2313
d89a22843c62
7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents:
2006
diff
changeset
|
1416 if (entry != NULL) { |
d89a22843c62
7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents:
2006
diff
changeset
|
1417 *entry = __ pc(); |
d89a22843c62
7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents:
2006
diff
changeset
|
1418 // caller can pass a 64-bit byte count here (from Unsafe.copyMemory) |
d89a22843c62
7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents:
2006
diff
changeset
|
1419 BLOCK_COMMENT("Entry:"); |
d89a22843c62
7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents:
2006
diff
changeset
|
1420 } |
0 | 1421 |
1422 setup_arg_regs(); // from => rdi, to => rsi, count => rdx | |
1423 // r9 and r10 may be used to save non-volatile registers | |
1424 | |
1425 // 'from', 'to' and 'count' are now valid | |
304 | 1426 __ movptr(byte_count, count); |
1427 __ shrptr(count, 3); // count => qword_count | |
0 | 1428 |
1429 // Copy from low to high addresses. Use 'to' as scratch. | |
304 | 1430 __ lea(end_from, Address(from, qword_count, Address::times_8, -8)); |
1431 __ lea(end_to, Address(to, qword_count, Address::times_8, -8)); | |
1432 __ negptr(qword_count); // make the count negative | |
0 | 1433 __ jmp(L_copy_32_bytes); |
1434 | |
1435 // Copy trailing qwords | |
1436 __ BIND(L_copy_8_bytes); | |
1437 __ movq(rax, Address(end_from, qword_count, Address::times_8, 8)); | |
1438 __ movq(Address(end_to, qword_count, Address::times_8, 8), rax); | |
304 | 1439 __ increment(qword_count); |
0 | 1440 __ jcc(Assembler::notZero, L_copy_8_bytes); |
1441 | |
1442 // Check for and copy trailing dword | |
1443 __ BIND(L_copy_4_bytes); | |
304 | 1444 __ testl(byte_count, 4); |
0 | 1445 __ jccb(Assembler::zero, L_copy_2_bytes); |
1446 __ movl(rax, Address(end_from, 8)); | |
1447 __ movl(Address(end_to, 8), rax); | |
1448 | |
304 | 1449 __ addptr(end_from, 4); |
1450 __ addptr(end_to, 4); | |
0 | 1451 |
1452 // Check for and copy trailing word | |
1453 __ BIND(L_copy_2_bytes); | |
304 | 1454 __ testl(byte_count, 2); |
0 | 1455 __ jccb(Assembler::zero, L_copy_byte); |
1456 __ movw(rax, Address(end_from, 8)); | |
1457 __ movw(Address(end_to, 8), rax); | |
1458 | |
304 | 1459 __ addptr(end_from, 2); |
1460 __ addptr(end_to, 2); | |
0 | 1461 |
1462 // Check for and copy trailing byte | |
1463 __ BIND(L_copy_byte); | |
304 | 1464 __ testl(byte_count, 1); |
0 | 1465 __ jccb(Assembler::zero, L_exit); |
1466 __ movb(rax, Address(end_from, 8)); | |
1467 __ movb(Address(end_to, 8), rax); | |
1468 | |
1469 __ BIND(L_exit); | |
1470 restore_arg_regs(); | |
4118
59bc0d4d9ea3
7110489: C1: 64-bit tiered with ForceUnreachable: assert(reachable(src)) failed: Address should be reachable
never
parents:
4114
diff
changeset
|
1471 inc_counter_np(SharedRuntime::_jbyte_array_copy_ctr); // Update counter after rscratch1 is free |
304 | 1472 __ xorptr(rax, rax); // return 0 |
0 | 1473 __ leave(); // required for proper stackwalking of RuntimeStub frame |
1474 __ ret(0); | |
1475 | |
1476 // Copy in 32-bytes chunks | |
1477 copy_32_bytes_forward(end_from, end_to, qword_count, rax, L_copy_32_bytes, L_copy_8_bytes); | |
1478 __ jmp(L_copy_4_bytes); | |
1479 | |
1480 return start; | |
1481 } | |
1482 | |
1483 // Arguments: | |
1484 // aligned - true => Input and output aligned on a HeapWord == 8-byte boundary | |
1485 // ignored | |
1486 // name - stub name string | |
1487 // | |
1488 // Inputs: | |
1489 // c_rarg0 - source array address | |
1490 // c_rarg1 - destination array address | |
1491 // c_rarg2 - element count, treated as ssize_t, can be zero | |
1492 // | |
1493 // If 'from' and/or 'to' are aligned on 4-, 2-, or 1-byte boundaries, | |
1494 // we let the hardware handle it. The one to eight bytes within words, | |
1495 // dwords or qwords that span cache line boundaries will still be loaded | |
1496 // and stored atomically. | |
1497 // | |
2313
d89a22843c62
7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents:
2006
diff
changeset
|
1498 address generate_conjoint_byte_copy(bool aligned, address nooverlap_target, |
d89a22843c62
7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents:
2006
diff
changeset
|
1499 address* entry, const char *name) { |
0 | 1500 __ align(CodeEntryAlignment); |
1501 StubCodeMark mark(this, "StubRoutines", name); | |
1502 address start = __ pc(); | |
1503 | |
1504 Label L_copy_32_bytes, L_copy_8_bytes, L_copy_4_bytes, L_copy_2_bytes; | |
1505 const Register from = rdi; // source array address | |
1506 const Register to = rsi; // destination array address | |
1507 const Register count = rdx; // elements count | |
1508 const Register byte_count = rcx; | |
1509 const Register qword_count = count; | |
1510 | |
1511 __ enter(); // required for proper stackwalking of RuntimeStub frame | |
1512 assert_clean_int(c_rarg2, rax); // Make sure 'count' is clean int. | |
1513 | |
2313
d89a22843c62
7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents:
2006
diff
changeset
|
1514 if (entry != NULL) { |
d89a22843c62
7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents:
2006
diff
changeset
|
1515 *entry = __ pc(); |
d89a22843c62
7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents:
2006
diff
changeset
|
1516 // caller can pass a 64-bit byte count here (from Unsafe.copyMemory) |
d89a22843c62
7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents:
2006
diff
changeset
|
1517 BLOCK_COMMENT("Entry:"); |
d89a22843c62
7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents:
2006
diff
changeset
|
1518 } |
d89a22843c62
7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents:
2006
diff
changeset
|
1519 |
d89a22843c62
7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents:
2006
diff
changeset
|
1520 array_overlap_test(nooverlap_target, Address::times_1); |
0 | 1521 setup_arg_regs(); // from => rdi, to => rsi, count => rdx |
1522 // r9 and r10 may be used to save non-volatile registers | |
1523 | |
1524 // 'from', 'to' and 'count' are now valid | |
304 | 1525 __ movptr(byte_count, count); |
1526 __ shrptr(count, 3); // count => qword_count | |
0 | 1527 |
1528 // Copy from high to low addresses. | |
1529 | |
1530 // Check for and copy trailing byte | |
304 | 1531 __ testl(byte_count, 1); |
0 | 1532 __ jcc(Assembler::zero, L_copy_2_bytes); |
1533 __ movb(rax, Address(from, byte_count, Address::times_1, -1)); | |
1534 __ movb(Address(to, byte_count, Address::times_1, -1), rax); | |
304 | 1535 __ decrement(byte_count); // Adjust for possible trailing word |
0 | 1536 |
1537 // Check for and copy trailing word | |
1538 __ BIND(L_copy_2_bytes); | |
304 | 1539 __ testl(byte_count, 2); |
0 | 1540 __ jcc(Assembler::zero, L_copy_4_bytes); |
1541 __ movw(rax, Address(from, byte_count, Address::times_1, -2)); | |
1542 __ movw(Address(to, byte_count, Address::times_1, -2), rax); | |
1543 | |
1544 // Check for and copy trailing dword | |
1545 __ BIND(L_copy_4_bytes); | |
304 | 1546 __ testl(byte_count, 4); |
0 | 1547 __ jcc(Assembler::zero, L_copy_32_bytes); |
1548 __ movl(rax, Address(from, qword_count, Address::times_8)); | |
1549 __ movl(Address(to, qword_count, Address::times_8), rax); | |
1550 __ jmp(L_copy_32_bytes); | |
1551 | |
1552 // Copy trailing qwords | |
1553 __ BIND(L_copy_8_bytes); | |
1554 __ movq(rax, Address(from, qword_count, Address::times_8, -8)); | |
1555 __ movq(Address(to, qword_count, Address::times_8, -8), rax); | |
304 | 1556 __ decrement(qword_count); |
0 | 1557 __ jcc(Assembler::notZero, L_copy_8_bytes); |
1558 | |
1559 restore_arg_regs(); | |
4118
59bc0d4d9ea3
7110489: C1: 64-bit tiered with ForceUnreachable: assert(reachable(src)) failed: Address should be reachable
never
parents:
4114
diff
changeset
|
1560 inc_counter_np(SharedRuntime::_jbyte_array_copy_ctr); // Update counter after rscratch1 is free |
304 | 1561 __ xorptr(rax, rax); // return 0 |
0 | 1562 __ leave(); // required for proper stackwalking of RuntimeStub frame |
1563 __ ret(0); | |
1564 | |
1565 // Copy in 32-bytes chunks | |
1566 copy_32_bytes_backward(from, to, qword_count, rax, L_copy_32_bytes, L_copy_8_bytes); | |
1567 | |
1568 restore_arg_regs(); | |
4118
59bc0d4d9ea3
7110489: C1: 64-bit tiered with ForceUnreachable: assert(reachable(src)) failed: Address should be reachable
never
parents:
4114
diff
changeset
|
1569 inc_counter_np(SharedRuntime::_jbyte_array_copy_ctr); // Update counter after rscratch1 is free |
304 | 1570 __ xorptr(rax, rax); // return 0 |
0 | 1571 __ leave(); // required for proper stackwalking of RuntimeStub frame |
1572 __ ret(0); | |
1573 | |
1574 return start; | |
1575 } | |
1576 | |
1577 // Arguments: | |
1578 // aligned - true => Input and output aligned on a HeapWord == 8-byte boundary | |
1579 // ignored | |
1580 // name - stub name string | |
1581 // | |
1582 // Inputs: | |
1583 // c_rarg0 - source array address | |
1584 // c_rarg1 - destination array address | |
1585 // c_rarg2 - element count, treated as ssize_t, can be zero | |
1586 // | |
1587 // If 'from' and/or 'to' are aligned on 4- or 2-byte boundaries, we | |
1588 // let the hardware handle it. The two or four words within dwords | |
1589 // or qwords that span cache line boundaries will still be loaded | |
1590 // and stored atomically. | |
1591 // | |
1592 // Side Effects: | |
1593 // disjoint_short_copy_entry is set to the no-overlap entry point | |
1594 // used by generate_conjoint_short_copy(). | |
1595 // | |
2313
d89a22843c62
7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents:
2006
diff
changeset
|
1596 address generate_disjoint_short_copy(bool aligned, address *entry, const char *name) { |
0 | 1597 __ align(CodeEntryAlignment); |
1598 StubCodeMark mark(this, "StubRoutines", name); | |
1599 address start = __ pc(); | |
1600 | |
1601 Label L_copy_32_bytes, L_copy_8_bytes, L_copy_4_bytes,L_copy_2_bytes,L_exit; | |
1602 const Register from = rdi; // source array address | |
1603 const Register to = rsi; // destination array address | |
1604 const Register count = rdx; // elements count | |
1605 const Register word_count = rcx; | |
1606 const Register qword_count = count; | |
1607 const Register end_from = from; // source array end address | |
1608 const Register end_to = to; // destination array end address | |
1609 // End pointers are inclusive, and if count is not zero they point | |
1610 // to the last unit copied: end_to[0] := end_from[0] | |
1611 | |
1612 __ enter(); // required for proper stackwalking of RuntimeStub frame | |
1613 assert_clean_int(c_rarg2, rax); // Make sure 'count' is clean int. | |
1614 | |
2313
d89a22843c62
7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents:
2006
diff
changeset
|
1615 if (entry != NULL) { |
d89a22843c62
7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents:
2006
diff
changeset
|
1616 *entry = __ pc(); |
d89a22843c62
7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents:
2006
diff
changeset
|
1617 // caller can pass a 64-bit byte count here (from Unsafe.copyMemory) |
d89a22843c62
7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents:
2006
diff
changeset
|
1618 BLOCK_COMMENT("Entry:"); |
d89a22843c62
7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents:
2006
diff
changeset
|
1619 } |
0 | 1620 |
1621 setup_arg_regs(); // from => rdi, to => rsi, count => rdx | |
1622 // r9 and r10 may be used to save non-volatile registers | |
1623 | |
1624 // 'from', 'to' and 'count' are now valid | |
304 | 1625 __ movptr(word_count, count); |
1626 __ shrptr(count, 2); // count => qword_count | |
0 | 1627 |
1628 // Copy from low to high addresses. Use 'to' as scratch. | |
304 | 1629 __ lea(end_from, Address(from, qword_count, Address::times_8, -8)); |
1630 __ lea(end_to, Address(to, qword_count, Address::times_8, -8)); | |
1631 __ negptr(qword_count); | |
0 | 1632 __ jmp(L_copy_32_bytes); |
1633 | |
1634 // Copy trailing qwords | |
1635 __ BIND(L_copy_8_bytes); | |
1636 __ movq(rax, Address(end_from, qword_count, Address::times_8, 8)); | |
1637 __ movq(Address(end_to, qword_count, Address::times_8, 8), rax); | |
304 | 1638 __ increment(qword_count); |
0 | 1639 __ jcc(Assembler::notZero, L_copy_8_bytes); |
1640 | |
1641 // Original 'dest' is trashed, so we can't use it as a | |
1642 // base register for a possible trailing word copy | |
1643 | |
1644 // Check for and copy trailing dword | |
1645 __ BIND(L_copy_4_bytes); | |
304 | 1646 __ testl(word_count, 2); |
0 | 1647 __ jccb(Assembler::zero, L_copy_2_bytes); |
1648 __ movl(rax, Address(end_from, 8)); | |
1649 __ movl(Address(end_to, 8), rax); | |
1650 | |
304 | 1651 __ addptr(end_from, 4); |
1652 __ addptr(end_to, 4); | |
0 | 1653 |
1654 // Check for and copy trailing word | |
1655 __ BIND(L_copy_2_bytes); | |
304 | 1656 __ testl(word_count, 1); |
0 | 1657 __ jccb(Assembler::zero, L_exit); |
1658 __ movw(rax, Address(end_from, 8)); | |
1659 __ movw(Address(end_to, 8), rax); | |
1660 | |
1661 __ BIND(L_exit); | |
1662 restore_arg_regs(); | |
4118
59bc0d4d9ea3
7110489: C1: 64-bit tiered with ForceUnreachable: assert(reachable(src)) failed: Address should be reachable
never
parents:
4114
diff
changeset
|
1663 inc_counter_np(SharedRuntime::_jshort_array_copy_ctr); // Update counter after rscratch1 is free |
304 | 1664 __ xorptr(rax, rax); // return 0 |
0 | 1665 __ leave(); // required for proper stackwalking of RuntimeStub frame |
1666 __ ret(0); | |
1667 | |
1668 // Copy in 32-bytes chunks | |
1669 copy_32_bytes_forward(end_from, end_to, qword_count, rax, L_copy_32_bytes, L_copy_8_bytes); | |
1670 __ jmp(L_copy_4_bytes); | |
1671 | |
1672 return start; | |
1673 } | |
1674 | |
1763 | 1675 address generate_fill(BasicType t, bool aligned, const char *name) { |
1676 __ align(CodeEntryAlignment); | |
1677 StubCodeMark mark(this, "StubRoutines", name); | |
1678 address start = __ pc(); | |
1679 | |
1680 BLOCK_COMMENT("Entry:"); | |
1681 | |
1682 const Register to = c_rarg0; // source array address | |
1683 const Register value = c_rarg1; // value | |
1684 const Register count = c_rarg2; // elements count | |
1685 | |
1686 __ enter(); // required for proper stackwalking of RuntimeStub frame | |
1687 | |
1688 __ generate_fill(t, aligned, to, value, count, rax, xmm0); | |
1689 | |
1690 __ leave(); // required for proper stackwalking of RuntimeStub frame | |
1691 __ ret(0); | |
1692 return start; | |
1693 } | |
1694 | |
0 | 1695 // Arguments: |
1696 // aligned - true => Input and output aligned on a HeapWord == 8-byte boundary | |
1697 // ignored | |
1698 // name - stub name string | |
1699 // | |
1700 // Inputs: | |
1701 // c_rarg0 - source array address | |
1702 // c_rarg1 - destination array address | |
1703 // c_rarg2 - element count, treated as ssize_t, can be zero | |
1704 // | |
1705 // If 'from' and/or 'to' are aligned on 4- or 2-byte boundaries, we | |
1706 // let the hardware handle it. The two or four words within dwords | |
1707 // or qwords that span cache line boundaries will still be loaded | |
1708 // and stored atomically. | |
1709 // | |
2313
d89a22843c62
7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents:
2006
diff
changeset
|
1710 address generate_conjoint_short_copy(bool aligned, address nooverlap_target, |
d89a22843c62
7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents:
2006
diff
changeset
|
1711 address *entry, const char *name) { |
0 | 1712 __ align(CodeEntryAlignment); |
1713 StubCodeMark mark(this, "StubRoutines", name); | |
1714 address start = __ pc(); | |
1715 | |
1716 Label L_copy_32_bytes, L_copy_8_bytes, L_copy_4_bytes; | |
1717 const Register from = rdi; // source array address | |
1718 const Register to = rsi; // destination array address | |
1719 const Register count = rdx; // elements count | |
1720 const Register word_count = rcx; | |
1721 const Register qword_count = count; | |
1722 | |
1723 __ enter(); // required for proper stackwalking of RuntimeStub frame | |
1724 assert_clean_int(c_rarg2, rax); // Make sure 'count' is clean int. | |
1725 | |
2313
d89a22843c62
7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents:
2006
diff
changeset
|
1726 if (entry != NULL) { |
d89a22843c62
7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents:
2006
diff
changeset
|
1727 *entry = __ pc(); |
d89a22843c62
7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents:
2006
diff
changeset
|
1728 // caller can pass a 64-bit byte count here (from Unsafe.copyMemory) |
d89a22843c62
7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents:
2006
diff
changeset
|
1729 BLOCK_COMMENT("Entry:"); |
d89a22843c62
7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents:
2006
diff
changeset
|
1730 } |
d89a22843c62
7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents:
2006
diff
changeset
|
1731 |
d89a22843c62
7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents:
2006
diff
changeset
|
1732 array_overlap_test(nooverlap_target, Address::times_2); |
0 | 1733 setup_arg_regs(); // from => rdi, to => rsi, count => rdx |
1734 // r9 and r10 may be used to save non-volatile registers | |
1735 | |
1736 // 'from', 'to' and 'count' are now valid | |
304 | 1737 __ movptr(word_count, count); |
1738 __ shrptr(count, 2); // count => qword_count | |
0 | 1739 |
1740 // Copy from high to low addresses. Use 'to' as scratch. | |
1741 | |
1742 // Check for and copy trailing word | |
304 | 1743 __ testl(word_count, 1); |
0 | 1744 __ jccb(Assembler::zero, L_copy_4_bytes); |
1745 __ movw(rax, Address(from, word_count, Address::times_2, -2)); | |
1746 __ movw(Address(to, word_count, Address::times_2, -2), rax); | |
1747 | |
1748 // Check for and copy trailing dword | |
1749 __ BIND(L_copy_4_bytes); | |
304 | 1750 __ testl(word_count, 2); |
0 | 1751 __ jcc(Assembler::zero, L_copy_32_bytes); |
1752 __ movl(rax, Address(from, qword_count, Address::times_8)); | |
1753 __ movl(Address(to, qword_count, Address::times_8), rax); | |
1754 __ jmp(L_copy_32_bytes); | |
1755 | |
1756 // Copy trailing qwords | |
1757 __ BIND(L_copy_8_bytes); | |
1758 __ movq(rax, Address(from, qword_count, Address::times_8, -8)); | |
1759 __ movq(Address(to, qword_count, Address::times_8, -8), rax); | |
304 | 1760 __ decrement(qword_count); |
0 | 1761 __ jcc(Assembler::notZero, L_copy_8_bytes); |
1762 | |
1763 restore_arg_regs(); | |
4118
59bc0d4d9ea3
7110489: C1: 64-bit tiered with ForceUnreachable: assert(reachable(src)) failed: Address should be reachable
never
parents:
4114
diff
changeset
|
1764 inc_counter_np(SharedRuntime::_jshort_array_copy_ctr); // Update counter after rscratch1 is free |
304 | 1765 __ xorptr(rax, rax); // return 0 |
0 | 1766 __ leave(); // required for proper stackwalking of RuntimeStub frame |
1767 __ ret(0); | |
1768 | |
1769 // Copy in 32-bytes chunks | |
1770 copy_32_bytes_backward(from, to, qword_count, rax, L_copy_32_bytes, L_copy_8_bytes); | |
1771 | |
1772 restore_arg_regs(); | |
4118
59bc0d4d9ea3
7110489: C1: 64-bit tiered with ForceUnreachable: assert(reachable(src)) failed: Address should be reachable
never
parents:
4114
diff
changeset
|
1773 inc_counter_np(SharedRuntime::_jshort_array_copy_ctr); // Update counter after rscratch1 is free |
304 | 1774 __ xorptr(rax, rax); // return 0 |
0 | 1775 __ leave(); // required for proper stackwalking of RuntimeStub frame |
1776 __ ret(0); | |
1777 | |
1778 return start; | |
1779 } | |
1780 | |
1781 // Arguments: | |
1782 // aligned - true => Input and output aligned on a HeapWord == 8-byte boundary | |
1783 // ignored | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
16
diff
changeset
|
1784 // is_oop - true => oop array, so generate store check code |
0 | 1785 // name - stub name string |
1786 // | |
1787 // Inputs: | |
1788 // c_rarg0 - source array address | |
1789 // c_rarg1 - destination array address | |
1790 // c_rarg2 - element count, treated as ssize_t, can be zero | |
1791 // | |
1792 // If 'from' and/or 'to' are aligned on 4-byte boundaries, we let | |
1793 // the hardware handle it. The two dwords within qwords that span | |
1794 // cache line boundaries will still be loaded and stored atomicly. | |
1795 // | |
1796 // Side Effects: | |
1797 // disjoint_int_copy_entry is set to the no-overlap entry point | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
16
diff
changeset
|
1798 // used by generate_conjoint_int_oop_copy(). |
0 | 1799 // |
2324 | 1800 address generate_disjoint_int_oop_copy(bool aligned, bool is_oop, address* entry, |
1801 const char *name, bool dest_uninitialized = false) { | |
0 | 1802 __ align(CodeEntryAlignment); |
1803 StubCodeMark mark(this, "StubRoutines", name); | |
1804 address start = __ pc(); | |
1805 | |
1806 Label L_copy_32_bytes, L_copy_8_bytes, L_copy_4_bytes, L_exit; | |
1807 const Register from = rdi; // source array address | |
1808 const Register to = rsi; // destination array address | |
1809 const Register count = rdx; // elements count | |
1810 const Register dword_count = rcx; | |
1811 const Register qword_count = count; | |
1812 const Register end_from = from; // source array end address | |
1813 const Register end_to = to; // destination array end address | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
16
diff
changeset
|
1814 const Register saved_to = r11; // saved destination array address |
0 | 1815 // End pointers are inclusive, and if count is not zero they point |
1816 // to the last unit copied: end_to[0] := end_from[0] | |
1817 | |
1818 __ enter(); // required for proper stackwalking of RuntimeStub frame | |
1819 assert_clean_int(c_rarg2, rax); // Make sure 'count' is clean int. | |
1820 | |
2313
d89a22843c62
7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents:
2006
diff
changeset
|
1821 if (entry != NULL) { |
d89a22843c62
7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents:
2006
diff
changeset
|
1822 *entry = __ pc(); |
d89a22843c62
7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents:
2006
diff
changeset
|
1823 // caller can pass a 64-bit byte count here (from Unsafe.copyMemory) |
d89a22843c62
7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents:
2006
diff
changeset
|
1824 BLOCK_COMMENT("Entry:"); |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
16
diff
changeset
|
1825 } |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
16
diff
changeset
|
1826 |
0 | 1827 setup_arg_regs(); // from => rdi, to => rsi, count => rdx |
1828 // r9 and r10 may be used to save non-volatile registers | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
16
diff
changeset
|
1829 if (is_oop) { |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
16
diff
changeset
|
1830 __ movq(saved_to, to); |
2324 | 1831 gen_write_ref_array_pre_barrier(to, count, dest_uninitialized); |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
16
diff
changeset
|
1832 } |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
16
diff
changeset
|
1833 |
0 | 1834 // 'from', 'to' and 'count' are now valid |
304 | 1835 __ movptr(dword_count, count); |
1836 __ shrptr(count, 1); // count => qword_count | |
0 | 1837 |
1838 // Copy from low to high addresses. Use 'to' as scratch. | |
304 | 1839 __ lea(end_from, Address(from, qword_count, Address::times_8, -8)); |
1840 __ lea(end_to, Address(to, qword_count, Address::times_8, -8)); | |
1841 __ negptr(qword_count); | |
0 | 1842 __ jmp(L_copy_32_bytes); |
1843 | |
1844 // Copy trailing qwords | |
1845 __ BIND(L_copy_8_bytes); | |
1846 __ movq(rax, Address(end_from, qword_count, Address::times_8, 8)); | |
1847 __ movq(Address(end_to, qword_count, Address::times_8, 8), rax); | |
304 | 1848 __ increment(qword_count); |
0 | 1849 __ jcc(Assembler::notZero, L_copy_8_bytes); |
1850 | |
1851 // Check for and copy trailing dword | |
1852 __ BIND(L_copy_4_bytes); | |
304 | 1853 __ testl(dword_count, 1); // Only byte test since the value is 0 or 1 |
0 | 1854 __ jccb(Assembler::zero, L_exit); |
1855 __ movl(rax, Address(end_from, 8)); | |
1856 __ movl(Address(end_to, 8), rax); | |
1857 | |
1858 __ BIND(L_exit); | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
16
diff
changeset
|
1859 if (is_oop) { |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
16
diff
changeset
|
1860 __ leaq(end_to, Address(saved_to, dword_count, Address::times_4, -4)); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
16
diff
changeset
|
1861 gen_write_ref_array_post_barrier(saved_to, end_to, rax); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
16
diff
changeset
|
1862 } |
0 | 1863 restore_arg_regs(); |
4118
59bc0d4d9ea3
7110489: C1: 64-bit tiered with ForceUnreachable: assert(reachable(src)) failed: Address should be reachable
never
parents:
4114
diff
changeset
|
1864 inc_counter_np(SharedRuntime::_jint_array_copy_ctr); // Update counter after rscratch1 is free |
304 | 1865 __ xorptr(rax, rax); // return 0 |
0 | 1866 __ leave(); // required for proper stackwalking of RuntimeStub frame |
1867 __ ret(0); | |
1868 | |
1869 // Copy 32-bytes chunks | |
1870 copy_32_bytes_forward(end_from, end_to, qword_count, rax, L_copy_32_bytes, L_copy_8_bytes); | |
1871 __ jmp(L_copy_4_bytes); | |
1872 | |
1873 return start; | |
1874 } | |
1875 | |
1876 // Arguments: | |
1877 // aligned - true => Input and output aligned on a HeapWord == 8-byte boundary | |
1878 // ignored | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
16
diff
changeset
|
1879 // is_oop - true => oop array, so generate store check code |
0 | 1880 // name - stub name string |
1881 // | |
1882 // Inputs: | |
1883 // c_rarg0 - source array address | |
1884 // c_rarg1 - destination array address | |
1885 // c_rarg2 - element count, treated as ssize_t, can be zero | |
1886 // | |
1887 // If 'from' and/or 'to' are aligned on 4-byte boundaries, we let | |
1888 // the hardware handle it. The two dwords within qwords that span | |
1889 // cache line boundaries will still be loaded and stored atomicly. | |
1890 // | |
2313
d89a22843c62
7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents:
2006
diff
changeset
|
1891 address generate_conjoint_int_oop_copy(bool aligned, bool is_oop, address nooverlap_target, |
2324 | 1892 address *entry, const char *name, |
1893 bool dest_uninitialized = false) { | |
0 | 1894 __ align(CodeEntryAlignment); |
1895 StubCodeMark mark(this, "StubRoutines", name); | |
1896 address start = __ pc(); | |
1897 | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
16
diff
changeset
|
1898 Label L_copy_32_bytes, L_copy_8_bytes, L_copy_2_bytes, L_exit; |
0 | 1899 const Register from = rdi; // source array address |
1900 const Register to = rsi; // destination array address | |
1901 const Register count = rdx; // elements count | |
1902 const Register dword_count = rcx; | |
1903 const Register qword_count = count; | |
1904 | |
1905 __ enter(); // required for proper stackwalking of RuntimeStub frame | |
1906 assert_clean_int(c_rarg2, rax); // Make sure 'count' is clean int. | |
1907 | |
2313
d89a22843c62
7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents:
2006
diff
changeset
|
1908 if (entry != NULL) { |
d89a22843c62
7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents:
2006
diff
changeset
|
1909 *entry = __ pc(); |
d89a22843c62
7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents:
2006
diff
changeset
|
1910 // caller can pass a 64-bit byte count here (from Unsafe.copyMemory) |
d89a22843c62
7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents:
2006
diff
changeset
|
1911 BLOCK_COMMENT("Entry:"); |
d89a22843c62
7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents:
2006
diff
changeset
|
1912 } |
d89a22843c62
7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents:
2006
diff
changeset
|
1913 |
d89a22843c62
7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents:
2006
diff
changeset
|
1914 array_overlap_test(nooverlap_target, Address::times_4); |
d89a22843c62
7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents:
2006
diff
changeset
|
1915 setup_arg_regs(); // from => rdi, to => rsi, count => rdx |
d89a22843c62
7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents:
2006
diff
changeset
|
1916 // r9 and r10 may be used to save non-volatile registers |
d89a22843c62
7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents:
2006
diff
changeset
|
1917 |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
16
diff
changeset
|
1918 if (is_oop) { |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
16
diff
changeset
|
1919 // no registers are destroyed by this call |
2324 | 1920 gen_write_ref_array_pre_barrier(to, count, dest_uninitialized); |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
16
diff
changeset
|
1921 } |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
16
diff
changeset
|
1922 |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
16
diff
changeset
|
1923 assert_clean_int(count, rax); // Make sure 'count' is clean int. |
0 | 1924 // 'from', 'to' and 'count' are now valid |
304 | 1925 __ movptr(dword_count, count); |
1926 __ shrptr(count, 1); // count => qword_count | |
0 | 1927 |
1928 // Copy from high to low addresses. Use 'to' as scratch. | |
1929 | |
1930 // Check for and copy trailing dword | |
304 | 1931 __ testl(dword_count, 1); |
0 | 1932 __ jcc(Assembler::zero, L_copy_32_bytes); |
1933 __ movl(rax, Address(from, dword_count, Address::times_4, -4)); | |
1934 __ movl(Address(to, dword_count, Address::times_4, -4), rax); | |
1935 __ jmp(L_copy_32_bytes); | |
1936 | |
1937 // Copy trailing qwords | |
1938 __ BIND(L_copy_8_bytes); | |
1939 __ movq(rax, Address(from, qword_count, Address::times_8, -8)); | |
1940 __ movq(Address(to, qword_count, Address::times_8, -8), rax); | |
304 | 1941 __ decrement(qword_count); |
0 | 1942 __ jcc(Assembler::notZero, L_copy_8_bytes); |
1943 | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
16
diff
changeset
|
1944 if (is_oop) { |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
16
diff
changeset
|
1945 __ jmp(L_exit); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
16
diff
changeset
|
1946 } |
0 | 1947 restore_arg_regs(); |
4118
59bc0d4d9ea3
7110489: C1: 64-bit tiered with ForceUnreachable: assert(reachable(src)) failed: Address should be reachable
never
parents:
4114
diff
changeset
|
1948 inc_counter_np(SharedRuntime::_jint_array_copy_ctr); // Update counter after rscratch1 is free |
304 | 1949 __ xorptr(rax, rax); // return 0 |
0 | 1950 __ leave(); // required for proper stackwalking of RuntimeStub frame |
1951 __ ret(0); | |
1952 | |
1953 // Copy in 32-bytes chunks | |
1954 copy_32_bytes_backward(from, to, qword_count, rax, L_copy_32_bytes, L_copy_8_bytes); | |
1955 | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
16
diff
changeset
|
1956 __ bind(L_exit); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
16
diff
changeset
|
1957 if (is_oop) { |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
16
diff
changeset
|
1958 Register end_to = rdx; |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
16
diff
changeset
|
1959 __ leaq(end_to, Address(to, dword_count, Address::times_4, -4)); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
16
diff
changeset
|
1960 gen_write_ref_array_post_barrier(to, end_to, rax); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
16
diff
changeset
|
1961 } |
0 | 1962 restore_arg_regs(); |
4118
59bc0d4d9ea3
7110489: C1: 64-bit tiered with ForceUnreachable: assert(reachable(src)) failed: Address should be reachable
never
parents:
4114
diff
changeset
|
1963 inc_counter_np(SharedRuntime::_jint_array_copy_ctr); // Update counter after rscratch1 is free |
304 | 1964 __ xorptr(rax, rax); // return 0 |
0 | 1965 __ leave(); // required for proper stackwalking of RuntimeStub frame |
1966 __ ret(0); | |
1967 | |
1968 return start; | |
1969 } | |
1970 | |
1971 // Arguments: | |
1972 // aligned - true => Input and output aligned on a HeapWord boundary == 8 bytes | |
1973 // ignored | |
1974 // is_oop - true => oop array, so generate store check code | |
1975 // name - stub name string | |
1976 // | |
1977 // Inputs: | |
1978 // c_rarg0 - source array address | |
1979 // c_rarg1 - destination array address | |
1980 // c_rarg2 - element count, treated as ssize_t, can be zero | |
1981 // | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
16
diff
changeset
|
1982 // Side Effects: |
0 | 1983 // disjoint_oop_copy_entry or disjoint_long_copy_entry is set to the |
1984 // no-overlap entry point used by generate_conjoint_long_oop_copy(). | |
1985 // | |
2324 | 1986 address generate_disjoint_long_oop_copy(bool aligned, bool is_oop, address *entry, |
1987 const char *name, bool dest_uninitialized = false) { | |
0 | 1988 __ align(CodeEntryAlignment); |
1989 StubCodeMark mark(this, "StubRoutines", name); | |
1990 address start = __ pc(); | |
1991 | |
1992 Label L_copy_32_bytes, L_copy_8_bytes, L_exit; | |
1993 const Register from = rdi; // source array address | |
1994 const Register to = rsi; // destination array address | |
1995 const Register qword_count = rdx; // elements count | |
1996 const Register end_from = from; // source array end address | |
1997 const Register end_to = rcx; // destination array end address | |
1998 const Register saved_to = to; | |
1999 // End pointers are inclusive, and if count is not zero they point | |
2000 // to the last unit copied: end_to[0] := end_from[0] | |
2001 | |
2002 __ enter(); // required for proper stackwalking of RuntimeStub frame | |
2003 // Save no-overlap entry point for generate_conjoint_long_oop_copy() | |
2004 assert_clean_int(c_rarg2, rax); // Make sure 'count' is clean int. | |
2005 | |
2313
d89a22843c62
7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents:
2006
diff
changeset
|
2006 if (entry != NULL) { |
d89a22843c62
7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents:
2006
diff
changeset
|
2007 *entry = __ pc(); |
d89a22843c62
7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents:
2006
diff
changeset
|
2008 // caller can pass a 64-bit byte count here (from Unsafe.copyMemory) |
d89a22843c62
7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents:
2006
diff
changeset
|
2009 BLOCK_COMMENT("Entry:"); |
0 | 2010 } |
2011 | |
2012 setup_arg_regs(); // from => rdi, to => rsi, count => rdx | |
2013 // r9 and r10 may be used to save non-volatile registers | |
2014 // 'from', 'to' and 'qword_count' are now valid | |
2313
d89a22843c62
7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents:
2006
diff
changeset
|
2015 if (is_oop) { |
d89a22843c62
7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents:
2006
diff
changeset
|
2016 // no registers are destroyed by this call |
2324 | 2017 gen_write_ref_array_pre_barrier(to, qword_count, dest_uninitialized); |
2313
d89a22843c62
7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents:
2006
diff
changeset
|
2018 } |
0 | 2019 |
2020 // Copy from low to high addresses. Use 'to' as scratch. | |
304 | 2021 __ lea(end_from, Address(from, qword_count, Address::times_8, -8)); |
2022 __ lea(end_to, Address(to, qword_count, Address::times_8, -8)); | |
2023 __ negptr(qword_count); | |
0 | 2024 __ jmp(L_copy_32_bytes); |
2025 | |
2026 // Copy trailing qwords | |
2027 __ BIND(L_copy_8_bytes); | |
2028 __ movq(rax, Address(end_from, qword_count, Address::times_8, 8)); | |
2029 __ movq(Address(end_to, qword_count, Address::times_8, 8), rax); | |
304 | 2030 __ increment(qword_count); |
0 | 2031 __ jcc(Assembler::notZero, L_copy_8_bytes); |
2032 | |
2033 if (is_oop) { | |
2034 __ jmp(L_exit); | |
2035 } else { | |
2036 restore_arg_regs(); | |
4118
59bc0d4d9ea3
7110489: C1: 64-bit tiered with ForceUnreachable: assert(reachable(src)) failed: Address should be reachable
never
parents:
4114
diff
changeset
|
2037 inc_counter_np(SharedRuntime::_jlong_array_copy_ctr); // Update counter after rscratch1 is free |
304 | 2038 __ xorptr(rax, rax); // return 0 |
0 | 2039 __ leave(); // required for proper stackwalking of RuntimeStub frame |
2040 __ ret(0); | |
2041 } | |
2042 | |
2043 // Copy 64-byte chunks | |
2044 copy_32_bytes_forward(end_from, end_to, qword_count, rax, L_copy_32_bytes, L_copy_8_bytes); | |
2045 | |
2046 if (is_oop) { | |
2047 __ BIND(L_exit); | |
2048 gen_write_ref_array_post_barrier(saved_to, end_to, rax); | |
2049 } | |
2050 restore_arg_regs(); | |
4118
59bc0d4d9ea3
7110489: C1: 64-bit tiered with ForceUnreachable: assert(reachable(src)) failed: Address should be reachable
never
parents:
4114
diff
changeset
|
2051 if (is_oop) { |
59bc0d4d9ea3
7110489: C1: 64-bit tiered with ForceUnreachable: assert(reachable(src)) failed: Address should be reachable
never
parents:
4114
diff
changeset
|
2052 inc_counter_np(SharedRuntime::_oop_array_copy_ctr); // Update counter after rscratch1 is free |
59bc0d4d9ea3
7110489: C1: 64-bit tiered with ForceUnreachable: assert(reachable(src)) failed: Address should be reachable
never
parents:
4114
diff
changeset
|
2053 } else { |
59bc0d4d9ea3
7110489: C1: 64-bit tiered with ForceUnreachable: assert(reachable(src)) failed: Address should be reachable
never
parents:
4114
diff
changeset
|
2054 inc_counter_np(SharedRuntime::_jlong_array_copy_ctr); // Update counter after rscratch1 is free |
59bc0d4d9ea3
7110489: C1: 64-bit tiered with ForceUnreachable: assert(reachable(src)) failed: Address should be reachable
never
parents:
4114
diff
changeset
|
2055 } |
304 | 2056 __ xorptr(rax, rax); // return 0 |
0 | 2057 __ leave(); // required for proper stackwalking of RuntimeStub frame |
2058 __ ret(0); | |
2059 | |
2060 return start; | |
2061 } | |
2062 | |
2063 // Arguments: | |
2064 // aligned - true => Input and output aligned on a HeapWord boundary == 8 bytes | |
2065 // ignored | |
2066 // is_oop - true => oop array, so generate store check code | |
2067 // name - stub name string | |
2068 // | |
2069 // Inputs: | |
2070 // c_rarg0 - source array address | |
2071 // c_rarg1 - destination array address | |
2072 // c_rarg2 - element count, treated as ssize_t, can be zero | |
2073 // | |
2324 | 2074 address generate_conjoint_long_oop_copy(bool aligned, bool is_oop, |
2075 address nooverlap_target, address *entry, | |
2076 const char *name, bool dest_uninitialized = false) { | |
0 | 2077 __ align(CodeEntryAlignment); |
2078 StubCodeMark mark(this, "StubRoutines", name); | |
2079 address start = __ pc(); | |
2080 | |
2081 Label L_copy_32_bytes, L_copy_8_bytes, L_exit; | |
2082 const Register from = rdi; // source array address | |
2083 const Register to = rsi; // destination array address | |
2084 const Register qword_count = rdx; // elements count | |
2085 const Register saved_count = rcx; | |
2086 | |
2087 __ enter(); // required for proper stackwalking of RuntimeStub frame | |
2088 assert_clean_int(c_rarg2, rax); // Make sure 'count' is clean int. | |
2089 | |
2313
d89a22843c62
7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents:
2006
diff
changeset
|
2090 if (entry != NULL) { |
d89a22843c62
7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents:
2006
diff
changeset
|
2091 *entry = __ pc(); |
d89a22843c62
7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents:
2006
diff
changeset
|
2092 // caller can pass a 64-bit byte count here (from Unsafe.copyMemory) |
d89a22843c62
7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents:
2006
diff
changeset
|
2093 BLOCK_COMMENT("Entry:"); |
0 | 2094 } |
2313
d89a22843c62
7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents:
2006
diff
changeset
|
2095 |
d89a22843c62
7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents:
2006
diff
changeset
|
2096 array_overlap_test(nooverlap_target, Address::times_8); |
0 | 2097 setup_arg_regs(); // from => rdi, to => rsi, count => rdx |
2098 // r9 and r10 may be used to save non-volatile registers | |
2099 // 'from', 'to' and 'qword_count' are now valid | |
2100 if (is_oop) { | |
2101 // Save to and count for store barrier | |
304 | 2102 __ movptr(saved_count, qword_count); |
0 | 2103 // No registers are destroyed by this call |
2324 | 2104 gen_write_ref_array_pre_barrier(to, saved_count, dest_uninitialized); |
0 | 2105 } |
2106 | |
2107 __ jmp(L_copy_32_bytes); | |
2108 | |
2109 // Copy trailing qwords | |
2110 __ BIND(L_copy_8_bytes); | |
2111 __ movq(rax, Address(from, qword_count, Address::times_8, -8)); | |
2112 __ movq(Address(to, qword_count, Address::times_8, -8), rax); | |
304 | 2113 __ decrement(qword_count); |
0 | 2114 __ jcc(Assembler::notZero, L_copy_8_bytes); |
2115 | |
2116 if (is_oop) { | |
2117 __ jmp(L_exit); | |
2118 } else { | |
2119 restore_arg_regs(); | |
4118
59bc0d4d9ea3
7110489: C1: 64-bit tiered with ForceUnreachable: assert(reachable(src)) failed: Address should be reachable
never
parents:
4114
diff
changeset
|
2120 inc_counter_np(SharedRuntime::_jlong_array_copy_ctr); // Update counter after rscratch1 is free |
304 | 2121 __ xorptr(rax, rax); // return 0 |
0 | 2122 __ leave(); // required for proper stackwalking of RuntimeStub frame |
2123 __ ret(0); | |
2124 } | |
2125 | |
2126 // Copy in 32-bytes chunks | |
2127 copy_32_bytes_backward(from, to, qword_count, rax, L_copy_32_bytes, L_copy_8_bytes); | |
2128 | |
2129 if (is_oop) { | |
2130 __ BIND(L_exit); | |
304 | 2131 __ lea(rcx, Address(to, saved_count, Address::times_8, -8)); |
0 | 2132 gen_write_ref_array_post_barrier(to, rcx, rax); |
2133 } | |
2134 restore_arg_regs(); | |
4118
59bc0d4d9ea3
7110489: C1: 64-bit tiered with ForceUnreachable: assert(reachable(src)) failed: Address should be reachable
never
parents:
4114
diff
changeset
|
2135 if (is_oop) { |
59bc0d4d9ea3
7110489: C1: 64-bit tiered with ForceUnreachable: assert(reachable(src)) failed: Address should be reachable
never
parents:
4114
diff
changeset
|
2136 inc_counter_np(SharedRuntime::_oop_array_copy_ctr); // Update counter after rscratch1 is free |
59bc0d4d9ea3
7110489: C1: 64-bit tiered with ForceUnreachable: assert(reachable(src)) failed: Address should be reachable
never
parents:
4114
diff
changeset
|
2137 } else { |
59bc0d4d9ea3
7110489: C1: 64-bit tiered with ForceUnreachable: assert(reachable(src)) failed: Address should be reachable
never
parents:
4114
diff
changeset
|
2138 inc_counter_np(SharedRuntime::_jlong_array_copy_ctr); // Update counter after rscratch1 is free |
59bc0d4d9ea3
7110489: C1: 64-bit tiered with ForceUnreachable: assert(reachable(src)) failed: Address should be reachable
never
parents:
4114
diff
changeset
|
2139 } |
304 | 2140 __ xorptr(rax, rax); // return 0 |
0 | 2141 __ leave(); // required for proper stackwalking of RuntimeStub frame |
2142 __ ret(0); | |
2143 | |
2144 return start; | |
2145 } | |
2146 | |
2147 | |
2148 // Helper for generating a dynamic type check. | |
2149 // Smashes no registers. | |
2150 void generate_type_check(Register sub_klass, | |
2151 Register super_check_offset, | |
2152 Register super_klass, | |
2153 Label& L_success) { | |
2154 assert_different_registers(sub_klass, super_check_offset, super_klass); | |
2155 | |
2156 BLOCK_COMMENT("type_check:"); | |
2157 | |
2158 Label L_miss; | |
2159 | |
644
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
512
diff
changeset
|
2160 __ check_klass_subtype_fast_path(sub_klass, super_klass, noreg, &L_success, &L_miss, NULL, |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
512
diff
changeset
|
2161 super_check_offset); |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
512
diff
changeset
|
2162 __ check_klass_subtype_slow_path(sub_klass, super_klass, noreg, noreg, &L_success, NULL); |
0 | 2163 |
2164 // Fall through on failure! | |
2165 __ BIND(L_miss); | |
2166 } | |
2167 | |
2168 // | |
2169 // Generate checkcasting array copy stub | |
2170 // | |
2171 // Input: | |
2172 // c_rarg0 - source array address | |
2173 // c_rarg1 - destination array address | |
2174 // c_rarg2 - element count, treated as ssize_t, can be zero | |
2175 // c_rarg3 - size_t ckoff (super_check_offset) | |
2176 // not Win64 | |
2177 // c_rarg4 - oop ckval (super_klass) | |
2178 // Win64 | |
2179 // rsp+40 - oop ckval (super_klass) | |
2180 // | |
2181 // Output: | |
2182 // rax == 0 - success | |
2183 // rax == -1^K - failure, where K is partial transfer count | |
2184 // | |
2324 | 2185 address generate_checkcast_copy(const char *name, address *entry, |
2186 bool dest_uninitialized = false) { | |
0 | 2187 |
2188 Label L_load_element, L_store_element, L_do_card_marks, L_done; | |
2189 | |
2190 // Input registers (after setup_arg_regs) | |
2191 const Register from = rdi; // source array address | |
2192 const Register to = rsi; // destination array address | |
2193 const Register length = rdx; // elements count | |
2194 const Register ckoff = rcx; // super_check_offset | |
2195 const Register ckval = r8; // super_klass | |
2196 | |
2197 // Registers used as temps (r13, r14 are save-on-entry) | |
2198 const Register end_from = from; // source array end address | |
2199 const Register end_to = r13; // destination array end address | |
2200 const Register count = rdx; // -(count_remaining) | |
2201 const Register r14_length = r14; // saved copy of length | |
2202 // End pointers are inclusive, and if length is not zero they point | |
2203 // to the last unit copied: end_to[0] := end_from[0] | |
2204 | |
2205 const Register rax_oop = rax; // actual oop copied | |
2206 const Register r11_klass = r11; // oop._klass | |
2207 | |
2208 //--------------------------------------------------------------- | |
2209 // Assembler stub will be used for this call to arraycopy | |
2210 // if the two arrays are subtypes of Object[] but the | |
2211 // destination array type is not equal to or a supertype | |
2212 // of the source type. Each element must be separately | |
2213 // checked. | |
2214 | |
2215 __ align(CodeEntryAlignment); | |
2216 StubCodeMark mark(this, "StubRoutines", name); | |
2217 address start = __ pc(); | |
2218 | |
2219 __ enter(); // required for proper stackwalking of RuntimeStub frame | |
2220 | |
2221 #ifdef ASSERT | |
2222 // caller guarantees that the arrays really are different | |
2223 // otherwise, we would have to make conjoint checks | |
2224 { Label L; | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
16
diff
changeset
|
2225 array_overlap_test(L, TIMES_OOP); |
0 | 2226 __ stop("checkcast_copy within a single array"); |
2227 __ bind(L); | |
2228 } | |
2229 #endif //ASSERT | |
2230 | |
2231 setup_arg_regs(4); // from => rdi, to => rsi, length => rdx | |
2232 // ckoff => rcx, ckval => r8 | |
2233 // r9 and r10 may be used to save non-volatile registers | |
2234 #ifdef _WIN64 | |
2235 // last argument (#4) is on stack on Win64 | |
2006
bbefa3ca1543
6998985: faulty generic arraycopy on windows x86_64: 4th arg overwritten with oop
twisti
parents:
1972
diff
changeset
|
2236 __ movptr(ckval, Address(rsp, 6 * wordSize)); |
0 | 2237 #endif |
2238 | |
2006
bbefa3ca1543
6998985: faulty generic arraycopy on windows x86_64: 4th arg overwritten with oop
twisti
parents:
1972
diff
changeset
|
2239 // Caller of this entry point must set up the argument registers. |
2313
d89a22843c62
7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents:
2006
diff
changeset
|
2240 if (entry != NULL) { |
d89a22843c62
7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents:
2006
diff
changeset
|
2241 *entry = __ pc(); |
d89a22843c62
7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents:
2006
diff
changeset
|
2242 BLOCK_COMMENT("Entry:"); |
d89a22843c62
7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents:
2006
diff
changeset
|
2243 } |
2006
bbefa3ca1543
6998985: faulty generic arraycopy on windows x86_64: 4th arg overwritten with oop
twisti
parents:
1972
diff
changeset
|
2244 |
bbefa3ca1543
6998985: faulty generic arraycopy on windows x86_64: 4th arg overwritten with oop
twisti
parents:
1972
diff
changeset
|
2245 // allocate spill slots for r13, r14 |
bbefa3ca1543
6998985: faulty generic arraycopy on windows x86_64: 4th arg overwritten with oop
twisti
parents:
1972
diff
changeset
|
2246 enum { |
bbefa3ca1543
6998985: faulty generic arraycopy on windows x86_64: 4th arg overwritten with oop
twisti
parents:
1972
diff
changeset
|
2247 saved_r13_offset, |
bbefa3ca1543
6998985: faulty generic arraycopy on windows x86_64: 4th arg overwritten with oop
twisti
parents:
1972
diff
changeset
|
2248 saved_r14_offset, |
bbefa3ca1543
6998985: faulty generic arraycopy on windows x86_64: 4th arg overwritten with oop
twisti
parents:
1972
diff
changeset
|
2249 saved_rbp_offset |
bbefa3ca1543
6998985: faulty generic arraycopy on windows x86_64: 4th arg overwritten with oop
twisti
parents:
1972
diff
changeset
|
2250 }; |
bbefa3ca1543
6998985: faulty generic arraycopy on windows x86_64: 4th arg overwritten with oop
twisti
parents:
1972
diff
changeset
|
2251 __ subptr(rsp, saved_rbp_offset * wordSize); |
bbefa3ca1543
6998985: faulty generic arraycopy on windows x86_64: 4th arg overwritten with oop
twisti
parents:
1972
diff
changeset
|
2252 __ movptr(Address(rsp, saved_r13_offset * wordSize), r13); |
bbefa3ca1543
6998985: faulty generic arraycopy on windows x86_64: 4th arg overwritten with oop
twisti
parents:
1972
diff
changeset
|
2253 __ movptr(Address(rsp, saved_r14_offset * wordSize), r14); |
bbefa3ca1543
6998985: faulty generic arraycopy on windows x86_64: 4th arg overwritten with oop
twisti
parents:
1972
diff
changeset
|
2254 |
0 | 2255 // check that int operands are properly extended to size_t |
2256 assert_clean_int(length, rax); | |
2257 assert_clean_int(ckoff, rax); | |
2258 | |
2259 #ifdef ASSERT | |
2260 BLOCK_COMMENT("assert consistent ckoff/ckval"); | |
2261 // The ckoff and ckval must be mutually consistent, | |
2262 // even though caller generates both. | |
2263 { Label L; | |
2264 int sco_offset = (klassOopDesc::header_size() * HeapWordSize + | |
2265 Klass::super_check_offset_offset_in_bytes()); | |
2266 __ cmpl(ckoff, Address(ckval, sco_offset)); | |
2267 __ jcc(Assembler::equal, L); | |
2268 __ stop("super_check_offset inconsistent"); | |
2269 __ bind(L); | |
2270 } | |
2271 #endif //ASSERT | |
2272 | |
2273 // Loop-invariant addresses. They are exclusive end pointers. | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
16
diff
changeset
|
2274 Address end_from_addr(from, length, TIMES_OOP, 0); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
16
diff
changeset
|
2275 Address end_to_addr(to, length, TIMES_OOP, 0); |
0 | 2276 // Loop-variant addresses. They assume post-incremented count < 0. |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
16
diff
changeset
|
2277 Address from_element_addr(end_from, count, TIMES_OOP, 0); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
16
diff
changeset
|
2278 Address to_element_addr(end_to, count, TIMES_OOP, 0); |
0 | 2279 |
2324 | 2280 gen_write_ref_array_pre_barrier(to, count, dest_uninitialized); |
0 | 2281 |
2282 // Copy from low to high addresses, indexed from the end of each array. | |
304 | 2283 __ lea(end_from, end_from_addr); |
2284 __ lea(end_to, end_to_addr); | |
2285 __ movptr(r14_length, length); // save a copy of the length | |
2286 assert(length == count, ""); // else fix next line: | |
2287 __ negptr(count); // negate and test the length | |
0 | 2288 __ jcc(Assembler::notZero, L_load_element); |
2289 | |
2290 // Empty array: Nothing to do. | |
304 | 2291 __ xorptr(rax, rax); // return 0 on (trivial) success |
0 | 2292 __ jmp(L_done); |
2293 | |
2294 // ======== begin loop ======== | |
2295 // (Loop is rotated; its entry is L_load_element.) | |
2296 // Loop control: | |
2297 // for (count = -count; count != 0; count++) | |
2298 // Base pointers src, dst are biased by 8*(count-1),to last element. | |
1365 | 2299 __ align(OptoLoopAlignment); |
0 | 2300 |
2301 __ BIND(L_store_element); | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
16
diff
changeset
|
2302 __ store_heap_oop(to_element_addr, rax_oop); // store the oop |
304 | 2303 __ increment(count); // increment the count toward zero |
0 | 2304 __ jcc(Assembler::zero, L_do_card_marks); |
2305 | |
2306 // ======== loop entry is here ======== | |
2307 __ BIND(L_load_element); | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
16
diff
changeset
|
2308 __ load_heap_oop(rax_oop, from_element_addr); // load the oop |
304 | 2309 __ testptr(rax_oop, rax_oop); |
0 | 2310 __ jcc(Assembler::zero, L_store_element); |
2311 | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
16
diff
changeset
|
2312 __ load_klass(r11_klass, rax_oop);// query the object klass |
0 | 2313 generate_type_check(r11_klass, ckoff, ckval, L_store_element); |
2314 // ======== end loop ======== | |
2315 | |
2316 // It was a real error; we must depend on the caller to finish the job. | |
2317 // Register rdx = -1 * number of *remaining* oops, r14 = *total* oops. | |
2318 // Emit GC store barriers for the oops we have copied (r14 + rdx), | |
2319 // and report their number to the caller. | |
2320 assert_different_registers(rax, r14_length, count, to, end_to, rcx); | |
304 | 2321 __ lea(end_to, to_element_addr); |
845
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
671
diff
changeset
|
2322 __ addptr(end_to, -heapOopSize); // make an inclusive end pointer |
362 | 2323 gen_write_ref_array_post_barrier(to, end_to, rscratch1); |
304 | 2324 __ movptr(rax, r14_length); // original oops |
2325 __ addptr(rax, count); // K = (original - remaining) oops | |
2326 __ notptr(rax); // report (-1^K) to caller | |
0 | 2327 __ jmp(L_done); |
2328 | |
2329 // Come here on success only. | |
2330 __ BIND(L_do_card_marks); | |
845
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
671
diff
changeset
|
2331 __ addptr(end_to, -heapOopSize); // make an inclusive end pointer |
362 | 2332 gen_write_ref_array_post_barrier(to, end_to, rscratch1); |
304 | 2333 __ xorptr(rax, rax); // return 0 on success |
0 | 2334 |
2335 // Common exit point (success or failure). | |
2336 __ BIND(L_done); | |
304 | 2337 __ movptr(r13, Address(rsp, saved_r13_offset * wordSize)); |
2338 __ movptr(r14, Address(rsp, saved_r14_offset * wordSize)); | |
0 | 2339 restore_arg_regs(); |
4118
59bc0d4d9ea3
7110489: C1: 64-bit tiered with ForceUnreachable: assert(reachable(src)) failed: Address should be reachable
never
parents:
4114
diff
changeset
|
2340 inc_counter_np(SharedRuntime::_checkcast_array_copy_ctr); // Update counter after rscratch1 is free |
0 | 2341 __ leave(); // required for proper stackwalking of RuntimeStub frame |
2342 __ ret(0); | |
2343 | |
2344 return start; | |
2345 } | |
2346 | |
2347 // | |
2348 // Generate 'unsafe' array copy stub | |
2349 // Though just as safe as the other stubs, it takes an unscaled | |
2350 // size_t argument instead of an element count. | |
2351 // | |
2352 // Input: | |
2353 // c_rarg0 - source array address | |
2354 // c_rarg1 - destination array address | |
2355 // c_rarg2 - byte count, treated as ssize_t, can be zero | |
2356 // | |
2357 // Examines the alignment of the operands and dispatches | |
2358 // to a long, int, short, or byte copy loop. | |
2359 // | |
2313
d89a22843c62
7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents:
2006
diff
changeset
|
2360 address generate_unsafe_copy(const char *name, |
d89a22843c62
7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents:
2006
diff
changeset
|
2361 address byte_copy_entry, address short_copy_entry, |
d89a22843c62
7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents:
2006
diff
changeset
|
2362 address int_copy_entry, address long_copy_entry) { |
0 | 2363 |
2364 Label L_long_aligned, L_int_aligned, L_short_aligned; | |
2365 | |
2366 // Input registers (before setup_arg_regs) | |
2367 const Register from = c_rarg0; // source array address | |
2368 const Register to = c_rarg1; // destination array address | |
2369 const Register size = c_rarg2; // byte count (size_t) | |
2370 | |
2371 // Register used as a temp | |
2372 const Register bits = rax; // test copy of low bits | |
2373 | |
2374 __ align(CodeEntryAlignment); | |
2375 StubCodeMark mark(this, "StubRoutines", name); | |
2376 address start = __ pc(); | |
2377 | |
2378 __ enter(); // required for proper stackwalking of RuntimeStub frame | |
2379 | |
2380 // bump this on entry, not on exit: | |
2381 inc_counter_np(SharedRuntime::_unsafe_array_copy_ctr); | |
2382 | |
304 | 2383 __ mov(bits, from); |
2384 __ orptr(bits, to); | |
2385 __ orptr(bits, size); | |
0 | 2386 |
2387 __ testb(bits, BytesPerLong-1); | |
2388 __ jccb(Assembler::zero, L_long_aligned); | |
2389 | |
2390 __ testb(bits, BytesPerInt-1); | |
2391 __ jccb(Assembler::zero, L_int_aligned); | |
2392 | |
2393 __ testb(bits, BytesPerShort-1); | |
2394 __ jump_cc(Assembler::notZero, RuntimeAddress(byte_copy_entry)); | |
2395 | |
2396 __ BIND(L_short_aligned); | |
304 | 2397 __ shrptr(size, LogBytesPerShort); // size => short_count |
0 | 2398 __ jump(RuntimeAddress(short_copy_entry)); |
2399 | |
2400 __ BIND(L_int_aligned); | |
304 | 2401 __ shrptr(size, LogBytesPerInt); // size => int_count |
0 | 2402 __ jump(RuntimeAddress(int_copy_entry)); |
2403 | |
2404 __ BIND(L_long_aligned); | |
304 | 2405 __ shrptr(size, LogBytesPerLong); // size => qword_count |
0 | 2406 __ jump(RuntimeAddress(long_copy_entry)); |
2407 | |
2408 return start; | |
2409 } | |
2410 | |
2411 // Perform range checks on the proposed arraycopy. | |
2412 // Kills temp, but nothing else. | |
2413 // Also, clean the sign bits of src_pos and dst_pos. | |
2414 void arraycopy_range_checks(Register src, // source array oop (c_rarg0) | |
2415 Register src_pos, // source position (c_rarg1) | |
2416 Register dst, // destination array oo (c_rarg2) | |
2417 Register dst_pos, // destination position (c_rarg3) | |
2418 Register length, | |
2419 Register temp, | |
2420 Label& L_failed) { | |
2421 BLOCK_COMMENT("arraycopy_range_checks:"); | |
2422 | |
2423 // if (src_pos + length > arrayOop(src)->length()) FAIL; | |
2424 __ movl(temp, length); | |
2425 __ addl(temp, src_pos); // src_pos + length | |
2426 __ cmpl(temp, Address(src, arrayOopDesc::length_offset_in_bytes())); | |
2427 __ jcc(Assembler::above, L_failed); | |
2428 | |
2429 // if (dst_pos + length > arrayOop(dst)->length()) FAIL; | |
2430 __ movl(temp, length); | |
2431 __ addl(temp, dst_pos); // dst_pos + length | |
2432 __ cmpl(temp, Address(dst, arrayOopDesc::length_offset_in_bytes())); | |
2433 __ jcc(Assembler::above, L_failed); | |
2434 | |
2435 // Have to clean up high 32-bits of 'src_pos' and 'dst_pos'. | |
2436 // Move with sign extension can be used since they are positive. | |
2437 __ movslq(src_pos, src_pos); | |
2438 __ movslq(dst_pos, dst_pos); | |
2439 | |
2440 BLOCK_COMMENT("arraycopy_range_checks done"); | |
2441 } | |
2442 | |
2443 // | |
2444 // Generate generic array copy stubs | |
2445 // | |
2446 // Input: | |
2447 // c_rarg0 - src oop | |
2448 // c_rarg1 - src_pos (32-bits) | |
2449 // c_rarg2 - dst oop | |
2450 // c_rarg3 - dst_pos (32-bits) | |
2451 // not Win64 | |
2452 // c_rarg4 - element count (32-bits) | |
2453 // Win64 | |
2454 // rsp+40 - element count (32-bits) | |
2455 // | |
2456 // Output: | |
2457 // rax == 0 - success | |
2458 // rax == -1^K - failure, where K is partial transfer count | |
2459 // | |
2313
d89a22843c62
7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents:
2006
diff
changeset
|
2460 address generate_generic_copy(const char *name, |
d89a22843c62
7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents:
2006
diff
changeset
|
2461 address byte_copy_entry, address short_copy_entry, |
2409
348c0df561a9
7026307: DEBUG MESSAGE: broken null klass on amd64
iveresov
parents:
2407
diff
changeset
|
2462 address int_copy_entry, address oop_copy_entry, |
348c0df561a9
7026307: DEBUG MESSAGE: broken null klass on amd64
iveresov
parents:
2407
diff
changeset
|
2463 address long_copy_entry, address checkcast_copy_entry) { |
0 | 2464 |
2465 Label L_failed, L_failed_0, L_objArray; | |
2466 Label L_copy_bytes, L_copy_shorts, L_copy_ints, L_copy_longs; | |
2467 | |
2468 // Input registers | |
2469 const Register src = c_rarg0; // source array oop | |
2470 const Register src_pos = c_rarg1; // source position | |
2471 const Register dst = c_rarg2; // destination array oop | |
2472 const Register dst_pos = c_rarg3; // destination position | |
2006
bbefa3ca1543
6998985: faulty generic arraycopy on windows x86_64: 4th arg overwritten with oop
twisti
parents:
1972
diff
changeset
|
2473 #ifndef _WIN64 |
bbefa3ca1543
6998985: faulty generic arraycopy on windows x86_64: 4th arg overwritten with oop
twisti
parents:
1972
diff
changeset
|
2474 const Register length = c_rarg4; |
0 | 2475 #else |
2006
bbefa3ca1543
6998985: faulty generic arraycopy on windows x86_64: 4th arg overwritten with oop
twisti
parents:
1972
diff
changeset
|
2476 const Address length(rsp, 6 * wordSize); // elements count is on stack on Win64 |
0 | 2477 #endif |
2478 | |
2479 { int modulus = CodeEntryAlignment; | |
2480 int target = modulus - 5; // 5 = sizeof jmp(L_failed) | |
2481 int advance = target - (__ offset() % modulus); | |
2482 if (advance < 0) advance += modulus; | |
2483 if (advance > 0) __ nop(advance); | |
2484 } | |
2485 StubCodeMark mark(this, "StubRoutines", name); | |
2486 | |
2487 // Short-hop target to L_failed. Makes for denser prologue code. | |
2488 __ BIND(L_failed_0); | |
2489 __ jmp(L_failed); | |
2490 assert(__ offset() % CodeEntryAlignment == 0, "no further alignment needed"); | |
2491 | |
2492 __ align(CodeEntryAlignment); | |
2493 address start = __ pc(); | |
2494 | |
2495 __ enter(); // required for proper stackwalking of RuntimeStub frame | |
2496 | |
2497 // bump this on entry, not on exit: | |
2498 inc_counter_np(SharedRuntime::_generic_array_copy_ctr); | |
2499 | |
2500 //----------------------------------------------------------------------- | |
2501 // Assembler stub will be used for this call to arraycopy | |
2502 // if the following conditions are met: | |
2503 // | |
2504 // (1) src and dst must not be null. | |
2505 // (2) src_pos must not be negative. | |
2506 // (3) dst_pos must not be negative. | |
2507 // (4) length must not be negative. | |
2508 // (5) src klass and dst klass should be the same and not NULL. | |
2509 // (6) src and dst should be arrays. | |
2510 // (7) src_pos + length must not exceed length of src. | |
2511 // (8) dst_pos + length must not exceed length of dst. | |
2512 // | |
2513 | |
2514 // if (src == NULL) return -1; | |
304 | 2515 __ testptr(src, src); // src oop |
0 | 2516 size_t j1off = __ offset(); |
2517 __ jccb(Assembler::zero, L_failed_0); | |
2518 | |
2519 // if (src_pos < 0) return -1; | |
2520 __ testl(src_pos, src_pos); // src_pos (32-bits) | |
2521 __ jccb(Assembler::negative, L_failed_0); | |
2522 | |
2523 // if (dst == NULL) return -1; | |
304 | 2524 __ testptr(dst, dst); // dst oop |
0 | 2525 __ jccb(Assembler::zero, L_failed_0); |
2526 | |
2527 // if (dst_pos < 0) return -1; | |
2528 __ testl(dst_pos, dst_pos); // dst_pos (32-bits) | |
2529 size_t j4off = __ offset(); | |
2530 __ jccb(Assembler::negative, L_failed_0); | |
2531 | |
2532 // The first four tests are very dense code, | |
2533 // but not quite dense enough to put four | |
2534 // jumps in a 16-byte instruction fetch buffer. | |
2535 // That's good, because some branch predicters | |
2536 // do not like jumps so close together. | |
2537 // Make sure of this. | |
2538 guarantee(((j1off ^ j4off) & ~15) != 0, "I$ line of 1st & 4th jumps"); | |
2539 | |
2540 // registers used as temp | |
2541 const Register r11_length = r11; // elements count to copy | |
2542 const Register r10_src_klass = r10; // array klass | |
2543 | |
2544 // if (length < 0) return -1; | |
2006
bbefa3ca1543
6998985: faulty generic arraycopy on windows x86_64: 4th arg overwritten with oop
twisti
parents:
1972
diff
changeset
|
2545 __ movl(r11_length, length); // length (elements count, 32-bits value) |
0 | 2546 __ testl(r11_length, r11_length); |
2547 __ jccb(Assembler::negative, L_failed_0); | |
2548 | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
16
diff
changeset
|
2549 __ load_klass(r10_src_klass, src); |
0 | 2550 #ifdef ASSERT |
2551 // assert(src->klass() != NULL); | |
2006
bbefa3ca1543
6998985: faulty generic arraycopy on windows x86_64: 4th arg overwritten with oop
twisti
parents:
1972
diff
changeset
|
2552 { |
bbefa3ca1543
6998985: faulty generic arraycopy on windows x86_64: 4th arg overwritten with oop
twisti
parents:
1972
diff
changeset
|
2553 BLOCK_COMMENT("assert klasses not null {"); |
bbefa3ca1543
6998985: faulty generic arraycopy on windows x86_64: 4th arg overwritten with oop
twisti
parents:
1972
diff
changeset
|
2554 Label L1, L2; |
304 | 2555 __ testptr(r10_src_klass, r10_src_klass); |
0 | 2556 __ jcc(Assembler::notZero, L2); // it is broken if klass is NULL |
2557 __ bind(L1); | |
2558 __ stop("broken null klass"); | |
2559 __ bind(L2); | |
2006
bbefa3ca1543
6998985: faulty generic arraycopy on windows x86_64: 4th arg overwritten with oop
twisti
parents:
1972
diff
changeset
|
2560 __ load_klass(rax, dst); |
bbefa3ca1543
6998985: faulty generic arraycopy on windows x86_64: 4th arg overwritten with oop
twisti
parents:
1972
diff
changeset
|
2561 __ cmpq(rax, 0); |
0 | 2562 __ jcc(Assembler::equal, L1); // this would be broken also |
2006
bbefa3ca1543
6998985: faulty generic arraycopy on windows x86_64: 4th arg overwritten with oop
twisti
parents:
1972
diff
changeset
|
2563 BLOCK_COMMENT("} assert klasses not null done"); |
0 | 2564 } |
2565 #endif | |
2566 | |
2567 // Load layout helper (32-bits) | |
2568 // | |
2569 // |array_tag| | header_size | element_type | |log2_element_size| | |
2570 // 32 30 24 16 8 2 0 | |
2571 // | |
2572 // array_tag: typeArray = 0x3, objArray = 0x2, non-array = 0x0 | |
2573 // | |
2574 | |
2006
bbefa3ca1543
6998985: faulty generic arraycopy on windows x86_64: 4th arg overwritten with oop
twisti
parents:
1972
diff
changeset
|
2575 const int lh_offset = klassOopDesc::header_size() * HeapWordSize + |
bbefa3ca1543
6998985: faulty generic arraycopy on windows x86_64: 4th arg overwritten with oop
twisti
parents:
1972
diff
changeset
|
2576 Klass::layout_helper_offset_in_bytes(); |
0 | 2577 |
2578 // Handle objArrays completely differently... | |
2006
bbefa3ca1543
6998985: faulty generic arraycopy on windows x86_64: 4th arg overwritten with oop
twisti
parents:
1972
diff
changeset
|
2579 const jint objArray_lh = Klass::array_layout_helper(T_OBJECT); |
bbefa3ca1543
6998985: faulty generic arraycopy on windows x86_64: 4th arg overwritten with oop
twisti
parents:
1972
diff
changeset
|
2580 __ cmpl(Address(r10_src_klass, lh_offset), objArray_lh); |
0 | 2581 __ jcc(Assembler::equal, L_objArray); |
2582 | |
2583 // if (src->klass() != dst->klass()) return -1; | |
2006
bbefa3ca1543
6998985: faulty generic arraycopy on windows x86_64: 4th arg overwritten with oop
twisti
parents:
1972
diff
changeset
|
2584 __ load_klass(rax, dst); |
bbefa3ca1543
6998985: faulty generic arraycopy on windows x86_64: 4th arg overwritten with oop
twisti
parents:
1972
diff
changeset
|
2585 __ cmpq(r10_src_klass, rax); |
0 | 2586 __ jcc(Assembler::notEqual, L_failed); |
2587 | |
2006
bbefa3ca1543
6998985: faulty generic arraycopy on windows x86_64: 4th arg overwritten with oop
twisti
parents:
1972
diff
changeset
|
2588 const Register rax_lh = rax; // layout helper |
bbefa3ca1543
6998985: faulty generic arraycopy on windows x86_64: 4th arg overwritten with oop
twisti
parents:
1972
diff
changeset
|
2589 __ movl(rax_lh, Address(r10_src_klass, lh_offset)); |
bbefa3ca1543
6998985: faulty generic arraycopy on windows x86_64: 4th arg overwritten with oop
twisti
parents:
1972
diff
changeset
|
2590 |
0 | 2591 // if (!src->is_Array()) return -1; |
2592 __ cmpl(rax_lh, Klass::_lh_neutral_value); | |
2593 __ jcc(Assembler::greaterEqual, L_failed); | |
2594 | |
2595 // At this point, it is known to be a typeArray (array_tag 0x3). | |
2596 #ifdef ASSERT | |
2006
bbefa3ca1543
6998985: faulty generic arraycopy on windows x86_64: 4th arg overwritten with oop
twisti
parents:
1972
diff
changeset
|
2597 { |
bbefa3ca1543
6998985: faulty generic arraycopy on windows x86_64: 4th arg overwritten with oop
twisti
parents:
1972
diff
changeset
|
2598 BLOCK_COMMENT("assert primitive array {"); |
bbefa3ca1543
6998985: faulty generic arraycopy on windows x86_64: 4th arg overwritten with oop
twisti
parents:
1972
diff
changeset
|
2599 Label L; |
0 | 2600 __ cmpl(rax_lh, (Klass::_lh_array_tag_type_value << Klass::_lh_array_tag_shift)); |
2601 __ jcc(Assembler::greaterEqual, L); | |
2602 __ stop("must be a primitive array"); | |
2603 __ bind(L); | |
2006
bbefa3ca1543
6998985: faulty generic arraycopy on windows x86_64: 4th arg overwritten with oop
twisti
parents:
1972
diff
changeset
|
2604 BLOCK_COMMENT("} assert primitive array done"); |
0 | 2605 } |
2606 #endif | |
2607 | |
2608 arraycopy_range_checks(src, src_pos, dst, dst_pos, r11_length, | |
2609 r10, L_failed); | |
2610 | |
2611 // typeArrayKlass | |
2612 // | |
2613 // src_addr = (src + array_header_in_bytes()) + (src_pos << log2elemsize); | |
2614 // dst_addr = (dst + array_header_in_bytes()) + (dst_pos << log2elemsize); | |
2615 // | |
2616 | |
2617 const Register r10_offset = r10; // array offset | |
2618 const Register rax_elsize = rax_lh; // element size | |
2619 | |
2620 __ movl(r10_offset, rax_lh); | |
2621 __ shrl(r10_offset, Klass::_lh_header_size_shift); | |
304 | 2622 __ andptr(r10_offset, Klass::_lh_header_size_mask); // array_offset |
2623 __ addptr(src, r10_offset); // src array offset | |
2624 __ addptr(dst, r10_offset); // dst array offset | |
0 | 2625 BLOCK_COMMENT("choose copy loop based on element size"); |
2626 __ andl(rax_lh, Klass::_lh_log2_element_size_mask); // rax_lh -> rax_elsize | |
2627 | |
2628 // next registers should be set before the jump to corresponding stub | |
2629 const Register from = c_rarg0; // source array address | |
2630 const Register to = c_rarg1; // destination array address | |
2631 const Register count = c_rarg2; // elements count | |
2632 | |
2633 // 'from', 'to', 'count' registers should be set in such order | |
2634 // since they are the same as 'src', 'src_pos', 'dst'. | |
2635 | |
2636 __ BIND(L_copy_bytes); | |
2637 __ cmpl(rax_elsize, 0); | |
2638 __ jccb(Assembler::notEqual, L_copy_shorts); | |
304 | 2639 __ lea(from, Address(src, src_pos, Address::times_1, 0));// src_addr |
2640 __ lea(to, Address(dst, dst_pos, Address::times_1, 0));// dst_addr | |
2641 __ movl2ptr(count, r11_length); // length | |
0 | 2642 __ jump(RuntimeAddress(byte_copy_entry)); |
2643 | |
2644 __ BIND(L_copy_shorts); | |
2645 __ cmpl(rax_elsize, LogBytesPerShort); | |
2646 __ jccb(Assembler::notEqual, L_copy_ints); | |
304 | 2647 __ lea(from, Address(src, src_pos, Address::times_2, 0));// src_addr |
2648 __ lea(to, Address(dst, dst_pos, Address::times_2, 0));// dst_addr | |
2649 __ movl2ptr(count, r11_length); // length | |
0 | 2650 __ jump(RuntimeAddress(short_copy_entry)); |
2651 | |
2652 __ BIND(L_copy_ints); | |
2653 __ cmpl(rax_elsize, LogBytesPerInt); | |
2654 __ jccb(Assembler::notEqual, L_copy_longs); | |
304 | 2655 __ lea(from, Address(src, src_pos, Address::times_4, 0));// src_addr |
2656 __ lea(to, Address(dst, dst_pos, Address::times_4, 0));// dst_addr | |
2657 __ movl2ptr(count, r11_length); // length | |
0 | 2658 __ jump(RuntimeAddress(int_copy_entry)); |
2659 | |
2660 __ BIND(L_copy_longs); | |
2661 #ifdef ASSERT | |
2006
bbefa3ca1543
6998985: faulty generic arraycopy on windows x86_64: 4th arg overwritten with oop
twisti
parents:
1972
diff
changeset
|
2662 { |
bbefa3ca1543
6998985: faulty generic arraycopy on windows x86_64: 4th arg overwritten with oop
twisti
parents:
1972
diff
changeset
|
2663 BLOCK_COMMENT("assert long copy {"); |
bbefa3ca1543
6998985: faulty generic arraycopy on windows x86_64: 4th arg overwritten with oop
twisti
parents:
1972
diff
changeset
|
2664 Label L; |
0 | 2665 __ cmpl(rax_elsize, LogBytesPerLong); |
2666 __ jcc(Assembler::equal, L); | |
2667 __ stop("must be long copy, but elsize is wrong"); | |
2668 __ bind(L); | |
2006
bbefa3ca1543
6998985: faulty generic arraycopy on windows x86_64: 4th arg overwritten with oop
twisti
parents:
1972
diff
changeset
|
2669 BLOCK_COMMENT("} assert long copy done"); |
0 | 2670 } |
2671 #endif | |
304 | 2672 __ lea(from, Address(src, src_pos, Address::times_8, 0));// src_addr |
2673 __ lea(to, Address(dst, dst_pos, Address::times_8, 0));// dst_addr | |
2674 __ movl2ptr(count, r11_length); // length | |
0 | 2675 __ jump(RuntimeAddress(long_copy_entry)); |
2676 | |
2677 // objArrayKlass | |
2678 __ BIND(L_objArray); | |
2006
bbefa3ca1543
6998985: faulty generic arraycopy on windows x86_64: 4th arg overwritten with oop
twisti
parents:
1972
diff
changeset
|
2679 // live at this point: r10_src_klass, r11_length, src[_pos], dst[_pos] |
0 | 2680 |
2681 Label L_plain_copy, L_checkcast_copy; | |
2682 // test array classes for subtyping | |
2006
bbefa3ca1543
6998985: faulty generic arraycopy on windows x86_64: 4th arg overwritten with oop
twisti
parents:
1972
diff
changeset
|
2683 __ load_klass(rax, dst); |
bbefa3ca1543
6998985: faulty generic arraycopy on windows x86_64: 4th arg overwritten with oop
twisti
parents:
1972
diff
changeset
|
2684 __ cmpq(r10_src_klass, rax); // usual case is exact equality |
0 | 2685 __ jcc(Assembler::notEqual, L_checkcast_copy); |
2686 | |
2687 // Identically typed arrays can be copied without element-wise checks. | |
2688 arraycopy_range_checks(src, src_pos, dst, dst_pos, r11_length, | |
2689 r10, L_failed); | |
2690 | |
304 | 2691 __ lea(from, Address(src, src_pos, TIMES_OOP, |
0 | 2692 arrayOopDesc::base_offset_in_bytes(T_OBJECT))); // src_addr |
304 | 2693 __ lea(to, Address(dst, dst_pos, TIMES_OOP, |
2694 arrayOopDesc::base_offset_in_bytes(T_OBJECT))); // dst_addr | |
2695 __ movl2ptr(count, r11_length); // length | |
0 | 2696 __ BIND(L_plain_copy); |
2697 __ jump(RuntimeAddress(oop_copy_entry)); | |
2698 | |
2699 __ BIND(L_checkcast_copy); | |
2006
bbefa3ca1543
6998985: faulty generic arraycopy on windows x86_64: 4th arg overwritten with oop
twisti
parents:
1972
diff
changeset
|
2700 // live at this point: r10_src_klass, r11_length, rax (dst_klass) |
0 | 2701 { |
2702 // Before looking at dst.length, make sure dst is also an objArray. | |
2006
bbefa3ca1543
6998985: faulty generic arraycopy on windows x86_64: 4th arg overwritten with oop
twisti
parents:
1972
diff
changeset
|
2703 __ cmpl(Address(rax, lh_offset), objArray_lh); |
0 | 2704 __ jcc(Assembler::notEqual, L_failed); |
2705 | |
2706 // It is safe to examine both src.length and dst.length. | |
2707 arraycopy_range_checks(src, src_pos, dst, dst_pos, r11_length, | |
2708 rax, L_failed); | |
2006
bbefa3ca1543
6998985: faulty generic arraycopy on windows x86_64: 4th arg overwritten with oop
twisti
parents:
1972
diff
changeset
|
2709 |
bbefa3ca1543
6998985: faulty generic arraycopy on windows x86_64: 4th arg overwritten with oop
twisti
parents:
1972
diff
changeset
|
2710 const Register r11_dst_klass = r11; |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
16
diff
changeset
|
2711 __ load_klass(r11_dst_klass, dst); // reload |
0 | 2712 |
2713 // Marshal the base address arguments now, freeing registers. | |
304 | 2714 __ lea(from, Address(src, src_pos, TIMES_OOP, |
0 | 2715 arrayOopDesc::base_offset_in_bytes(T_OBJECT))); |
304 | 2716 __ lea(to, Address(dst, dst_pos, TIMES_OOP, |
0 | 2717 arrayOopDesc::base_offset_in_bytes(T_OBJECT))); |
2006
bbefa3ca1543
6998985: faulty generic arraycopy on windows x86_64: 4th arg overwritten with oop
twisti
parents:
1972
diff
changeset
|
2718 __ movl(count, length); // length (reloaded) |
0 | 2719 Register sco_temp = c_rarg3; // this register is free now |
2720 assert_different_registers(from, to, count, sco_temp, | |
2721 r11_dst_klass, r10_src_klass); | |
2722 assert_clean_int(count, sco_temp); | |
2723 | |
2724 // Generate the type check. | |
2006
bbefa3ca1543
6998985: faulty generic arraycopy on windows x86_64: 4th arg overwritten with oop
twisti
parents:
1972
diff
changeset
|
2725 const int sco_offset = (klassOopDesc::header_size() * HeapWordSize + |
bbefa3ca1543
6998985: faulty generic arraycopy on windows x86_64: 4th arg overwritten with oop
twisti
parents:
1972
diff
changeset
|
2726 Klass::super_check_offset_offset_in_bytes()); |
0 | 2727 __ movl(sco_temp, Address(r11_dst_klass, sco_offset)); |
2728 assert_clean_int(sco_temp, rax); | |
2729 generate_type_check(r10_src_klass, sco_temp, r11_dst_klass, L_plain_copy); | |
2730 | |
2731 // Fetch destination element klass from the objArrayKlass header. | |
2732 int ek_offset = (klassOopDesc::header_size() * HeapWordSize + | |
2733 objArrayKlass::element_klass_offset_in_bytes()); | |
304 | 2734 __ movptr(r11_dst_klass, Address(r11_dst_klass, ek_offset)); |
2006
bbefa3ca1543
6998985: faulty generic arraycopy on windows x86_64: 4th arg overwritten with oop
twisti
parents:
1972
diff
changeset
|
2735 __ movl( sco_temp, Address(r11_dst_klass, sco_offset)); |
0 | 2736 assert_clean_int(sco_temp, rax); |
2737 | |
2738 // the checkcast_copy loop needs two extra arguments: | |
2739 assert(c_rarg3 == sco_temp, "#3 already in place"); | |
2006
bbefa3ca1543
6998985: faulty generic arraycopy on windows x86_64: 4th arg overwritten with oop
twisti
parents:
1972
diff
changeset
|
2740 // Set up arguments for checkcast_copy_entry. |
bbefa3ca1543
6998985: faulty generic arraycopy on windows x86_64: 4th arg overwritten with oop
twisti
parents:
1972
diff
changeset
|
2741 setup_arg_regs(4); |
bbefa3ca1543
6998985: faulty generic arraycopy on windows x86_64: 4th arg overwritten with oop
twisti
parents:
1972
diff
changeset
|
2742 __ movptr(r8, r11_dst_klass); // dst.klass.element_klass, r8 is c_rarg4 on Linux/Solaris |
0 | 2743 __ jump(RuntimeAddress(checkcast_copy_entry)); |
2744 } | |
2745 | |
2746 __ BIND(L_failed); | |
304 | 2747 __ xorptr(rax, rax); |
2748 __ notptr(rax); // return -1 | |
0 | 2749 __ leave(); // required for proper stackwalking of RuntimeStub frame |
2750 __ ret(0); | |
2751 | |
2752 return start; | |
2753 } | |
2754 | |
2755 void generate_arraycopy_stubs() { | |
2313
d89a22843c62
7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents:
2006
diff
changeset
|
2756 address entry; |
d89a22843c62
7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents:
2006
diff
changeset
|
2757 address entry_jbyte_arraycopy; |
d89a22843c62
7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents:
2006
diff
changeset
|
2758 address entry_jshort_arraycopy; |
d89a22843c62
7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents:
2006
diff
changeset
|
2759 address entry_jint_arraycopy; |
d89a22843c62
7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents:
2006
diff
changeset
|
2760 address entry_oop_arraycopy; |
d89a22843c62
7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents:
2006
diff
changeset
|
2761 address entry_jlong_arraycopy; |
d89a22843c62
7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents:
2006
diff
changeset
|
2762 address entry_checkcast_arraycopy; |
d89a22843c62
7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents:
2006
diff
changeset
|
2763 |
d89a22843c62
7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents:
2006
diff
changeset
|
2764 StubRoutines::_jbyte_disjoint_arraycopy = generate_disjoint_byte_copy(false, &entry, |
d89a22843c62
7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents:
2006
diff
changeset
|
2765 "jbyte_disjoint_arraycopy"); |
d89a22843c62
7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents:
2006
diff
changeset
|
2766 StubRoutines::_jbyte_arraycopy = generate_conjoint_byte_copy(false, entry, &entry_jbyte_arraycopy, |
d89a22843c62
7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents:
2006
diff
changeset
|
2767 "jbyte_arraycopy"); |
d89a22843c62
7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents:
2006
diff
changeset
|
2768 |
d89a22843c62
7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents:
2006
diff
changeset
|
2769 StubRoutines::_jshort_disjoint_arraycopy = generate_disjoint_short_copy(false, &entry, |
d89a22843c62
7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents:
2006
diff
changeset
|
2770 "jshort_disjoint_arraycopy"); |
d89a22843c62
7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents:
2006
diff
changeset
|
2771 StubRoutines::_jshort_arraycopy = generate_conjoint_short_copy(false, entry, &entry_jshort_arraycopy, |
d89a22843c62
7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents:
2006
diff
changeset
|
2772 "jshort_arraycopy"); |
d89a22843c62
7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents:
2006
diff
changeset
|
2773 |
d89a22843c62
7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents:
2006
diff
changeset
|
2774 StubRoutines::_jint_disjoint_arraycopy = generate_disjoint_int_oop_copy(false, false, &entry, |
d89a22843c62
7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents:
2006
diff
changeset
|
2775 "jint_disjoint_arraycopy"); |
d89a22843c62
7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents:
2006
diff
changeset
|
2776 StubRoutines::_jint_arraycopy = generate_conjoint_int_oop_copy(false, false, entry, |
d89a22843c62
7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents:
2006
diff
changeset
|
2777 &entry_jint_arraycopy, "jint_arraycopy"); |
d89a22843c62
7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents:
2006
diff
changeset
|
2778 |
d89a22843c62
7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents:
2006
diff
changeset
|
2779 StubRoutines::_jlong_disjoint_arraycopy = generate_disjoint_long_oop_copy(false, false, &entry, |
d89a22843c62
7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents:
2006
diff
changeset
|
2780 "jlong_disjoint_arraycopy"); |
d89a22843c62
7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents:
2006
diff
changeset
|
2781 StubRoutines::_jlong_arraycopy = generate_conjoint_long_oop_copy(false, false, entry, |
d89a22843c62
7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents:
2006
diff
changeset
|
2782 &entry_jlong_arraycopy, "jlong_arraycopy"); |
0 | 2783 |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
16
diff
changeset
|
2784 |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
16
diff
changeset
|
2785 if (UseCompressedOops) { |
2313
d89a22843c62
7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents:
2006
diff
changeset
|
2786 StubRoutines::_oop_disjoint_arraycopy = generate_disjoint_int_oop_copy(false, true, &entry, |
d89a22843c62
7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents:
2006
diff
changeset
|
2787 "oop_disjoint_arraycopy"); |
d89a22843c62
7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents:
2006
diff
changeset
|
2788 StubRoutines::_oop_arraycopy = generate_conjoint_int_oop_copy(false, true, entry, |
d89a22843c62
7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents:
2006
diff
changeset
|
2789 &entry_oop_arraycopy, "oop_arraycopy"); |
2324 | 2790 StubRoutines::_oop_disjoint_arraycopy_uninit = generate_disjoint_int_oop_copy(false, true, &entry, |
2791 "oop_disjoint_arraycopy_uninit", | |
2792 /*dest_uninitialized*/true); | |
2793 StubRoutines::_oop_arraycopy_uninit = generate_conjoint_int_oop_copy(false, true, entry, | |
2794 NULL, "oop_arraycopy_uninit", | |
2795 /*dest_uninitialized*/true); | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
16
diff
changeset
|
2796 } else { |
2313
d89a22843c62
7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents:
2006
diff
changeset
|
2797 StubRoutines::_oop_disjoint_arraycopy = generate_disjoint_long_oop_copy(false, true, &entry, |
d89a22843c62
7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents:
2006
diff
changeset
|
2798 "oop_disjoint_arraycopy"); |
d89a22843c62
7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents:
2006
diff
changeset
|
2799 StubRoutines::_oop_arraycopy = generate_conjoint_long_oop_copy(false, true, entry, |
d89a22843c62
7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents:
2006
diff
changeset
|
2800 &entry_oop_arraycopy, "oop_arraycopy"); |
2324 | 2801 StubRoutines::_oop_disjoint_arraycopy_uninit = generate_disjoint_long_oop_copy(false, true, &entry, |
2802 "oop_disjoint_arraycopy_uninit", | |
2803 /*dest_uninitialized*/true); | |
2804 StubRoutines::_oop_arraycopy_uninit = generate_conjoint_long_oop_copy(false, true, entry, | |
2805 NULL, "oop_arraycopy_uninit", | |
2806 /*dest_uninitialized*/true); | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
16
diff
changeset
|
2807 } |
0 | 2808 |
2324 | 2809 StubRoutines::_checkcast_arraycopy = generate_checkcast_copy("checkcast_arraycopy", &entry_checkcast_arraycopy); |
2810 StubRoutines::_checkcast_arraycopy_uninit = generate_checkcast_copy("checkcast_arraycopy_uninit", NULL, | |
2811 /*dest_uninitialized*/true); | |
2812 | |
2313
d89a22843c62
7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents:
2006
diff
changeset
|
2813 StubRoutines::_unsafe_arraycopy = generate_unsafe_copy("unsafe_arraycopy", |
d89a22843c62
7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents:
2006
diff
changeset
|
2814 entry_jbyte_arraycopy, |
d89a22843c62
7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents:
2006
diff
changeset
|
2815 entry_jshort_arraycopy, |
d89a22843c62
7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents:
2006
diff
changeset
|
2816 entry_jint_arraycopy, |
d89a22843c62
7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents:
2006
diff
changeset
|
2817 entry_jlong_arraycopy); |
d89a22843c62
7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents:
2006
diff
changeset
|
2818 StubRoutines::_generic_arraycopy = generate_generic_copy("generic_arraycopy", |
d89a22843c62
7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents:
2006
diff
changeset
|
2819 entry_jbyte_arraycopy, |
d89a22843c62
7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents:
2006
diff
changeset
|
2820 entry_jshort_arraycopy, |
d89a22843c62
7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents:
2006
diff
changeset
|
2821 entry_jint_arraycopy, |
d89a22843c62
7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents:
2006
diff
changeset
|
2822 entry_oop_arraycopy, |
d89a22843c62
7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents:
2006
diff
changeset
|
2823 entry_jlong_arraycopy, |
d89a22843c62
7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents:
2006
diff
changeset
|
2824 entry_checkcast_arraycopy); |
0 | 2825 |
1763 | 2826 StubRoutines::_jbyte_fill = generate_fill(T_BYTE, false, "jbyte_fill"); |
2827 StubRoutines::_jshort_fill = generate_fill(T_SHORT, false, "jshort_fill"); | |
2828 StubRoutines::_jint_fill = generate_fill(T_INT, false, "jint_fill"); | |
2829 StubRoutines::_arrayof_jbyte_fill = generate_fill(T_BYTE, true, "arrayof_jbyte_fill"); | |
2830 StubRoutines::_arrayof_jshort_fill = generate_fill(T_SHORT, true, "arrayof_jshort_fill"); | |
2831 StubRoutines::_arrayof_jint_fill = generate_fill(T_INT, true, "arrayof_jint_fill"); | |
2832 | |
0 | 2833 // We don't generate specialized code for HeapWord-aligned source |
2834 // arrays, so just use the code we've already generated | |
2835 StubRoutines::_arrayof_jbyte_disjoint_arraycopy = StubRoutines::_jbyte_disjoint_arraycopy; | |
2836 StubRoutines::_arrayof_jbyte_arraycopy = StubRoutines::_jbyte_arraycopy; | |
2837 | |
2838 StubRoutines::_arrayof_jshort_disjoint_arraycopy = StubRoutines::_jshort_disjoint_arraycopy; | |
2839 StubRoutines::_arrayof_jshort_arraycopy = StubRoutines::_jshort_arraycopy; | |
2840 | |
2841 StubRoutines::_arrayof_jint_disjoint_arraycopy = StubRoutines::_jint_disjoint_arraycopy; | |
2842 StubRoutines::_arrayof_jint_arraycopy = StubRoutines::_jint_arraycopy; | |
2843 | |
2844 StubRoutines::_arrayof_jlong_disjoint_arraycopy = StubRoutines::_jlong_disjoint_arraycopy; | |
2845 StubRoutines::_arrayof_jlong_arraycopy = StubRoutines::_jlong_arraycopy; | |
2846 | |
2847 StubRoutines::_arrayof_oop_disjoint_arraycopy = StubRoutines::_oop_disjoint_arraycopy; | |
2848 StubRoutines::_arrayof_oop_arraycopy = StubRoutines::_oop_arraycopy; | |
2324 | 2849 |
2850 StubRoutines::_arrayof_oop_disjoint_arraycopy_uninit = StubRoutines::_oop_disjoint_arraycopy_uninit; | |
2851 StubRoutines::_arrayof_oop_arraycopy_uninit = StubRoutines::_oop_arraycopy_uninit; | |
0 | 2852 } |
2853 | |
1174
ddb7834449d0
6849984: Value methods for platform dependent math functions constant fold incorrectly
never
parents:
1108
diff
changeset
|
2854 void generate_math_stubs() { |
ddb7834449d0
6849984: Value methods for platform dependent math functions constant fold incorrectly
never
parents:
1108
diff
changeset
|
2855 { |
ddb7834449d0
6849984: Value methods for platform dependent math functions constant fold incorrectly
never
parents:
1108
diff
changeset
|
2856 StubCodeMark mark(this, "StubRoutines", "log"); |
ddb7834449d0
6849984: Value methods for platform dependent math functions constant fold incorrectly
never
parents:
1108
diff
changeset
|
2857 StubRoutines::_intrinsic_log = (double (*)(double)) __ pc(); |
ddb7834449d0
6849984: Value methods for platform dependent math functions constant fold incorrectly
never
parents:
1108
diff
changeset
|
2858 |
ddb7834449d0
6849984: Value methods for platform dependent math functions constant fold incorrectly
never
parents:
1108
diff
changeset
|
2859 __ subq(rsp, 8); |
ddb7834449d0
6849984: Value methods for platform dependent math functions constant fold incorrectly
never
parents:
1108
diff
changeset
|
2860 __ movdbl(Address(rsp, 0), xmm0); |
ddb7834449d0
6849984: Value methods for platform dependent math functions constant fold incorrectly
never
parents:
1108
diff
changeset
|
2861 __ fld_d(Address(rsp, 0)); |
ddb7834449d0
6849984: Value methods for platform dependent math functions constant fold incorrectly
never
parents:
1108
diff
changeset
|
2862 __ flog(); |
ddb7834449d0
6849984: Value methods for platform dependent math functions constant fold incorrectly
never
parents:
1108
diff
changeset
|
2863 __ fstp_d(Address(rsp, 0)); |
ddb7834449d0
6849984: Value methods for platform dependent math functions constant fold incorrectly
never
parents:
1108
diff
changeset
|
2864 __ movdbl(xmm0, Address(rsp, 0)); |
ddb7834449d0
6849984: Value methods for platform dependent math functions constant fold incorrectly
never
parents:
1108
diff
changeset
|
2865 __ addq(rsp, 8); |
ddb7834449d0
6849984: Value methods for platform dependent math functions constant fold incorrectly
never
parents:
1108
diff
changeset
|
2866 __ ret(0); |
ddb7834449d0
6849984: Value methods for platform dependent math functions constant fold incorrectly
never
parents:
1108
diff
changeset
|
2867 } |
ddb7834449d0
6849984: Value methods for platform dependent math functions constant fold incorrectly
never
parents:
1108
diff
changeset
|
2868 { |
ddb7834449d0
6849984: Value methods for platform dependent math functions constant fold incorrectly
never
parents:
1108
diff
changeset
|
2869 StubCodeMark mark(this, "StubRoutines", "log10"); |
ddb7834449d0
6849984: Value methods for platform dependent math functions constant fold incorrectly
never
parents:
1108
diff
changeset
|
2870 StubRoutines::_intrinsic_log10 = (double (*)(double)) __ pc(); |
ddb7834449d0
6849984: Value methods for platform dependent math functions constant fold incorrectly
never
parents:
1108
diff
changeset
|
2871 |
ddb7834449d0
6849984: Value methods for platform dependent math functions constant fold incorrectly
never
parents:
1108
diff
changeset
|
2872 __ subq(rsp, 8); |
ddb7834449d0
6849984: Value methods for platform dependent math functions constant fold incorrectly
never
parents:
1108
diff
changeset
|
2873 __ movdbl(Address(rsp, 0), xmm0); |
ddb7834449d0
6849984: Value methods for platform dependent math functions constant fold incorrectly
never
parents:
1108
diff
changeset
|
2874 __ fld_d(Address(rsp, 0)); |
ddb7834449d0
6849984: Value methods for platform dependent math functions constant fold incorrectly
never
parents:
1108
diff
changeset
|
2875 __ flog10(); |
ddb7834449d0
6849984: Value methods for platform dependent math functions constant fold incorrectly
never
parents:
1108
diff
changeset
|
2876 __ fstp_d(Address(rsp, 0)); |
ddb7834449d0
6849984: Value methods for platform dependent math functions constant fold incorrectly
never
parents:
1108
diff
changeset
|
2877 __ movdbl(xmm0, Address(rsp, 0)); |
ddb7834449d0
6849984: Value methods for platform dependent math functions constant fold incorrectly
never
parents:
1108
diff
changeset
|
2878 __ addq(rsp, 8); |
ddb7834449d0
6849984: Value methods for platform dependent math functions constant fold incorrectly
never
parents:
1108
diff
changeset
|
2879 __ ret(0); |
ddb7834449d0
6849984: Value methods for platform dependent math functions constant fold incorrectly
never
parents:
1108
diff
changeset
|
2880 } |
ddb7834449d0
6849984: Value methods for platform dependent math functions constant fold incorrectly
never
parents:
1108
diff
changeset
|
2881 { |
ddb7834449d0
6849984: Value methods for platform dependent math functions constant fold incorrectly
never
parents:
1108
diff
changeset
|
2882 StubCodeMark mark(this, "StubRoutines", "sin"); |
ddb7834449d0
6849984: Value methods for platform dependent math functions constant fold incorrectly
never
parents:
1108
diff
changeset
|
2883 StubRoutines::_intrinsic_sin = (double (*)(double)) __ pc(); |
ddb7834449d0
6849984: Value methods for platform dependent math functions constant fold incorrectly
never
parents:
1108
diff
changeset
|
2884 |
ddb7834449d0
6849984: Value methods for platform dependent math functions constant fold incorrectly
never
parents:
1108
diff
changeset
|
2885 __ subq(rsp, 8); |
ddb7834449d0
6849984: Value methods for platform dependent math functions constant fold incorrectly
never
parents:
1108
diff
changeset
|
2886 __ movdbl(Address(rsp, 0), xmm0); |
ddb7834449d0
6849984: Value methods for platform dependent math functions constant fold incorrectly
never
parents:
1108
diff
changeset
|
2887 __ fld_d(Address(rsp, 0)); |
ddb7834449d0
6849984: Value methods for platform dependent math functions constant fold incorrectly
never
parents:
1108
diff
changeset
|
2888 __ trigfunc('s'); |
ddb7834449d0
6849984: Value methods for platform dependent math functions constant fold incorrectly
never
parents:
1108
diff
changeset
|
2889 __ fstp_d(Address(rsp, 0)); |
ddb7834449d0
6849984: Value methods for platform dependent math functions constant fold incorrectly
never
parents:
1108
diff
changeset
|
2890 __ movdbl(xmm0, Address(rsp, 0)); |
ddb7834449d0
6849984: Value methods for platform dependent math functions constant fold incorrectly
never
parents:
1108
diff
changeset
|
2891 __ addq(rsp, 8); |
ddb7834449d0
6849984: Value methods for platform dependent math functions constant fold incorrectly
never
parents:
1108
diff
changeset
|
2892 __ ret(0); |
ddb7834449d0
6849984: Value methods for platform dependent math functions constant fold incorrectly
never
parents:
1108
diff
changeset
|
2893 } |
ddb7834449d0
6849984: Value methods for platform dependent math functions constant fold incorrectly
never
parents:
1108
diff
changeset
|
2894 { |
ddb7834449d0
6849984: Value methods for platform dependent math functions constant fold incorrectly
never
parents:
1108
diff
changeset
|
2895 StubCodeMark mark(this, "StubRoutines", "cos"); |
ddb7834449d0
6849984: Value methods for platform dependent math functions constant fold incorrectly
never
parents:
1108
diff
changeset
|
2896 StubRoutines::_intrinsic_cos = (double (*)(double)) __ pc(); |
ddb7834449d0
6849984: Value methods for platform dependent math functions constant fold incorrectly
never
parents:
1108
diff
changeset
|
2897 |
ddb7834449d0
6849984: Value methods for platform dependent math functions constant fold incorrectly
never
parents:
1108
diff
changeset
|
2898 __ subq(rsp, 8); |
ddb7834449d0
6849984: Value methods for platform dependent math functions constant fold incorrectly
never
parents:
1108
diff
changeset
|
2899 __ movdbl(Address(rsp, 0), xmm0); |
ddb7834449d0
6849984: Value methods for platform dependent math functions constant fold incorrectly
never
parents:
1108
diff
changeset
|
2900 __ fld_d(Address(rsp, 0)); |
ddb7834449d0
6849984: Value methods for platform dependent math functions constant fold incorrectly
never
parents:
1108
diff
changeset
|
2901 __ trigfunc('c'); |
ddb7834449d0
6849984: Value methods for platform dependent math functions constant fold incorrectly
never
parents:
1108
diff
changeset
|
2902 __ fstp_d(Address(rsp, 0)); |
ddb7834449d0
6849984: Value methods for platform dependent math functions constant fold incorrectly
never
parents:
1108
diff
changeset
|
2903 __ movdbl(xmm0, Address(rsp, 0)); |
ddb7834449d0
6849984: Value methods for platform dependent math functions constant fold incorrectly
never
parents:
1108
diff
changeset
|
2904 __ addq(rsp, 8); |
ddb7834449d0
6849984: Value methods for platform dependent math functions constant fold incorrectly
never
parents:
1108
diff
changeset
|
2905 __ ret(0); |
ddb7834449d0
6849984: Value methods for platform dependent math functions constant fold incorrectly
never
parents:
1108
diff
changeset
|
2906 } |
ddb7834449d0
6849984: Value methods for platform dependent math functions constant fold incorrectly
never
parents:
1108
diff
changeset
|
2907 { |
ddb7834449d0
6849984: Value methods for platform dependent math functions constant fold incorrectly
never
parents:
1108
diff
changeset
|
2908 StubCodeMark mark(this, "StubRoutines", "tan"); |
ddb7834449d0
6849984: Value methods for platform dependent math functions constant fold incorrectly
never
parents:
1108
diff
changeset
|
2909 StubRoutines::_intrinsic_tan = (double (*)(double)) __ pc(); |
ddb7834449d0
6849984: Value methods for platform dependent math functions constant fold incorrectly
never
parents:
1108
diff
changeset
|
2910 |
ddb7834449d0
6849984: Value methods for platform dependent math functions constant fold incorrectly
never
parents:
1108
diff
changeset
|
2911 __ subq(rsp, 8); |
ddb7834449d0
6849984: Value methods for platform dependent math functions constant fold incorrectly
never
parents:
1108
diff
changeset
|
2912 __ movdbl(Address(rsp, 0), xmm0); |
ddb7834449d0
6849984: Value methods for platform dependent math functions constant fold incorrectly
never
parents:
1108
diff
changeset
|
2913 __ fld_d(Address(rsp, 0)); |
ddb7834449d0
6849984: Value methods for platform dependent math functions constant fold incorrectly
never
parents:
1108
diff
changeset
|
2914 __ trigfunc('t'); |
ddb7834449d0
6849984: Value methods for platform dependent math functions constant fold incorrectly
never
parents:
1108
diff
changeset
|
2915 __ fstp_d(Address(rsp, 0)); |
ddb7834449d0
6849984: Value methods for platform dependent math functions constant fold incorrectly
never
parents:
1108
diff
changeset
|
2916 __ movdbl(xmm0, Address(rsp, 0)); |
ddb7834449d0
6849984: Value methods for platform dependent math functions constant fold incorrectly
never
parents:
1108
diff
changeset
|
2917 __ addq(rsp, 8); |
ddb7834449d0
6849984: Value methods for platform dependent math functions constant fold incorrectly
never
parents:
1108
diff
changeset
|
2918 __ ret(0); |
ddb7834449d0
6849984: Value methods for platform dependent math functions constant fold incorrectly
never
parents:
1108
diff
changeset
|
2919 } |
ddb7834449d0
6849984: Value methods for platform dependent math functions constant fold incorrectly
never
parents:
1108
diff
changeset
|
2920 |
ddb7834449d0
6849984: Value methods for platform dependent math functions constant fold incorrectly
never
parents:
1108
diff
changeset
|
2921 // The intrinsic version of these seem to return the same value as |
ddb7834449d0
6849984: Value methods for platform dependent math functions constant fold incorrectly
never
parents:
1108
diff
changeset
|
2922 // the strict version. |
ddb7834449d0
6849984: Value methods for platform dependent math functions constant fold incorrectly
never
parents:
1108
diff
changeset
|
2923 StubRoutines::_intrinsic_exp = SharedRuntime::dexp; |
ddb7834449d0
6849984: Value methods for platform dependent math functions constant fold incorrectly
never
parents:
1108
diff
changeset
|
2924 StubRoutines::_intrinsic_pow = SharedRuntime::dpow; |
ddb7834449d0
6849984: Value methods for platform dependent math functions constant fold incorrectly
never
parents:
1108
diff
changeset
|
2925 } |
ddb7834449d0
6849984: Value methods for platform dependent math functions constant fold incorrectly
never
parents:
1108
diff
changeset
|
2926 |
0 | 2927 #undef __ |
2928 #define __ masm-> | |
2929 | |
2930 // Continuation point for throwing of implicit exceptions that are | |
2931 // not handled in the current activation. Fabricates an exception | |
2932 // oop and initiates normal exception dispatching in this | |
2933 // frame. Since we need to preserve callee-saved values (currently | |
2934 // only for C2, but done for C1 as well) we need a callee-saved oop | |
2935 // map and therefore have to make these stubs into RuntimeStubs | |
2936 // rather than BufferBlobs. If the compiler needs all registers to | |
2937 // be preserved between the fault point and the exception handler | |
2938 // then it must assume responsibility for that in | |
2939 // AbstractCompiler::continuation_for_implicit_null_exception or | |
2940 // continuation_for_implicit_division_by_zero_exception. All other | |
2941 // implicit exceptions (e.g., NullPointerException or | |
2942 // AbstractMethodError on entry) are either at call sites or | |
2943 // otherwise assume that stack unwinding will be initiated, so | |
2944 // caller saved registers were assumed volatile in the compiler. | |
2945 address generate_throw_exception(const char* name, | |
2946 address runtime_entry, | |
3451
38fa55e5e792
7055355: JSR 292: crash while throwing WrongMethodTypeException
never
parents:
2409
diff
changeset
|
2947 Register arg1 = noreg, |
38fa55e5e792
7055355: JSR 292: crash while throwing WrongMethodTypeException
never
parents:
2409
diff
changeset
|
2948 Register arg2 = noreg) { |
0 | 2949 // Information about frame layout at time of blocking runtime call. |
2950 // Note that we only have to preserve callee-saved registers since | |
2951 // the compilers are responsible for supplying a continuation point | |
2952 // if they expect all registers to be preserved. | |
2953 enum layout { | |
2954 rbp_off = frame::arg_reg_save_area_bytes/BytesPerInt, | |
2955 rbp_off2, | |
2956 return_off, | |
2957 return_off2, | |
2958 framesize // inclusive of return address | |
2959 }; | |
2960 | |
2961 int insts_size = 512; | |
2962 int locs_size = 64; | |
2963 | |
2964 CodeBuffer code(name, insts_size, locs_size); | |
2965 OopMapSet* oop_maps = new OopMapSet(); | |
2966 MacroAssembler* masm = new MacroAssembler(&code); | |
2967 | |
2968 address start = __ pc(); | |
2969 | |
2970 // This is an inlined and slightly modified version of call_VM | |
2971 // which has the ability to fetch the return PC out of | |
2972 // thread-local storage and also sets up last_Java_sp slightly | |
2973 // differently than the real call_VM | |
2974 | |
2975 __ enter(); // required for proper stackwalking of RuntimeStub frame | |
2976 | |
2977 assert(is_even(framesize/2), "sp not 16-byte aligned"); | |
2978 | |
2979 // return address and rbp are already in place | |
304 | 2980 __ subptr(rsp, (framesize-4) << LogBytesPerInt); // prolog |
0 | 2981 |
2982 int frame_complete = __ pc() - start; | |
2983 | |
2984 // Set up last_Java_sp and last_Java_fp | |
2985 __ set_last_Java_frame(rsp, rbp, NULL); | |
2986 | |
2987 // Call runtime | |
3451
38fa55e5e792
7055355: JSR 292: crash while throwing WrongMethodTypeException
never
parents:
2409
diff
changeset
|
2988 if (arg1 != noreg) { |
38fa55e5e792
7055355: JSR 292: crash while throwing WrongMethodTypeException
never
parents:
2409
diff
changeset
|
2989 assert(arg2 != c_rarg1, "clobbered"); |
38fa55e5e792
7055355: JSR 292: crash while throwing WrongMethodTypeException
never
parents:
2409
diff
changeset
|
2990 __ movptr(c_rarg1, arg1); |
38fa55e5e792
7055355: JSR 292: crash while throwing WrongMethodTypeException
never
parents:
2409
diff
changeset
|
2991 } |
38fa55e5e792
7055355: JSR 292: crash while throwing WrongMethodTypeException
never
parents:
2409
diff
changeset
|
2992 if (arg2 != noreg) { |
38fa55e5e792
7055355: JSR 292: crash while throwing WrongMethodTypeException
never
parents:
2409
diff
changeset
|
2993 __ movptr(c_rarg2, arg2); |
38fa55e5e792
7055355: JSR 292: crash while throwing WrongMethodTypeException
never
parents:
2409
diff
changeset
|
2994 } |
304 | 2995 __ movptr(c_rarg0, r15_thread); |
0 | 2996 BLOCK_COMMENT("call runtime_entry"); |
2997 __ call(RuntimeAddress(runtime_entry)); | |
2998 | |
2999 // Generate oop map | |
3000 OopMap* map = new OopMap(framesize, 0); | |
3001 | |
3002 oop_maps->add_gc_map(__ pc() - start, map); | |
3003 | |
3004 __ reset_last_Java_frame(true, false); | |
3005 | |
3006 __ leave(); // required for proper stackwalking of RuntimeStub frame | |
3007 | |
3008 // check for pending exceptions | |
3009 #ifdef ASSERT | |
3010 Label L; | |
304 | 3011 __ cmpptr(Address(r15_thread, Thread::pending_exception_offset()), |
3012 (int32_t) NULL_WORD); | |
0 | 3013 __ jcc(Assembler::notEqual, L); |
3014 __ should_not_reach_here(); | |
3015 __ bind(L); | |
3016 #endif // ASSERT | |
3017 __ jump(RuntimeAddress(StubRoutines::forward_exception_entry())); | |
3018 | |
3019 | |
3020 // codeBlob framesize is in words (not VMRegImpl::slot_size) | |
3021 RuntimeStub* stub = | |
3022 RuntimeStub::new_runtime_stub(name, | |
3023 &code, | |
3024 frame_complete, | |
3025 (framesize >> (LogBytesPerWord - LogBytesPerInt)), | |
3026 oop_maps, false); | |
3027 return stub->entry_point(); | |
3028 } | |
3029 | |
3030 // Initialization | |
3031 void generate_initial() { | |
3032 // Generates all stubs and initializes the entry points | |
3033 | |
3034 // This platform-specific stub is needed by generate_call_stub() | |
304 | 3035 StubRoutines::x86::_mxcsr_std = generate_fp_mask("mxcsr_std", 0x0000000000001F80); |
0 | 3036 |
3037 // entry points that exist in all platforms Note: This is code | |
3038 // that could be shared among different platforms - however the | |
3039 // benefit seems to be smaller than the disadvantage of having a | |
3040 // much more complicated generator structure. See also comment in | |
3041 // stubRoutines.hpp. | |
3042 | |
3043 StubRoutines::_forward_exception_entry = generate_forward_exception(); | |
3044 | |
3045 StubRoutines::_call_stub_entry = | |
3046 generate_call_stub(StubRoutines::_call_stub_return_address); | |
3047 | |
3048 // is referenced by megamorphic call | |
3049 StubRoutines::_catch_exception_entry = generate_catch_exception(); | |
3050 | |
3051 // atomic calls | |
3052 StubRoutines::_atomic_xchg_entry = generate_atomic_xchg(); | |
3053 StubRoutines::_atomic_xchg_ptr_entry = generate_atomic_xchg_ptr(); | |
3054 StubRoutines::_atomic_cmpxchg_entry = generate_atomic_cmpxchg(); | |
3055 StubRoutines::_atomic_cmpxchg_long_entry = generate_atomic_cmpxchg_long(); | |
3056 StubRoutines::_atomic_add_entry = generate_atomic_add(); | |
3057 StubRoutines::_atomic_add_ptr_entry = generate_atomic_add_ptr(); | |
3058 StubRoutines::_fence_entry = generate_orderaccess_fence(); | |
3059 | |
3060 StubRoutines::_handler_for_unsafe_access_entry = | |
3061 generate_handler_for_unsafe_access(); | |
3062 | |
3063 // platform dependent | |
304 | 3064 StubRoutines::x86::_get_previous_fp_entry = generate_get_previous_fp(); |
3065 | |
3066 StubRoutines::x86::_verify_mxcsr_entry = generate_verify_mxcsr(); | |
3451
38fa55e5e792
7055355: JSR 292: crash while throwing WrongMethodTypeException
never
parents:
2409
diff
changeset
|
3067 |
38fa55e5e792
7055355: JSR 292: crash while throwing WrongMethodTypeException
never
parents:
2409
diff
changeset
|
3068 // Build this early so it's available for the interpreter. Stub |
38fa55e5e792
7055355: JSR 292: crash while throwing WrongMethodTypeException
never
parents:
2409
diff
changeset
|
3069 // expects the required and actual types as register arguments in |
38fa55e5e792
7055355: JSR 292: crash while throwing WrongMethodTypeException
never
parents:
2409
diff
changeset
|
3070 // j_rarg0 and j_rarg1 respectively. |
38fa55e5e792
7055355: JSR 292: crash while throwing WrongMethodTypeException
never
parents:
2409
diff
changeset
|
3071 StubRoutines::_throw_WrongMethodTypeException_entry = |
38fa55e5e792
7055355: JSR 292: crash while throwing WrongMethodTypeException
never
parents:
2409
diff
changeset
|
3072 generate_throw_exception("WrongMethodTypeException throw_exception", |
38fa55e5e792
7055355: JSR 292: crash while throwing WrongMethodTypeException
never
parents:
2409
diff
changeset
|
3073 CAST_FROM_FN_PTR(address, SharedRuntime::throw_WrongMethodTypeException), |
4138
82af018d61db
Merge fixes.
Thomas Wuerthinger <thomas.wuerthinger@oracle.com>
parents:
4137
diff
changeset
|
3074 rax, rcx); |
0 | 3075 } |
3076 | |
3077 void generate_all() { | |
3078 // Generates all stubs and initializes the entry points | |
3079 | |
3080 // These entry points require SharedInfo::stack0 to be set up in | |
3081 // non-core builds and need to be relocatable, so they each | |
3082 // fabricate a RuntimeStub internally. | |
3083 StubRoutines::_throw_AbstractMethodError_entry = | |
3084 generate_throw_exception("AbstractMethodError throw_exception", | |
3085 CAST_FROM_FN_PTR(address, | |
3086 SharedRuntime:: | |
3937 | 3087 throw_AbstractMethodError)); |
0 | 3088 |
16
f8236e79048a
6664627: Merge changes made only in hotspot 11 forward to jdk 7
dcubed
parents:
0
diff
changeset
|
3089 StubRoutines::_throw_IncompatibleClassChangeError_entry = |
f8236e79048a
6664627: Merge changes made only in hotspot 11 forward to jdk 7
dcubed
parents:
0
diff
changeset
|
3090 generate_throw_exception("IncompatibleClassChangeError throw_exception", |
f8236e79048a
6664627: Merge changes made only in hotspot 11 forward to jdk 7
dcubed
parents:
0
diff
changeset
|
3091 CAST_FROM_FN_PTR(address, |
f8236e79048a
6664627: Merge changes made only in hotspot 11 forward to jdk 7
dcubed
parents:
0
diff
changeset
|
3092 SharedRuntime:: |
3937 | 3093 throw_IncompatibleClassChangeError)); |
0 | 3094 |
3095 StubRoutines::_throw_NullPointerException_at_call_entry = | |
3096 generate_throw_exception("NullPointerException at call throw_exception", | |
3097 CAST_FROM_FN_PTR(address, | |
3098 SharedRuntime:: | |
3937 | 3099 throw_NullPointerException_at_call)); |
0 | 3100 |
3101 StubRoutines::_throw_StackOverflowError_entry = | |
3102 generate_throw_exception("StackOverflowError throw_exception", | |
3103 CAST_FROM_FN_PTR(address, | |
3104 SharedRuntime:: | |
3937 | 3105 throw_StackOverflowError)); |
0 | 3106 |
3107 // entry points that are platform specific | |
304 | 3108 StubRoutines::x86::_f2i_fixup = generate_f2i_fixup(); |
3109 StubRoutines::x86::_f2l_fixup = generate_f2l_fixup(); | |
3110 StubRoutines::x86::_d2i_fixup = generate_d2i_fixup(); | |
3111 StubRoutines::x86::_d2l_fixup = generate_d2l_fixup(); | |
3112 | |
3113 StubRoutines::x86::_float_sign_mask = generate_fp_mask("float_sign_mask", 0x7FFFFFFF7FFFFFFF); | |
3114 StubRoutines::x86::_float_sign_flip = generate_fp_mask("float_sign_flip", 0x8000000080000000); | |
3115 StubRoutines::x86::_double_sign_mask = generate_fp_mask("double_sign_mask", 0x7FFFFFFFFFFFFFFF); | |
3116 StubRoutines::x86::_double_sign_flip = generate_fp_mask("double_sign_flip", 0x8000000000000000); | |
0 | 3117 |
3118 // support for verify_oop (must happen after universe_init) | |
3119 StubRoutines::_verify_oop_subroutine_entry = generate_verify_oop(); | |
3120 | |
3121 // arraycopy stubs used by compilers | |
3122 generate_arraycopy_stubs(); | |
1108 | 3123 |
1174
ddb7834449d0
6849984: Value methods for platform dependent math functions constant fold incorrectly
never
parents:
1108
diff
changeset
|
3124 generate_math_stubs(); |
0 | 3125 } |
3126 | |
3127 public: | |
3128 StubGenerator(CodeBuffer* code, bool all) : StubCodeGenerator(code) { | |
3129 if (all) { | |
3130 generate_all(); | |
3131 } else { | |
3132 generate_initial(); | |
3133 } | |
3134 } | |
3135 }; // end class declaration | |
3136 | |
3137 void StubGenerator_generate(CodeBuffer* code, bool all) { | |
3138 StubGenerator g(code, all); | |
3139 } |