annotate src/cpu/sparc/vm/stubGenerator_sparc.cpp @ 6812:988bf00cc564

7200261: G1: Liveness counting inconsistencies during marking verification Summary: The clipping code in the routine that sets the bits for a range of cards, in the liveness accounting verification code was incorrect. It set all the bits in the card bitmap from the given starting index which would lead to spurious marking verification failures. Reviewed-by: brutisso, jwilhelm, jmasa
author johnc
date Thu, 27 Sep 2012 15:44:01 -0700
parents da91efe96a93
children d8ce2825b193
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1 /*
6725
da91efe96a93 6964458: Reimplement class meta-data storage to use native memory
coleenp
parents: 6266
diff changeset
2 * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
0
a61af66fc99e Initial load
duke
parents:
diff changeset
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
a61af66fc99e Initial load
duke
parents:
diff changeset
4 *
a61af66fc99e Initial load
duke
parents:
diff changeset
5 * This code is free software; you can redistribute it and/or modify it
a61af66fc99e Initial load
duke
parents:
diff changeset
6 * under the terms of the GNU General Public License version 2 only, as
a61af66fc99e Initial load
duke
parents:
diff changeset
7 * published by the Free Software Foundation.
a61af66fc99e Initial load
duke
parents:
diff changeset
8 *
a61af66fc99e Initial load
duke
parents:
diff changeset
9 * This code is distributed in the hope that it will be useful, but WITHOUT
a61af66fc99e Initial load
duke
parents:
diff changeset
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
a61af66fc99e Initial load
duke
parents:
diff changeset
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
a61af66fc99e Initial load
duke
parents:
diff changeset
12 * version 2 for more details (a copy is included in the LICENSE file that
a61af66fc99e Initial load
duke
parents:
diff changeset
13 * accompanied this code).
a61af66fc99e Initial load
duke
parents:
diff changeset
14 *
a61af66fc99e Initial load
duke
parents:
diff changeset
15 * You should have received a copy of the GNU General Public License version
a61af66fc99e Initial load
duke
parents:
diff changeset
16 * 2 along with this work; if not, write to the Free Software Foundation,
a61af66fc99e Initial load
duke
parents:
diff changeset
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
a61af66fc99e Initial load
duke
parents:
diff changeset
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
a61af66fc99e Initial load
duke
parents:
diff changeset
22 *
a61af66fc99e Initial load
duke
parents:
diff changeset
23 */
a61af66fc99e Initial load
duke
parents:
diff changeset
24
1972
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1844
diff changeset
25 #include "precompiled.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1844
diff changeset
26 #include "asm/assembler.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1844
diff changeset
27 #include "assembler_sparc.inline.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1844
diff changeset
28 #include "interpreter/interpreter.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1844
diff changeset
29 #include "nativeInst_sparc.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1844
diff changeset
30 #include "oops/instanceOop.hpp"
6725
da91efe96a93 6964458: Reimplement class meta-data storage to use native memory
coleenp
parents: 6266
diff changeset
31 #include "oops/method.hpp"
1972
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1844
diff changeset
32 #include "oops/objArrayKlass.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1844
diff changeset
33 #include "oops/oop.inline.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1844
diff changeset
34 #include "prims/methodHandles.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1844
diff changeset
35 #include "runtime/frame.inline.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1844
diff changeset
36 #include "runtime/handles.inline.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1844
diff changeset
37 #include "runtime/sharedRuntime.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1844
diff changeset
38 #include "runtime/stubCodeGenerator.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1844
diff changeset
39 #include "runtime/stubRoutines.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1844
diff changeset
40 #include "utilities/top.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1844
diff changeset
41 #ifdef TARGET_OS_FAMILY_linux
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1844
diff changeset
42 # include "thread_linux.inline.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1844
diff changeset
43 #endif
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1844
diff changeset
44 #ifdef TARGET_OS_FAMILY_solaris
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1844
diff changeset
45 # include "thread_solaris.inline.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1844
diff changeset
46 #endif
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1844
diff changeset
47 #ifdef COMPILER2
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1844
diff changeset
48 #include "opto/runtime.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1844
diff changeset
49 #endif
0
a61af66fc99e Initial load
duke
parents:
diff changeset
50
a61af66fc99e Initial load
duke
parents:
diff changeset
51 // Declaration and definition of StubGenerator (no .hpp file).
a61af66fc99e Initial load
duke
parents:
diff changeset
52 // For a more detailed description of the stub routine structure
a61af66fc99e Initial load
duke
parents:
diff changeset
53 // see the comment in stubRoutines.hpp.
a61af66fc99e Initial load
duke
parents:
diff changeset
54
a61af66fc99e Initial load
duke
parents:
diff changeset
55 #define __ _masm->
a61af66fc99e Initial load
duke
parents:
diff changeset
56
a61af66fc99e Initial load
duke
parents:
diff changeset
57 #ifdef PRODUCT
a61af66fc99e Initial load
duke
parents:
diff changeset
58 #define BLOCK_COMMENT(str) /* nothing */
a61af66fc99e Initial load
duke
parents:
diff changeset
59 #else
a61af66fc99e Initial load
duke
parents:
diff changeset
60 #define BLOCK_COMMENT(str) __ block_comment(str)
a61af66fc99e Initial load
duke
parents:
diff changeset
61 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
62
a61af66fc99e Initial load
duke
parents:
diff changeset
63 #define BIND(label) bind(label); BLOCK_COMMENT(#label ":")
a61af66fc99e Initial load
duke
parents:
diff changeset
64
a61af66fc99e Initial load
duke
parents:
diff changeset
65 // Note: The register L7 is used as L7_thread_cache, and may not be used
a61af66fc99e Initial load
duke
parents:
diff changeset
66 // any other way within this module.
a61af66fc99e Initial load
duke
parents:
diff changeset
67
a61af66fc99e Initial load
duke
parents:
diff changeset
68
a61af66fc99e Initial load
duke
parents:
diff changeset
69 static const Register& Lstub_temp = L2;
a61af66fc99e Initial load
duke
parents:
diff changeset
70
a61af66fc99e Initial load
duke
parents:
diff changeset
71 // -------------------------------------------------------------------------------------------------------------------------
a61af66fc99e Initial load
duke
parents:
diff changeset
72 // Stub Code definitions
a61af66fc99e Initial load
duke
parents:
diff changeset
73
a61af66fc99e Initial load
duke
parents:
diff changeset
74 static address handle_unsafe_access() {
a61af66fc99e Initial load
duke
parents:
diff changeset
75 JavaThread* thread = JavaThread::current();
a61af66fc99e Initial load
duke
parents:
diff changeset
76 address pc = thread->saved_exception_pc();
a61af66fc99e Initial load
duke
parents:
diff changeset
77 address npc = thread->saved_exception_npc();
a61af66fc99e Initial load
duke
parents:
diff changeset
78 // pc is the instruction which we must emulate
a61af66fc99e Initial load
duke
parents:
diff changeset
79 // doing a no-op is fine: return garbage from the load
a61af66fc99e Initial load
duke
parents:
diff changeset
80
a61af66fc99e Initial load
duke
parents:
diff changeset
81 // request an async exception
a61af66fc99e Initial load
duke
parents:
diff changeset
82 thread->set_pending_unsafe_access_error();
a61af66fc99e Initial load
duke
parents:
diff changeset
83
a61af66fc99e Initial load
duke
parents:
diff changeset
84 // return address of next instruction to execute
a61af66fc99e Initial load
duke
parents:
diff changeset
85 return npc;
a61af66fc99e Initial load
duke
parents:
diff changeset
86 }
a61af66fc99e Initial load
duke
parents:
diff changeset
87
a61af66fc99e Initial load
duke
parents:
diff changeset
88 class StubGenerator: public StubCodeGenerator {
a61af66fc99e Initial load
duke
parents:
diff changeset
89 private:
a61af66fc99e Initial load
duke
parents:
diff changeset
90
a61af66fc99e Initial load
duke
parents:
diff changeset
91 #ifdef PRODUCT
a61af66fc99e Initial load
duke
parents:
diff changeset
92 #define inc_counter_np(a,b,c) (0)
a61af66fc99e Initial load
duke
parents:
diff changeset
93 #else
a61af66fc99e Initial load
duke
parents:
diff changeset
94 #define inc_counter_np(counter, t1, t2) \
a61af66fc99e Initial load
duke
parents:
diff changeset
95 BLOCK_COMMENT("inc_counter " #counter); \
727
6b2273dd6fa9 6822110: Add AddressLiteral class on SPARC
twisti
parents: 671
diff changeset
96 __ inc_counter(&counter, t1, t2);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
97 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
98
a61af66fc99e Initial load
duke
parents:
diff changeset
99 //----------------------------------------------------------------------------------------------------
a61af66fc99e Initial load
duke
parents:
diff changeset
100 // Call stubs are used to call Java from C
a61af66fc99e Initial load
duke
parents:
diff changeset
101
a61af66fc99e Initial load
duke
parents:
diff changeset
102 address generate_call_stub(address& return_pc) {
a61af66fc99e Initial load
duke
parents:
diff changeset
103 StubCodeMark mark(this, "StubRoutines", "call_stub");
a61af66fc99e Initial load
duke
parents:
diff changeset
104 address start = __ pc();
a61af66fc99e Initial load
duke
parents:
diff changeset
105
a61af66fc99e Initial load
duke
parents:
diff changeset
106 // Incoming arguments:
a61af66fc99e Initial load
duke
parents:
diff changeset
107 //
a61af66fc99e Initial load
duke
parents:
diff changeset
108 // o0 : call wrapper address
a61af66fc99e Initial load
duke
parents:
diff changeset
109 // o1 : result (address)
a61af66fc99e Initial load
duke
parents:
diff changeset
110 // o2 : result type
a61af66fc99e Initial load
duke
parents:
diff changeset
111 // o3 : method
a61af66fc99e Initial load
duke
parents:
diff changeset
112 // o4 : (interpreter) entry point
a61af66fc99e Initial load
duke
parents:
diff changeset
113 // o5 : parameters (address)
a61af66fc99e Initial load
duke
parents:
diff changeset
114 // [sp + 0x5c]: parameter size (in words)
a61af66fc99e Initial load
duke
parents:
diff changeset
115 // [sp + 0x60]: thread
a61af66fc99e Initial load
duke
parents:
diff changeset
116 //
a61af66fc99e Initial load
duke
parents:
diff changeset
117 // +---------------+ <--- sp + 0
a61af66fc99e Initial load
duke
parents:
diff changeset
118 // | |
a61af66fc99e Initial load
duke
parents:
diff changeset
119 // . reg save area .
a61af66fc99e Initial load
duke
parents:
diff changeset
120 // | |
a61af66fc99e Initial load
duke
parents:
diff changeset
121 // +---------------+ <--- sp + 0x40
a61af66fc99e Initial load
duke
parents:
diff changeset
122 // | |
a61af66fc99e Initial load
duke
parents:
diff changeset
123 // . extra 7 slots .
a61af66fc99e Initial load
duke
parents:
diff changeset
124 // | |
a61af66fc99e Initial load
duke
parents:
diff changeset
125 // +---------------+ <--- sp + 0x5c
a61af66fc99e Initial load
duke
parents:
diff changeset
126 // | param. size |
a61af66fc99e Initial load
duke
parents:
diff changeset
127 // +---------------+ <--- sp + 0x60
a61af66fc99e Initial load
duke
parents:
diff changeset
128 // | thread |
a61af66fc99e Initial load
duke
parents:
diff changeset
129 // +---------------+
a61af66fc99e Initial load
duke
parents:
diff changeset
130 // | |
a61af66fc99e Initial load
duke
parents:
diff changeset
131
a61af66fc99e Initial load
duke
parents:
diff changeset
132 // note: if the link argument position changes, adjust
a61af66fc99e Initial load
duke
parents:
diff changeset
133 // the code in frame::entry_frame_call_wrapper()
a61af66fc99e Initial load
duke
parents:
diff changeset
134
a61af66fc99e Initial load
duke
parents:
diff changeset
135 const Argument link = Argument(0, false); // used only for GC
a61af66fc99e Initial load
duke
parents:
diff changeset
136 const Argument result = Argument(1, false);
a61af66fc99e Initial load
duke
parents:
diff changeset
137 const Argument result_type = Argument(2, false);
a61af66fc99e Initial load
duke
parents:
diff changeset
138 const Argument method = Argument(3, false);
a61af66fc99e Initial load
duke
parents:
diff changeset
139 const Argument entry_point = Argument(4, false);
a61af66fc99e Initial load
duke
parents:
diff changeset
140 const Argument parameters = Argument(5, false);
a61af66fc99e Initial load
duke
parents:
diff changeset
141 const Argument parameter_size = Argument(6, false);
a61af66fc99e Initial load
duke
parents:
diff changeset
142 const Argument thread = Argument(7, false);
a61af66fc99e Initial load
duke
parents:
diff changeset
143
a61af66fc99e Initial load
duke
parents:
diff changeset
144 // setup thread register
a61af66fc99e Initial load
duke
parents:
diff changeset
145 __ ld_ptr(thread.as_address(), G2_thread);
113
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 16
diff changeset
146 __ reinit_heapbase();
0
a61af66fc99e Initial load
duke
parents:
diff changeset
147
a61af66fc99e Initial load
duke
parents:
diff changeset
148 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
149 // make sure we have no pending exceptions
a61af66fc99e Initial load
duke
parents:
diff changeset
150 { const Register t = G3_scratch;
a61af66fc99e Initial load
duke
parents:
diff changeset
151 Label L;
a61af66fc99e Initial load
duke
parents:
diff changeset
152 __ ld_ptr(G2_thread, in_bytes(Thread::pending_exception_offset()), t);
3839
3d42f82cd811 7063628: Use cbcond on T4
kvn
parents: 3781
diff changeset
153 __ br_null_short(t, Assembler::pt, L);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
154 __ stop("StubRoutines::call_stub: entered with pending exception");
a61af66fc99e Initial load
duke
parents:
diff changeset
155 __ bind(L);
a61af66fc99e Initial load
duke
parents:
diff changeset
156 }
a61af66fc99e Initial load
duke
parents:
diff changeset
157 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
158
a61af66fc99e Initial load
duke
parents:
diff changeset
159 // create activation frame & allocate space for parameters
a61af66fc99e Initial load
duke
parents:
diff changeset
160 { const Register t = G3_scratch;
a61af66fc99e Initial load
duke
parents:
diff changeset
161 __ ld_ptr(parameter_size.as_address(), t); // get parameter size (in words)
a61af66fc99e Initial load
duke
parents:
diff changeset
162 __ add(t, frame::memory_parameter_word_sp_offset, t); // add space for save area (in words)
a61af66fc99e Initial load
duke
parents:
diff changeset
163 __ round_to(t, WordsPerLong); // make sure it is multiple of 2 (in words)
1506
2338d41fbd81 6943304: remove tagged stack interpreter
twisti
parents: 1503
diff changeset
164 __ sll(t, Interpreter::logStackElementSize, t); // compute number of bytes
0
a61af66fc99e Initial load
duke
parents:
diff changeset
165 __ neg(t); // negate so it can be used with save
a61af66fc99e Initial load
duke
parents:
diff changeset
166 __ save(SP, t, SP); // setup new frame
a61af66fc99e Initial load
duke
parents:
diff changeset
167 }
a61af66fc99e Initial load
duke
parents:
diff changeset
168
a61af66fc99e Initial load
duke
parents:
diff changeset
169 // +---------------+ <--- sp + 0
a61af66fc99e Initial load
duke
parents:
diff changeset
170 // | |
a61af66fc99e Initial load
duke
parents:
diff changeset
171 // . reg save area .
a61af66fc99e Initial load
duke
parents:
diff changeset
172 // | |
a61af66fc99e Initial load
duke
parents:
diff changeset
173 // +---------------+ <--- sp + 0x40
a61af66fc99e Initial load
duke
parents:
diff changeset
174 // | |
a61af66fc99e Initial load
duke
parents:
diff changeset
175 // . extra 7 slots .
a61af66fc99e Initial load
duke
parents:
diff changeset
176 // | |
a61af66fc99e Initial load
duke
parents:
diff changeset
177 // +---------------+ <--- sp + 0x5c
a61af66fc99e Initial load
duke
parents:
diff changeset
178 // | empty slot | (only if parameter size is even)
a61af66fc99e Initial load
duke
parents:
diff changeset
179 // +---------------+
a61af66fc99e Initial load
duke
parents:
diff changeset
180 // | |
a61af66fc99e Initial load
duke
parents:
diff changeset
181 // . parameters .
a61af66fc99e Initial load
duke
parents:
diff changeset
182 // | |
a61af66fc99e Initial load
duke
parents:
diff changeset
183 // +---------------+ <--- fp + 0
a61af66fc99e Initial load
duke
parents:
diff changeset
184 // | |
a61af66fc99e Initial load
duke
parents:
diff changeset
185 // . reg save area .
a61af66fc99e Initial load
duke
parents:
diff changeset
186 // | |
a61af66fc99e Initial load
duke
parents:
diff changeset
187 // +---------------+ <--- fp + 0x40
a61af66fc99e Initial load
duke
parents:
diff changeset
188 // | |
a61af66fc99e Initial load
duke
parents:
diff changeset
189 // . extra 7 slots .
a61af66fc99e Initial load
duke
parents:
diff changeset
190 // | |
a61af66fc99e Initial load
duke
parents:
diff changeset
191 // +---------------+ <--- fp + 0x5c
a61af66fc99e Initial load
duke
parents:
diff changeset
192 // | param. size |
a61af66fc99e Initial load
duke
parents:
diff changeset
193 // +---------------+ <--- fp + 0x60
a61af66fc99e Initial load
duke
parents:
diff changeset
194 // | thread |
a61af66fc99e Initial load
duke
parents:
diff changeset
195 // +---------------+
a61af66fc99e Initial load
duke
parents:
diff changeset
196 // | |
a61af66fc99e Initial load
duke
parents:
diff changeset
197
a61af66fc99e Initial load
duke
parents:
diff changeset
198 // pass parameters if any
a61af66fc99e Initial load
duke
parents:
diff changeset
199 BLOCK_COMMENT("pass parameters if any");
a61af66fc99e Initial load
duke
parents:
diff changeset
200 { const Register src = parameters.as_in().as_register();
a61af66fc99e Initial load
duke
parents:
diff changeset
201 const Register dst = Lentry_args;
a61af66fc99e Initial load
duke
parents:
diff changeset
202 const Register tmp = G3_scratch;
a61af66fc99e Initial load
duke
parents:
diff changeset
203 const Register cnt = G4_scratch;
a61af66fc99e Initial load
duke
parents:
diff changeset
204
a61af66fc99e Initial load
duke
parents:
diff changeset
205 // test if any parameters & setup of Lentry_args
a61af66fc99e Initial load
duke
parents:
diff changeset
206 Label exit;
a61af66fc99e Initial load
duke
parents:
diff changeset
207 __ ld_ptr(parameter_size.as_in().as_address(), cnt); // parameter counter
a61af66fc99e Initial load
duke
parents:
diff changeset
208 __ add( FP, STACK_BIAS, dst );
3839
3d42f82cd811 7063628: Use cbcond on T4
kvn
parents: 3781
diff changeset
209 __ cmp_zero_and_br(Assembler::zero, cnt, exit);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
210 __ delayed()->sub(dst, BytesPerWord, dst); // setup Lentry_args
a61af66fc99e Initial load
duke
parents:
diff changeset
211
a61af66fc99e Initial load
duke
parents:
diff changeset
212 // copy parameters if any
a61af66fc99e Initial load
duke
parents:
diff changeset
213 Label loop;
a61af66fc99e Initial load
duke
parents:
diff changeset
214 __ BIND(loop);
a61af66fc99e Initial load
duke
parents:
diff changeset
215 // Store parameter value
a61af66fc99e Initial load
duke
parents:
diff changeset
216 __ ld_ptr(src, 0, tmp);
a61af66fc99e Initial load
duke
parents:
diff changeset
217 __ add(src, BytesPerWord, src);
1506
2338d41fbd81 6943304: remove tagged stack interpreter
twisti
parents: 1503
diff changeset
218 __ st_ptr(tmp, dst, 0);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
219 __ deccc(cnt);
a61af66fc99e Initial load
duke
parents:
diff changeset
220 __ br(Assembler::greater, false, Assembler::pt, loop);
1506
2338d41fbd81 6943304: remove tagged stack interpreter
twisti
parents: 1503
diff changeset
221 __ delayed()->sub(dst, Interpreter::stackElementSize, dst);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
222
a61af66fc99e Initial load
duke
parents:
diff changeset
223 // done
a61af66fc99e Initial load
duke
parents:
diff changeset
224 __ BIND(exit);
a61af66fc99e Initial load
duke
parents:
diff changeset
225 }
a61af66fc99e Initial load
duke
parents:
diff changeset
226
a61af66fc99e Initial load
duke
parents:
diff changeset
227 // setup parameters, method & call Java function
a61af66fc99e Initial load
duke
parents:
diff changeset
228 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
229 // layout_activation_impl checks it's notion of saved SP against
a61af66fc99e Initial load
duke
parents:
diff changeset
230 // this register, so if this changes update it as well.
a61af66fc99e Initial load
duke
parents:
diff changeset
231 const Register saved_SP = Lscratch;
a61af66fc99e Initial load
duke
parents:
diff changeset
232 __ mov(SP, saved_SP); // keep track of SP before call
a61af66fc99e Initial load
duke
parents:
diff changeset
233 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
234
a61af66fc99e Initial load
duke
parents:
diff changeset
235 // setup parameters
a61af66fc99e Initial load
duke
parents:
diff changeset
236 const Register t = G3_scratch;
a61af66fc99e Initial load
duke
parents:
diff changeset
237 __ ld_ptr(parameter_size.as_in().as_address(), t); // get parameter size (in words)
1506
2338d41fbd81 6943304: remove tagged stack interpreter
twisti
parents: 1503
diff changeset
238 __ sll(t, Interpreter::logStackElementSize, t); // compute number of bytes
0
a61af66fc99e Initial load
duke
parents:
diff changeset
239 __ sub(FP, t, Gargs); // setup parameter pointer
a61af66fc99e Initial load
duke
parents:
diff changeset
240 #ifdef _LP64
a61af66fc99e Initial load
duke
parents:
diff changeset
241 __ add( Gargs, STACK_BIAS, Gargs ); // Account for LP64 stack bias
a61af66fc99e Initial load
duke
parents:
diff changeset
242 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
243 __ mov(SP, O5_savedSP);
a61af66fc99e Initial load
duke
parents:
diff changeset
244
a61af66fc99e Initial load
duke
parents:
diff changeset
245
a61af66fc99e Initial load
duke
parents:
diff changeset
246 // do the call
a61af66fc99e Initial load
duke
parents:
diff changeset
247 //
a61af66fc99e Initial load
duke
parents:
diff changeset
248 // the following register must be setup:
a61af66fc99e Initial load
duke
parents:
diff changeset
249 //
a61af66fc99e Initial load
duke
parents:
diff changeset
250 // G2_thread
a61af66fc99e Initial load
duke
parents:
diff changeset
251 // G5_method
a61af66fc99e Initial load
duke
parents:
diff changeset
252 // Gargs
a61af66fc99e Initial load
duke
parents:
diff changeset
253 BLOCK_COMMENT("call Java function");
a61af66fc99e Initial load
duke
parents:
diff changeset
254 __ jmpl(entry_point.as_in().as_register(), G0, O7);
a61af66fc99e Initial load
duke
parents:
diff changeset
255 __ delayed()->mov(method.as_in().as_register(), G5_method); // setup method
a61af66fc99e Initial load
duke
parents:
diff changeset
256
a61af66fc99e Initial load
duke
parents:
diff changeset
257 BLOCK_COMMENT("call_stub_return_address:");
a61af66fc99e Initial load
duke
parents:
diff changeset
258 return_pc = __ pc();
a61af66fc99e Initial load
duke
parents:
diff changeset
259
a61af66fc99e Initial load
duke
parents:
diff changeset
260 // The callee, if it wasn't interpreted, can return with SP changed so
a61af66fc99e Initial load
duke
parents:
diff changeset
261 // we can no longer assert of change of SP.
a61af66fc99e Initial load
duke
parents:
diff changeset
262
a61af66fc99e Initial load
duke
parents:
diff changeset
263 // store result depending on type
a61af66fc99e Initial load
duke
parents:
diff changeset
264 // (everything that is not T_OBJECT, T_LONG, T_FLOAT, or T_DOUBLE
a61af66fc99e Initial load
duke
parents:
diff changeset
265 // is treated as T_INT)
a61af66fc99e Initial load
duke
parents:
diff changeset
266 { const Register addr = result .as_in().as_register();
a61af66fc99e Initial load
duke
parents:
diff changeset
267 const Register type = result_type.as_in().as_register();
a61af66fc99e Initial load
duke
parents:
diff changeset
268 Label is_long, is_float, is_double, is_object, exit;
a61af66fc99e Initial load
duke
parents:
diff changeset
269 __ cmp(type, T_OBJECT); __ br(Assembler::equal, false, Assembler::pn, is_object);
a61af66fc99e Initial load
duke
parents:
diff changeset
270 __ delayed()->cmp(type, T_FLOAT); __ br(Assembler::equal, false, Assembler::pn, is_float);
a61af66fc99e Initial load
duke
parents:
diff changeset
271 __ delayed()->cmp(type, T_DOUBLE); __ br(Assembler::equal, false, Assembler::pn, is_double);
a61af66fc99e Initial load
duke
parents:
diff changeset
272 __ delayed()->cmp(type, T_LONG); __ br(Assembler::equal, false, Assembler::pn, is_long);
a61af66fc99e Initial load
duke
parents:
diff changeset
273 __ delayed()->nop();
a61af66fc99e Initial load
duke
parents:
diff changeset
274
a61af66fc99e Initial load
duke
parents:
diff changeset
275 // store int result
a61af66fc99e Initial load
duke
parents:
diff changeset
276 __ st(O0, addr, G0);
a61af66fc99e Initial load
duke
parents:
diff changeset
277
a61af66fc99e Initial load
duke
parents:
diff changeset
278 __ BIND(exit);
a61af66fc99e Initial load
duke
parents:
diff changeset
279 __ ret();
a61af66fc99e Initial load
duke
parents:
diff changeset
280 __ delayed()->restore();
a61af66fc99e Initial load
duke
parents:
diff changeset
281
a61af66fc99e Initial load
duke
parents:
diff changeset
282 __ BIND(is_object);
3839
3d42f82cd811 7063628: Use cbcond on T4
kvn
parents: 3781
diff changeset
283 __ ba(exit);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
284 __ delayed()->st_ptr(O0, addr, G0);
a61af66fc99e Initial load
duke
parents:
diff changeset
285
a61af66fc99e Initial load
duke
parents:
diff changeset
286 __ BIND(is_float);
3839
3d42f82cd811 7063628: Use cbcond on T4
kvn
parents: 3781
diff changeset
287 __ ba(exit);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
288 __ delayed()->stf(FloatRegisterImpl::S, F0, addr, G0);
a61af66fc99e Initial load
duke
parents:
diff changeset
289
a61af66fc99e Initial load
duke
parents:
diff changeset
290 __ BIND(is_double);
3839
3d42f82cd811 7063628: Use cbcond on T4
kvn
parents: 3781
diff changeset
291 __ ba(exit);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
292 __ delayed()->stf(FloatRegisterImpl::D, F0, addr, G0);
a61af66fc99e Initial load
duke
parents:
diff changeset
293
a61af66fc99e Initial load
duke
parents:
diff changeset
294 __ BIND(is_long);
a61af66fc99e Initial load
duke
parents:
diff changeset
295 #ifdef _LP64
3839
3d42f82cd811 7063628: Use cbcond on T4
kvn
parents: 3781
diff changeset
296 __ ba(exit);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
297 __ delayed()->st_long(O0, addr, G0); // store entire long
a61af66fc99e Initial load
duke
parents:
diff changeset
298 #else
a61af66fc99e Initial load
duke
parents:
diff changeset
299 #if defined(COMPILER2)
a61af66fc99e Initial load
duke
parents:
diff changeset
300 // All return values are where we want them, except for Longs. C2 returns
a61af66fc99e Initial load
duke
parents:
diff changeset
301 // longs in G1 in the 32-bit build whereas the interpreter wants them in O0/O1.
a61af66fc99e Initial load
duke
parents:
diff changeset
302 // Since the interpreter will return longs in G1 and O0/O1 in the 32bit
a61af66fc99e Initial load
duke
parents:
diff changeset
303 // build we simply always use G1.
a61af66fc99e Initial load
duke
parents:
diff changeset
304 // Note: I tried to make c2 return longs in O0/O1 and G1 so we wouldn't have to
a61af66fc99e Initial load
duke
parents:
diff changeset
305 // do this here. Unfortunately if we did a rethrow we'd see an machepilog node
a61af66fc99e Initial load
duke
parents:
diff changeset
306 // first which would move g1 -> O0/O1 and destroy the exception we were throwing.
a61af66fc99e Initial load
duke
parents:
diff changeset
307
3839
3d42f82cd811 7063628: Use cbcond on T4
kvn
parents: 3781
diff changeset
308 __ ba(exit);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
309 __ delayed()->stx(G1, addr, G0); // store entire long
a61af66fc99e Initial load
duke
parents:
diff changeset
310 #else
a61af66fc99e Initial load
duke
parents:
diff changeset
311 __ st(O1, addr, BytesPerInt);
3839
3d42f82cd811 7063628: Use cbcond on T4
kvn
parents: 3781
diff changeset
312 __ ba(exit);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
313 __ delayed()->st(O0, addr, G0);
a61af66fc99e Initial load
duke
parents:
diff changeset
314 #endif /* COMPILER2 */
a61af66fc99e Initial load
duke
parents:
diff changeset
315 #endif /* _LP64 */
a61af66fc99e Initial load
duke
parents:
diff changeset
316 }
a61af66fc99e Initial load
duke
parents:
diff changeset
317 return start;
a61af66fc99e Initial load
duke
parents:
diff changeset
318 }
a61af66fc99e Initial load
duke
parents:
diff changeset
319
a61af66fc99e Initial load
duke
parents:
diff changeset
320
a61af66fc99e Initial load
duke
parents:
diff changeset
321 //----------------------------------------------------------------------------------------------------
a61af66fc99e Initial load
duke
parents:
diff changeset
322 // Return point for a Java call if there's an exception thrown in Java code.
a61af66fc99e Initial load
duke
parents:
diff changeset
323 // The exception is caught and transformed into a pending exception stored in
a61af66fc99e Initial load
duke
parents:
diff changeset
324 // JavaThread that can be tested from within the VM.
a61af66fc99e Initial load
duke
parents:
diff changeset
325 //
a61af66fc99e Initial load
duke
parents:
diff changeset
326 // Oexception: exception oop
a61af66fc99e Initial load
duke
parents:
diff changeset
327
a61af66fc99e Initial load
duke
parents:
diff changeset
328 address generate_catch_exception() {
a61af66fc99e Initial load
duke
parents:
diff changeset
329 StubCodeMark mark(this, "StubRoutines", "catch_exception");
a61af66fc99e Initial load
duke
parents:
diff changeset
330
a61af66fc99e Initial load
duke
parents:
diff changeset
331 address start = __ pc();
a61af66fc99e Initial load
duke
parents:
diff changeset
332 // verify that thread corresponds
a61af66fc99e Initial load
duke
parents:
diff changeset
333 __ verify_thread();
a61af66fc99e Initial load
duke
parents:
diff changeset
334
a61af66fc99e Initial load
duke
parents:
diff changeset
335 const Register& temp_reg = Gtemp;
727
6b2273dd6fa9 6822110: Add AddressLiteral class on SPARC
twisti
parents: 671
diff changeset
336 Address pending_exception_addr (G2_thread, Thread::pending_exception_offset());
6b2273dd6fa9 6822110: Add AddressLiteral class on SPARC
twisti
parents: 671
diff changeset
337 Address exception_file_offset_addr(G2_thread, Thread::exception_file_offset ());
6b2273dd6fa9 6822110: Add AddressLiteral class on SPARC
twisti
parents: 671
diff changeset
338 Address exception_line_offset_addr(G2_thread, Thread::exception_line_offset ());
0
a61af66fc99e Initial load
duke
parents:
diff changeset
339
a61af66fc99e Initial load
duke
parents:
diff changeset
340 // set pending exception
a61af66fc99e Initial load
duke
parents:
diff changeset
341 __ verify_oop(Oexception);
a61af66fc99e Initial load
duke
parents:
diff changeset
342 __ st_ptr(Oexception, pending_exception_addr);
a61af66fc99e Initial load
duke
parents:
diff changeset
343 __ set((intptr_t)__FILE__, temp_reg);
a61af66fc99e Initial load
duke
parents:
diff changeset
344 __ st_ptr(temp_reg, exception_file_offset_addr);
a61af66fc99e Initial load
duke
parents:
diff changeset
345 __ set((intptr_t)__LINE__, temp_reg);
a61af66fc99e Initial load
duke
parents:
diff changeset
346 __ st(temp_reg, exception_line_offset_addr);
a61af66fc99e Initial load
duke
parents:
diff changeset
347
a61af66fc99e Initial load
duke
parents:
diff changeset
348 // complete return to VM
a61af66fc99e Initial load
duke
parents:
diff changeset
349 assert(StubRoutines::_call_stub_return_address != NULL, "must have been generated before");
a61af66fc99e Initial load
duke
parents:
diff changeset
350
727
6b2273dd6fa9 6822110: Add AddressLiteral class on SPARC
twisti
parents: 671
diff changeset
351 AddressLiteral stub_ret(StubRoutines::_call_stub_return_address);
6b2273dd6fa9 6822110: Add AddressLiteral class on SPARC
twisti
parents: 671
diff changeset
352 __ jump_to(stub_ret, temp_reg);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
353 __ delayed()->nop();
a61af66fc99e Initial load
duke
parents:
diff changeset
354
a61af66fc99e Initial load
duke
parents:
diff changeset
355 return start;
a61af66fc99e Initial load
duke
parents:
diff changeset
356 }
a61af66fc99e Initial load
duke
parents:
diff changeset
357
a61af66fc99e Initial load
duke
parents:
diff changeset
358
a61af66fc99e Initial load
duke
parents:
diff changeset
359 //----------------------------------------------------------------------------------------------------
a61af66fc99e Initial load
duke
parents:
diff changeset
360 // Continuation point for runtime calls returning with a pending exception
a61af66fc99e Initial load
duke
parents:
diff changeset
361 // The pending exception check happened in the runtime or native call stub
a61af66fc99e Initial load
duke
parents:
diff changeset
362 // The pending exception in Thread is converted into a Java-level exception
a61af66fc99e Initial load
duke
parents:
diff changeset
363 //
a61af66fc99e Initial load
duke
parents:
diff changeset
364 // Contract with Java-level exception handler: O0 = exception
a61af66fc99e Initial load
duke
parents:
diff changeset
365 // O1 = throwing pc
a61af66fc99e Initial load
duke
parents:
diff changeset
366
a61af66fc99e Initial load
duke
parents:
diff changeset
367 address generate_forward_exception() {
a61af66fc99e Initial load
duke
parents:
diff changeset
368 StubCodeMark mark(this, "StubRoutines", "forward_exception");
a61af66fc99e Initial load
duke
parents:
diff changeset
369 address start = __ pc();
a61af66fc99e Initial load
duke
parents:
diff changeset
370
a61af66fc99e Initial load
duke
parents:
diff changeset
371 // Upon entry, O7 has the return address returning into Java
a61af66fc99e Initial load
duke
parents:
diff changeset
372 // (interpreted or compiled) code; i.e. the return address
a61af66fc99e Initial load
duke
parents:
diff changeset
373 // becomes the throwing pc.
a61af66fc99e Initial load
duke
parents:
diff changeset
374
a61af66fc99e Initial load
duke
parents:
diff changeset
375 const Register& handler_reg = Gtemp;
a61af66fc99e Initial load
duke
parents:
diff changeset
376
727
6b2273dd6fa9 6822110: Add AddressLiteral class on SPARC
twisti
parents: 671
diff changeset
377 Address exception_addr(G2_thread, Thread::pending_exception_offset());
0
a61af66fc99e Initial load
duke
parents:
diff changeset
378
a61af66fc99e Initial load
duke
parents:
diff changeset
379 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
380 // make sure that this code is only executed if there is a pending exception
a61af66fc99e Initial load
duke
parents:
diff changeset
381 { Label L;
a61af66fc99e Initial load
duke
parents:
diff changeset
382 __ ld_ptr(exception_addr, Gtemp);
3839
3d42f82cd811 7063628: Use cbcond on T4
kvn
parents: 3781
diff changeset
383 __ br_notnull_short(Gtemp, Assembler::pt, L);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
384 __ stop("StubRoutines::forward exception: no pending exception (1)");
a61af66fc99e Initial load
duke
parents:
diff changeset
385 __ bind(L);
a61af66fc99e Initial load
duke
parents:
diff changeset
386 }
a61af66fc99e Initial load
duke
parents:
diff changeset
387 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
388
a61af66fc99e Initial load
duke
parents:
diff changeset
389 // compute exception handler into handler_reg
a61af66fc99e Initial load
duke
parents:
diff changeset
390 __ get_thread();
a61af66fc99e Initial load
duke
parents:
diff changeset
391 __ ld_ptr(exception_addr, Oexception);
a61af66fc99e Initial load
duke
parents:
diff changeset
392 __ verify_oop(Oexception);
a61af66fc99e Initial load
duke
parents:
diff changeset
393 __ save_frame(0); // compensates for compiler weakness
a61af66fc99e Initial load
duke
parents:
diff changeset
394 __ add(O7->after_save(), frame::pc_return_offset, Lscratch); // save the issuing PC
a61af66fc99e Initial load
duke
parents:
diff changeset
395 BLOCK_COMMENT("call exception_handler_for_return_address");
1295
3cf667df43ef 6919934: JSR 292 needs to support x86 C1
twisti
parents: 1174
diff changeset
396 __ call_VM_leaf(L7_thread_cache, CAST_FROM_FN_PTR(address, SharedRuntime::exception_handler_for_return_address), G2_thread, Lscratch);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
397 __ mov(O0, handler_reg);
a61af66fc99e Initial load
duke
parents:
diff changeset
398 __ restore(); // compensates for compiler weakness
a61af66fc99e Initial load
duke
parents:
diff changeset
399
a61af66fc99e Initial load
duke
parents:
diff changeset
400 __ ld_ptr(exception_addr, Oexception);
a61af66fc99e Initial load
duke
parents:
diff changeset
401 __ add(O7, frame::pc_return_offset, Oissuing_pc); // save the issuing PC
a61af66fc99e Initial load
duke
parents:
diff changeset
402
a61af66fc99e Initial load
duke
parents:
diff changeset
403 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
404 // make sure exception is set
a61af66fc99e Initial load
duke
parents:
diff changeset
405 { Label L;
3839
3d42f82cd811 7063628: Use cbcond on T4
kvn
parents: 3781
diff changeset
406 __ br_notnull_short(Oexception, Assembler::pt, L);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
407 __ stop("StubRoutines::forward exception: no pending exception (2)");
a61af66fc99e Initial load
duke
parents:
diff changeset
408 __ bind(L);
a61af66fc99e Initial load
duke
parents:
diff changeset
409 }
a61af66fc99e Initial load
duke
parents:
diff changeset
410 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
411 // jump to exception handler
a61af66fc99e Initial load
duke
parents:
diff changeset
412 __ jmp(handler_reg, 0);
a61af66fc99e Initial load
duke
parents:
diff changeset
413 // clear pending exception
a61af66fc99e Initial load
duke
parents:
diff changeset
414 __ delayed()->st_ptr(G0, exception_addr);
a61af66fc99e Initial load
duke
parents:
diff changeset
415
a61af66fc99e Initial load
duke
parents:
diff changeset
416 return start;
a61af66fc99e Initial load
duke
parents:
diff changeset
417 }
a61af66fc99e Initial load
duke
parents:
diff changeset
418
a61af66fc99e Initial load
duke
parents:
diff changeset
419
a61af66fc99e Initial load
duke
parents:
diff changeset
420 //------------------------------------------------------------------------------------------------------------------------
a61af66fc99e Initial load
duke
parents:
diff changeset
421 // Continuation point for throwing of implicit exceptions that are not handled in
a61af66fc99e Initial load
duke
parents:
diff changeset
422 // the current activation. Fabricates an exception oop and initiates normal
a61af66fc99e Initial load
duke
parents:
diff changeset
423 // exception dispatching in this frame. Only callee-saved registers are preserved
a61af66fc99e Initial load
duke
parents:
diff changeset
424 // (through the normal register window / RegisterMap handling).
a61af66fc99e Initial load
duke
parents:
diff changeset
425 // If the compiler needs all registers to be preserved between the fault
a61af66fc99e Initial load
duke
parents:
diff changeset
426 // point and the exception handler then it must assume responsibility for that in
a61af66fc99e Initial load
duke
parents:
diff changeset
427 // AbstractCompiler::continuation_for_implicit_null_exception or
a61af66fc99e Initial load
duke
parents:
diff changeset
428 // continuation_for_implicit_division_by_zero_exception. All other implicit
a61af66fc99e Initial load
duke
parents:
diff changeset
429 // exceptions (e.g., NullPointerException or AbstractMethodError on entry) are
a61af66fc99e Initial load
duke
parents:
diff changeset
430 // either at call sites or otherwise assume that stack unwinding will be initiated,
a61af66fc99e Initial load
duke
parents:
diff changeset
431 // so caller saved registers were assumed volatile in the compiler.
a61af66fc99e Initial load
duke
parents:
diff changeset
432
a61af66fc99e Initial load
duke
parents:
diff changeset
433 // Note that we generate only this stub into a RuntimeStub, because it needs to be
a61af66fc99e Initial load
duke
parents:
diff changeset
434 // properly traversed and ignored during GC, so we change the meaning of the "__"
a61af66fc99e Initial load
duke
parents:
diff changeset
435 // macro within this method.
a61af66fc99e Initial load
duke
parents:
diff changeset
436 #undef __
a61af66fc99e Initial load
duke
parents:
diff changeset
437 #define __ masm->
a61af66fc99e Initial load
duke
parents:
diff changeset
438
3937
c565834fb592 7088020: SEGV in JNIHandleBlock::release_block
never
parents: 3903
diff changeset
439 address generate_throw_exception(const char* name, address runtime_entry,
3781
d83ac25d0304 7055355: JSR 292: crash while throwing WrongMethodTypeException
never
parents: 2324
diff changeset
440 Register arg1 = noreg, Register arg2 = noreg) {
0
a61af66fc99e Initial load
duke
parents:
diff changeset
441 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
442 int insts_size = VerifyThread ? 1 * K : 600;
a61af66fc99e Initial load
duke
parents:
diff changeset
443 #else
a61af66fc99e Initial load
duke
parents:
diff changeset
444 int insts_size = VerifyThread ? 1 * K : 256;
a61af66fc99e Initial load
duke
parents:
diff changeset
445 #endif /* ASSERT */
a61af66fc99e Initial load
duke
parents:
diff changeset
446 int locs_size = 32;
a61af66fc99e Initial load
duke
parents:
diff changeset
447
a61af66fc99e Initial load
duke
parents:
diff changeset
448 CodeBuffer code(name, insts_size, locs_size);
a61af66fc99e Initial load
duke
parents:
diff changeset
449 MacroAssembler* masm = new MacroAssembler(&code);
a61af66fc99e Initial load
duke
parents:
diff changeset
450
a61af66fc99e Initial load
duke
parents:
diff changeset
451 __ verify_thread();
a61af66fc99e Initial load
duke
parents:
diff changeset
452
a61af66fc99e Initial load
duke
parents:
diff changeset
453 // This is an inlined and slightly modified version of call_VM
a61af66fc99e Initial load
duke
parents:
diff changeset
454 // which has the ability to fetch the return PC out of thread-local storage
a61af66fc99e Initial load
duke
parents:
diff changeset
455 __ assert_not_delayed();
a61af66fc99e Initial load
duke
parents:
diff changeset
456
a61af66fc99e Initial load
duke
parents:
diff changeset
457 // Note that we always push a frame because on the SPARC
a61af66fc99e Initial load
duke
parents:
diff changeset
458 // architecture, for all of our implicit exception kinds at call
a61af66fc99e Initial load
duke
parents:
diff changeset
459 // sites, the implicit exception is taken before the callee frame
a61af66fc99e Initial load
duke
parents:
diff changeset
460 // is pushed.
a61af66fc99e Initial load
duke
parents:
diff changeset
461 __ save_frame(0);
a61af66fc99e Initial load
duke
parents:
diff changeset
462
a61af66fc99e Initial load
duke
parents:
diff changeset
463 int frame_complete = __ offset();
a61af66fc99e Initial load
duke
parents:
diff changeset
464
a61af66fc99e Initial load
duke
parents:
diff changeset
465 // Note that we always have a runtime stub frame on the top of stack by this point
a61af66fc99e Initial load
duke
parents:
diff changeset
466 Register last_java_sp = SP;
a61af66fc99e Initial load
duke
parents:
diff changeset
467 // 64-bit last_java_sp is biased!
a61af66fc99e Initial load
duke
parents:
diff changeset
468 __ set_last_Java_frame(last_java_sp, G0);
a61af66fc99e Initial load
duke
parents:
diff changeset
469 if (VerifyThread) __ mov(G2_thread, O0); // about to be smashed; pass early
a61af66fc99e Initial load
duke
parents:
diff changeset
470 __ save_thread(noreg);
3781
d83ac25d0304 7055355: JSR 292: crash while throwing WrongMethodTypeException
never
parents: 2324
diff changeset
471 if (arg1 != noreg) {
d83ac25d0304 7055355: JSR 292: crash while throwing WrongMethodTypeException
never
parents: 2324
diff changeset
472 assert(arg2 != O1, "clobbered");
d83ac25d0304 7055355: JSR 292: crash while throwing WrongMethodTypeException
never
parents: 2324
diff changeset
473 __ mov(arg1, O1);
d83ac25d0304 7055355: JSR 292: crash while throwing WrongMethodTypeException
never
parents: 2324
diff changeset
474 }
d83ac25d0304 7055355: JSR 292: crash while throwing WrongMethodTypeException
never
parents: 2324
diff changeset
475 if (arg2 != noreg) {
d83ac25d0304 7055355: JSR 292: crash while throwing WrongMethodTypeException
never
parents: 2324
diff changeset
476 __ mov(arg2, O2);
d83ac25d0304 7055355: JSR 292: crash while throwing WrongMethodTypeException
never
parents: 2324
diff changeset
477 }
0
a61af66fc99e Initial load
duke
parents:
diff changeset
478 // do the call
a61af66fc99e Initial load
duke
parents:
diff changeset
479 BLOCK_COMMENT("call runtime_entry");
a61af66fc99e Initial load
duke
parents:
diff changeset
480 __ call(runtime_entry, relocInfo::runtime_call_type);
a61af66fc99e Initial load
duke
parents:
diff changeset
481 if (!VerifyThread)
a61af66fc99e Initial load
duke
parents:
diff changeset
482 __ delayed()->mov(G2_thread, O0); // pass thread as first argument
a61af66fc99e Initial load
duke
parents:
diff changeset
483 else
a61af66fc99e Initial load
duke
parents:
diff changeset
484 __ delayed()->nop(); // (thread already passed)
a61af66fc99e Initial load
duke
parents:
diff changeset
485 __ restore_thread(noreg);
a61af66fc99e Initial load
duke
parents:
diff changeset
486 __ reset_last_Java_frame();
a61af66fc99e Initial load
duke
parents:
diff changeset
487
a61af66fc99e Initial load
duke
parents:
diff changeset
488 // check for pending exceptions. use Gtemp as scratch register.
a61af66fc99e Initial load
duke
parents:
diff changeset
489 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
490 Label L;
a61af66fc99e Initial load
duke
parents:
diff changeset
491
727
6b2273dd6fa9 6822110: Add AddressLiteral class on SPARC
twisti
parents: 671
diff changeset
492 Address exception_addr(G2_thread, Thread::pending_exception_offset());
0
a61af66fc99e Initial load
duke
parents:
diff changeset
493 Register scratch_reg = Gtemp;
a61af66fc99e Initial load
duke
parents:
diff changeset
494 __ ld_ptr(exception_addr, scratch_reg);
3839
3d42f82cd811 7063628: Use cbcond on T4
kvn
parents: 3781
diff changeset
495 __ br_notnull_short(scratch_reg, Assembler::pt, L);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
496 __ should_not_reach_here();
a61af66fc99e Initial load
duke
parents:
diff changeset
497 __ bind(L);
a61af66fc99e Initial load
duke
parents:
diff changeset
498 #endif // ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
499 BLOCK_COMMENT("call forward_exception_entry");
a61af66fc99e Initial load
duke
parents:
diff changeset
500 __ call(StubRoutines::forward_exception_entry(), relocInfo::runtime_call_type);
a61af66fc99e Initial load
duke
parents:
diff changeset
501 // we use O7 linkage so that forward_exception_entry has the issuing PC
a61af66fc99e Initial load
duke
parents:
diff changeset
502 __ delayed()->restore();
a61af66fc99e Initial load
duke
parents:
diff changeset
503
a61af66fc99e Initial load
duke
parents:
diff changeset
504 RuntimeStub* stub = RuntimeStub::new_runtime_stub(name, &code, frame_complete, masm->total_frame_size_in_bytes(0), NULL, false);
a61af66fc99e Initial load
duke
parents:
diff changeset
505 return stub->entry_point();
a61af66fc99e Initial load
duke
parents:
diff changeset
506 }
a61af66fc99e Initial load
duke
parents:
diff changeset
507
a61af66fc99e Initial load
duke
parents:
diff changeset
508 #undef __
a61af66fc99e Initial load
duke
parents:
diff changeset
509 #define __ _masm->
a61af66fc99e Initial load
duke
parents:
diff changeset
510
a61af66fc99e Initial load
duke
parents:
diff changeset
511
a61af66fc99e Initial load
duke
parents:
diff changeset
512 // Generate a routine that sets all the registers so we
a61af66fc99e Initial load
duke
parents:
diff changeset
513 // can tell if the stop routine prints them correctly.
a61af66fc99e Initial load
duke
parents:
diff changeset
514 address generate_test_stop() {
a61af66fc99e Initial load
duke
parents:
diff changeset
515 StubCodeMark mark(this, "StubRoutines", "test_stop");
a61af66fc99e Initial load
duke
parents:
diff changeset
516 address start = __ pc();
a61af66fc99e Initial load
duke
parents:
diff changeset
517
a61af66fc99e Initial load
duke
parents:
diff changeset
518 int i;
a61af66fc99e Initial load
duke
parents:
diff changeset
519
a61af66fc99e Initial load
duke
parents:
diff changeset
520 __ save_frame(0);
a61af66fc99e Initial load
duke
parents:
diff changeset
521
a61af66fc99e Initial load
duke
parents:
diff changeset
522 static jfloat zero = 0.0, one = 1.0;
a61af66fc99e Initial load
duke
parents:
diff changeset
523
a61af66fc99e Initial load
duke
parents:
diff changeset
524 // put addr in L0, then load through L0 to F0
a61af66fc99e Initial load
duke
parents:
diff changeset
525 __ set((intptr_t)&zero, L0); __ ldf( FloatRegisterImpl::S, L0, 0, F0);
a61af66fc99e Initial load
duke
parents:
diff changeset
526 __ set((intptr_t)&one, L0); __ ldf( FloatRegisterImpl::S, L0, 0, F1); // 1.0 to F1
a61af66fc99e Initial load
duke
parents:
diff changeset
527
a61af66fc99e Initial load
duke
parents:
diff changeset
528 // use add to put 2..18 in F2..F18
a61af66fc99e Initial load
duke
parents:
diff changeset
529 for ( i = 2; i <= 18; ++i ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
530 __ fadd( FloatRegisterImpl::S, F1, as_FloatRegister(i-1), as_FloatRegister(i));
a61af66fc99e Initial load
duke
parents:
diff changeset
531 }
a61af66fc99e Initial load
duke
parents:
diff changeset
532
a61af66fc99e Initial load
duke
parents:
diff changeset
533 // Now put double 2 in F16, double 18 in F18
a61af66fc99e Initial load
duke
parents:
diff changeset
534 __ ftof( FloatRegisterImpl::S, FloatRegisterImpl::D, F2, F16 );
a61af66fc99e Initial load
duke
parents:
diff changeset
535 __ ftof( FloatRegisterImpl::S, FloatRegisterImpl::D, F18, F18 );
a61af66fc99e Initial load
duke
parents:
diff changeset
536
a61af66fc99e Initial load
duke
parents:
diff changeset
537 // use add to put 20..32 in F20..F32
a61af66fc99e Initial load
duke
parents:
diff changeset
538 for (i = 20; i < 32; i += 2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
539 __ fadd( FloatRegisterImpl::D, F16, as_FloatRegister(i-2), as_FloatRegister(i));
a61af66fc99e Initial load
duke
parents:
diff changeset
540 }
a61af66fc99e Initial load
duke
parents:
diff changeset
541
a61af66fc99e Initial load
duke
parents:
diff changeset
542 // put 0..7 in i's, 8..15 in l's, 16..23 in o's, 24..31 in g's
a61af66fc99e Initial load
duke
parents:
diff changeset
543 for ( i = 0; i < 8; ++i ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
544 if (i < 6) {
a61af66fc99e Initial load
duke
parents:
diff changeset
545 __ set( i, as_iRegister(i));
a61af66fc99e Initial load
duke
parents:
diff changeset
546 __ set(16 + i, as_oRegister(i));
a61af66fc99e Initial load
duke
parents:
diff changeset
547 __ set(24 + i, as_gRegister(i));
a61af66fc99e Initial load
duke
parents:
diff changeset
548 }
a61af66fc99e Initial load
duke
parents:
diff changeset
549 __ set( 8 + i, as_lRegister(i));
a61af66fc99e Initial load
duke
parents:
diff changeset
550 }
a61af66fc99e Initial load
duke
parents:
diff changeset
551
a61af66fc99e Initial load
duke
parents:
diff changeset
552 __ stop("testing stop");
a61af66fc99e Initial load
duke
parents:
diff changeset
553
a61af66fc99e Initial load
duke
parents:
diff changeset
554
a61af66fc99e Initial load
duke
parents:
diff changeset
555 __ ret();
a61af66fc99e Initial load
duke
parents:
diff changeset
556 __ delayed()->restore();
a61af66fc99e Initial load
duke
parents:
diff changeset
557
a61af66fc99e Initial load
duke
parents:
diff changeset
558 return start;
a61af66fc99e Initial load
duke
parents:
diff changeset
559 }
a61af66fc99e Initial load
duke
parents:
diff changeset
560
a61af66fc99e Initial load
duke
parents:
diff changeset
561
a61af66fc99e Initial load
duke
parents:
diff changeset
562 address generate_stop_subroutine() {
a61af66fc99e Initial load
duke
parents:
diff changeset
563 StubCodeMark mark(this, "StubRoutines", "stop_subroutine");
a61af66fc99e Initial load
duke
parents:
diff changeset
564 address start = __ pc();
a61af66fc99e Initial load
duke
parents:
diff changeset
565
a61af66fc99e Initial load
duke
parents:
diff changeset
566 __ stop_subroutine();
a61af66fc99e Initial load
duke
parents:
diff changeset
567
a61af66fc99e Initial load
duke
parents:
diff changeset
568 return start;
a61af66fc99e Initial load
duke
parents:
diff changeset
569 }
a61af66fc99e Initial load
duke
parents:
diff changeset
570
a61af66fc99e Initial load
duke
parents:
diff changeset
571 address generate_flush_callers_register_windows() {
a61af66fc99e Initial load
duke
parents:
diff changeset
572 StubCodeMark mark(this, "StubRoutines", "flush_callers_register_windows");
a61af66fc99e Initial load
duke
parents:
diff changeset
573 address start = __ pc();
a61af66fc99e Initial load
duke
parents:
diff changeset
574
a61af66fc99e Initial load
duke
parents:
diff changeset
575 __ flush_windows();
a61af66fc99e Initial load
duke
parents:
diff changeset
576 __ retl(false);
a61af66fc99e Initial load
duke
parents:
diff changeset
577 __ delayed()->add( FP, STACK_BIAS, O0 );
a61af66fc99e Initial load
duke
parents:
diff changeset
578 // The returned value must be a stack pointer whose register save area
a61af66fc99e Initial load
duke
parents:
diff changeset
579 // is flushed, and will stay flushed while the caller executes.
a61af66fc99e Initial load
duke
parents:
diff changeset
580
a61af66fc99e Initial load
duke
parents:
diff changeset
581 return start;
a61af66fc99e Initial load
duke
parents:
diff changeset
582 }
a61af66fc99e Initial load
duke
parents:
diff changeset
583
a61af66fc99e Initial load
duke
parents:
diff changeset
584 // Helper functions for v8 atomic operations.
a61af66fc99e Initial load
duke
parents:
diff changeset
585 //
a61af66fc99e Initial load
duke
parents:
diff changeset
586 void get_v8_oop_lock_ptr(Register lock_ptr_reg, Register mark_oop_reg, Register scratch_reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
587 if (mark_oop_reg == noreg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
588 address lock_ptr = (address)StubRoutines::Sparc::atomic_memory_operation_lock_addr();
a61af66fc99e Initial load
duke
parents:
diff changeset
589 __ set((intptr_t)lock_ptr, lock_ptr_reg);
a61af66fc99e Initial load
duke
parents:
diff changeset
590 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
591 assert(scratch_reg != noreg, "just checking");
a61af66fc99e Initial load
duke
parents:
diff changeset
592 address lock_ptr = (address)StubRoutines::Sparc::_v8_oop_lock_cache;
a61af66fc99e Initial load
duke
parents:
diff changeset
593 __ set((intptr_t)lock_ptr, lock_ptr_reg);
a61af66fc99e Initial load
duke
parents:
diff changeset
594 __ and3(mark_oop_reg, StubRoutines::Sparc::v8_oop_lock_mask_in_place, scratch_reg);
a61af66fc99e Initial load
duke
parents:
diff changeset
595 __ add(lock_ptr_reg, scratch_reg, lock_ptr_reg);
a61af66fc99e Initial load
duke
parents:
diff changeset
596 }
a61af66fc99e Initial load
duke
parents:
diff changeset
597 }
a61af66fc99e Initial load
duke
parents:
diff changeset
598
a61af66fc99e Initial load
duke
parents:
diff changeset
599 void generate_v8_lock_prologue(Register lock_reg, Register lock_ptr_reg, Register yield_reg, Label& retry, Label& dontyield, Register mark_oop_reg = noreg, Register scratch_reg = noreg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
600
a61af66fc99e Initial load
duke
parents:
diff changeset
601 get_v8_oop_lock_ptr(lock_ptr_reg, mark_oop_reg, scratch_reg);
a61af66fc99e Initial load
duke
parents:
diff changeset
602 __ set(StubRoutines::Sparc::locked, lock_reg);
a61af66fc99e Initial load
duke
parents:
diff changeset
603 // Initialize yield counter
a61af66fc99e Initial load
duke
parents:
diff changeset
604 __ mov(G0,yield_reg);
a61af66fc99e Initial load
duke
parents:
diff changeset
605
a61af66fc99e Initial load
duke
parents:
diff changeset
606 __ BIND(retry);
3839
3d42f82cd811 7063628: Use cbcond on T4
kvn
parents: 3781
diff changeset
607 __ cmp_and_br_short(yield_reg, V8AtomicOperationUnderLockSpinCount, Assembler::less, Assembler::pt, dontyield);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
608
a61af66fc99e Initial load
duke
parents:
diff changeset
609 // This code can only be called from inside the VM, this
a61af66fc99e Initial load
duke
parents:
diff changeset
610 // stub is only invoked from Atomic::add(). We do not
a61af66fc99e Initial load
duke
parents:
diff changeset
611 // want to use call_VM, because _last_java_sp and such
a61af66fc99e Initial load
duke
parents:
diff changeset
612 // must already be set.
a61af66fc99e Initial load
duke
parents:
diff changeset
613 //
a61af66fc99e Initial load
duke
parents:
diff changeset
614 // Save the regs and make space for a C call
a61af66fc99e Initial load
duke
parents:
diff changeset
615 __ save(SP, -96, SP);
a61af66fc99e Initial load
duke
parents:
diff changeset
616 __ save_all_globals_into_locals();
a61af66fc99e Initial load
duke
parents:
diff changeset
617 BLOCK_COMMENT("call os::naked_sleep");
a61af66fc99e Initial load
duke
parents:
diff changeset
618 __ call(CAST_FROM_FN_PTR(address, os::naked_sleep));
a61af66fc99e Initial load
duke
parents:
diff changeset
619 __ delayed()->nop();
a61af66fc99e Initial load
duke
parents:
diff changeset
620 __ restore_globals_from_locals();
a61af66fc99e Initial load
duke
parents:
diff changeset
621 __ restore();
a61af66fc99e Initial load
duke
parents:
diff changeset
622 // reset the counter
a61af66fc99e Initial load
duke
parents:
diff changeset
623 __ mov(G0,yield_reg);
a61af66fc99e Initial load
duke
parents:
diff changeset
624
a61af66fc99e Initial load
duke
parents:
diff changeset
625 __ BIND(dontyield);
a61af66fc99e Initial load
duke
parents:
diff changeset
626
a61af66fc99e Initial load
duke
parents:
diff changeset
627 // try to get lock
a61af66fc99e Initial load
duke
parents:
diff changeset
628 __ swap(lock_ptr_reg, 0, lock_reg);
a61af66fc99e Initial load
duke
parents:
diff changeset
629
a61af66fc99e Initial load
duke
parents:
diff changeset
630 // did we get the lock?
a61af66fc99e Initial load
duke
parents:
diff changeset
631 __ cmp(lock_reg, StubRoutines::Sparc::unlocked);
a61af66fc99e Initial load
duke
parents:
diff changeset
632 __ br(Assembler::notEqual, true, Assembler::pn, retry);
a61af66fc99e Initial load
duke
parents:
diff changeset
633 __ delayed()->add(yield_reg,1,yield_reg);
a61af66fc99e Initial load
duke
parents:
diff changeset
634
a61af66fc99e Initial load
duke
parents:
diff changeset
635 // yes, got lock. do the operation here.
a61af66fc99e Initial load
duke
parents:
diff changeset
636 }
a61af66fc99e Initial load
duke
parents:
diff changeset
637
a61af66fc99e Initial load
duke
parents:
diff changeset
638 void generate_v8_lock_epilogue(Register lock_reg, Register lock_ptr_reg, Register yield_reg, Label& retry, Label& dontyield, Register mark_oop_reg = noreg, Register scratch_reg = noreg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
639 __ st(lock_reg, lock_ptr_reg, 0); // unlock
a61af66fc99e Initial load
duke
parents:
diff changeset
640 }
a61af66fc99e Initial load
duke
parents:
diff changeset
641
a61af66fc99e Initial load
duke
parents:
diff changeset
642 // Support for jint Atomic::xchg(jint exchange_value, volatile jint* dest).
a61af66fc99e Initial load
duke
parents:
diff changeset
643 //
a61af66fc99e Initial load
duke
parents:
diff changeset
644 // Arguments :
a61af66fc99e Initial load
duke
parents:
diff changeset
645 //
a61af66fc99e Initial load
duke
parents:
diff changeset
646 // exchange_value: O0
a61af66fc99e Initial load
duke
parents:
diff changeset
647 // dest: O1
a61af66fc99e Initial load
duke
parents:
diff changeset
648 //
a61af66fc99e Initial load
duke
parents:
diff changeset
649 // Results:
a61af66fc99e Initial load
duke
parents:
diff changeset
650 //
a61af66fc99e Initial load
duke
parents:
diff changeset
651 // O0: the value previously stored in dest
a61af66fc99e Initial load
duke
parents:
diff changeset
652 //
a61af66fc99e Initial load
duke
parents:
diff changeset
653 address generate_atomic_xchg() {
a61af66fc99e Initial load
duke
parents:
diff changeset
654 StubCodeMark mark(this, "StubRoutines", "atomic_xchg");
a61af66fc99e Initial load
duke
parents:
diff changeset
655 address start = __ pc();
a61af66fc99e Initial load
duke
parents:
diff changeset
656
a61af66fc99e Initial load
duke
parents:
diff changeset
657 if (UseCASForSwap) {
a61af66fc99e Initial load
duke
parents:
diff changeset
658 // Use CAS instead of swap, just in case the MP hardware
a61af66fc99e Initial load
duke
parents:
diff changeset
659 // prefers to work with just one kind of synch. instruction.
a61af66fc99e Initial load
duke
parents:
diff changeset
660 Label retry;
a61af66fc99e Initial load
duke
parents:
diff changeset
661 __ BIND(retry);
a61af66fc99e Initial load
duke
parents:
diff changeset
662 __ mov(O0, O3); // scratch copy of exchange value
a61af66fc99e Initial load
duke
parents:
diff changeset
663 __ ld(O1, 0, O2); // observe the previous value
a61af66fc99e Initial load
duke
parents:
diff changeset
664 // try to replace O2 with O3
a61af66fc99e Initial load
duke
parents:
diff changeset
665 __ cas_under_lock(O1, O2, O3,
a61af66fc99e Initial load
duke
parents:
diff changeset
666 (address)StubRoutines::Sparc::atomic_memory_operation_lock_addr(),false);
3839
3d42f82cd811 7063628: Use cbcond on T4
kvn
parents: 3781
diff changeset
667 __ cmp_and_br_short(O2, O3, Assembler::notEqual, Assembler::pn, retry);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
668
a61af66fc99e Initial load
duke
parents:
diff changeset
669 __ retl(false);
a61af66fc99e Initial load
duke
parents:
diff changeset
670 __ delayed()->mov(O2, O0); // report previous value to caller
a61af66fc99e Initial load
duke
parents:
diff changeset
671
a61af66fc99e Initial load
duke
parents:
diff changeset
672 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
673 if (VM_Version::v9_instructions_work()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
674 __ retl(false);
a61af66fc99e Initial load
duke
parents:
diff changeset
675 __ delayed()->swap(O1, 0, O0);
a61af66fc99e Initial load
duke
parents:
diff changeset
676 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
677 const Register& lock_reg = O2;
a61af66fc99e Initial load
duke
parents:
diff changeset
678 const Register& lock_ptr_reg = O3;
a61af66fc99e Initial load
duke
parents:
diff changeset
679 const Register& yield_reg = O4;
a61af66fc99e Initial load
duke
parents:
diff changeset
680
a61af66fc99e Initial load
duke
parents:
diff changeset
681 Label retry;
a61af66fc99e Initial load
duke
parents:
diff changeset
682 Label dontyield;
a61af66fc99e Initial load
duke
parents:
diff changeset
683
a61af66fc99e Initial load
duke
parents:
diff changeset
684 generate_v8_lock_prologue(lock_reg, lock_ptr_reg, yield_reg, retry, dontyield);
a61af66fc99e Initial load
duke
parents:
diff changeset
685 // got the lock, do the swap
a61af66fc99e Initial load
duke
parents:
diff changeset
686 __ swap(O1, 0, O0);
a61af66fc99e Initial load
duke
parents:
diff changeset
687
a61af66fc99e Initial load
duke
parents:
diff changeset
688 generate_v8_lock_epilogue(lock_reg, lock_ptr_reg, yield_reg, retry, dontyield);
a61af66fc99e Initial load
duke
parents:
diff changeset
689 __ retl(false);
a61af66fc99e Initial load
duke
parents:
diff changeset
690 __ delayed()->nop();
a61af66fc99e Initial load
duke
parents:
diff changeset
691 }
a61af66fc99e Initial load
duke
parents:
diff changeset
692 }
a61af66fc99e Initial load
duke
parents:
diff changeset
693
a61af66fc99e Initial load
duke
parents:
diff changeset
694 return start;
a61af66fc99e Initial load
duke
parents:
diff changeset
695 }
a61af66fc99e Initial load
duke
parents:
diff changeset
696
a61af66fc99e Initial load
duke
parents:
diff changeset
697
a61af66fc99e Initial load
duke
parents:
diff changeset
698 // Support for jint Atomic::cmpxchg(jint exchange_value, volatile jint* dest, jint compare_value)
a61af66fc99e Initial load
duke
parents:
diff changeset
699 //
a61af66fc99e Initial load
duke
parents:
diff changeset
700 // Arguments :
a61af66fc99e Initial load
duke
parents:
diff changeset
701 //
a61af66fc99e Initial load
duke
parents:
diff changeset
702 // exchange_value: O0
a61af66fc99e Initial load
duke
parents:
diff changeset
703 // dest: O1
a61af66fc99e Initial load
duke
parents:
diff changeset
704 // compare_value: O2
a61af66fc99e Initial load
duke
parents:
diff changeset
705 //
a61af66fc99e Initial load
duke
parents:
diff changeset
706 // Results:
a61af66fc99e Initial load
duke
parents:
diff changeset
707 //
a61af66fc99e Initial load
duke
parents:
diff changeset
708 // O0: the value previously stored in dest
a61af66fc99e Initial load
duke
parents:
diff changeset
709 //
a61af66fc99e Initial load
duke
parents:
diff changeset
710 // Overwrites (v8): O3,O4,O5
a61af66fc99e Initial load
duke
parents:
diff changeset
711 //
a61af66fc99e Initial load
duke
parents:
diff changeset
712 address generate_atomic_cmpxchg() {
a61af66fc99e Initial load
duke
parents:
diff changeset
713 StubCodeMark mark(this, "StubRoutines", "atomic_cmpxchg");
a61af66fc99e Initial load
duke
parents:
diff changeset
714 address start = __ pc();
a61af66fc99e Initial load
duke
parents:
diff changeset
715
a61af66fc99e Initial load
duke
parents:
diff changeset
716 // cmpxchg(dest, compare_value, exchange_value)
a61af66fc99e Initial load
duke
parents:
diff changeset
717 __ cas_under_lock(O1, O2, O0,
a61af66fc99e Initial load
duke
parents:
diff changeset
718 (address)StubRoutines::Sparc::atomic_memory_operation_lock_addr(),false);
a61af66fc99e Initial load
duke
parents:
diff changeset
719 __ retl(false);
a61af66fc99e Initial load
duke
parents:
diff changeset
720 __ delayed()->nop();
a61af66fc99e Initial load
duke
parents:
diff changeset
721
a61af66fc99e Initial load
duke
parents:
diff changeset
722 return start;
a61af66fc99e Initial load
duke
parents:
diff changeset
723 }
a61af66fc99e Initial load
duke
parents:
diff changeset
724
a61af66fc99e Initial load
duke
parents:
diff changeset
725 // Support for jlong Atomic::cmpxchg(jlong exchange_value, volatile jlong *dest, jlong compare_value)
a61af66fc99e Initial load
duke
parents:
diff changeset
726 //
a61af66fc99e Initial load
duke
parents:
diff changeset
727 // Arguments :
a61af66fc99e Initial load
duke
parents:
diff changeset
728 //
a61af66fc99e Initial load
duke
parents:
diff changeset
729 // exchange_value: O1:O0
a61af66fc99e Initial load
duke
parents:
diff changeset
730 // dest: O2
a61af66fc99e Initial load
duke
parents:
diff changeset
731 // compare_value: O4:O3
a61af66fc99e Initial load
duke
parents:
diff changeset
732 //
a61af66fc99e Initial load
duke
parents:
diff changeset
733 // Results:
a61af66fc99e Initial load
duke
parents:
diff changeset
734 //
a61af66fc99e Initial load
duke
parents:
diff changeset
735 // O1:O0: the value previously stored in dest
a61af66fc99e Initial load
duke
parents:
diff changeset
736 //
a61af66fc99e Initial load
duke
parents:
diff changeset
737 // This only works on V9, on V8 we don't generate any
a61af66fc99e Initial load
duke
parents:
diff changeset
738 // code and just return NULL.
a61af66fc99e Initial load
duke
parents:
diff changeset
739 //
a61af66fc99e Initial load
duke
parents:
diff changeset
740 // Overwrites: G1,G2,G3
a61af66fc99e Initial load
duke
parents:
diff changeset
741 //
a61af66fc99e Initial load
duke
parents:
diff changeset
742 address generate_atomic_cmpxchg_long() {
a61af66fc99e Initial load
duke
parents:
diff changeset
743 StubCodeMark mark(this, "StubRoutines", "atomic_cmpxchg_long");
a61af66fc99e Initial load
duke
parents:
diff changeset
744 address start = __ pc();
a61af66fc99e Initial load
duke
parents:
diff changeset
745
a61af66fc99e Initial load
duke
parents:
diff changeset
746 if (!VM_Version::supports_cx8())
a61af66fc99e Initial load
duke
parents:
diff changeset
747 return NULL;;
a61af66fc99e Initial load
duke
parents:
diff changeset
748 __ sllx(O0, 32, O0);
a61af66fc99e Initial load
duke
parents:
diff changeset
749 __ srl(O1, 0, O1);
a61af66fc99e Initial load
duke
parents:
diff changeset
750 __ or3(O0,O1,O0); // O0 holds 64-bit value from compare_value
a61af66fc99e Initial load
duke
parents:
diff changeset
751 __ sllx(O3, 32, O3);
a61af66fc99e Initial load
duke
parents:
diff changeset
752 __ srl(O4, 0, O4);
a61af66fc99e Initial load
duke
parents:
diff changeset
753 __ or3(O3,O4,O3); // O3 holds 64-bit value from exchange_value
a61af66fc99e Initial load
duke
parents:
diff changeset
754 __ casx(O2, O3, O0);
a61af66fc99e Initial load
duke
parents:
diff changeset
755 __ srl(O0, 0, O1); // unpacked return value in O1:O0
a61af66fc99e Initial load
duke
parents:
diff changeset
756 __ retl(false);
a61af66fc99e Initial load
duke
parents:
diff changeset
757 __ delayed()->srlx(O0, 32, O0);
a61af66fc99e Initial load
duke
parents:
diff changeset
758
a61af66fc99e Initial load
duke
parents:
diff changeset
759 return start;
a61af66fc99e Initial load
duke
parents:
diff changeset
760 }
a61af66fc99e Initial load
duke
parents:
diff changeset
761
a61af66fc99e Initial load
duke
parents:
diff changeset
762
a61af66fc99e Initial load
duke
parents:
diff changeset
763 // Support for jint Atomic::add(jint add_value, volatile jint* dest).
a61af66fc99e Initial load
duke
parents:
diff changeset
764 //
a61af66fc99e Initial load
duke
parents:
diff changeset
765 // Arguments :
a61af66fc99e Initial load
duke
parents:
diff changeset
766 //
a61af66fc99e Initial load
duke
parents:
diff changeset
767 // add_value: O0 (e.g., +1 or -1)
a61af66fc99e Initial load
duke
parents:
diff changeset
768 // dest: O1
a61af66fc99e Initial load
duke
parents:
diff changeset
769 //
a61af66fc99e Initial load
duke
parents:
diff changeset
770 // Results:
a61af66fc99e Initial load
duke
parents:
diff changeset
771 //
a61af66fc99e Initial load
duke
parents:
diff changeset
772 // O0: the new value stored in dest
a61af66fc99e Initial load
duke
parents:
diff changeset
773 //
a61af66fc99e Initial load
duke
parents:
diff changeset
774 // Overwrites (v9): O3
a61af66fc99e Initial load
duke
parents:
diff changeset
775 // Overwrites (v8): O3,O4,O5
a61af66fc99e Initial load
duke
parents:
diff changeset
776 //
a61af66fc99e Initial load
duke
parents:
diff changeset
777 address generate_atomic_add() {
a61af66fc99e Initial load
duke
parents:
diff changeset
778 StubCodeMark mark(this, "StubRoutines", "atomic_add");
a61af66fc99e Initial load
duke
parents:
diff changeset
779 address start = __ pc();
a61af66fc99e Initial load
duke
parents:
diff changeset
780 __ BIND(_atomic_add_stub);
a61af66fc99e Initial load
duke
parents:
diff changeset
781
a61af66fc99e Initial load
duke
parents:
diff changeset
782 if (VM_Version::v9_instructions_work()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
783 Label(retry);
a61af66fc99e Initial load
duke
parents:
diff changeset
784 __ BIND(retry);
a61af66fc99e Initial load
duke
parents:
diff changeset
785
a61af66fc99e Initial load
duke
parents:
diff changeset
786 __ lduw(O1, 0, O2);
3839
3d42f82cd811 7063628: Use cbcond on T4
kvn
parents: 3781
diff changeset
787 __ add(O0, O2, O3);
3d42f82cd811 7063628: Use cbcond on T4
kvn
parents: 3781
diff changeset
788 __ cas(O1, O2, O3);
3d42f82cd811 7063628: Use cbcond on T4
kvn
parents: 3781
diff changeset
789 __ cmp_and_br_short(O2, O3, Assembler::notEqual, Assembler::pn, retry);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
790 __ retl(false);
a61af66fc99e Initial load
duke
parents:
diff changeset
791 __ delayed()->add(O0, O2, O0); // note that cas made O2==O3
a61af66fc99e Initial load
duke
parents:
diff changeset
792 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
793 const Register& lock_reg = O2;
a61af66fc99e Initial load
duke
parents:
diff changeset
794 const Register& lock_ptr_reg = O3;
a61af66fc99e Initial load
duke
parents:
diff changeset
795 const Register& value_reg = O4;
a61af66fc99e Initial load
duke
parents:
diff changeset
796 const Register& yield_reg = O5;
a61af66fc99e Initial load
duke
parents:
diff changeset
797
a61af66fc99e Initial load
duke
parents:
diff changeset
798 Label(retry);
a61af66fc99e Initial load
duke
parents:
diff changeset
799 Label(dontyield);
a61af66fc99e Initial load
duke
parents:
diff changeset
800
a61af66fc99e Initial load
duke
parents:
diff changeset
801 generate_v8_lock_prologue(lock_reg, lock_ptr_reg, yield_reg, retry, dontyield);
a61af66fc99e Initial load
duke
parents:
diff changeset
802 // got lock, do the increment
a61af66fc99e Initial load
duke
parents:
diff changeset
803 __ ld(O1, 0, value_reg);
a61af66fc99e Initial load
duke
parents:
diff changeset
804 __ add(O0, value_reg, value_reg);
a61af66fc99e Initial load
duke
parents:
diff changeset
805 __ st(value_reg, O1, 0);
a61af66fc99e Initial load
duke
parents:
diff changeset
806
a61af66fc99e Initial load
duke
parents:
diff changeset
807 // %%% only for RMO and PSO
a61af66fc99e Initial load
duke
parents:
diff changeset
808 __ membar(Assembler::StoreStore);
a61af66fc99e Initial load
duke
parents:
diff changeset
809
a61af66fc99e Initial load
duke
parents:
diff changeset
810 generate_v8_lock_epilogue(lock_reg, lock_ptr_reg, yield_reg, retry, dontyield);
a61af66fc99e Initial load
duke
parents:
diff changeset
811
a61af66fc99e Initial load
duke
parents:
diff changeset
812 __ retl(false);
a61af66fc99e Initial load
duke
parents:
diff changeset
813 __ delayed()->mov(value_reg, O0);
a61af66fc99e Initial load
duke
parents:
diff changeset
814 }
a61af66fc99e Initial load
duke
parents:
diff changeset
815
a61af66fc99e Initial load
duke
parents:
diff changeset
816 return start;
a61af66fc99e Initial load
duke
parents:
diff changeset
817 }
a61af66fc99e Initial load
duke
parents:
diff changeset
818 Label _atomic_add_stub; // called from other stubs
a61af66fc99e Initial load
duke
parents:
diff changeset
819
a61af66fc99e Initial load
duke
parents:
diff changeset
820
a61af66fc99e Initial load
duke
parents:
diff changeset
821 //------------------------------------------------------------------------------------------------------------------------
a61af66fc99e Initial load
duke
parents:
diff changeset
822 // The following routine generates a subroutine to throw an asynchronous
a61af66fc99e Initial load
duke
parents:
diff changeset
823 // UnknownError when an unsafe access gets a fault that could not be
a61af66fc99e Initial load
duke
parents:
diff changeset
824 // reasonably prevented by the programmer. (Example: SIGBUS/OBJERR.)
a61af66fc99e Initial load
duke
parents:
diff changeset
825 //
a61af66fc99e Initial load
duke
parents:
diff changeset
826 // Arguments :
a61af66fc99e Initial load
duke
parents:
diff changeset
827 //
a61af66fc99e Initial load
duke
parents:
diff changeset
828 // trapping PC: O7
a61af66fc99e Initial load
duke
parents:
diff changeset
829 //
a61af66fc99e Initial load
duke
parents:
diff changeset
830 // Results:
a61af66fc99e Initial load
duke
parents:
diff changeset
831 // posts an asynchronous exception, skips the trapping instruction
a61af66fc99e Initial load
duke
parents:
diff changeset
832 //
a61af66fc99e Initial load
duke
parents:
diff changeset
833
a61af66fc99e Initial load
duke
parents:
diff changeset
834 address generate_handler_for_unsafe_access() {
a61af66fc99e Initial load
duke
parents:
diff changeset
835 StubCodeMark mark(this, "StubRoutines", "handler_for_unsafe_access");
a61af66fc99e Initial load
duke
parents:
diff changeset
836 address start = __ pc();
a61af66fc99e Initial load
duke
parents:
diff changeset
837
a61af66fc99e Initial load
duke
parents:
diff changeset
838 const int preserve_register_words = (64 * 2);
727
6b2273dd6fa9 6822110: Add AddressLiteral class on SPARC
twisti
parents: 671
diff changeset
839 Address preserve_addr(FP, (-preserve_register_words * wordSize) + STACK_BIAS);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
840
a61af66fc99e Initial load
duke
parents:
diff changeset
841 Register Lthread = L7_thread_cache;
a61af66fc99e Initial load
duke
parents:
diff changeset
842 int i;
a61af66fc99e Initial load
duke
parents:
diff changeset
843
a61af66fc99e Initial load
duke
parents:
diff changeset
844 __ save_frame(0);
a61af66fc99e Initial load
duke
parents:
diff changeset
845 __ mov(G1, L1);
a61af66fc99e Initial load
duke
parents:
diff changeset
846 __ mov(G2, L2);
a61af66fc99e Initial load
duke
parents:
diff changeset
847 __ mov(G3, L3);
a61af66fc99e Initial load
duke
parents:
diff changeset
848 __ mov(G4, L4);
a61af66fc99e Initial load
duke
parents:
diff changeset
849 __ mov(G5, L5);
a61af66fc99e Initial load
duke
parents:
diff changeset
850 for (i = 0; i < (VM_Version::v9_instructions_work() ? 64 : 32); i += 2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
851 __ stf(FloatRegisterImpl::D, as_FloatRegister(i), preserve_addr, i * wordSize);
a61af66fc99e Initial load
duke
parents:
diff changeset
852 }
a61af66fc99e Initial load
duke
parents:
diff changeset
853
a61af66fc99e Initial load
duke
parents:
diff changeset
854 address entry_point = CAST_FROM_FN_PTR(address, handle_unsafe_access);
a61af66fc99e Initial load
duke
parents:
diff changeset
855 BLOCK_COMMENT("call handle_unsafe_access");
a61af66fc99e Initial load
duke
parents:
diff changeset
856 __ call(entry_point, relocInfo::runtime_call_type);
a61af66fc99e Initial load
duke
parents:
diff changeset
857 __ delayed()->nop();
a61af66fc99e Initial load
duke
parents:
diff changeset
858
a61af66fc99e Initial load
duke
parents:
diff changeset
859 __ mov(L1, G1);
a61af66fc99e Initial load
duke
parents:
diff changeset
860 __ mov(L2, G2);
a61af66fc99e Initial load
duke
parents:
diff changeset
861 __ mov(L3, G3);
a61af66fc99e Initial load
duke
parents:
diff changeset
862 __ mov(L4, G4);
a61af66fc99e Initial load
duke
parents:
diff changeset
863 __ mov(L5, G5);
a61af66fc99e Initial load
duke
parents:
diff changeset
864 for (i = 0; i < (VM_Version::v9_instructions_work() ? 64 : 32); i += 2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
865 __ ldf(FloatRegisterImpl::D, preserve_addr, as_FloatRegister(i), i * wordSize);
a61af66fc99e Initial load
duke
parents:
diff changeset
866 }
a61af66fc99e Initial load
duke
parents:
diff changeset
867
a61af66fc99e Initial load
duke
parents:
diff changeset
868 __ verify_thread();
a61af66fc99e Initial load
duke
parents:
diff changeset
869
a61af66fc99e Initial load
duke
parents:
diff changeset
870 __ jmp(O0, 0);
a61af66fc99e Initial load
duke
parents:
diff changeset
871 __ delayed()->restore();
a61af66fc99e Initial load
duke
parents:
diff changeset
872
a61af66fc99e Initial load
duke
parents:
diff changeset
873 return start;
a61af66fc99e Initial load
duke
parents:
diff changeset
874 }
a61af66fc99e Initial load
duke
parents:
diff changeset
875
a61af66fc99e Initial load
duke
parents:
diff changeset
876
a61af66fc99e Initial load
duke
parents:
diff changeset
877 // Support for uint StubRoutine::Sparc::partial_subtype_check( Klass sub, Klass super );
a61af66fc99e Initial load
duke
parents:
diff changeset
878 // Arguments :
a61af66fc99e Initial load
duke
parents:
diff changeset
879 //
a61af66fc99e Initial load
duke
parents:
diff changeset
880 // ret : O0, returned
a61af66fc99e Initial load
duke
parents:
diff changeset
881 // icc/xcc: set as O0 (depending on wordSize)
a61af66fc99e Initial load
duke
parents:
diff changeset
882 // sub : O1, argument, not changed
a61af66fc99e Initial load
duke
parents:
diff changeset
883 // super: O2, argument, not changed
a61af66fc99e Initial load
duke
parents:
diff changeset
884 // raddr: O7, blown by call
a61af66fc99e Initial load
duke
parents:
diff changeset
885 address generate_partial_subtype_check() {
113
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 16
diff changeset
886 __ align(CodeEntryAlignment);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
887 StubCodeMark mark(this, "StubRoutines", "partial_subtype_check");
a61af66fc99e Initial load
duke
parents:
diff changeset
888 address start = __ pc();
644
c517646eef23 6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents: 642
diff changeset
889 Label miss;
0
a61af66fc99e Initial load
duke
parents:
diff changeset
890
a61af66fc99e Initial load
duke
parents:
diff changeset
891 #if defined(COMPILER2) && !defined(_LP64)
a61af66fc99e Initial load
duke
parents:
diff changeset
892 // Do not use a 'save' because it blows the 64-bit O registers.
113
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 16
diff changeset
893 __ add(SP,-4*wordSize,SP); // Make space for 4 temps (stack must be 2 words aligned)
0
a61af66fc99e Initial load
duke
parents:
diff changeset
894 __ st_ptr(L0,SP,(frame::register_save_words+0)*wordSize);
a61af66fc99e Initial load
duke
parents:
diff changeset
895 __ st_ptr(L1,SP,(frame::register_save_words+1)*wordSize);
a61af66fc99e Initial load
duke
parents:
diff changeset
896 __ st_ptr(L2,SP,(frame::register_save_words+2)*wordSize);
a61af66fc99e Initial load
duke
parents:
diff changeset
897 __ st_ptr(L3,SP,(frame::register_save_words+3)*wordSize);
a61af66fc99e Initial load
duke
parents:
diff changeset
898 Register Rret = O0;
a61af66fc99e Initial load
duke
parents:
diff changeset
899 Register Rsub = O1;
a61af66fc99e Initial load
duke
parents:
diff changeset
900 Register Rsuper = O2;
a61af66fc99e Initial load
duke
parents:
diff changeset
901 #else
a61af66fc99e Initial load
duke
parents:
diff changeset
902 __ save_frame(0);
a61af66fc99e Initial load
duke
parents:
diff changeset
903 Register Rret = I0;
a61af66fc99e Initial load
duke
parents:
diff changeset
904 Register Rsub = I1;
a61af66fc99e Initial load
duke
parents:
diff changeset
905 Register Rsuper = I2;
a61af66fc99e Initial load
duke
parents:
diff changeset
906 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
907
a61af66fc99e Initial load
duke
parents:
diff changeset
908 Register L0_ary_len = L0;
a61af66fc99e Initial load
duke
parents:
diff changeset
909 Register L1_ary_ptr = L1;
a61af66fc99e Initial load
duke
parents:
diff changeset
910 Register L2_super = L2;
a61af66fc99e Initial load
duke
parents:
diff changeset
911 Register L3_index = L3;
a61af66fc99e Initial load
duke
parents:
diff changeset
912
644
c517646eef23 6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents: 642
diff changeset
913 __ check_klass_subtype_slow_path(Rsub, Rsuper,
c517646eef23 6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents: 642
diff changeset
914 L0, L1, L2, L3,
c517646eef23 6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents: 642
diff changeset
915 NULL, &miss);
c517646eef23 6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents: 642
diff changeset
916
c517646eef23 6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents: 642
diff changeset
917 // Match falls through here.
c517646eef23 6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents: 642
diff changeset
918 __ addcc(G0,0,Rret); // set Z flags, Z result
0
a61af66fc99e Initial load
duke
parents:
diff changeset
919
a61af66fc99e Initial load
duke
parents:
diff changeset
920 #if defined(COMPILER2) && !defined(_LP64)
a61af66fc99e Initial load
duke
parents:
diff changeset
921 __ ld_ptr(SP,(frame::register_save_words+0)*wordSize,L0);
a61af66fc99e Initial load
duke
parents:
diff changeset
922 __ ld_ptr(SP,(frame::register_save_words+1)*wordSize,L1);
a61af66fc99e Initial load
duke
parents:
diff changeset
923 __ ld_ptr(SP,(frame::register_save_words+2)*wordSize,L2);
a61af66fc99e Initial load
duke
parents:
diff changeset
924 __ ld_ptr(SP,(frame::register_save_words+3)*wordSize,L3);
a61af66fc99e Initial load
duke
parents:
diff changeset
925 __ retl(); // Result in Rret is zero; flags set to Z
a61af66fc99e Initial load
duke
parents:
diff changeset
926 __ delayed()->add(SP,4*wordSize,SP);
a61af66fc99e Initial load
duke
parents:
diff changeset
927 #else
a61af66fc99e Initial load
duke
parents:
diff changeset
928 __ ret(); // Result in Rret is zero; flags set to Z
a61af66fc99e Initial load
duke
parents:
diff changeset
929 __ delayed()->restore();
a61af66fc99e Initial load
duke
parents:
diff changeset
930 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
931
a61af66fc99e Initial load
duke
parents:
diff changeset
932 __ BIND(miss);
a61af66fc99e Initial load
duke
parents:
diff changeset
933 __ addcc(G0,1,Rret); // set NZ flags, NZ result
a61af66fc99e Initial load
duke
parents:
diff changeset
934
a61af66fc99e Initial load
duke
parents:
diff changeset
935 #if defined(COMPILER2) && !defined(_LP64)
a61af66fc99e Initial load
duke
parents:
diff changeset
936 __ ld_ptr(SP,(frame::register_save_words+0)*wordSize,L0);
a61af66fc99e Initial load
duke
parents:
diff changeset
937 __ ld_ptr(SP,(frame::register_save_words+1)*wordSize,L1);
a61af66fc99e Initial load
duke
parents:
diff changeset
938 __ ld_ptr(SP,(frame::register_save_words+2)*wordSize,L2);
a61af66fc99e Initial load
duke
parents:
diff changeset
939 __ ld_ptr(SP,(frame::register_save_words+3)*wordSize,L3);
a61af66fc99e Initial load
duke
parents:
diff changeset
940 __ retl(); // Result in Rret is != 0; flags set to NZ
a61af66fc99e Initial load
duke
parents:
diff changeset
941 __ delayed()->add(SP,4*wordSize,SP);
a61af66fc99e Initial load
duke
parents:
diff changeset
942 #else
a61af66fc99e Initial load
duke
parents:
diff changeset
943 __ ret(); // Result in Rret is != 0; flags set to NZ
a61af66fc99e Initial load
duke
parents:
diff changeset
944 __ delayed()->restore();
a61af66fc99e Initial load
duke
parents:
diff changeset
945 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
946
a61af66fc99e Initial load
duke
parents:
diff changeset
947 return start;
a61af66fc99e Initial load
duke
parents:
diff changeset
948 }
a61af66fc99e Initial load
duke
parents:
diff changeset
949
a61af66fc99e Initial load
duke
parents:
diff changeset
950
a61af66fc99e Initial load
duke
parents:
diff changeset
951 // Called from MacroAssembler::verify_oop
a61af66fc99e Initial load
duke
parents:
diff changeset
952 //
a61af66fc99e Initial load
duke
parents:
diff changeset
953 address generate_verify_oop_subroutine() {
a61af66fc99e Initial load
duke
parents:
diff changeset
954 StubCodeMark mark(this, "StubRoutines", "verify_oop_stub");
a61af66fc99e Initial load
duke
parents:
diff changeset
955
a61af66fc99e Initial load
duke
parents:
diff changeset
956 address start = __ pc();
a61af66fc99e Initial load
duke
parents:
diff changeset
957
a61af66fc99e Initial load
duke
parents:
diff changeset
958 __ verify_oop_subroutine();
a61af66fc99e Initial load
duke
parents:
diff changeset
959
a61af66fc99e Initial load
duke
parents:
diff changeset
960 return start;
a61af66fc99e Initial load
duke
parents:
diff changeset
961 }
a61af66fc99e Initial load
duke
parents:
diff changeset
962
a61af66fc99e Initial load
duke
parents:
diff changeset
963
a61af66fc99e Initial load
duke
parents:
diff changeset
964 //
a61af66fc99e Initial load
duke
parents:
diff changeset
965 // Verify that a register contains clean 32-bits positive value
a61af66fc99e Initial load
duke
parents:
diff changeset
966 // (high 32-bits are 0) so it could be used in 64-bits shifts (sllx, srax).
a61af66fc99e Initial load
duke
parents:
diff changeset
967 //
a61af66fc99e Initial load
duke
parents:
diff changeset
968 // Input:
a61af66fc99e Initial load
duke
parents:
diff changeset
969 // Rint - 32-bits value
a61af66fc99e Initial load
duke
parents:
diff changeset
970 // Rtmp - scratch
a61af66fc99e Initial load
duke
parents:
diff changeset
971 //
a61af66fc99e Initial load
duke
parents:
diff changeset
972 void assert_clean_int(Register Rint, Register Rtmp) {
a61af66fc99e Initial load
duke
parents:
diff changeset
973 #if defined(ASSERT) && defined(_LP64)
a61af66fc99e Initial load
duke
parents:
diff changeset
974 __ signx(Rint, Rtmp);
a61af66fc99e Initial load
duke
parents:
diff changeset
975 __ cmp(Rint, Rtmp);
a61af66fc99e Initial load
duke
parents:
diff changeset
976 __ breakpoint_trap(Assembler::notEqual, Assembler::xcc);
a61af66fc99e Initial load
duke
parents:
diff changeset
977 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
978 }
a61af66fc99e Initial load
duke
parents:
diff changeset
979
a61af66fc99e Initial load
duke
parents:
diff changeset
980 //
a61af66fc99e Initial load
duke
parents:
diff changeset
981 // Generate overlap test for array copy stubs
a61af66fc99e Initial load
duke
parents:
diff changeset
982 //
a61af66fc99e Initial load
duke
parents:
diff changeset
983 // Input:
a61af66fc99e Initial load
duke
parents:
diff changeset
984 // O0 - array1
a61af66fc99e Initial load
duke
parents:
diff changeset
985 // O1 - array2
a61af66fc99e Initial load
duke
parents:
diff changeset
986 // O2 - element count
a61af66fc99e Initial load
duke
parents:
diff changeset
987 //
a61af66fc99e Initial load
duke
parents:
diff changeset
988 // Kills temps: O3, O4
a61af66fc99e Initial load
duke
parents:
diff changeset
989 //
a61af66fc99e Initial load
duke
parents:
diff changeset
990 void array_overlap_test(address no_overlap_target, int log2_elem_size) {
a61af66fc99e Initial load
duke
parents:
diff changeset
991 assert(no_overlap_target != NULL, "must be generated");
a61af66fc99e Initial load
duke
parents:
diff changeset
992 array_overlap_test(no_overlap_target, NULL, log2_elem_size);
a61af66fc99e Initial load
duke
parents:
diff changeset
993 }
a61af66fc99e Initial load
duke
parents:
diff changeset
994 void array_overlap_test(Label& L_no_overlap, int log2_elem_size) {
a61af66fc99e Initial load
duke
parents:
diff changeset
995 array_overlap_test(NULL, &L_no_overlap, log2_elem_size);
a61af66fc99e Initial load
duke
parents:
diff changeset
996 }
a61af66fc99e Initial load
duke
parents:
diff changeset
997 void array_overlap_test(address no_overlap_target, Label* NOLp, int log2_elem_size) {
a61af66fc99e Initial load
duke
parents:
diff changeset
998 const Register from = O0;
a61af66fc99e Initial load
duke
parents:
diff changeset
999 const Register to = O1;
a61af66fc99e Initial load
duke
parents:
diff changeset
1000 const Register count = O2;
a61af66fc99e Initial load
duke
parents:
diff changeset
1001 const Register to_from = O3; // to - from
a61af66fc99e Initial load
duke
parents:
diff changeset
1002 const Register byte_count = O4; // count << log2_elem_size
a61af66fc99e Initial load
duke
parents:
diff changeset
1003
a61af66fc99e Initial load
duke
parents:
diff changeset
1004 __ subcc(to, from, to_from);
a61af66fc99e Initial load
duke
parents:
diff changeset
1005 __ sll_ptr(count, log2_elem_size, byte_count);
a61af66fc99e Initial load
duke
parents:
diff changeset
1006 if (NOLp == NULL)
a61af66fc99e Initial load
duke
parents:
diff changeset
1007 __ brx(Assembler::lessEqualUnsigned, false, Assembler::pt, no_overlap_target);
a61af66fc99e Initial load
duke
parents:
diff changeset
1008 else
a61af66fc99e Initial load
duke
parents:
diff changeset
1009 __ brx(Assembler::lessEqualUnsigned, false, Assembler::pt, (*NOLp));
a61af66fc99e Initial load
duke
parents:
diff changeset
1010 __ delayed()->cmp(to_from, byte_count);
a61af66fc99e Initial load
duke
parents:
diff changeset
1011 if (NOLp == NULL)
1655
e7ec8cd4dd8a 6962569: assembler_sparc.cpp:1969: assert(false) failed: error
tonyp
parents: 1579
diff changeset
1012 __ brx(Assembler::greaterEqualUnsigned, false, Assembler::pt, no_overlap_target);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1013 else
1655
e7ec8cd4dd8a 6962569: assembler_sparc.cpp:1969: assert(false) failed: error
tonyp
parents: 1579
diff changeset
1014 __ brx(Assembler::greaterEqualUnsigned, false, Assembler::pt, (*NOLp));
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1015 __ delayed()->nop();
a61af66fc99e Initial load
duke
parents:
diff changeset
1016 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1017
a61af66fc99e Initial load
duke
parents:
diff changeset
1018 //
a61af66fc99e Initial load
duke
parents:
diff changeset
1019 // Generate pre-write barrier for array.
a61af66fc99e Initial load
duke
parents:
diff changeset
1020 //
a61af66fc99e Initial load
duke
parents:
diff changeset
1021 // Input:
a61af66fc99e Initial load
duke
parents:
diff changeset
1022 // addr - register containing starting address
a61af66fc99e Initial load
duke
parents:
diff changeset
1023 // count - register containing element count
a61af66fc99e Initial load
duke
parents:
diff changeset
1024 // tmp - scratch register
a61af66fc99e Initial load
duke
parents:
diff changeset
1025 //
a61af66fc99e Initial load
duke
parents:
diff changeset
1026 // The input registers are overwritten.
a61af66fc99e Initial load
duke
parents:
diff changeset
1027 //
2324
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
1028 void gen_write_ref_array_pre_barrier(Register addr, Register count, bool dest_uninitialized) {
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1029 BarrierSet* bs = Universe::heap()->barrier_set();
2324
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
1030 switch (bs->kind()) {
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
1031 case BarrierSet::G1SATBCT:
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
1032 case BarrierSet::G1SATBCTLogging:
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
1033 // With G1, don't generate the call if we statically know that the target in uninitialized
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
1034 if (!dest_uninitialized) {
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
1035 __ save_frame(0);
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
1036 // Save the necessary global regs... will be used after.
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
1037 if (addr->is_global()) {
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
1038 __ mov(addr, L0);
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
1039 }
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
1040 if (count->is_global()) {
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
1041 __ mov(count, L1);
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
1042 }
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
1043 __ mov(addr->after_save(), O0);
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
1044 // Get the count into O1
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
1045 __ call(CAST_FROM_FN_PTR(address, BarrierSet::static_write_ref_array_pre));
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
1046 __ delayed()->mov(count->after_save(), O1);
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
1047 if (addr->is_global()) {
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
1048 __ mov(L0, addr);
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
1049 }
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
1050 if (count->is_global()) {
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
1051 __ mov(L1, count);
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
1052 }
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
1053 __ restore();
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
1054 }
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
1055 break;
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
1056 case BarrierSet::CardTableModRef:
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
1057 case BarrierSet::CardTableExtension:
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
1058 case BarrierSet::ModRef:
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
1059 break;
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
1060 default:
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
1061 ShouldNotReachHere();
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1062 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1063 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1064 //
a61af66fc99e Initial load
duke
parents:
diff changeset
1065 // Generate post-write barrier for array.
a61af66fc99e Initial load
duke
parents:
diff changeset
1066 //
a61af66fc99e Initial load
duke
parents:
diff changeset
1067 // Input:
a61af66fc99e Initial load
duke
parents:
diff changeset
1068 // addr - register containing starting address
a61af66fc99e Initial load
duke
parents:
diff changeset
1069 // count - register containing element count
a61af66fc99e Initial load
duke
parents:
diff changeset
1070 // tmp - scratch register
a61af66fc99e Initial load
duke
parents:
diff changeset
1071 //
a61af66fc99e Initial load
duke
parents:
diff changeset
1072 // The input registers are overwritten.
a61af66fc99e Initial load
duke
parents:
diff changeset
1073 //
a61af66fc99e Initial load
duke
parents:
diff changeset
1074 void gen_write_ref_array_post_barrier(Register addr, Register count,
2324
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
1075 Register tmp) {
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1076 BarrierSet* bs = Universe::heap()->barrier_set();
a61af66fc99e Initial load
duke
parents:
diff changeset
1077
a61af66fc99e Initial load
duke
parents:
diff changeset
1078 switch (bs->kind()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1079 case BarrierSet::G1SATBCT:
a61af66fc99e Initial load
duke
parents:
diff changeset
1080 case BarrierSet::G1SATBCTLogging:
a61af66fc99e Initial load
duke
parents:
diff changeset
1081 {
a61af66fc99e Initial load
duke
parents:
diff changeset
1082 // Get some new fresh output registers.
a61af66fc99e Initial load
duke
parents:
diff changeset
1083 __ save_frame(0);
342
37f87013dfd8 6711316: Open source the Garbage-First garbage collector
ysr
parents: 113
diff changeset
1084 __ mov(addr->after_save(), O0);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1085 __ call(CAST_FROM_FN_PTR(address, BarrierSet::static_write_ref_array_post));
342
37f87013dfd8 6711316: Open source the Garbage-First garbage collector
ysr
parents: 113
diff changeset
1086 __ delayed()->mov(count->after_save(), O1);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1087 __ restore();
a61af66fc99e Initial load
duke
parents:
diff changeset
1088 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1089 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
1090 case BarrierSet::CardTableModRef:
a61af66fc99e Initial load
duke
parents:
diff changeset
1091 case BarrierSet::CardTableExtension:
a61af66fc99e Initial load
duke
parents:
diff changeset
1092 {
a61af66fc99e Initial load
duke
parents:
diff changeset
1093 CardTableModRefBS* ct = (CardTableModRefBS*)bs;
a61af66fc99e Initial load
duke
parents:
diff changeset
1094 assert(sizeof(*ct->byte_map_base) == sizeof(jbyte), "adjust this code");
a61af66fc99e Initial load
duke
parents:
diff changeset
1095 assert_different_registers(addr, count, tmp);
a61af66fc99e Initial load
duke
parents:
diff changeset
1096
a61af66fc99e Initial load
duke
parents:
diff changeset
1097 Label L_loop;
a61af66fc99e Initial load
duke
parents:
diff changeset
1098
113
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 16
diff changeset
1099 __ sll_ptr(count, LogBytesPerHeapOop, count);
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 16
diff changeset
1100 __ sub(count, BytesPerHeapOop, count);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1101 __ add(count, addr, count);
a61af66fc99e Initial load
duke
parents:
diff changeset
1102 // Use two shifts to clear out those low order two bits! (Cannot opt. into 1.)
a61af66fc99e Initial load
duke
parents:
diff changeset
1103 __ srl_ptr(addr, CardTableModRefBS::card_shift, addr);
a61af66fc99e Initial load
duke
parents:
diff changeset
1104 __ srl_ptr(count, CardTableModRefBS::card_shift, count);
a61af66fc99e Initial load
duke
parents:
diff changeset
1105 __ sub(count, addr, count);
727
6b2273dd6fa9 6822110: Add AddressLiteral class on SPARC
twisti
parents: 671
diff changeset
1106 AddressLiteral rs(ct->byte_map_base);
6b2273dd6fa9 6822110: Add AddressLiteral class on SPARC
twisti
parents: 671
diff changeset
1107 __ set(rs, tmp);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1108 __ BIND(L_loop);
727
6b2273dd6fa9 6822110: Add AddressLiteral class on SPARC
twisti
parents: 671
diff changeset
1109 __ stb(G0, tmp, addr);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1110 __ subcc(count, 1, count);
a61af66fc99e Initial load
duke
parents:
diff changeset
1111 __ brx(Assembler::greaterEqual, false, Assembler::pt, L_loop);
a61af66fc99e Initial load
duke
parents:
diff changeset
1112 __ delayed()->add(addr, 1, addr);
727
6b2273dd6fa9 6822110: Add AddressLiteral class on SPARC
twisti
parents: 671
diff changeset
1113 }
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1114 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
1115 case BarrierSet::ModRef:
a61af66fc99e Initial load
duke
parents:
diff changeset
1116 break;
727
6b2273dd6fa9 6822110: Add AddressLiteral class on SPARC
twisti
parents: 671
diff changeset
1117 default:
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1118 ShouldNotReachHere();
a61af66fc99e Initial load
duke
parents:
diff changeset
1119 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1120 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1121
3903
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1122 //
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1123 // Generate main code for disjoint arraycopy
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1124 //
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1125 typedef void (StubGenerator::*CopyLoopFunc)(Register from, Register to, Register count, int count_dec,
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1126 Label& L_loop, bool use_prefetch, bool use_bis);
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1127
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1128 void disjoint_copy_core(Register from, Register to, Register count, int log2_elem_size,
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1129 int iter_size, CopyLoopFunc copy_loop_func) {
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1130 Label L_copy;
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1131
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1132 assert(log2_elem_size <= 3, "the following code should be changed");
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1133 int count_dec = 16>>log2_elem_size;
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1134
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1135 int prefetch_dist = MAX2(ArraycopySrcPrefetchDistance, ArraycopyDstPrefetchDistance);
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1136 assert(prefetch_dist < 4096, "invalid value");
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1137 prefetch_dist = (prefetch_dist + (iter_size-1)) & (-iter_size); // round up to one iteration copy size
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1138 int prefetch_count = (prefetch_dist >> log2_elem_size); // elements count
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1139
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1140 if (UseBlockCopy) {
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1141 Label L_block_copy, L_block_copy_prefetch, L_skip_block_copy;
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1142
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1143 // 64 bytes tail + bytes copied in one loop iteration
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1144 int tail_size = 64 + iter_size;
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1145 int block_copy_count = (MAX2(tail_size, (int)BlockCopyLowLimit)) >> log2_elem_size;
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1146 // Use BIS copy only for big arrays since it requires membar.
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1147 __ set(block_copy_count, O4);
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1148 __ cmp_and_br_short(count, O4, Assembler::lessUnsigned, Assembler::pt, L_skip_block_copy);
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1149 // This code is for disjoint source and destination:
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1150 // to <= from || to >= from+count
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1151 // but BIS will stomp over 'from' if (to > from-tail_size && to <= from)
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1152 __ sub(from, to, O4);
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1153 __ srax(O4, 4, O4); // divide by 16 since following short branch have only 5 bits for imm.
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1154 __ cmp_and_br_short(O4, (tail_size>>4), Assembler::lessEqualUnsigned, Assembler::pn, L_skip_block_copy);
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1155
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1156 __ wrasi(G0, Assembler::ASI_ST_BLKINIT_PRIMARY);
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1157 // BIS should not be used to copy tail (64 bytes+iter_size)
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1158 // to avoid zeroing of following values.
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1159 __ sub(count, (tail_size>>log2_elem_size), count); // count is still positive >= 0
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1160
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1161 if (prefetch_count > 0) { // rounded up to one iteration count
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1162 // Do prefetching only if copy size is bigger
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1163 // than prefetch distance.
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1164 __ set(prefetch_count, O4);
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1165 __ cmp_and_brx_short(count, O4, Assembler::less, Assembler::pt, L_block_copy);
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1166 __ sub(count, prefetch_count, count);
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1167
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1168 (this->*copy_loop_func)(from, to, count, count_dec, L_block_copy_prefetch, true, true);
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1169 __ add(count, prefetch_count, count); // restore count
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1170
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1171 } // prefetch_count > 0
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1172
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1173 (this->*copy_loop_func)(from, to, count, count_dec, L_block_copy, false, true);
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1174 __ add(count, (tail_size>>log2_elem_size), count); // restore count
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1175
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1176 __ wrasi(G0, Assembler::ASI_PRIMARY_NOFAULT);
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1177 // BIS needs membar.
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1178 __ membar(Assembler::StoreLoad);
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1179 // Copy tail
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1180 __ ba_short(L_copy);
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1181
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1182 __ BIND(L_skip_block_copy);
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1183 } // UseBlockCopy
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1184
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1185 if (prefetch_count > 0) { // rounded up to one iteration count
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1186 // Do prefetching only if copy size is bigger
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1187 // than prefetch distance.
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1188 __ set(prefetch_count, O4);
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1189 __ cmp_and_brx_short(count, O4, Assembler::lessUnsigned, Assembler::pt, L_copy);
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1190 __ sub(count, prefetch_count, count);
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1191
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1192 Label L_copy_prefetch;
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1193 (this->*copy_loop_func)(from, to, count, count_dec, L_copy_prefetch, true, false);
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1194 __ add(count, prefetch_count, count); // restore count
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1195
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1196 } // prefetch_count > 0
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1197
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1198 (this->*copy_loop_func)(from, to, count, count_dec, L_copy, false, false);
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1199 }
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1200
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1201
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1202
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1203 //
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1204 // Helper methods for copy_16_bytes_forward_with_shift()
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1205 //
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1206 void copy_16_bytes_shift_loop(Register from, Register to, Register count, int count_dec,
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1207 Label& L_loop, bool use_prefetch, bool use_bis) {
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1208
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1209 const Register left_shift = G1; // left shift bit counter
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1210 const Register right_shift = G5; // right shift bit counter
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1211
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1212 __ align(OptoLoopAlignment);
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1213 __ BIND(L_loop);
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1214 if (use_prefetch) {
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1215 if (ArraycopySrcPrefetchDistance > 0) {
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1216 __ prefetch(from, ArraycopySrcPrefetchDistance, Assembler::severalReads);
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1217 }
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1218 if (ArraycopyDstPrefetchDistance > 0) {
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1219 __ prefetch(to, ArraycopyDstPrefetchDistance, Assembler::severalWritesAndPossiblyReads);
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1220 }
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1221 }
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1222 __ ldx(from, 0, O4);
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1223 __ ldx(from, 8, G4);
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1224 __ inc(to, 16);
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1225 __ inc(from, 16);
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1226 __ deccc(count, count_dec); // Can we do next iteration after this one?
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1227 __ srlx(O4, right_shift, G3);
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1228 __ bset(G3, O3);
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1229 __ sllx(O4, left_shift, O4);
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1230 __ srlx(G4, right_shift, G3);
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1231 __ bset(G3, O4);
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1232 if (use_bis) {
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1233 __ stxa(O3, to, -16);
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1234 __ stxa(O4, to, -8);
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1235 } else {
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1236 __ stx(O3, to, -16);
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1237 __ stx(O4, to, -8);
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1238 }
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1239 __ brx(Assembler::greaterEqual, false, Assembler::pt, L_loop);
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1240 __ delayed()->sllx(G4, left_shift, O3);
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1241 }
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1242
a61af66fc99e Initial load
duke
parents:
diff changeset
1243 // Copy big chunks forward with shift
a61af66fc99e Initial load
duke
parents:
diff changeset
1244 //
a61af66fc99e Initial load
duke
parents:
diff changeset
1245 // Inputs:
a61af66fc99e Initial load
duke
parents:
diff changeset
1246 // from - source arrays
a61af66fc99e Initial load
duke
parents:
diff changeset
1247 // to - destination array aligned to 8-bytes
a61af66fc99e Initial load
duke
parents:
diff changeset
1248 // count - elements count to copy >= the count equivalent to 16 bytes
a61af66fc99e Initial load
duke
parents:
diff changeset
1249 // count_dec - elements count's decrement equivalent to 16 bytes
a61af66fc99e Initial load
duke
parents:
diff changeset
1250 // L_copy_bytes - copy exit label
a61af66fc99e Initial load
duke
parents:
diff changeset
1251 //
a61af66fc99e Initial load
duke
parents:
diff changeset
1252 void copy_16_bytes_forward_with_shift(Register from, Register to,
3903
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1253 Register count, int log2_elem_size, Label& L_copy_bytes) {
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1254 Label L_aligned_copy, L_copy_last_bytes;
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1255 assert(log2_elem_size <= 3, "the following code should be changed");
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1256 int count_dec = 16>>log2_elem_size;
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1257
a61af66fc99e Initial load
duke
parents:
diff changeset
1258 // if both arrays have the same alignment mod 8, do 8 bytes aligned copy
3903
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1259 __ andcc(from, 7, G1); // misaligned bytes
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1260 __ br(Assembler::zero, false, Assembler::pt, L_aligned_copy);
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1261 __ delayed()->nop();
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1262
a61af66fc99e Initial load
duke
parents:
diff changeset
1263 const Register left_shift = G1; // left shift bit counter
a61af66fc99e Initial load
duke
parents:
diff changeset
1264 const Register right_shift = G5; // right shift bit counter
a61af66fc99e Initial load
duke
parents:
diff changeset
1265
3903
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1266 __ sll(G1, LogBitsPerByte, left_shift);
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1267 __ mov(64, right_shift);
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1268 __ sub(right_shift, left_shift, right_shift);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1269
a61af66fc99e Initial load
duke
parents:
diff changeset
1270 //
a61af66fc99e Initial load
duke
parents:
diff changeset
1271 // Load 2 aligned 8-bytes chunks and use one from previous iteration
a61af66fc99e Initial load
duke
parents:
diff changeset
1272 // to form 2 aligned 8-bytes chunks to store.
a61af66fc99e Initial load
duke
parents:
diff changeset
1273 //
3903
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1274 __ dec(count, count_dec); // Pre-decrement 'count'
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1275 __ andn(from, 7, from); // Align address
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1276 __ ldx(from, 0, O3);
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1277 __ inc(from, 8);
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1278 __ sllx(O3, left_shift, O3);
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1279
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1280 disjoint_copy_core(from, to, count, log2_elem_size, 16, copy_16_bytes_shift_loop);
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1281
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1282 __ inccc(count, count_dec>>1 ); // + 8 bytes
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1283 __ brx(Assembler::negative, true, Assembler::pn, L_copy_last_bytes);
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1284 __ delayed()->inc(count, count_dec>>1); // restore 'count'
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1285
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1286 // copy 8 bytes, part of them already loaded in O3
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1287 __ ldx(from, 0, O4);
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1288 __ inc(to, 8);
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1289 __ inc(from, 8);
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1290 __ srlx(O4, right_shift, G3);
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1291 __ bset(O3, G3);
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1292 __ stx(G3, to, -8);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1293
a61af66fc99e Initial load
duke
parents:
diff changeset
1294 __ BIND(L_copy_last_bytes);
3903
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1295 __ srl(right_shift, LogBitsPerByte, right_shift); // misaligned bytes
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1296 __ br(Assembler::always, false, Assembler::pt, L_copy_bytes);
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1297 __ delayed()->sub(from, right_shift, from); // restore address
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1298
a61af66fc99e Initial load
duke
parents:
diff changeset
1299 __ BIND(L_aligned_copy);
a61af66fc99e Initial load
duke
parents:
diff changeset
1300 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1301
a61af66fc99e Initial load
duke
parents:
diff changeset
1302 // Copy big chunks backward with shift
a61af66fc99e Initial load
duke
parents:
diff changeset
1303 //
a61af66fc99e Initial load
duke
parents:
diff changeset
1304 // Inputs:
a61af66fc99e Initial load
duke
parents:
diff changeset
1305 // end_from - source arrays end address
a61af66fc99e Initial load
duke
parents:
diff changeset
1306 // end_to - destination array end address aligned to 8-bytes
a61af66fc99e Initial load
duke
parents:
diff changeset
1307 // count - elements count to copy >= the count equivalent to 16 bytes
a61af66fc99e Initial load
duke
parents:
diff changeset
1308 // count_dec - elements count's decrement equivalent to 16 bytes
a61af66fc99e Initial load
duke
parents:
diff changeset
1309 // L_aligned_copy - aligned copy exit label
a61af66fc99e Initial load
duke
parents:
diff changeset
1310 // L_copy_bytes - copy exit label
a61af66fc99e Initial load
duke
parents:
diff changeset
1311 //
a61af66fc99e Initial load
duke
parents:
diff changeset
1312 void copy_16_bytes_backward_with_shift(Register end_from, Register end_to,
a61af66fc99e Initial load
duke
parents:
diff changeset
1313 Register count, int count_dec,
a61af66fc99e Initial load
duke
parents:
diff changeset
1314 Label& L_aligned_copy, Label& L_copy_bytes) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1315 Label L_loop, L_copy_last_bytes;
a61af66fc99e Initial load
duke
parents:
diff changeset
1316
a61af66fc99e Initial load
duke
parents:
diff changeset
1317 // if both arrays have the same alignment mod 8, do 8 bytes aligned copy
a61af66fc99e Initial load
duke
parents:
diff changeset
1318 __ andcc(end_from, 7, G1); // misaligned bytes
a61af66fc99e Initial load
duke
parents:
diff changeset
1319 __ br(Assembler::zero, false, Assembler::pt, L_aligned_copy);
a61af66fc99e Initial load
duke
parents:
diff changeset
1320 __ delayed()->deccc(count, count_dec); // Pre-decrement 'count'
a61af66fc99e Initial load
duke
parents:
diff changeset
1321
a61af66fc99e Initial load
duke
parents:
diff changeset
1322 const Register left_shift = G1; // left shift bit counter
a61af66fc99e Initial load
duke
parents:
diff changeset
1323 const Register right_shift = G5; // right shift bit counter
a61af66fc99e Initial load
duke
parents:
diff changeset
1324
a61af66fc99e Initial load
duke
parents:
diff changeset
1325 __ sll(G1, LogBitsPerByte, left_shift);
a61af66fc99e Initial load
duke
parents:
diff changeset
1326 __ mov(64, right_shift);
a61af66fc99e Initial load
duke
parents:
diff changeset
1327 __ sub(right_shift, left_shift, right_shift);
a61af66fc99e Initial load
duke
parents:
diff changeset
1328
a61af66fc99e Initial load
duke
parents:
diff changeset
1329 //
a61af66fc99e Initial load
duke
parents:
diff changeset
1330 // Load 2 aligned 8-bytes chunks and use one from previous iteration
a61af66fc99e Initial load
duke
parents:
diff changeset
1331 // to form 2 aligned 8-bytes chunks to store.
a61af66fc99e Initial load
duke
parents:
diff changeset
1332 //
a61af66fc99e Initial load
duke
parents:
diff changeset
1333 __ andn(end_from, 7, end_from); // Align address
a61af66fc99e Initial load
duke
parents:
diff changeset
1334 __ ldx(end_from, 0, O3);
1365
6476042f815c 6940701: Don't align loops in stubs for Niagara sparc
kvn
parents: 1364
diff changeset
1335 __ align(OptoLoopAlignment);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1336 __ BIND(L_loop);
a61af66fc99e Initial load
duke
parents:
diff changeset
1337 __ ldx(end_from, -8, O4);
a61af66fc99e Initial load
duke
parents:
diff changeset
1338 __ deccc(count, count_dec); // Can we do next iteration after this one?
a61af66fc99e Initial load
duke
parents:
diff changeset
1339 __ ldx(end_from, -16, G4);
a61af66fc99e Initial load
duke
parents:
diff changeset
1340 __ dec(end_to, 16);
a61af66fc99e Initial load
duke
parents:
diff changeset
1341 __ dec(end_from, 16);
a61af66fc99e Initial load
duke
parents:
diff changeset
1342 __ srlx(O3, right_shift, O3);
a61af66fc99e Initial load
duke
parents:
diff changeset
1343 __ sllx(O4, left_shift, G3);
a61af66fc99e Initial load
duke
parents:
diff changeset
1344 __ bset(G3, O3);
a61af66fc99e Initial load
duke
parents:
diff changeset
1345 __ stx(O3, end_to, 8);
a61af66fc99e Initial load
duke
parents:
diff changeset
1346 __ srlx(O4, right_shift, O4);
a61af66fc99e Initial load
duke
parents:
diff changeset
1347 __ sllx(G4, left_shift, G3);
a61af66fc99e Initial load
duke
parents:
diff changeset
1348 __ bset(G3, O4);
a61af66fc99e Initial load
duke
parents:
diff changeset
1349 __ stx(O4, end_to, 0);
a61af66fc99e Initial load
duke
parents:
diff changeset
1350 __ brx(Assembler::greaterEqual, false, Assembler::pt, L_loop);
a61af66fc99e Initial load
duke
parents:
diff changeset
1351 __ delayed()->mov(G4, O3);
a61af66fc99e Initial load
duke
parents:
diff changeset
1352
a61af66fc99e Initial load
duke
parents:
diff changeset
1353 __ inccc(count, count_dec>>1 ); // + 8 bytes
a61af66fc99e Initial load
duke
parents:
diff changeset
1354 __ brx(Assembler::negative, true, Assembler::pn, L_copy_last_bytes);
a61af66fc99e Initial load
duke
parents:
diff changeset
1355 __ delayed()->inc(count, count_dec>>1); // restore 'count'
a61af66fc99e Initial load
duke
parents:
diff changeset
1356
a61af66fc99e Initial load
duke
parents:
diff changeset
1357 // copy 8 bytes, part of them already loaded in O3
a61af66fc99e Initial load
duke
parents:
diff changeset
1358 __ ldx(end_from, -8, O4);
a61af66fc99e Initial load
duke
parents:
diff changeset
1359 __ dec(end_to, 8);
a61af66fc99e Initial load
duke
parents:
diff changeset
1360 __ dec(end_from, 8);
a61af66fc99e Initial load
duke
parents:
diff changeset
1361 __ srlx(O3, right_shift, O3);
a61af66fc99e Initial load
duke
parents:
diff changeset
1362 __ sllx(O4, left_shift, G3);
a61af66fc99e Initial load
duke
parents:
diff changeset
1363 __ bset(O3, G3);
a61af66fc99e Initial load
duke
parents:
diff changeset
1364 __ stx(G3, end_to, 0);
a61af66fc99e Initial load
duke
parents:
diff changeset
1365
a61af66fc99e Initial load
duke
parents:
diff changeset
1366 __ BIND(L_copy_last_bytes);
a61af66fc99e Initial load
duke
parents:
diff changeset
1367 __ srl(left_shift, LogBitsPerByte, left_shift); // misaligned bytes
a61af66fc99e Initial load
duke
parents:
diff changeset
1368 __ br(Assembler::always, false, Assembler::pt, L_copy_bytes);
a61af66fc99e Initial load
duke
parents:
diff changeset
1369 __ delayed()->add(end_from, left_shift, end_from); // restore address
a61af66fc99e Initial load
duke
parents:
diff changeset
1370 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1371
a61af66fc99e Initial load
duke
parents:
diff changeset
1372 //
a61af66fc99e Initial load
duke
parents:
diff changeset
1373 // Generate stub for disjoint byte copy. If "aligned" is true, the
a61af66fc99e Initial load
duke
parents:
diff changeset
1374 // "from" and "to" addresses are assumed to be heapword aligned.
a61af66fc99e Initial load
duke
parents:
diff changeset
1375 //
a61af66fc99e Initial load
duke
parents:
diff changeset
1376 // Arguments for generated stub:
a61af66fc99e Initial load
duke
parents:
diff changeset
1377 // from: O0
a61af66fc99e Initial load
duke
parents:
diff changeset
1378 // to: O1
a61af66fc99e Initial load
duke
parents:
diff changeset
1379 // count: O2 treated as signed
a61af66fc99e Initial load
duke
parents:
diff changeset
1380 //
2313
d89a22843c62 7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents: 1972
diff changeset
1381 address generate_disjoint_byte_copy(bool aligned, address *entry, const char *name) {
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1382 __ align(CodeEntryAlignment);
a61af66fc99e Initial load
duke
parents:
diff changeset
1383 StubCodeMark mark(this, "StubRoutines", name);
a61af66fc99e Initial load
duke
parents:
diff changeset
1384 address start = __ pc();
a61af66fc99e Initial load
duke
parents:
diff changeset
1385
a61af66fc99e Initial load
duke
parents:
diff changeset
1386 Label L_skip_alignment, L_align;
a61af66fc99e Initial load
duke
parents:
diff changeset
1387 Label L_copy_byte, L_copy_byte_loop, L_exit;
a61af66fc99e Initial load
duke
parents:
diff changeset
1388
a61af66fc99e Initial load
duke
parents:
diff changeset
1389 const Register from = O0; // source array address
a61af66fc99e Initial load
duke
parents:
diff changeset
1390 const Register to = O1; // destination array address
a61af66fc99e Initial load
duke
parents:
diff changeset
1391 const Register count = O2; // elements count
a61af66fc99e Initial load
duke
parents:
diff changeset
1392 const Register offset = O5; // offset from start of arrays
a61af66fc99e Initial load
duke
parents:
diff changeset
1393 // O3, O4, G3, G4 are used as temp registers
a61af66fc99e Initial load
duke
parents:
diff changeset
1394
a61af66fc99e Initial load
duke
parents:
diff changeset
1395 assert_clean_int(count, O3); // Make sure 'count' is clean int.
a61af66fc99e Initial load
duke
parents:
diff changeset
1396
2313
d89a22843c62 7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents: 1972
diff changeset
1397 if (entry != NULL) {
d89a22843c62 7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents: 1972
diff changeset
1398 *entry = __ pc();
d89a22843c62 7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents: 1972
diff changeset
1399 // caller can pass a 64-bit byte count here (from Unsafe.copyMemory)
d89a22843c62 7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents: 1972
diff changeset
1400 BLOCK_COMMENT("Entry:");
d89a22843c62 7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents: 1972
diff changeset
1401 }
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1402
a61af66fc99e Initial load
duke
parents:
diff changeset
1403 // for short arrays, just do single element copy
a61af66fc99e Initial load
duke
parents:
diff changeset
1404 __ cmp(count, 23); // 16 + 7
a61af66fc99e Initial load
duke
parents:
diff changeset
1405 __ brx(Assembler::less, false, Assembler::pn, L_copy_byte);
a61af66fc99e Initial load
duke
parents:
diff changeset
1406 __ delayed()->mov(G0, offset);
a61af66fc99e Initial load
duke
parents:
diff changeset
1407
a61af66fc99e Initial load
duke
parents:
diff changeset
1408 if (aligned) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1409 // 'aligned' == true when it is known statically during compilation
a61af66fc99e Initial load
duke
parents:
diff changeset
1410 // of this arraycopy call site that both 'from' and 'to' addresses
a61af66fc99e Initial load
duke
parents:
diff changeset
1411 // are HeapWordSize aligned (see LibraryCallKit::basictype2arraycopy()).
a61af66fc99e Initial load
duke
parents:
diff changeset
1412 //
a61af66fc99e Initial load
duke
parents:
diff changeset
1413 // Aligned arrays have 4 bytes alignment in 32-bits VM
a61af66fc99e Initial load
duke
parents:
diff changeset
1414 // and 8 bytes - in 64-bits VM. So we do it only for 32-bits VM
a61af66fc99e Initial load
duke
parents:
diff changeset
1415 //
a61af66fc99e Initial load
duke
parents:
diff changeset
1416 #ifndef _LP64
a61af66fc99e Initial load
duke
parents:
diff changeset
1417 // copy a 4-bytes word if necessary to align 'to' to 8 bytes
a61af66fc99e Initial load
duke
parents:
diff changeset
1418 __ andcc(to, 7, G0);
a61af66fc99e Initial load
duke
parents:
diff changeset
1419 __ br(Assembler::zero, false, Assembler::pn, L_skip_alignment);
a61af66fc99e Initial load
duke
parents:
diff changeset
1420 __ delayed()->ld(from, 0, O3);
a61af66fc99e Initial load
duke
parents:
diff changeset
1421 __ inc(from, 4);
a61af66fc99e Initial load
duke
parents:
diff changeset
1422 __ inc(to, 4);
a61af66fc99e Initial load
duke
parents:
diff changeset
1423 __ dec(count, 4);
a61af66fc99e Initial load
duke
parents:
diff changeset
1424 __ st(O3, to, -4);
a61af66fc99e Initial load
duke
parents:
diff changeset
1425 __ BIND(L_skip_alignment);
a61af66fc99e Initial load
duke
parents:
diff changeset
1426 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
1427 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
1428 // copy bytes to align 'to' on 8 byte boundary
a61af66fc99e Initial load
duke
parents:
diff changeset
1429 __ andcc(to, 7, G1); // misaligned bytes
a61af66fc99e Initial load
duke
parents:
diff changeset
1430 __ br(Assembler::zero, false, Assembler::pt, L_skip_alignment);
a61af66fc99e Initial load
duke
parents:
diff changeset
1431 __ delayed()->neg(G1);
a61af66fc99e Initial load
duke
parents:
diff changeset
1432 __ inc(G1, 8); // bytes need to copy to next 8-bytes alignment
a61af66fc99e Initial load
duke
parents:
diff changeset
1433 __ sub(count, G1, count);
a61af66fc99e Initial load
duke
parents:
diff changeset
1434 __ BIND(L_align);
a61af66fc99e Initial load
duke
parents:
diff changeset
1435 __ ldub(from, 0, O3);
a61af66fc99e Initial load
duke
parents:
diff changeset
1436 __ deccc(G1);
a61af66fc99e Initial load
duke
parents:
diff changeset
1437 __ inc(from);
a61af66fc99e Initial load
duke
parents:
diff changeset
1438 __ stb(O3, to, 0);
a61af66fc99e Initial load
duke
parents:
diff changeset
1439 __ br(Assembler::notZero, false, Assembler::pt, L_align);
a61af66fc99e Initial load
duke
parents:
diff changeset
1440 __ delayed()->inc(to);
a61af66fc99e Initial load
duke
parents:
diff changeset
1441 __ BIND(L_skip_alignment);
a61af66fc99e Initial load
duke
parents:
diff changeset
1442 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1443 #ifdef _LP64
a61af66fc99e Initial load
duke
parents:
diff changeset
1444 if (!aligned)
a61af66fc99e Initial load
duke
parents:
diff changeset
1445 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
1446 {
a61af66fc99e Initial load
duke
parents:
diff changeset
1447 // Copy with shift 16 bytes per iteration if arrays do not have
a61af66fc99e Initial load
duke
parents:
diff changeset
1448 // the same alignment mod 8, otherwise fall through to the next
a61af66fc99e Initial load
duke
parents:
diff changeset
1449 // code for aligned copy.
a61af66fc99e Initial load
duke
parents:
diff changeset
1450 // The compare above (count >= 23) guarantes 'count' >= 16 bytes.
a61af66fc99e Initial load
duke
parents:
diff changeset
1451 // Also jump over aligned copy after the copy with shift completed.
a61af66fc99e Initial load
duke
parents:
diff changeset
1452
3903
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1453 copy_16_bytes_forward_with_shift(from, to, count, 0, L_copy_byte);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1454 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1455
a61af66fc99e Initial load
duke
parents:
diff changeset
1456 // Both array are 8 bytes aligned, copy 16 bytes at a time
a61af66fc99e Initial load
duke
parents:
diff changeset
1457 __ and3(count, 7, G4); // Save count
a61af66fc99e Initial load
duke
parents:
diff changeset
1458 __ srl(count, 3, count);
a61af66fc99e Initial load
duke
parents:
diff changeset
1459 generate_disjoint_long_copy_core(aligned);
a61af66fc99e Initial load
duke
parents:
diff changeset
1460 __ mov(G4, count); // Restore count
a61af66fc99e Initial load
duke
parents:
diff changeset
1461
a61af66fc99e Initial load
duke
parents:
diff changeset
1462 // copy tailing bytes
a61af66fc99e Initial load
duke
parents:
diff changeset
1463 __ BIND(L_copy_byte);
3839
3d42f82cd811 7063628: Use cbcond on T4
kvn
parents: 3781
diff changeset
1464 __ cmp_and_br_short(count, 0, Assembler::equal, Assembler::pt, L_exit);
1365
6476042f815c 6940701: Don't align loops in stubs for Niagara sparc
kvn
parents: 1364
diff changeset
1465 __ align(OptoLoopAlignment);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1466 __ BIND(L_copy_byte_loop);
a61af66fc99e Initial load
duke
parents:
diff changeset
1467 __ ldub(from, offset, O3);
a61af66fc99e Initial load
duke
parents:
diff changeset
1468 __ deccc(count);
a61af66fc99e Initial load
duke
parents:
diff changeset
1469 __ stb(O3, to, offset);
a61af66fc99e Initial load
duke
parents:
diff changeset
1470 __ brx(Assembler::notZero, false, Assembler::pt, L_copy_byte_loop);
a61af66fc99e Initial load
duke
parents:
diff changeset
1471 __ delayed()->inc(offset);
a61af66fc99e Initial load
duke
parents:
diff changeset
1472
a61af66fc99e Initial load
duke
parents:
diff changeset
1473 __ BIND(L_exit);
a61af66fc99e Initial load
duke
parents:
diff changeset
1474 // O3, O4 are used as temp registers
a61af66fc99e Initial load
duke
parents:
diff changeset
1475 inc_counter_np(SharedRuntime::_jbyte_array_copy_ctr, O3, O4);
a61af66fc99e Initial load
duke
parents:
diff changeset
1476 __ retl();
a61af66fc99e Initial load
duke
parents:
diff changeset
1477 __ delayed()->mov(G0, O0); // return 0
a61af66fc99e Initial load
duke
parents:
diff changeset
1478 return start;
a61af66fc99e Initial load
duke
parents:
diff changeset
1479 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1480
a61af66fc99e Initial load
duke
parents:
diff changeset
1481 //
a61af66fc99e Initial load
duke
parents:
diff changeset
1482 // Generate stub for conjoint byte copy. If "aligned" is true, the
a61af66fc99e Initial load
duke
parents:
diff changeset
1483 // "from" and "to" addresses are assumed to be heapword aligned.
a61af66fc99e Initial load
duke
parents:
diff changeset
1484 //
a61af66fc99e Initial load
duke
parents:
diff changeset
1485 // Arguments for generated stub:
a61af66fc99e Initial load
duke
parents:
diff changeset
1486 // from: O0
a61af66fc99e Initial load
duke
parents:
diff changeset
1487 // to: O1
a61af66fc99e Initial load
duke
parents:
diff changeset
1488 // count: O2 treated as signed
a61af66fc99e Initial load
duke
parents:
diff changeset
1489 //
2313
d89a22843c62 7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents: 1972
diff changeset
1490 address generate_conjoint_byte_copy(bool aligned, address nooverlap_target,
d89a22843c62 7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents: 1972
diff changeset
1491 address *entry, const char *name) {
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1492 // Do reverse copy.
a61af66fc99e Initial load
duke
parents:
diff changeset
1493
a61af66fc99e Initial load
duke
parents:
diff changeset
1494 __ align(CodeEntryAlignment);
a61af66fc99e Initial load
duke
parents:
diff changeset
1495 StubCodeMark mark(this, "StubRoutines", name);
a61af66fc99e Initial load
duke
parents:
diff changeset
1496 address start = __ pc();
a61af66fc99e Initial load
duke
parents:
diff changeset
1497
a61af66fc99e Initial load
duke
parents:
diff changeset
1498 Label L_skip_alignment, L_align, L_aligned_copy;
a61af66fc99e Initial load
duke
parents:
diff changeset
1499 Label L_copy_byte, L_copy_byte_loop, L_exit;
a61af66fc99e Initial load
duke
parents:
diff changeset
1500
a61af66fc99e Initial load
duke
parents:
diff changeset
1501 const Register from = O0; // source array address
a61af66fc99e Initial load
duke
parents:
diff changeset
1502 const Register to = O1; // destination array address
a61af66fc99e Initial load
duke
parents:
diff changeset
1503 const Register count = O2; // elements count
a61af66fc99e Initial load
duke
parents:
diff changeset
1504 const Register end_from = from; // source array end address
a61af66fc99e Initial load
duke
parents:
diff changeset
1505 const Register end_to = to; // destination array end address
a61af66fc99e Initial load
duke
parents:
diff changeset
1506
a61af66fc99e Initial load
duke
parents:
diff changeset
1507 assert_clean_int(count, O3); // Make sure 'count' is clean int.
a61af66fc99e Initial load
duke
parents:
diff changeset
1508
2313
d89a22843c62 7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents: 1972
diff changeset
1509 if (entry != NULL) {
d89a22843c62 7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents: 1972
diff changeset
1510 *entry = __ pc();
d89a22843c62 7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents: 1972
diff changeset
1511 // caller can pass a 64-bit byte count here (from Unsafe.copyMemory)
d89a22843c62 7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents: 1972
diff changeset
1512 BLOCK_COMMENT("Entry:");
d89a22843c62 7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents: 1972
diff changeset
1513 }
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1514
a61af66fc99e Initial load
duke
parents:
diff changeset
1515 array_overlap_test(nooverlap_target, 0);
a61af66fc99e Initial load
duke
parents:
diff changeset
1516
a61af66fc99e Initial load
duke
parents:
diff changeset
1517 __ add(to, count, end_to); // offset after last copied element
a61af66fc99e Initial load
duke
parents:
diff changeset
1518
a61af66fc99e Initial load
duke
parents:
diff changeset
1519 // for short arrays, just do single element copy
a61af66fc99e Initial load
duke
parents:
diff changeset
1520 __ cmp(count, 23); // 16 + 7
a61af66fc99e Initial load
duke
parents:
diff changeset
1521 __ brx(Assembler::less, false, Assembler::pn, L_copy_byte);
a61af66fc99e Initial load
duke
parents:
diff changeset
1522 __ delayed()->add(from, count, end_from);
a61af66fc99e Initial load
duke
parents:
diff changeset
1523
a61af66fc99e Initial load
duke
parents:
diff changeset
1524 {
a61af66fc99e Initial load
duke
parents:
diff changeset
1525 // Align end of arrays since they could be not aligned even
a61af66fc99e Initial load
duke
parents:
diff changeset
1526 // when arrays itself are aligned.
a61af66fc99e Initial load
duke
parents:
diff changeset
1527
a61af66fc99e Initial load
duke
parents:
diff changeset
1528 // copy bytes to align 'end_to' on 8 byte boundary
a61af66fc99e Initial load
duke
parents:
diff changeset
1529 __ andcc(end_to, 7, G1); // misaligned bytes
a61af66fc99e Initial load
duke
parents:
diff changeset
1530 __ br(Assembler::zero, false, Assembler::pt, L_skip_alignment);
a61af66fc99e Initial load
duke
parents:
diff changeset
1531 __ delayed()->nop();
a61af66fc99e Initial load
duke
parents:
diff changeset
1532 __ sub(count, G1, count);
a61af66fc99e Initial load
duke
parents:
diff changeset
1533 __ BIND(L_align);
a61af66fc99e Initial load
duke
parents:
diff changeset
1534 __ dec(end_from);
a61af66fc99e Initial load
duke
parents:
diff changeset
1535 __ dec(end_to);
a61af66fc99e Initial load
duke
parents:
diff changeset
1536 __ ldub(end_from, 0, O3);
a61af66fc99e Initial load
duke
parents:
diff changeset
1537 __ deccc(G1);
a61af66fc99e Initial load
duke
parents:
diff changeset
1538 __ brx(Assembler::notZero, false, Assembler::pt, L_align);
a61af66fc99e Initial load
duke
parents:
diff changeset
1539 __ delayed()->stb(O3, end_to, 0);
a61af66fc99e Initial load
duke
parents:
diff changeset
1540 __ BIND(L_skip_alignment);
a61af66fc99e Initial load
duke
parents:
diff changeset
1541 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1542 #ifdef _LP64
a61af66fc99e Initial load
duke
parents:
diff changeset
1543 if (aligned) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1544 // Both arrays are aligned to 8-bytes in 64-bits VM.
a61af66fc99e Initial load
duke
parents:
diff changeset
1545 // The 'count' is decremented in copy_16_bytes_backward_with_shift()
a61af66fc99e Initial load
duke
parents:
diff changeset
1546 // in unaligned case.
a61af66fc99e Initial load
duke
parents:
diff changeset
1547 __ dec(count, 16);
a61af66fc99e Initial load
duke
parents:
diff changeset
1548 } else
a61af66fc99e Initial load
duke
parents:
diff changeset
1549 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
1550 {
a61af66fc99e Initial load
duke
parents:
diff changeset
1551 // Copy with shift 16 bytes per iteration if arrays do not have
a61af66fc99e Initial load
duke
parents:
diff changeset
1552 // the same alignment mod 8, otherwise jump to the next
a61af66fc99e Initial load
duke
parents:
diff changeset
1553 // code for aligned copy (and substracting 16 from 'count' before jump).
a61af66fc99e Initial load
duke
parents:
diff changeset
1554 // The compare above (count >= 11) guarantes 'count' >= 16 bytes.
a61af66fc99e Initial load
duke
parents:
diff changeset
1555 // Also jump over aligned copy after the copy with shift completed.
a61af66fc99e Initial load
duke
parents:
diff changeset
1556
a61af66fc99e Initial load
duke
parents:
diff changeset
1557 copy_16_bytes_backward_with_shift(end_from, end_to, count, 16,
a61af66fc99e Initial load
duke
parents:
diff changeset
1558 L_aligned_copy, L_copy_byte);
a61af66fc99e Initial load
duke
parents:
diff changeset
1559 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1560 // copy 4 elements (16 bytes) at a time
1365
6476042f815c 6940701: Don't align loops in stubs for Niagara sparc
kvn
parents: 1364
diff changeset
1561 __ align(OptoLoopAlignment);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1562 __ BIND(L_aligned_copy);
a61af66fc99e Initial load
duke
parents:
diff changeset
1563 __ dec(end_from, 16);
a61af66fc99e Initial load
duke
parents:
diff changeset
1564 __ ldx(end_from, 8, O3);
a61af66fc99e Initial load
duke
parents:
diff changeset
1565 __ ldx(end_from, 0, O4);
a61af66fc99e Initial load
duke
parents:
diff changeset
1566 __ dec(end_to, 16);
a61af66fc99e Initial load
duke
parents:
diff changeset
1567 __ deccc(count, 16);
a61af66fc99e Initial load
duke
parents:
diff changeset
1568 __ stx(O3, end_to, 8);
a61af66fc99e Initial load
duke
parents:
diff changeset
1569 __ brx(Assembler::greaterEqual, false, Assembler::pt, L_aligned_copy);
a61af66fc99e Initial load
duke
parents:
diff changeset
1570 __ delayed()->stx(O4, end_to, 0);
a61af66fc99e Initial load
duke
parents:
diff changeset
1571 __ inc(count, 16);
a61af66fc99e Initial load
duke
parents:
diff changeset
1572
a61af66fc99e Initial load
duke
parents:
diff changeset
1573 // copy 1 element (2 bytes) at a time
a61af66fc99e Initial load
duke
parents:
diff changeset
1574 __ BIND(L_copy_byte);
3839
3d42f82cd811 7063628: Use cbcond on T4
kvn
parents: 3781
diff changeset
1575 __ cmp_and_br_short(count, 0, Assembler::equal, Assembler::pt, L_exit);
1365
6476042f815c 6940701: Don't align loops in stubs for Niagara sparc
kvn
parents: 1364
diff changeset
1576 __ align(OptoLoopAlignment);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1577 __ BIND(L_copy_byte_loop);
a61af66fc99e Initial load
duke
parents:
diff changeset
1578 __ dec(end_from);
a61af66fc99e Initial load
duke
parents:
diff changeset
1579 __ dec(end_to);
a61af66fc99e Initial load
duke
parents:
diff changeset
1580 __ ldub(end_from, 0, O4);
a61af66fc99e Initial load
duke
parents:
diff changeset
1581 __ deccc(count);
a61af66fc99e Initial load
duke
parents:
diff changeset
1582 __ brx(Assembler::greater, false, Assembler::pt, L_copy_byte_loop);
a61af66fc99e Initial load
duke
parents:
diff changeset
1583 __ delayed()->stb(O4, end_to, 0);
a61af66fc99e Initial load
duke
parents:
diff changeset
1584
a61af66fc99e Initial load
duke
parents:
diff changeset
1585 __ BIND(L_exit);
a61af66fc99e Initial load
duke
parents:
diff changeset
1586 // O3, O4 are used as temp registers
a61af66fc99e Initial load
duke
parents:
diff changeset
1587 inc_counter_np(SharedRuntime::_jbyte_array_copy_ctr, O3, O4);
a61af66fc99e Initial load
duke
parents:
diff changeset
1588 __ retl();
a61af66fc99e Initial load
duke
parents:
diff changeset
1589 __ delayed()->mov(G0, O0); // return 0
a61af66fc99e Initial load
duke
parents:
diff changeset
1590 return start;
a61af66fc99e Initial load
duke
parents:
diff changeset
1591 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1592
a61af66fc99e Initial load
duke
parents:
diff changeset
1593 //
a61af66fc99e Initial load
duke
parents:
diff changeset
1594 // Generate stub for disjoint short copy. If "aligned" is true, the
a61af66fc99e Initial load
duke
parents:
diff changeset
1595 // "from" and "to" addresses are assumed to be heapword aligned.
a61af66fc99e Initial load
duke
parents:
diff changeset
1596 //
a61af66fc99e Initial load
duke
parents:
diff changeset
1597 // Arguments for generated stub:
a61af66fc99e Initial load
duke
parents:
diff changeset
1598 // from: O0
a61af66fc99e Initial load
duke
parents:
diff changeset
1599 // to: O1
a61af66fc99e Initial load
duke
parents:
diff changeset
1600 // count: O2 treated as signed
a61af66fc99e Initial load
duke
parents:
diff changeset
1601 //
2313
d89a22843c62 7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents: 1972
diff changeset
1602 address generate_disjoint_short_copy(bool aligned, address *entry, const char * name) {
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1603 __ align(CodeEntryAlignment);
a61af66fc99e Initial load
duke
parents:
diff changeset
1604 StubCodeMark mark(this, "StubRoutines", name);
a61af66fc99e Initial load
duke
parents:
diff changeset
1605 address start = __ pc();
a61af66fc99e Initial load
duke
parents:
diff changeset
1606
a61af66fc99e Initial load
duke
parents:
diff changeset
1607 Label L_skip_alignment, L_skip_alignment2;
a61af66fc99e Initial load
duke
parents:
diff changeset
1608 Label L_copy_2_bytes, L_copy_2_bytes_loop, L_exit;
a61af66fc99e Initial load
duke
parents:
diff changeset
1609
a61af66fc99e Initial load
duke
parents:
diff changeset
1610 const Register from = O0; // source array address
a61af66fc99e Initial load
duke
parents:
diff changeset
1611 const Register to = O1; // destination array address
a61af66fc99e Initial load
duke
parents:
diff changeset
1612 const Register count = O2; // elements count
a61af66fc99e Initial load
duke
parents:
diff changeset
1613 const Register offset = O5; // offset from start of arrays
a61af66fc99e Initial load
duke
parents:
diff changeset
1614 // O3, O4, G3, G4 are used as temp registers
a61af66fc99e Initial load
duke
parents:
diff changeset
1615
a61af66fc99e Initial load
duke
parents:
diff changeset
1616 assert_clean_int(count, O3); // Make sure 'count' is clean int.
a61af66fc99e Initial load
duke
parents:
diff changeset
1617
2313
d89a22843c62 7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents: 1972
diff changeset
1618 if (entry != NULL) {
d89a22843c62 7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents: 1972
diff changeset
1619 *entry = __ pc();
d89a22843c62 7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents: 1972
diff changeset
1620 // caller can pass a 64-bit byte count here (from Unsafe.copyMemory)
d89a22843c62 7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents: 1972
diff changeset
1621 BLOCK_COMMENT("Entry:");
d89a22843c62 7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents: 1972
diff changeset
1622 }
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1623
a61af66fc99e Initial load
duke
parents:
diff changeset
1624 // for short arrays, just do single element copy
a61af66fc99e Initial load
duke
parents:
diff changeset
1625 __ cmp(count, 11); // 8 + 3 (22 bytes)
a61af66fc99e Initial load
duke
parents:
diff changeset
1626 __ brx(Assembler::less, false, Assembler::pn, L_copy_2_bytes);
a61af66fc99e Initial load
duke
parents:
diff changeset
1627 __ delayed()->mov(G0, offset);
a61af66fc99e Initial load
duke
parents:
diff changeset
1628
a61af66fc99e Initial load
duke
parents:
diff changeset
1629 if (aligned) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1630 // 'aligned' == true when it is known statically during compilation
a61af66fc99e Initial load
duke
parents:
diff changeset
1631 // of this arraycopy call site that both 'from' and 'to' addresses
a61af66fc99e Initial load
duke
parents:
diff changeset
1632 // are HeapWordSize aligned (see LibraryCallKit::basictype2arraycopy()).
a61af66fc99e Initial load
duke
parents:
diff changeset
1633 //
a61af66fc99e Initial load
duke
parents:
diff changeset
1634 // Aligned arrays have 4 bytes alignment in 32-bits VM
a61af66fc99e Initial load
duke
parents:
diff changeset
1635 // and 8 bytes - in 64-bits VM.
a61af66fc99e Initial load
duke
parents:
diff changeset
1636 //
a61af66fc99e Initial load
duke
parents:
diff changeset
1637 #ifndef _LP64
a61af66fc99e Initial load
duke
parents:
diff changeset
1638 // copy a 2-elements word if necessary to align 'to' to 8 bytes
a61af66fc99e Initial load
duke
parents:
diff changeset
1639 __ andcc(to, 7, G0);
a61af66fc99e Initial load
duke
parents:
diff changeset
1640 __ br(Assembler::zero, false, Assembler::pt, L_skip_alignment);
a61af66fc99e Initial load
duke
parents:
diff changeset
1641 __ delayed()->ld(from, 0, O3);
a61af66fc99e Initial load
duke
parents:
diff changeset
1642 __ inc(from, 4);
a61af66fc99e Initial load
duke
parents:
diff changeset
1643 __ inc(to, 4);
a61af66fc99e Initial load
duke
parents:
diff changeset
1644 __ dec(count, 2);
a61af66fc99e Initial load
duke
parents:
diff changeset
1645 __ st(O3, to, -4);
a61af66fc99e Initial load
duke
parents:
diff changeset
1646 __ BIND(L_skip_alignment);
a61af66fc99e Initial load
duke
parents:
diff changeset
1647 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
1648 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
1649 // copy 1 element if necessary to align 'to' on an 4 bytes
a61af66fc99e Initial load
duke
parents:
diff changeset
1650 __ andcc(to, 3, G0);
a61af66fc99e Initial load
duke
parents:
diff changeset
1651 __ br(Assembler::zero, false, Assembler::pt, L_skip_alignment);
a61af66fc99e Initial load
duke
parents:
diff changeset
1652 __ delayed()->lduh(from, 0, O3);
a61af66fc99e Initial load
duke
parents:
diff changeset
1653 __ inc(from, 2);
a61af66fc99e Initial load
duke
parents:
diff changeset
1654 __ inc(to, 2);
a61af66fc99e Initial load
duke
parents:
diff changeset
1655 __ dec(count);
a61af66fc99e Initial load
duke
parents:
diff changeset
1656 __ sth(O3, to, -2);
a61af66fc99e Initial load
duke
parents:
diff changeset
1657 __ BIND(L_skip_alignment);
a61af66fc99e Initial load
duke
parents:
diff changeset
1658
a61af66fc99e Initial load
duke
parents:
diff changeset
1659 // copy 2 elements to align 'to' on an 8 byte boundary
a61af66fc99e Initial load
duke
parents:
diff changeset
1660 __ andcc(to, 7, G0);
a61af66fc99e Initial load
duke
parents:
diff changeset
1661 __ br(Assembler::zero, false, Assembler::pn, L_skip_alignment2);
a61af66fc99e Initial load
duke
parents:
diff changeset
1662 __ delayed()->lduh(from, 0, O3);
a61af66fc99e Initial load
duke
parents:
diff changeset
1663 __ dec(count, 2);
a61af66fc99e Initial load
duke
parents:
diff changeset
1664 __ lduh(from, 2, O4);
a61af66fc99e Initial load
duke
parents:
diff changeset
1665 __ inc(from, 4);
a61af66fc99e Initial load
duke
parents:
diff changeset
1666 __ inc(to, 4);
a61af66fc99e Initial load
duke
parents:
diff changeset
1667 __ sth(O3, to, -4);
a61af66fc99e Initial load
duke
parents:
diff changeset
1668 __ sth(O4, to, -2);
a61af66fc99e Initial load
duke
parents:
diff changeset
1669 __ BIND(L_skip_alignment2);
a61af66fc99e Initial load
duke
parents:
diff changeset
1670 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1671 #ifdef _LP64
a61af66fc99e Initial load
duke
parents:
diff changeset
1672 if (!aligned)
a61af66fc99e Initial load
duke
parents:
diff changeset
1673 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
1674 {
a61af66fc99e Initial load
duke
parents:
diff changeset
1675 // Copy with shift 16 bytes per iteration if arrays do not have
a61af66fc99e Initial load
duke
parents:
diff changeset
1676 // the same alignment mod 8, otherwise fall through to the next
a61af66fc99e Initial load
duke
parents:
diff changeset
1677 // code for aligned copy.
a61af66fc99e Initial load
duke
parents:
diff changeset
1678 // The compare above (count >= 11) guarantes 'count' >= 16 bytes.
a61af66fc99e Initial load
duke
parents:
diff changeset
1679 // Also jump over aligned copy after the copy with shift completed.
a61af66fc99e Initial load
duke
parents:
diff changeset
1680
3903
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
1681 copy_16_bytes_forward_with_shift(from, to, count, 1, L_copy_2_bytes);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1682 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1683
a61af66fc99e Initial load
duke
parents:
diff changeset
1684 // Both array are 8 bytes aligned, copy 16 bytes at a time
a61af66fc99e Initial load
duke
parents:
diff changeset
1685 __ and3(count, 3, G4); // Save
a61af66fc99e Initial load
duke
parents:
diff changeset
1686 __ srl(count, 2, count);
a61af66fc99e Initial load
duke
parents:
diff changeset
1687 generate_disjoint_long_copy_core(aligned);
a61af66fc99e Initial load
duke
parents:
diff changeset
1688 __ mov(G4, count); // restore
a61af66fc99e Initial load
duke
parents:
diff changeset
1689
a61af66fc99e Initial load
duke
parents:
diff changeset
1690 // copy 1 element at a time
a61af66fc99e Initial load
duke
parents:
diff changeset
1691 __ BIND(L_copy_2_bytes);
3839
3d42f82cd811 7063628: Use cbcond on T4
kvn
parents: 3781
diff changeset
1692 __ cmp_and_br_short(count, 0, Assembler::equal, Assembler::pt, L_exit);
1365
6476042f815c 6940701: Don't align loops in stubs for Niagara sparc
kvn
parents: 1364
diff changeset
1693 __ align(OptoLoopAlignment);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1694 __ BIND(L_copy_2_bytes_loop);
a61af66fc99e Initial load
duke
parents:
diff changeset
1695 __ lduh(from, offset, O3);
a61af66fc99e Initial load
duke
parents:
diff changeset
1696 __ deccc(count);
a61af66fc99e Initial load
duke
parents:
diff changeset
1697 __ sth(O3, to, offset);
a61af66fc99e Initial load
duke
parents:
diff changeset
1698 __ brx(Assembler::notZero, false, Assembler::pt, L_copy_2_bytes_loop);
a61af66fc99e Initial load
duke
parents:
diff changeset
1699 __ delayed()->inc(offset, 2);
a61af66fc99e Initial load
duke
parents:
diff changeset
1700
a61af66fc99e Initial load
duke
parents:
diff changeset
1701 __ BIND(L_exit);
a61af66fc99e Initial load
duke
parents:
diff changeset
1702 // O3, O4 are used as temp registers
a61af66fc99e Initial load
duke
parents:
diff changeset
1703 inc_counter_np(SharedRuntime::_jshort_array_copy_ctr, O3, O4);
a61af66fc99e Initial load
duke
parents:
diff changeset
1704 __ retl();
a61af66fc99e Initial load
duke
parents:
diff changeset
1705 __ delayed()->mov(G0, O0); // return 0
a61af66fc99e Initial load
duke
parents:
diff changeset
1706 return start;
a61af66fc99e Initial load
duke
parents:
diff changeset
1707 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1708
a61af66fc99e Initial load
duke
parents:
diff changeset
1709 //
1763
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1710 // Generate stub for disjoint short fill. If "aligned" is true, the
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1711 // "to" address is assumed to be heapword aligned.
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1712 //
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1713 // Arguments for generated stub:
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1714 // to: O0
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1715 // value: O1
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1716 // count: O2 treated as signed
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1717 //
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1718 address generate_fill(BasicType t, bool aligned, const char* name) {
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1719 __ align(CodeEntryAlignment);
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1720 StubCodeMark mark(this, "StubRoutines", name);
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1721 address start = __ pc();
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1722
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1723 const Register to = O0; // source array address
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1724 const Register value = O1; // fill value
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1725 const Register count = O2; // elements count
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1726 // O3 is used as a temp register
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1727
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1728 assert_clean_int(count, O3); // Make sure 'count' is clean int.
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1729
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1730 Label L_exit, L_skip_align1, L_skip_align2, L_fill_byte;
1794
065dd1ca3ab6 6982370: SIGBUS in jbyte_fill
never
parents: 1782
diff changeset
1731 Label L_fill_2_bytes, L_fill_elements, L_fill_32_bytes;
1763
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1732
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1733 int shift = -1;
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1734 switch (t) {
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1735 case T_BYTE:
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1736 shift = 2;
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1737 break;
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1738 case T_SHORT:
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1739 shift = 1;
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1740 break;
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1741 case T_INT:
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1742 shift = 0;
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1743 break;
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1744 default: ShouldNotReachHere();
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1745 }
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1746
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1747 BLOCK_COMMENT("Entry:");
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1748
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1749 if (t == T_BYTE) {
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1750 // Zero extend value
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1751 __ and3(value, 0xff, value);
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1752 __ sllx(value, 8, O3);
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1753 __ or3(value, O3, value);
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1754 }
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1755 if (t == T_SHORT) {
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1756 // Zero extend value
1794
065dd1ca3ab6 6982370: SIGBUS in jbyte_fill
never
parents: 1782
diff changeset
1757 __ sllx(value, 48, value);
065dd1ca3ab6 6982370: SIGBUS in jbyte_fill
never
parents: 1782
diff changeset
1758 __ srlx(value, 48, value);
1763
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1759 }
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1760 if (t == T_BYTE || t == T_SHORT) {
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1761 __ sllx(value, 16, O3);
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1762 __ or3(value, O3, value);
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1763 }
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1764
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1765 __ cmp(count, 2<<shift); // Short arrays (< 8 bytes) fill by element
1794
065dd1ca3ab6 6982370: SIGBUS in jbyte_fill
never
parents: 1782
diff changeset
1766 __ brx(Assembler::lessUnsigned, false, Assembler::pn, L_fill_elements); // use unsigned cmp
065dd1ca3ab6 6982370: SIGBUS in jbyte_fill
never
parents: 1782
diff changeset
1767 __ delayed()->andcc(count, 1, G0);
1763
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1768
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1769 if (!aligned && (t == T_BYTE || t == T_SHORT)) {
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1770 // align source address at 4 bytes address boundary
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1771 if (t == T_BYTE) {
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1772 // One byte misalignment happens only for byte arrays
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1773 __ andcc(to, 1, G0);
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1774 __ br(Assembler::zero, false, Assembler::pt, L_skip_align1);
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1775 __ delayed()->nop();
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1776 __ stb(value, to, 0);
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1777 __ inc(to, 1);
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1778 __ dec(count, 1);
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1779 __ BIND(L_skip_align1);
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1780 }
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1781 // Two bytes misalignment happens only for byte and short (char) arrays
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1782 __ andcc(to, 2, G0);
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1783 __ br(Assembler::zero, false, Assembler::pt, L_skip_align2);
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1784 __ delayed()->nop();
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1785 __ sth(value, to, 0);
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1786 __ inc(to, 2);
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1787 __ dec(count, 1 << (shift - 1));
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1788 __ BIND(L_skip_align2);
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1789 }
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1790 #ifdef _LP64
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1791 if (!aligned) {
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1792 #endif
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1793 // align to 8 bytes, we know we are 4 byte aligned to start
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1794 __ andcc(to, 7, G0);
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1795 __ br(Assembler::zero, false, Assembler::pt, L_fill_32_bytes);
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1796 __ delayed()->nop();
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1797 __ stw(value, to, 0);
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1798 __ inc(to, 4);
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1799 __ dec(count, 1 << shift);
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1800 __ BIND(L_fill_32_bytes);
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1801 #ifdef _LP64
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1802 }
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1803 #endif
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1804
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1805 if (t == T_INT) {
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1806 // Zero extend value
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1807 __ srl(value, 0, value);
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1808 }
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1809 if (t == T_BYTE || t == T_SHORT || t == T_INT) {
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1810 __ sllx(value, 32, O3);
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1811 __ or3(value, O3, value);
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1812 }
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1813
1782
f353275af40e 6981773: incorrect fill value with OptimizeFill
never
parents: 1763
diff changeset
1814 Label L_check_fill_8_bytes;
f353275af40e 6981773: incorrect fill value with OptimizeFill
never
parents: 1763
diff changeset
1815 // Fill 32-byte chunks
f353275af40e 6981773: incorrect fill value with OptimizeFill
never
parents: 1763
diff changeset
1816 __ subcc(count, 8 << shift, count);
f353275af40e 6981773: incorrect fill value with OptimizeFill
never
parents: 1763
diff changeset
1817 __ brx(Assembler::less, false, Assembler::pt, L_check_fill_8_bytes);
f353275af40e 6981773: incorrect fill value with OptimizeFill
never
parents: 1763
diff changeset
1818 __ delayed()->nop();
f353275af40e 6981773: incorrect fill value with OptimizeFill
never
parents: 1763
diff changeset
1819
1794
065dd1ca3ab6 6982370: SIGBUS in jbyte_fill
never
parents: 1782
diff changeset
1820 Label L_fill_32_bytes_loop, L_fill_4_bytes;
1763
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1821 __ align(16);
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1822 __ BIND(L_fill_32_bytes_loop);
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1823
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1824 __ stx(value, to, 0);
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1825 __ stx(value, to, 8);
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1826 __ stx(value, to, 16);
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1827 __ stx(value, to, 24);
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1828
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1829 __ subcc(count, 8 << shift, count);
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1830 __ brx(Assembler::greaterEqual, false, Assembler::pt, L_fill_32_bytes_loop);
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1831 __ delayed()->add(to, 32, to);
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1832
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1833 __ BIND(L_check_fill_8_bytes);
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1834 __ addcc(count, 8 << shift, count);
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1835 __ brx(Assembler::zero, false, Assembler::pn, L_exit);
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1836 __ delayed()->subcc(count, 1 << (shift + 1), count);
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1837 __ brx(Assembler::less, false, Assembler::pn, L_fill_4_bytes);
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1838 __ delayed()->andcc(count, 1<<shift, G0);
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1839
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1840 //
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1841 // length is too short, just fill 8 bytes at a time
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1842 //
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1843 Label L_fill_8_bytes_loop;
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1844 __ BIND(L_fill_8_bytes_loop);
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1845 __ stx(value, to, 0);
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1846 __ subcc(count, 1 << (shift + 1), count);
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1847 __ brx(Assembler::greaterEqual, false, Assembler::pn, L_fill_8_bytes_loop);
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1848 __ delayed()->add(to, 8, to);
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1849
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1850 // fill trailing 4 bytes
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1851 __ andcc(count, 1<<shift, G0); // in delay slot of branches
1794
065dd1ca3ab6 6982370: SIGBUS in jbyte_fill
never
parents: 1782
diff changeset
1852 if (t == T_INT) {
065dd1ca3ab6 6982370: SIGBUS in jbyte_fill
never
parents: 1782
diff changeset
1853 __ BIND(L_fill_elements);
065dd1ca3ab6 6982370: SIGBUS in jbyte_fill
never
parents: 1782
diff changeset
1854 }
1763
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1855 __ BIND(L_fill_4_bytes);
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1856 __ brx(Assembler::zero, false, Assembler::pt, L_fill_2_bytes);
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1857 if (t == T_BYTE || t == T_SHORT) {
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1858 __ delayed()->andcc(count, 1<<(shift-1), G0);
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1859 } else {
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1860 __ delayed()->nop();
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1861 }
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1862 __ stw(value, to, 0);
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1863 if (t == T_BYTE || t == T_SHORT) {
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1864 __ inc(to, 4);
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1865 // fill trailing 2 bytes
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1866 __ andcc(count, 1<<(shift-1), G0); // in delay slot of branches
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1867 __ BIND(L_fill_2_bytes);
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1868 __ brx(Assembler::zero, false, Assembler::pt, L_fill_byte);
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1869 __ delayed()->andcc(count, 1, count);
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1870 __ sth(value, to, 0);
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1871 if (t == T_BYTE) {
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1872 __ inc(to, 2);
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1873 // fill trailing byte
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1874 __ andcc(count, 1, count); // in delay slot of branches
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1875 __ BIND(L_fill_byte);
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1876 __ brx(Assembler::zero, false, Assembler::pt, L_exit);
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1877 __ delayed()->nop();
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1878 __ stb(value, to, 0);
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1879 } else {
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1880 __ BIND(L_fill_byte);
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1881 }
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1882 } else {
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1883 __ BIND(L_fill_2_bytes);
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1884 }
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1885 __ BIND(L_exit);
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1886 __ retl();
1794
065dd1ca3ab6 6982370: SIGBUS in jbyte_fill
never
parents: 1782
diff changeset
1887 __ delayed()->nop();
065dd1ca3ab6 6982370: SIGBUS in jbyte_fill
never
parents: 1782
diff changeset
1888
065dd1ca3ab6 6982370: SIGBUS in jbyte_fill
never
parents: 1782
diff changeset
1889 // Handle copies less than 8 bytes. Int is handled elsewhere.
065dd1ca3ab6 6982370: SIGBUS in jbyte_fill
never
parents: 1782
diff changeset
1890 if (t == T_BYTE) {
065dd1ca3ab6 6982370: SIGBUS in jbyte_fill
never
parents: 1782
diff changeset
1891 __ BIND(L_fill_elements);
065dd1ca3ab6 6982370: SIGBUS in jbyte_fill
never
parents: 1782
diff changeset
1892 Label L_fill_2, L_fill_4;
065dd1ca3ab6 6982370: SIGBUS in jbyte_fill
never
parents: 1782
diff changeset
1893 // in delay slot __ andcc(count, 1, G0);
065dd1ca3ab6 6982370: SIGBUS in jbyte_fill
never
parents: 1782
diff changeset
1894 __ brx(Assembler::zero, false, Assembler::pt, L_fill_2);
065dd1ca3ab6 6982370: SIGBUS in jbyte_fill
never
parents: 1782
diff changeset
1895 __ delayed()->andcc(count, 2, G0);
065dd1ca3ab6 6982370: SIGBUS in jbyte_fill
never
parents: 1782
diff changeset
1896 __ stb(value, to, 0);
065dd1ca3ab6 6982370: SIGBUS in jbyte_fill
never
parents: 1782
diff changeset
1897 __ inc(to, 1);
065dd1ca3ab6 6982370: SIGBUS in jbyte_fill
never
parents: 1782
diff changeset
1898 __ BIND(L_fill_2);
065dd1ca3ab6 6982370: SIGBUS in jbyte_fill
never
parents: 1782
diff changeset
1899 __ brx(Assembler::zero, false, Assembler::pt, L_fill_4);
065dd1ca3ab6 6982370: SIGBUS in jbyte_fill
never
parents: 1782
diff changeset
1900 __ delayed()->andcc(count, 4, G0);
065dd1ca3ab6 6982370: SIGBUS in jbyte_fill
never
parents: 1782
diff changeset
1901 __ stb(value, to, 0);
065dd1ca3ab6 6982370: SIGBUS in jbyte_fill
never
parents: 1782
diff changeset
1902 __ stb(value, to, 1);
065dd1ca3ab6 6982370: SIGBUS in jbyte_fill
never
parents: 1782
diff changeset
1903 __ inc(to, 2);
065dd1ca3ab6 6982370: SIGBUS in jbyte_fill
never
parents: 1782
diff changeset
1904 __ BIND(L_fill_4);
065dd1ca3ab6 6982370: SIGBUS in jbyte_fill
never
parents: 1782
diff changeset
1905 __ brx(Assembler::zero, false, Assembler::pt, L_exit);
065dd1ca3ab6 6982370: SIGBUS in jbyte_fill
never
parents: 1782
diff changeset
1906 __ delayed()->nop();
065dd1ca3ab6 6982370: SIGBUS in jbyte_fill
never
parents: 1782
diff changeset
1907 __ stb(value, to, 0);
065dd1ca3ab6 6982370: SIGBUS in jbyte_fill
never
parents: 1782
diff changeset
1908 __ stb(value, to, 1);
065dd1ca3ab6 6982370: SIGBUS in jbyte_fill
never
parents: 1782
diff changeset
1909 __ stb(value, to, 2);
065dd1ca3ab6 6982370: SIGBUS in jbyte_fill
never
parents: 1782
diff changeset
1910 __ retl();
065dd1ca3ab6 6982370: SIGBUS in jbyte_fill
never
parents: 1782
diff changeset
1911 __ delayed()->stb(value, to, 3);
065dd1ca3ab6 6982370: SIGBUS in jbyte_fill
never
parents: 1782
diff changeset
1912 }
065dd1ca3ab6 6982370: SIGBUS in jbyte_fill
never
parents: 1782
diff changeset
1913
065dd1ca3ab6 6982370: SIGBUS in jbyte_fill
never
parents: 1782
diff changeset
1914 if (t == T_SHORT) {
065dd1ca3ab6 6982370: SIGBUS in jbyte_fill
never
parents: 1782
diff changeset
1915 Label L_fill_2;
065dd1ca3ab6 6982370: SIGBUS in jbyte_fill
never
parents: 1782
diff changeset
1916 __ BIND(L_fill_elements);
065dd1ca3ab6 6982370: SIGBUS in jbyte_fill
never
parents: 1782
diff changeset
1917 // in delay slot __ andcc(count, 1, G0);
065dd1ca3ab6 6982370: SIGBUS in jbyte_fill
never
parents: 1782
diff changeset
1918 __ brx(Assembler::zero, false, Assembler::pt, L_fill_2);
065dd1ca3ab6 6982370: SIGBUS in jbyte_fill
never
parents: 1782
diff changeset
1919 __ delayed()->andcc(count, 2, G0);
065dd1ca3ab6 6982370: SIGBUS in jbyte_fill
never
parents: 1782
diff changeset
1920 __ sth(value, to, 0);
065dd1ca3ab6 6982370: SIGBUS in jbyte_fill
never
parents: 1782
diff changeset
1921 __ inc(to, 2);
065dd1ca3ab6 6982370: SIGBUS in jbyte_fill
never
parents: 1782
diff changeset
1922 __ BIND(L_fill_2);
065dd1ca3ab6 6982370: SIGBUS in jbyte_fill
never
parents: 1782
diff changeset
1923 __ brx(Assembler::zero, false, Assembler::pt, L_exit);
065dd1ca3ab6 6982370: SIGBUS in jbyte_fill
never
parents: 1782
diff changeset
1924 __ delayed()->nop();
065dd1ca3ab6 6982370: SIGBUS in jbyte_fill
never
parents: 1782
diff changeset
1925 __ sth(value, to, 0);
065dd1ca3ab6 6982370: SIGBUS in jbyte_fill
never
parents: 1782
diff changeset
1926 __ retl();
065dd1ca3ab6 6982370: SIGBUS in jbyte_fill
never
parents: 1782
diff changeset
1927 __ delayed()->sth(value, to, 2);
065dd1ca3ab6 6982370: SIGBUS in jbyte_fill
never
parents: 1782
diff changeset
1928 }
1763
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1929 return start;
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1930 }
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1931
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
1932 //
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1933 // Generate stub for conjoint short copy. If "aligned" is true, the
a61af66fc99e Initial load
duke
parents:
diff changeset
1934 // "from" and "to" addresses are assumed to be heapword aligned.
a61af66fc99e Initial load
duke
parents:
diff changeset
1935 //
a61af66fc99e Initial load
duke
parents:
diff changeset
1936 // Arguments for generated stub:
a61af66fc99e Initial load
duke
parents:
diff changeset
1937 // from: O0
a61af66fc99e Initial load
duke
parents:
diff changeset
1938 // to: O1
a61af66fc99e Initial load
duke
parents:
diff changeset
1939 // count: O2 treated as signed
a61af66fc99e Initial load
duke
parents:
diff changeset
1940 //
2313
d89a22843c62 7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents: 1972
diff changeset
1941 address generate_conjoint_short_copy(bool aligned, address nooverlap_target,
d89a22843c62 7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents: 1972
diff changeset
1942 address *entry, const char *name) {
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1943 // Do reverse copy.
a61af66fc99e Initial load
duke
parents:
diff changeset
1944
a61af66fc99e Initial load
duke
parents:
diff changeset
1945 __ align(CodeEntryAlignment);
a61af66fc99e Initial load
duke
parents:
diff changeset
1946 StubCodeMark mark(this, "StubRoutines", name);
a61af66fc99e Initial load
duke
parents:
diff changeset
1947 address start = __ pc();
a61af66fc99e Initial load
duke
parents:
diff changeset
1948
a61af66fc99e Initial load
duke
parents:
diff changeset
1949 Label L_skip_alignment, L_skip_alignment2, L_aligned_copy;
a61af66fc99e Initial load
duke
parents:
diff changeset
1950 Label L_copy_2_bytes, L_copy_2_bytes_loop, L_exit;
a61af66fc99e Initial load
duke
parents:
diff changeset
1951
a61af66fc99e Initial load
duke
parents:
diff changeset
1952 const Register from = O0; // source array address
a61af66fc99e Initial load
duke
parents:
diff changeset
1953 const Register to = O1; // destination array address
a61af66fc99e Initial load
duke
parents:
diff changeset
1954 const Register count = O2; // elements count
a61af66fc99e Initial load
duke
parents:
diff changeset
1955 const Register end_from = from; // source array end address
a61af66fc99e Initial load
duke
parents:
diff changeset
1956 const Register end_to = to; // destination array end address
a61af66fc99e Initial load
duke
parents:
diff changeset
1957
a61af66fc99e Initial load
duke
parents:
diff changeset
1958 const Register byte_count = O3; // bytes count to copy
a61af66fc99e Initial load
duke
parents:
diff changeset
1959
a61af66fc99e Initial load
duke
parents:
diff changeset
1960 assert_clean_int(count, O3); // Make sure 'count' is clean int.
a61af66fc99e Initial load
duke
parents:
diff changeset
1961
2313
d89a22843c62 7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents: 1972
diff changeset
1962 if (entry != NULL) {
d89a22843c62 7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents: 1972
diff changeset
1963 *entry = __ pc();
d89a22843c62 7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents: 1972
diff changeset
1964 // caller can pass a 64-bit byte count here (from Unsafe.copyMemory)
d89a22843c62 7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents: 1972
diff changeset
1965 BLOCK_COMMENT("Entry:");
d89a22843c62 7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents: 1972
diff changeset
1966 }
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1967
a61af66fc99e Initial load
duke
parents:
diff changeset
1968 array_overlap_test(nooverlap_target, 1);
a61af66fc99e Initial load
duke
parents:
diff changeset
1969
a61af66fc99e Initial load
duke
parents:
diff changeset
1970 __ sllx(count, LogBytesPerShort, byte_count);
a61af66fc99e Initial load
duke
parents:
diff changeset
1971 __ add(to, byte_count, end_to); // offset after last copied element
a61af66fc99e Initial load
duke
parents:
diff changeset
1972
a61af66fc99e Initial load
duke
parents:
diff changeset
1973 // for short arrays, just do single element copy
a61af66fc99e Initial load
duke
parents:
diff changeset
1974 __ cmp(count, 11); // 8 + 3 (22 bytes)
a61af66fc99e Initial load
duke
parents:
diff changeset
1975 __ brx(Assembler::less, false, Assembler::pn, L_copy_2_bytes);
a61af66fc99e Initial load
duke
parents:
diff changeset
1976 __ delayed()->add(from, byte_count, end_from);
a61af66fc99e Initial load
duke
parents:
diff changeset
1977
a61af66fc99e Initial load
duke
parents:
diff changeset
1978 {
a61af66fc99e Initial load
duke
parents:
diff changeset
1979 // Align end of arrays since they could be not aligned even
a61af66fc99e Initial load
duke
parents:
diff changeset
1980 // when arrays itself are aligned.
a61af66fc99e Initial load
duke
parents:
diff changeset
1981
a61af66fc99e Initial load
duke
parents:
diff changeset
1982 // copy 1 element if necessary to align 'end_to' on an 4 bytes
a61af66fc99e Initial load
duke
parents:
diff changeset
1983 __ andcc(end_to, 3, G0);
a61af66fc99e Initial load
duke
parents:
diff changeset
1984 __ br(Assembler::zero, false, Assembler::pt, L_skip_alignment);
a61af66fc99e Initial load
duke
parents:
diff changeset
1985 __ delayed()->lduh(end_from, -2, O3);
a61af66fc99e Initial load
duke
parents:
diff changeset
1986 __ dec(end_from, 2);
a61af66fc99e Initial load
duke
parents:
diff changeset
1987 __ dec(end_to, 2);
a61af66fc99e Initial load
duke
parents:
diff changeset
1988 __ dec(count);
a61af66fc99e Initial load
duke
parents:
diff changeset
1989 __ sth(O3, end_to, 0);
a61af66fc99e Initial load
duke
parents:
diff changeset
1990 __ BIND(L_skip_alignment);
a61af66fc99e Initial load
duke
parents:
diff changeset
1991
a61af66fc99e Initial load
duke
parents:
diff changeset
1992 // copy 2 elements to align 'end_to' on an 8 byte boundary
a61af66fc99e Initial load
duke
parents:
diff changeset
1993 __ andcc(end_to, 7, G0);
a61af66fc99e Initial load
duke
parents:
diff changeset
1994 __ br(Assembler::zero, false, Assembler::pn, L_skip_alignment2);
a61af66fc99e Initial load
duke
parents:
diff changeset
1995 __ delayed()->lduh(end_from, -2, O3);
a61af66fc99e Initial load
duke
parents:
diff changeset
1996 __ dec(count, 2);
a61af66fc99e Initial load
duke
parents:
diff changeset
1997 __ lduh(end_from, -4, O4);
a61af66fc99e Initial load
duke
parents:
diff changeset
1998 __ dec(end_from, 4);
a61af66fc99e Initial load
duke
parents:
diff changeset
1999 __ dec(end_to, 4);
a61af66fc99e Initial load
duke
parents:
diff changeset
2000 __ sth(O3, end_to, 2);
a61af66fc99e Initial load
duke
parents:
diff changeset
2001 __ sth(O4, end_to, 0);
a61af66fc99e Initial load
duke
parents:
diff changeset
2002 __ BIND(L_skip_alignment2);
a61af66fc99e Initial load
duke
parents:
diff changeset
2003 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2004 #ifdef _LP64
a61af66fc99e Initial load
duke
parents:
diff changeset
2005 if (aligned) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2006 // Both arrays are aligned to 8-bytes in 64-bits VM.
a61af66fc99e Initial load
duke
parents:
diff changeset
2007 // The 'count' is decremented in copy_16_bytes_backward_with_shift()
a61af66fc99e Initial load
duke
parents:
diff changeset
2008 // in unaligned case.
a61af66fc99e Initial load
duke
parents:
diff changeset
2009 __ dec(count, 8);
a61af66fc99e Initial load
duke
parents:
diff changeset
2010 } else
a61af66fc99e Initial load
duke
parents:
diff changeset
2011 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
2012 {
a61af66fc99e Initial load
duke
parents:
diff changeset
2013 // Copy with shift 16 bytes per iteration if arrays do not have
a61af66fc99e Initial load
duke
parents:
diff changeset
2014 // the same alignment mod 8, otherwise jump to the next
a61af66fc99e Initial load
duke
parents:
diff changeset
2015 // code for aligned copy (and substracting 8 from 'count' before jump).
a61af66fc99e Initial load
duke
parents:
diff changeset
2016 // The compare above (count >= 11) guarantes 'count' >= 16 bytes.
a61af66fc99e Initial load
duke
parents:
diff changeset
2017 // Also jump over aligned copy after the copy with shift completed.
a61af66fc99e Initial load
duke
parents:
diff changeset
2018
a61af66fc99e Initial load
duke
parents:
diff changeset
2019 copy_16_bytes_backward_with_shift(end_from, end_to, count, 8,
a61af66fc99e Initial load
duke
parents:
diff changeset
2020 L_aligned_copy, L_copy_2_bytes);
a61af66fc99e Initial load
duke
parents:
diff changeset
2021 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2022 // copy 4 elements (16 bytes) at a time
1365
6476042f815c 6940701: Don't align loops in stubs for Niagara sparc
kvn
parents: 1364
diff changeset
2023 __ align(OptoLoopAlignment);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2024 __ BIND(L_aligned_copy);
a61af66fc99e Initial load
duke
parents:
diff changeset
2025 __ dec(end_from, 16);
a61af66fc99e Initial load
duke
parents:
diff changeset
2026 __ ldx(end_from, 8, O3);
a61af66fc99e Initial load
duke
parents:
diff changeset
2027 __ ldx(end_from, 0, O4);
a61af66fc99e Initial load
duke
parents:
diff changeset
2028 __ dec(end_to, 16);
a61af66fc99e Initial load
duke
parents:
diff changeset
2029 __ deccc(count, 8);
a61af66fc99e Initial load
duke
parents:
diff changeset
2030 __ stx(O3, end_to, 8);
a61af66fc99e Initial load
duke
parents:
diff changeset
2031 __ brx(Assembler::greaterEqual, false, Assembler::pt, L_aligned_copy);
a61af66fc99e Initial load
duke
parents:
diff changeset
2032 __ delayed()->stx(O4, end_to, 0);
a61af66fc99e Initial load
duke
parents:
diff changeset
2033 __ inc(count, 8);
a61af66fc99e Initial load
duke
parents:
diff changeset
2034
a61af66fc99e Initial load
duke
parents:
diff changeset
2035 // copy 1 element (2 bytes) at a time
a61af66fc99e Initial load
duke
parents:
diff changeset
2036 __ BIND(L_copy_2_bytes);
3839
3d42f82cd811 7063628: Use cbcond on T4
kvn
parents: 3781
diff changeset
2037 __ cmp_and_br_short(count, 0, Assembler::equal, Assembler::pt, L_exit);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2038 __ BIND(L_copy_2_bytes_loop);
a61af66fc99e Initial load
duke
parents:
diff changeset
2039 __ dec(end_from, 2);
a61af66fc99e Initial load
duke
parents:
diff changeset
2040 __ dec(end_to, 2);
a61af66fc99e Initial load
duke
parents:
diff changeset
2041 __ lduh(end_from, 0, O4);
a61af66fc99e Initial load
duke
parents:
diff changeset
2042 __ deccc(count);
a61af66fc99e Initial load
duke
parents:
diff changeset
2043 __ brx(Assembler::greater, false, Assembler::pt, L_copy_2_bytes_loop);
a61af66fc99e Initial load
duke
parents:
diff changeset
2044 __ delayed()->sth(O4, end_to, 0);
a61af66fc99e Initial load
duke
parents:
diff changeset
2045
a61af66fc99e Initial load
duke
parents:
diff changeset
2046 __ BIND(L_exit);
a61af66fc99e Initial load
duke
parents:
diff changeset
2047 // O3, O4 are used as temp registers
a61af66fc99e Initial load
duke
parents:
diff changeset
2048 inc_counter_np(SharedRuntime::_jshort_array_copy_ctr, O3, O4);
a61af66fc99e Initial load
duke
parents:
diff changeset
2049 __ retl();
a61af66fc99e Initial load
duke
parents:
diff changeset
2050 __ delayed()->mov(G0, O0); // return 0
a61af66fc99e Initial load
duke
parents:
diff changeset
2051 return start;
a61af66fc99e Initial load
duke
parents:
diff changeset
2052 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2053
a61af66fc99e Initial load
duke
parents:
diff changeset
2054 //
3903
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
2055 // Helper methods for generate_disjoint_int_copy_core()
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
2056 //
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
2057 void copy_16_bytes_loop(Register from, Register to, Register count, int count_dec,
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
2058 Label& L_loop, bool use_prefetch, bool use_bis) {
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
2059
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
2060 __ align(OptoLoopAlignment);
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
2061 __ BIND(L_loop);
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
2062 if (use_prefetch) {
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
2063 if (ArraycopySrcPrefetchDistance > 0) {
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
2064 __ prefetch(from, ArraycopySrcPrefetchDistance, Assembler::severalReads);
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
2065 }
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
2066 if (ArraycopyDstPrefetchDistance > 0) {
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
2067 __ prefetch(to, ArraycopyDstPrefetchDistance, Assembler::severalWritesAndPossiblyReads);
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
2068 }
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
2069 }
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
2070 __ ldx(from, 4, O4);
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
2071 __ ldx(from, 12, G4);
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
2072 __ inc(to, 16);
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
2073 __ inc(from, 16);
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
2074 __ deccc(count, 4); // Can we do next iteration after this one?
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
2075
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
2076 __ srlx(O4, 32, G3);
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
2077 __ bset(G3, O3);
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
2078 __ sllx(O4, 32, O4);
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
2079 __ srlx(G4, 32, G3);
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
2080 __ bset(G3, O4);
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
2081 if (use_bis) {
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
2082 __ stxa(O3, to, -16);
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
2083 __ stxa(O4, to, -8);
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
2084 } else {
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
2085 __ stx(O3, to, -16);
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
2086 __ stx(O4, to, -8);
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
2087 }
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
2088 __ brx(Assembler::greaterEqual, false, Assembler::pt, L_loop);
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
2089 __ delayed()->sllx(G4, 32, O3);
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
2090
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
2091 }
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
2092
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
2093 //
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2094 // Generate core code for disjoint int copy (and oop copy on 32-bit).
a61af66fc99e Initial load
duke
parents:
diff changeset
2095 // If "aligned" is true, the "from" and "to" addresses are assumed
a61af66fc99e Initial load
duke
parents:
diff changeset
2096 // to be heapword aligned.
a61af66fc99e Initial load
duke
parents:
diff changeset
2097 //
a61af66fc99e Initial load
duke
parents:
diff changeset
2098 // Arguments:
a61af66fc99e Initial load
duke
parents:
diff changeset
2099 // from: O0
a61af66fc99e Initial load
duke
parents:
diff changeset
2100 // to: O1
a61af66fc99e Initial load
duke
parents:
diff changeset
2101 // count: O2 treated as signed
a61af66fc99e Initial load
duke
parents:
diff changeset
2102 //
a61af66fc99e Initial load
duke
parents:
diff changeset
2103 void generate_disjoint_int_copy_core(bool aligned) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2104
a61af66fc99e Initial load
duke
parents:
diff changeset
2105 Label L_skip_alignment, L_aligned_copy;
3903
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
2106 Label L_copy_4_bytes, L_copy_4_bytes_loop, L_exit;
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2107
a61af66fc99e Initial load
duke
parents:
diff changeset
2108 const Register from = O0; // source array address
a61af66fc99e Initial load
duke
parents:
diff changeset
2109 const Register to = O1; // destination array address
a61af66fc99e Initial load
duke
parents:
diff changeset
2110 const Register count = O2; // elements count
a61af66fc99e Initial load
duke
parents:
diff changeset
2111 const Register offset = O5; // offset from start of arrays
a61af66fc99e Initial load
duke
parents:
diff changeset
2112 // O3, O4, G3, G4 are used as temp registers
a61af66fc99e Initial load
duke
parents:
diff changeset
2113
a61af66fc99e Initial load
duke
parents:
diff changeset
2114 // 'aligned' == true when it is known statically during compilation
a61af66fc99e Initial load
duke
parents:
diff changeset
2115 // of this arraycopy call site that both 'from' and 'to' addresses
a61af66fc99e Initial load
duke
parents:
diff changeset
2116 // are HeapWordSize aligned (see LibraryCallKit::basictype2arraycopy()).
a61af66fc99e Initial load
duke
parents:
diff changeset
2117 //
a61af66fc99e Initial load
duke
parents:
diff changeset
2118 // Aligned arrays have 4 bytes alignment in 32-bits VM
a61af66fc99e Initial load
duke
parents:
diff changeset
2119 // and 8 bytes - in 64-bits VM.
a61af66fc99e Initial load
duke
parents:
diff changeset
2120 //
a61af66fc99e Initial load
duke
parents:
diff changeset
2121 #ifdef _LP64
a61af66fc99e Initial load
duke
parents:
diff changeset
2122 if (!aligned)
a61af66fc99e Initial load
duke
parents:
diff changeset
2123 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
2124 {
a61af66fc99e Initial load
duke
parents:
diff changeset
2125 // The next check could be put under 'ifndef' since the code in
a61af66fc99e Initial load
duke
parents:
diff changeset
2126 // generate_disjoint_long_copy_core() has own checks and set 'offset'.
a61af66fc99e Initial load
duke
parents:
diff changeset
2127
a61af66fc99e Initial load
duke
parents:
diff changeset
2128 // for short arrays, just do single element copy
a61af66fc99e Initial load
duke
parents:
diff changeset
2129 __ cmp(count, 5); // 4 + 1 (20 bytes)
a61af66fc99e Initial load
duke
parents:
diff changeset
2130 __ brx(Assembler::lessEqual, false, Assembler::pn, L_copy_4_bytes);
a61af66fc99e Initial load
duke
parents:
diff changeset
2131 __ delayed()->mov(G0, offset);
a61af66fc99e Initial load
duke
parents:
diff changeset
2132
a61af66fc99e Initial load
duke
parents:
diff changeset
2133 // copy 1 element to align 'to' on an 8 byte boundary
a61af66fc99e Initial load
duke
parents:
diff changeset
2134 __ andcc(to, 7, G0);
a61af66fc99e Initial load
duke
parents:
diff changeset
2135 __ br(Assembler::zero, false, Assembler::pt, L_skip_alignment);
a61af66fc99e Initial load
duke
parents:
diff changeset
2136 __ delayed()->ld(from, 0, O3);
a61af66fc99e Initial load
duke
parents:
diff changeset
2137 __ inc(from, 4);
a61af66fc99e Initial load
duke
parents:
diff changeset
2138 __ inc(to, 4);
a61af66fc99e Initial load
duke
parents:
diff changeset
2139 __ dec(count);
a61af66fc99e Initial load
duke
parents:
diff changeset
2140 __ st(O3, to, -4);
a61af66fc99e Initial load
duke
parents:
diff changeset
2141 __ BIND(L_skip_alignment);
a61af66fc99e Initial load
duke
parents:
diff changeset
2142
a61af66fc99e Initial load
duke
parents:
diff changeset
2143 // if arrays have same alignment mod 8, do 4 elements copy
a61af66fc99e Initial load
duke
parents:
diff changeset
2144 __ andcc(from, 7, G0);
a61af66fc99e Initial load
duke
parents:
diff changeset
2145 __ br(Assembler::zero, false, Assembler::pt, L_aligned_copy);
a61af66fc99e Initial load
duke
parents:
diff changeset
2146 __ delayed()->ld(from, 0, O3);
a61af66fc99e Initial load
duke
parents:
diff changeset
2147
a61af66fc99e Initial load
duke
parents:
diff changeset
2148 //
a61af66fc99e Initial load
duke
parents:
diff changeset
2149 // Load 2 aligned 8-bytes chunks and use one from previous iteration
a61af66fc99e Initial load
duke
parents:
diff changeset
2150 // to form 2 aligned 8-bytes chunks to store.
a61af66fc99e Initial load
duke
parents:
diff changeset
2151 //
a61af66fc99e Initial load
duke
parents:
diff changeset
2152 // copy_16_bytes_forward_with_shift() is not used here since this
a61af66fc99e Initial load
duke
parents:
diff changeset
2153 // code is more optimal.
a61af66fc99e Initial load
duke
parents:
diff changeset
2154
a61af66fc99e Initial load
duke
parents:
diff changeset
2155 // copy with shift 4 elements (16 bytes) at a time
a61af66fc99e Initial load
duke
parents:
diff changeset
2156 __ dec(count, 4); // The cmp at the beginning guaranty count >= 4
3903
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
2157 __ sllx(O3, 32, O3);
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
2158
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
2159 disjoint_copy_core(from, to, count, 2, 16, copy_16_bytes_loop);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2160
a61af66fc99e Initial load
duke
parents:
diff changeset
2161 __ br(Assembler::always, false, Assembler::pt, L_copy_4_bytes);
a61af66fc99e Initial load
duke
parents:
diff changeset
2162 __ delayed()->inc(count, 4); // restore 'count'
a61af66fc99e Initial load
duke
parents:
diff changeset
2163
a61af66fc99e Initial load
duke
parents:
diff changeset
2164 __ BIND(L_aligned_copy);
3903
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
2165 } // !aligned
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
2166
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2167 // copy 4 elements (16 bytes) at a time
a61af66fc99e Initial load
duke
parents:
diff changeset
2168 __ and3(count, 1, G4); // Save
a61af66fc99e Initial load
duke
parents:
diff changeset
2169 __ srl(count, 1, count);
a61af66fc99e Initial load
duke
parents:
diff changeset
2170 generate_disjoint_long_copy_core(aligned);
a61af66fc99e Initial load
duke
parents:
diff changeset
2171 __ mov(G4, count); // Restore
a61af66fc99e Initial load
duke
parents:
diff changeset
2172
a61af66fc99e Initial load
duke
parents:
diff changeset
2173 // copy 1 element at a time
a61af66fc99e Initial load
duke
parents:
diff changeset
2174 __ BIND(L_copy_4_bytes);
3839
3d42f82cd811 7063628: Use cbcond on T4
kvn
parents: 3781
diff changeset
2175 __ cmp_and_br_short(count, 0, Assembler::equal, Assembler::pt, L_exit);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2176 __ BIND(L_copy_4_bytes_loop);
a61af66fc99e Initial load
duke
parents:
diff changeset
2177 __ ld(from, offset, O3);
a61af66fc99e Initial load
duke
parents:
diff changeset
2178 __ deccc(count);
a61af66fc99e Initial load
duke
parents:
diff changeset
2179 __ st(O3, to, offset);
a61af66fc99e Initial load
duke
parents:
diff changeset
2180 __ brx(Assembler::notZero, false, Assembler::pt, L_copy_4_bytes_loop);
a61af66fc99e Initial load
duke
parents:
diff changeset
2181 __ delayed()->inc(offset, 4);
a61af66fc99e Initial load
duke
parents:
diff changeset
2182 __ BIND(L_exit);
a61af66fc99e Initial load
duke
parents:
diff changeset
2183 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2184
a61af66fc99e Initial load
duke
parents:
diff changeset
2185 //
a61af66fc99e Initial load
duke
parents:
diff changeset
2186 // Generate stub for disjoint int copy. If "aligned" is true, the
a61af66fc99e Initial load
duke
parents:
diff changeset
2187 // "from" and "to" addresses are assumed to be heapword aligned.
a61af66fc99e Initial load
duke
parents:
diff changeset
2188 //
a61af66fc99e Initial load
duke
parents:
diff changeset
2189 // Arguments for generated stub:
a61af66fc99e Initial load
duke
parents:
diff changeset
2190 // from: O0
a61af66fc99e Initial load
duke
parents:
diff changeset
2191 // to: O1
a61af66fc99e Initial load
duke
parents:
diff changeset
2192 // count: O2 treated as signed
a61af66fc99e Initial load
duke
parents:
diff changeset
2193 //
2313
d89a22843c62 7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents: 1972
diff changeset
2194 address generate_disjoint_int_copy(bool aligned, address *entry, const char *name) {
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2195 __ align(CodeEntryAlignment);
a61af66fc99e Initial load
duke
parents:
diff changeset
2196 StubCodeMark mark(this, "StubRoutines", name);
a61af66fc99e Initial load
duke
parents:
diff changeset
2197 address start = __ pc();
a61af66fc99e Initial load
duke
parents:
diff changeset
2198
a61af66fc99e Initial load
duke
parents:
diff changeset
2199 const Register count = O2;
a61af66fc99e Initial load
duke
parents:
diff changeset
2200 assert_clean_int(count, O3); // Make sure 'count' is clean int.
a61af66fc99e Initial load
duke
parents:
diff changeset
2201
2313
d89a22843c62 7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents: 1972
diff changeset
2202 if (entry != NULL) {
d89a22843c62 7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents: 1972
diff changeset
2203 *entry = __ pc();
d89a22843c62 7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents: 1972
diff changeset
2204 // caller can pass a 64-bit byte count here (from Unsafe.copyMemory)
d89a22843c62 7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents: 1972
diff changeset
2205 BLOCK_COMMENT("Entry:");
d89a22843c62 7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents: 1972
diff changeset
2206 }
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2207
a61af66fc99e Initial load
duke
parents:
diff changeset
2208 generate_disjoint_int_copy_core(aligned);
a61af66fc99e Initial load
duke
parents:
diff changeset
2209
a61af66fc99e Initial load
duke
parents:
diff changeset
2210 // O3, O4 are used as temp registers
a61af66fc99e Initial load
duke
parents:
diff changeset
2211 inc_counter_np(SharedRuntime::_jint_array_copy_ctr, O3, O4);
a61af66fc99e Initial load
duke
parents:
diff changeset
2212 __ retl();
a61af66fc99e Initial load
duke
parents:
diff changeset
2213 __ delayed()->mov(G0, O0); // return 0
a61af66fc99e Initial load
duke
parents:
diff changeset
2214 return start;
a61af66fc99e Initial load
duke
parents:
diff changeset
2215 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2216
a61af66fc99e Initial load
duke
parents:
diff changeset
2217 //
a61af66fc99e Initial load
duke
parents:
diff changeset
2218 // Generate core code for conjoint int copy (and oop copy on 32-bit).
a61af66fc99e Initial load
duke
parents:
diff changeset
2219 // If "aligned" is true, the "from" and "to" addresses are assumed
a61af66fc99e Initial load
duke
parents:
diff changeset
2220 // to be heapword aligned.
a61af66fc99e Initial load
duke
parents:
diff changeset
2221 //
a61af66fc99e Initial load
duke
parents:
diff changeset
2222 // Arguments:
a61af66fc99e Initial load
duke
parents:
diff changeset
2223 // from: O0
a61af66fc99e Initial load
duke
parents:
diff changeset
2224 // to: O1
a61af66fc99e Initial load
duke
parents:
diff changeset
2225 // count: O2 treated as signed
a61af66fc99e Initial load
duke
parents:
diff changeset
2226 //
a61af66fc99e Initial load
duke
parents:
diff changeset
2227 void generate_conjoint_int_copy_core(bool aligned) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2228 // Do reverse copy.
a61af66fc99e Initial load
duke
parents:
diff changeset
2229
a61af66fc99e Initial load
duke
parents:
diff changeset
2230 Label L_skip_alignment, L_aligned_copy;
a61af66fc99e Initial load
duke
parents:
diff changeset
2231 Label L_copy_16_bytes, L_copy_4_bytes, L_copy_4_bytes_loop, L_exit;
a61af66fc99e Initial load
duke
parents:
diff changeset
2232
a61af66fc99e Initial load
duke
parents:
diff changeset
2233 const Register from = O0; // source array address
a61af66fc99e Initial load
duke
parents:
diff changeset
2234 const Register to = O1; // destination array address
a61af66fc99e Initial load
duke
parents:
diff changeset
2235 const Register count = O2; // elements count
a61af66fc99e Initial load
duke
parents:
diff changeset
2236 const Register end_from = from; // source array end address
a61af66fc99e Initial load
duke
parents:
diff changeset
2237 const Register end_to = to; // destination array end address
a61af66fc99e Initial load
duke
parents:
diff changeset
2238 // O3, O4, O5, G3 are used as temp registers
a61af66fc99e Initial load
duke
parents:
diff changeset
2239
a61af66fc99e Initial load
duke
parents:
diff changeset
2240 const Register byte_count = O3; // bytes count to copy
a61af66fc99e Initial load
duke
parents:
diff changeset
2241
a61af66fc99e Initial load
duke
parents:
diff changeset
2242 __ sllx(count, LogBytesPerInt, byte_count);
a61af66fc99e Initial load
duke
parents:
diff changeset
2243 __ add(to, byte_count, end_to); // offset after last copied element
a61af66fc99e Initial load
duke
parents:
diff changeset
2244
a61af66fc99e Initial load
duke
parents:
diff changeset
2245 __ cmp(count, 5); // for short arrays, just do single element copy
a61af66fc99e Initial load
duke
parents:
diff changeset
2246 __ brx(Assembler::lessEqual, false, Assembler::pn, L_copy_4_bytes);
a61af66fc99e Initial load
duke
parents:
diff changeset
2247 __ delayed()->add(from, byte_count, end_from);
a61af66fc99e Initial load
duke
parents:
diff changeset
2248
a61af66fc99e Initial load
duke
parents:
diff changeset
2249 // copy 1 element to align 'to' on an 8 byte boundary
a61af66fc99e Initial load
duke
parents:
diff changeset
2250 __ andcc(end_to, 7, G0);
a61af66fc99e Initial load
duke
parents:
diff changeset
2251 __ br(Assembler::zero, false, Assembler::pt, L_skip_alignment);
a61af66fc99e Initial load
duke
parents:
diff changeset
2252 __ delayed()->nop();
a61af66fc99e Initial load
duke
parents:
diff changeset
2253 __ dec(count);
a61af66fc99e Initial load
duke
parents:
diff changeset
2254 __ dec(end_from, 4);
a61af66fc99e Initial load
duke
parents:
diff changeset
2255 __ dec(end_to, 4);
a61af66fc99e Initial load
duke
parents:
diff changeset
2256 __ ld(end_from, 0, O4);
a61af66fc99e Initial load
duke
parents:
diff changeset
2257 __ st(O4, end_to, 0);
a61af66fc99e Initial load
duke
parents:
diff changeset
2258 __ BIND(L_skip_alignment);
a61af66fc99e Initial load
duke
parents:
diff changeset
2259
a61af66fc99e Initial load
duke
parents:
diff changeset
2260 // Check if 'end_from' and 'end_to' has the same alignment.
a61af66fc99e Initial load
duke
parents:
diff changeset
2261 __ andcc(end_from, 7, G0);
a61af66fc99e Initial load
duke
parents:
diff changeset
2262 __ br(Assembler::zero, false, Assembler::pt, L_aligned_copy);
a61af66fc99e Initial load
duke
parents:
diff changeset
2263 __ delayed()->dec(count, 4); // The cmp at the start guaranty cnt >= 4
a61af66fc99e Initial load
duke
parents:
diff changeset
2264
a61af66fc99e Initial load
duke
parents:
diff changeset
2265 // copy with shift 4 elements (16 bytes) at a time
a61af66fc99e Initial load
duke
parents:
diff changeset
2266 //
a61af66fc99e Initial load
duke
parents:
diff changeset
2267 // Load 2 aligned 8-bytes chunks and use one from previous iteration
a61af66fc99e Initial load
duke
parents:
diff changeset
2268 // to form 2 aligned 8-bytes chunks to store.
a61af66fc99e Initial load
duke
parents:
diff changeset
2269 //
a61af66fc99e Initial load
duke
parents:
diff changeset
2270 __ ldx(end_from, -4, O3);
1365
6476042f815c 6940701: Don't align loops in stubs for Niagara sparc
kvn
parents: 1364
diff changeset
2271 __ align(OptoLoopAlignment);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2272 __ BIND(L_copy_16_bytes);
a61af66fc99e Initial load
duke
parents:
diff changeset
2273 __ ldx(end_from, -12, O4);
a61af66fc99e Initial load
duke
parents:
diff changeset
2274 __ deccc(count, 4);
a61af66fc99e Initial load
duke
parents:
diff changeset
2275 __ ldx(end_from, -20, O5);
a61af66fc99e Initial load
duke
parents:
diff changeset
2276 __ dec(end_to, 16);
a61af66fc99e Initial load
duke
parents:
diff changeset
2277 __ dec(end_from, 16);
a61af66fc99e Initial load
duke
parents:
diff changeset
2278 __ srlx(O3, 32, O3);
a61af66fc99e Initial load
duke
parents:
diff changeset
2279 __ sllx(O4, 32, G3);
a61af66fc99e Initial load
duke
parents:
diff changeset
2280 __ bset(G3, O3);
a61af66fc99e Initial load
duke
parents:
diff changeset
2281 __ stx(O3, end_to, 8);
a61af66fc99e Initial load
duke
parents:
diff changeset
2282 __ srlx(O4, 32, O4);
a61af66fc99e Initial load
duke
parents:
diff changeset
2283 __ sllx(O5, 32, G3);
a61af66fc99e Initial load
duke
parents:
diff changeset
2284 __ bset(O4, G3);
a61af66fc99e Initial load
duke
parents:
diff changeset
2285 __ stx(G3, end_to, 0);
a61af66fc99e Initial load
duke
parents:
diff changeset
2286 __ brx(Assembler::greaterEqual, false, Assembler::pt, L_copy_16_bytes);
a61af66fc99e Initial load
duke
parents:
diff changeset
2287 __ delayed()->mov(O5, O3);
a61af66fc99e Initial load
duke
parents:
diff changeset
2288
a61af66fc99e Initial load
duke
parents:
diff changeset
2289 __ br(Assembler::always, false, Assembler::pt, L_copy_4_bytes);
a61af66fc99e Initial load
duke
parents:
diff changeset
2290 __ delayed()->inc(count, 4);
a61af66fc99e Initial load
duke
parents:
diff changeset
2291
a61af66fc99e Initial load
duke
parents:
diff changeset
2292 // copy 4 elements (16 bytes) at a time
1365
6476042f815c 6940701: Don't align loops in stubs for Niagara sparc
kvn
parents: 1364
diff changeset
2293 __ align(OptoLoopAlignment);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2294 __ BIND(L_aligned_copy);
a61af66fc99e Initial load
duke
parents:
diff changeset
2295 __ dec(end_from, 16);
a61af66fc99e Initial load
duke
parents:
diff changeset
2296 __ ldx(end_from, 8, O3);
a61af66fc99e Initial load
duke
parents:
diff changeset
2297 __ ldx(end_from, 0, O4);
a61af66fc99e Initial load
duke
parents:
diff changeset
2298 __ dec(end_to, 16);
a61af66fc99e Initial load
duke
parents:
diff changeset
2299 __ deccc(count, 4);
a61af66fc99e Initial load
duke
parents:
diff changeset
2300 __ stx(O3, end_to, 8);
a61af66fc99e Initial load
duke
parents:
diff changeset
2301 __ brx(Assembler::greaterEqual, false, Assembler::pt, L_aligned_copy);
a61af66fc99e Initial load
duke
parents:
diff changeset
2302 __ delayed()->stx(O4, end_to, 0);
a61af66fc99e Initial load
duke
parents:
diff changeset
2303 __ inc(count, 4);
a61af66fc99e Initial load
duke
parents:
diff changeset
2304
a61af66fc99e Initial load
duke
parents:
diff changeset
2305 // copy 1 element (4 bytes) at a time
a61af66fc99e Initial load
duke
parents:
diff changeset
2306 __ BIND(L_copy_4_bytes);
3839
3d42f82cd811 7063628: Use cbcond on T4
kvn
parents: 3781
diff changeset
2307 __ cmp_and_br_short(count, 0, Assembler::equal, Assembler::pt, L_exit);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2308 __ BIND(L_copy_4_bytes_loop);
a61af66fc99e Initial load
duke
parents:
diff changeset
2309 __ dec(end_from, 4);
a61af66fc99e Initial load
duke
parents:
diff changeset
2310 __ dec(end_to, 4);
a61af66fc99e Initial load
duke
parents:
diff changeset
2311 __ ld(end_from, 0, O4);
a61af66fc99e Initial load
duke
parents:
diff changeset
2312 __ deccc(count);
a61af66fc99e Initial load
duke
parents:
diff changeset
2313 __ brx(Assembler::greater, false, Assembler::pt, L_copy_4_bytes_loop);
a61af66fc99e Initial load
duke
parents:
diff changeset
2314 __ delayed()->st(O4, end_to, 0);
a61af66fc99e Initial load
duke
parents:
diff changeset
2315 __ BIND(L_exit);
a61af66fc99e Initial load
duke
parents:
diff changeset
2316 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2317
a61af66fc99e Initial load
duke
parents:
diff changeset
2318 //
a61af66fc99e Initial load
duke
parents:
diff changeset
2319 // Generate stub for conjoint int copy. If "aligned" is true, the
a61af66fc99e Initial load
duke
parents:
diff changeset
2320 // "from" and "to" addresses are assumed to be heapword aligned.
a61af66fc99e Initial load
duke
parents:
diff changeset
2321 //
a61af66fc99e Initial load
duke
parents:
diff changeset
2322 // Arguments for generated stub:
a61af66fc99e Initial load
duke
parents:
diff changeset
2323 // from: O0
a61af66fc99e Initial load
duke
parents:
diff changeset
2324 // to: O1
a61af66fc99e Initial load
duke
parents:
diff changeset
2325 // count: O2 treated as signed
a61af66fc99e Initial load
duke
parents:
diff changeset
2326 //
2313
d89a22843c62 7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents: 1972
diff changeset
2327 address generate_conjoint_int_copy(bool aligned, address nooverlap_target,
d89a22843c62 7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents: 1972
diff changeset
2328 address *entry, const char *name) {
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2329 __ align(CodeEntryAlignment);
a61af66fc99e Initial load
duke
parents:
diff changeset
2330 StubCodeMark mark(this, "StubRoutines", name);
a61af66fc99e Initial load
duke
parents:
diff changeset
2331 address start = __ pc();
a61af66fc99e Initial load
duke
parents:
diff changeset
2332
a61af66fc99e Initial load
duke
parents:
diff changeset
2333 assert_clean_int(O2, O3); // Make sure 'count' is clean int.
a61af66fc99e Initial load
duke
parents:
diff changeset
2334
2313
d89a22843c62 7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents: 1972
diff changeset
2335 if (entry != NULL) {
d89a22843c62 7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents: 1972
diff changeset
2336 *entry = __ pc();
d89a22843c62 7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents: 1972
diff changeset
2337 // caller can pass a 64-bit byte count here (from Unsafe.copyMemory)
d89a22843c62 7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents: 1972
diff changeset
2338 BLOCK_COMMENT("Entry:");
d89a22843c62 7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents: 1972
diff changeset
2339 }
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2340
a61af66fc99e Initial load
duke
parents:
diff changeset
2341 array_overlap_test(nooverlap_target, 2);
a61af66fc99e Initial load
duke
parents:
diff changeset
2342
a61af66fc99e Initial load
duke
parents:
diff changeset
2343 generate_conjoint_int_copy_core(aligned);
a61af66fc99e Initial load
duke
parents:
diff changeset
2344
a61af66fc99e Initial load
duke
parents:
diff changeset
2345 // O3, O4 are used as temp registers
a61af66fc99e Initial load
duke
parents:
diff changeset
2346 inc_counter_np(SharedRuntime::_jint_array_copy_ctr, O3, O4);
a61af66fc99e Initial load
duke
parents:
diff changeset
2347 __ retl();
a61af66fc99e Initial load
duke
parents:
diff changeset
2348 __ delayed()->mov(G0, O0); // return 0
a61af66fc99e Initial load
duke
parents:
diff changeset
2349 return start;
a61af66fc99e Initial load
duke
parents:
diff changeset
2350 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2351
a61af66fc99e Initial load
duke
parents:
diff changeset
2352 //
3903
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
2353 // Helper methods for generate_disjoint_long_copy_core()
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
2354 //
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
2355 void copy_64_bytes_loop(Register from, Register to, Register count, int count_dec,
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
2356 Label& L_loop, bool use_prefetch, bool use_bis) {
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
2357 __ align(OptoLoopAlignment);
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
2358 __ BIND(L_loop);
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
2359 for (int off = 0; off < 64; off += 16) {
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
2360 if (use_prefetch && (off & 31) == 0) {
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
2361 if (ArraycopySrcPrefetchDistance > 0) {
3961
a92cdbac8b9e 7081933: Use zeroing elimination optimization for large array
kvn
parents: 3937
diff changeset
2362 __ prefetch(from, ArraycopySrcPrefetchDistance+off, Assembler::severalReads);
3903
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
2363 }
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
2364 if (ArraycopyDstPrefetchDistance > 0) {
3961
a92cdbac8b9e 7081933: Use zeroing elimination optimization for large array
kvn
parents: 3937
diff changeset
2365 __ prefetch(to, ArraycopyDstPrefetchDistance+off, Assembler::severalWritesAndPossiblyReads);
3903
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
2366 }
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
2367 }
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
2368 __ ldx(from, off+0, O4);
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
2369 __ ldx(from, off+8, O5);
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
2370 if (use_bis) {
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
2371 __ stxa(O4, to, off+0);
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
2372 __ stxa(O5, to, off+8);
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
2373 } else {
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
2374 __ stx(O4, to, off+0);
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
2375 __ stx(O5, to, off+8);
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
2376 }
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
2377 }
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
2378 __ deccc(count, 8);
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
2379 __ inc(from, 64);
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
2380 __ brx(Assembler::greaterEqual, false, Assembler::pt, L_loop);
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
2381 __ delayed()->inc(to, 64);
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
2382 }
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
2383
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
2384 //
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2385 // Generate core code for disjoint long copy (and oop copy on 64-bit).
a61af66fc99e Initial load
duke
parents:
diff changeset
2386 // "aligned" is ignored, because we must make the stronger
a61af66fc99e Initial load
duke
parents:
diff changeset
2387 // assumption that both addresses are always 64-bit aligned.
a61af66fc99e Initial load
duke
parents:
diff changeset
2388 //
a61af66fc99e Initial load
duke
parents:
diff changeset
2389 // Arguments:
a61af66fc99e Initial load
duke
parents:
diff changeset
2390 // from: O0
a61af66fc99e Initial load
duke
parents:
diff changeset
2391 // to: O1
a61af66fc99e Initial load
duke
parents:
diff changeset
2392 // count: O2 treated as signed
a61af66fc99e Initial load
duke
parents:
diff changeset
2393 //
1364
0dc88ad3244e 6940677: Use 64 bytes chunk copy for arraycopy on Sparc
kvn
parents: 1295
diff changeset
2394 // count -= 2;
0dc88ad3244e 6940677: Use 64 bytes chunk copy for arraycopy on Sparc
kvn
parents: 1295
diff changeset
2395 // if ( count >= 0 ) { // >= 2 elements
0dc88ad3244e 6940677: Use 64 bytes chunk copy for arraycopy on Sparc
kvn
parents: 1295
diff changeset
2396 // if ( count > 6) { // >= 8 elements
0dc88ad3244e 6940677: Use 64 bytes chunk copy for arraycopy on Sparc
kvn
parents: 1295
diff changeset
2397 // count -= 6; // original count - 8
0dc88ad3244e 6940677: Use 64 bytes chunk copy for arraycopy on Sparc
kvn
parents: 1295
diff changeset
2398 // do {
0dc88ad3244e 6940677: Use 64 bytes chunk copy for arraycopy on Sparc
kvn
parents: 1295
diff changeset
2399 // copy_8_elements;
0dc88ad3244e 6940677: Use 64 bytes chunk copy for arraycopy on Sparc
kvn
parents: 1295
diff changeset
2400 // count -= 8;
0dc88ad3244e 6940677: Use 64 bytes chunk copy for arraycopy on Sparc
kvn
parents: 1295
diff changeset
2401 // } while ( count >= 0 );
0dc88ad3244e 6940677: Use 64 bytes chunk copy for arraycopy on Sparc
kvn
parents: 1295
diff changeset
2402 // count += 6;
0dc88ad3244e 6940677: Use 64 bytes chunk copy for arraycopy on Sparc
kvn
parents: 1295
diff changeset
2403 // }
0dc88ad3244e 6940677: Use 64 bytes chunk copy for arraycopy on Sparc
kvn
parents: 1295
diff changeset
2404 // if ( count >= 0 ) { // >= 2 elements
0dc88ad3244e 6940677: Use 64 bytes chunk copy for arraycopy on Sparc
kvn
parents: 1295
diff changeset
2405 // do {
0dc88ad3244e 6940677: Use 64 bytes chunk copy for arraycopy on Sparc
kvn
parents: 1295
diff changeset
2406 // copy_2_elements;
0dc88ad3244e 6940677: Use 64 bytes chunk copy for arraycopy on Sparc
kvn
parents: 1295
diff changeset
2407 // } while ( (count=count-2) >= 0 );
0dc88ad3244e 6940677: Use 64 bytes chunk copy for arraycopy on Sparc
kvn
parents: 1295
diff changeset
2408 // }
0dc88ad3244e 6940677: Use 64 bytes chunk copy for arraycopy on Sparc
kvn
parents: 1295
diff changeset
2409 // }
0dc88ad3244e 6940677: Use 64 bytes chunk copy for arraycopy on Sparc
kvn
parents: 1295
diff changeset
2410 // count += 2;
0dc88ad3244e 6940677: Use 64 bytes chunk copy for arraycopy on Sparc
kvn
parents: 1295
diff changeset
2411 // if ( count != 0 ) { // 1 element left
0dc88ad3244e 6940677: Use 64 bytes chunk copy for arraycopy on Sparc
kvn
parents: 1295
diff changeset
2412 // copy_1_element;
0dc88ad3244e 6940677: Use 64 bytes chunk copy for arraycopy on Sparc
kvn
parents: 1295
diff changeset
2413 // }
0dc88ad3244e 6940677: Use 64 bytes chunk copy for arraycopy on Sparc
kvn
parents: 1295
diff changeset
2414 //
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2415 void generate_disjoint_long_copy_core(bool aligned) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2416 Label L_copy_8_bytes, L_copy_16_bytes, L_exit;
a61af66fc99e Initial load
duke
parents:
diff changeset
2417 const Register from = O0; // source array address
a61af66fc99e Initial load
duke
parents:
diff changeset
2418 const Register to = O1; // destination array address
a61af66fc99e Initial load
duke
parents:
diff changeset
2419 const Register count = O2; // elements count
a61af66fc99e Initial load
duke
parents:
diff changeset
2420 const Register offset0 = O4; // element offset
a61af66fc99e Initial load
duke
parents:
diff changeset
2421 const Register offset8 = O5; // next element offset
a61af66fc99e Initial load
duke
parents:
diff changeset
2422
3903
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
2423 __ deccc(count, 2);
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
2424 __ mov(G0, offset0); // offset from start of arrays (0)
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
2425 __ brx(Assembler::negative, false, Assembler::pn, L_copy_8_bytes );
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
2426 __ delayed()->add(offset0, 8, offset8);
1364
0dc88ad3244e 6940677: Use 64 bytes chunk copy for arraycopy on Sparc
kvn
parents: 1295
diff changeset
2427
0dc88ad3244e 6940677: Use 64 bytes chunk copy for arraycopy on Sparc
kvn
parents: 1295
diff changeset
2428 // Copy by 64 bytes chunks
3903
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
2429
1364
0dc88ad3244e 6940677: Use 64 bytes chunk copy for arraycopy on Sparc
kvn
parents: 1295
diff changeset
2430 const Register from64 = O3; // source address
0dc88ad3244e 6940677: Use 64 bytes chunk copy for arraycopy on Sparc
kvn
parents: 1295
diff changeset
2431 const Register to64 = G3; // destination address
3903
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
2432 __ subcc(count, 6, O3);
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
2433 __ brx(Assembler::negative, false, Assembler::pt, L_copy_16_bytes );
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
2434 __ delayed()->mov(to, to64);
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
2435 // Now we can use O4(offset0), O5(offset8) as temps
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
2436 __ mov(O3, count);
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
2437 // count >= 0 (original count - 8)
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
2438 __ mov(from, from64);
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
2439
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
2440 disjoint_copy_core(from64, to64, count, 3, 64, copy_64_bytes_loop);
1364
0dc88ad3244e 6940677: Use 64 bytes chunk copy for arraycopy on Sparc
kvn
parents: 1295
diff changeset
2441
0dc88ad3244e 6940677: Use 64 bytes chunk copy for arraycopy on Sparc
kvn
parents: 1295
diff changeset
2442 // Restore O4(offset0), O5(offset8)
0dc88ad3244e 6940677: Use 64 bytes chunk copy for arraycopy on Sparc
kvn
parents: 1295
diff changeset
2443 __ sub(from64, from, offset0);
3903
2f9b79ddb05c 7039731: arraycopy could use prefetch on SPARC
kvn
parents: 3892
diff changeset
2444 __ inccc(count, 6); // restore count
1364
0dc88ad3244e 6940677: Use 64 bytes chunk copy for arraycopy on Sparc
kvn
parents: 1295
diff changeset
2445 __ brx(Assembler::negative, false, Assembler::pn, L_copy_8_bytes );
0dc88ad3244e 6940677: Use 64 bytes chunk copy for arraycopy on Sparc
kvn
parents: 1295
diff changeset
2446 __ delayed()->add(offset0, 8, offset8);
0dc88ad3244e 6940677: Use 64 bytes chunk copy for arraycopy on Sparc
kvn
parents: 1295
diff changeset
2447
0dc88ad3244e 6940677: Use 64 bytes chunk copy for arraycopy on Sparc
kvn
parents: 1295
diff changeset
2448 // Copy by 16 bytes chunks
1365
6476042f815c 6940701: Don't align loops in stubs for Niagara sparc
kvn
parents: 1364
diff changeset
2449 __ align(OptoLoopAlignment);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2450 __ BIND(L_copy_16_bytes);
a61af66fc99e Initial load
duke
parents:
diff changeset
2451 __ ldx(from, offset0, O3);
a61af66fc99e Initial load
duke
parents:
diff changeset
2452 __ ldx(from, offset8, G3);
a61af66fc99e Initial load
duke
parents:
diff changeset
2453 __ deccc(count, 2);
a61af66fc99e Initial load
duke
parents:
diff changeset
2454 __ stx(O3, to, offset0);
a61af66fc99e Initial load
duke
parents:
diff changeset
2455 __ inc(offset0, 16);
a61af66fc99e Initial load
duke
parents:
diff changeset
2456 __ stx(G3, to, offset8);
a61af66fc99e Initial load
duke
parents:
diff changeset
2457 __ brx(Assembler::greaterEqual, false, Assembler::pt, L_copy_16_bytes);
a61af66fc99e Initial load
duke
parents:
diff changeset
2458 __ delayed()->inc(offset8, 16);
a61af66fc99e Initial load
duke
parents:
diff changeset
2459
1364
0dc88ad3244e 6940677: Use 64 bytes chunk copy for arraycopy on Sparc
kvn
parents: 1295
diff changeset
2460 // Copy last 8 bytes
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2461 __ BIND(L_copy_8_bytes);
a61af66fc99e Initial load
duke
parents:
diff changeset
2462 __ inccc(count, 2);
a61af66fc99e Initial load
duke
parents:
diff changeset
2463 __ brx(Assembler::zero, true, Assembler::pn, L_exit );
a61af66fc99e Initial load
duke
parents:
diff changeset
2464 __ delayed()->mov(offset0, offset8); // Set O5 used by other stubs
a61af66fc99e Initial load
duke
parents:
diff changeset
2465 __ ldx(from, offset0, O3);
a61af66fc99e Initial load
duke
parents:
diff changeset
2466 __ stx(O3, to, offset0);
a61af66fc99e Initial load
duke
parents:
diff changeset
2467 __ BIND(L_exit);
a61af66fc99e Initial load
duke
parents:
diff changeset
2468 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2469
a61af66fc99e Initial load
duke
parents:
diff changeset
2470 //
a61af66fc99e Initial load
duke
parents:
diff changeset
2471 // Generate stub for disjoint long copy.
a61af66fc99e Initial load
duke
parents:
diff changeset
2472 // "aligned" is ignored, because we must make the stronger
a61af66fc99e Initial load
duke
parents:
diff changeset
2473 // assumption that both addresses are always 64-bit aligned.
a61af66fc99e Initial load
duke
parents:
diff changeset
2474 //
a61af66fc99e Initial load
duke
parents:
diff changeset
2475 // Arguments for generated stub:
a61af66fc99e Initial load
duke
parents:
diff changeset
2476 // from: O0
a61af66fc99e Initial load
duke
parents:
diff changeset
2477 // to: O1
a61af66fc99e Initial load
duke
parents:
diff changeset
2478 // count: O2 treated as signed
a61af66fc99e Initial load
duke
parents:
diff changeset
2479 //
2313
d89a22843c62 7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents: 1972
diff changeset
2480 address generate_disjoint_long_copy(bool aligned, address *entry, const char *name) {
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2481 __ align(CodeEntryAlignment);
a61af66fc99e Initial load
duke
parents:
diff changeset
2482 StubCodeMark mark(this, "StubRoutines", name);
a61af66fc99e Initial load
duke
parents:
diff changeset
2483 address start = __ pc();
a61af66fc99e Initial load
duke
parents:
diff changeset
2484
a61af66fc99e Initial load
duke
parents:
diff changeset
2485 assert_clean_int(O2, O3); // Make sure 'count' is clean int.
a61af66fc99e Initial load
duke
parents:
diff changeset
2486
2313
d89a22843c62 7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents: 1972
diff changeset
2487 if (entry != NULL) {
d89a22843c62 7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents: 1972
diff changeset
2488 *entry = __ pc();
d89a22843c62 7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents: 1972
diff changeset
2489 // caller can pass a 64-bit byte count here (from Unsafe.copyMemory)
d89a22843c62 7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents: 1972
diff changeset
2490 BLOCK_COMMENT("Entry:");
d89a22843c62 7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents: 1972
diff changeset
2491 }
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2492
a61af66fc99e Initial load
duke
parents:
diff changeset
2493 generate_disjoint_long_copy_core(aligned);
a61af66fc99e Initial load
duke
parents:
diff changeset
2494
a61af66fc99e Initial load
duke
parents:
diff changeset
2495 // O3, O4 are used as temp registers
a61af66fc99e Initial load
duke
parents:
diff changeset
2496 inc_counter_np(SharedRuntime::_jlong_array_copy_ctr, O3, O4);
a61af66fc99e Initial load
duke
parents:
diff changeset
2497 __ retl();
a61af66fc99e Initial load
duke
parents:
diff changeset
2498 __ delayed()->mov(G0, O0); // return 0
a61af66fc99e Initial load
duke
parents:
diff changeset
2499 return start;
a61af66fc99e Initial load
duke
parents:
diff changeset
2500 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2501
a61af66fc99e Initial load
duke
parents:
diff changeset
2502 //
a61af66fc99e Initial load
duke
parents:
diff changeset
2503 // Generate core code for conjoint long copy (and oop copy on 64-bit).
a61af66fc99e Initial load
duke
parents:
diff changeset
2504 // "aligned" is ignored, because we must make the stronger
a61af66fc99e Initial load
duke
parents:
diff changeset
2505 // assumption that both addresses are always 64-bit aligned.
a61af66fc99e Initial load
duke
parents:
diff changeset
2506 //
a61af66fc99e Initial load
duke
parents:
diff changeset
2507 // Arguments:
a61af66fc99e Initial load
duke
parents:
diff changeset
2508 // from: O0
a61af66fc99e Initial load
duke
parents:
diff changeset
2509 // to: O1
a61af66fc99e Initial load
duke
parents:
diff changeset
2510 // count: O2 treated as signed
a61af66fc99e Initial load
duke
parents:
diff changeset
2511 //
a61af66fc99e Initial load
duke
parents:
diff changeset
2512 void generate_conjoint_long_copy_core(bool aligned) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2513 // Do reverse copy.
a61af66fc99e Initial load
duke
parents:
diff changeset
2514 Label L_copy_8_bytes, L_copy_16_bytes, L_exit;
a61af66fc99e Initial load
duke
parents:
diff changeset
2515 const Register from = O0; // source array address
a61af66fc99e Initial load
duke
parents:
diff changeset
2516 const Register to = O1; // destination array address
a61af66fc99e Initial load
duke
parents:
diff changeset
2517 const Register count = O2; // elements count
a61af66fc99e Initial load
duke
parents:
diff changeset
2518 const Register offset8 = O4; // element offset
a61af66fc99e Initial load
duke
parents:
diff changeset
2519 const Register offset0 = O5; // previous element offset
a61af66fc99e Initial load
duke
parents:
diff changeset
2520
a61af66fc99e Initial load
duke
parents:
diff changeset
2521 __ subcc(count, 1, count);
a61af66fc99e Initial load
duke
parents:
diff changeset
2522 __ brx(Assembler::lessEqual, false, Assembler::pn, L_copy_8_bytes );
a61af66fc99e Initial load
duke
parents:
diff changeset
2523 __ delayed()->sllx(count, LogBytesPerLong, offset8);
a61af66fc99e Initial load
duke
parents:
diff changeset
2524 __ sub(offset8, 8, offset0);
1365
6476042f815c 6940701: Don't align loops in stubs for Niagara sparc
kvn
parents: 1364
diff changeset
2525 __ align(OptoLoopAlignment);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2526 __ BIND(L_copy_16_bytes);
a61af66fc99e Initial load
duke
parents:
diff changeset
2527 __ ldx(from, offset8, O2);
a61af66fc99e Initial load
duke
parents:
diff changeset
2528 __ ldx(from, offset0, O3);
a61af66fc99e Initial load
duke
parents:
diff changeset
2529 __ stx(O2, to, offset8);
a61af66fc99e Initial load
duke
parents:
diff changeset
2530 __ deccc(offset8, 16); // use offset8 as counter
a61af66fc99e Initial load
duke
parents:
diff changeset
2531 __ stx(O3, to, offset0);
a61af66fc99e Initial load
duke
parents:
diff changeset
2532 __ brx(Assembler::greater, false, Assembler::pt, L_copy_16_bytes);
a61af66fc99e Initial load
duke
parents:
diff changeset
2533 __ delayed()->dec(offset0, 16);
a61af66fc99e Initial load
duke
parents:
diff changeset
2534
a61af66fc99e Initial load
duke
parents:
diff changeset
2535 __ BIND(L_copy_8_bytes);
a61af66fc99e Initial load
duke
parents:
diff changeset
2536 __ brx(Assembler::negative, false, Assembler::pn, L_exit );
a61af66fc99e Initial load
duke
parents:
diff changeset
2537 __ delayed()->nop();
a61af66fc99e Initial load
duke
parents:
diff changeset
2538 __ ldx(from, 0, O3);
a61af66fc99e Initial load
duke
parents:
diff changeset
2539 __ stx(O3, to, 0);
a61af66fc99e Initial load
duke
parents:
diff changeset
2540 __ BIND(L_exit);
a61af66fc99e Initial load
duke
parents:
diff changeset
2541 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2542
a61af66fc99e Initial load
duke
parents:
diff changeset
2543 // Generate stub for conjoint long copy.
a61af66fc99e Initial load
duke
parents:
diff changeset
2544 // "aligned" is ignored, because we must make the stronger
a61af66fc99e Initial load
duke
parents:
diff changeset
2545 // assumption that both addresses are always 64-bit aligned.
a61af66fc99e Initial load
duke
parents:
diff changeset
2546 //
a61af66fc99e Initial load
duke
parents:
diff changeset
2547 // Arguments for generated stub:
a61af66fc99e Initial load
duke
parents:
diff changeset
2548 // from: O0
a61af66fc99e Initial load
duke
parents:
diff changeset
2549 // to: O1
a61af66fc99e Initial load
duke
parents:
diff changeset
2550 // count: O2 treated as signed
a61af66fc99e Initial load
duke
parents:
diff changeset
2551 //
2313
d89a22843c62 7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents: 1972
diff changeset
2552 address generate_conjoint_long_copy(bool aligned, address nooverlap_target,
d89a22843c62 7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents: 1972
diff changeset
2553 address *entry, const char *name) {
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2554 __ align(CodeEntryAlignment);
a61af66fc99e Initial load
duke
parents:
diff changeset
2555 StubCodeMark mark(this, "StubRoutines", name);
a61af66fc99e Initial load
duke
parents:
diff changeset
2556 address start = __ pc();
a61af66fc99e Initial load
duke
parents:
diff changeset
2557
2324
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
2558 assert(aligned, "Should always be aligned");
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2559
a61af66fc99e Initial load
duke
parents:
diff changeset
2560 assert_clean_int(O2, O3); // Make sure 'count' is clean int.
a61af66fc99e Initial load
duke
parents:
diff changeset
2561
2313
d89a22843c62 7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents: 1972
diff changeset
2562 if (entry != NULL) {
d89a22843c62 7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents: 1972
diff changeset
2563 *entry = __ pc();
d89a22843c62 7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents: 1972
diff changeset
2564 // caller can pass a 64-bit byte count here (from Unsafe.copyMemory)
d89a22843c62 7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents: 1972
diff changeset
2565 BLOCK_COMMENT("Entry:");
d89a22843c62 7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents: 1972
diff changeset
2566 }
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2567
a61af66fc99e Initial load
duke
parents:
diff changeset
2568 array_overlap_test(nooverlap_target, 3);
a61af66fc99e Initial load
duke
parents:
diff changeset
2569
a61af66fc99e Initial load
duke
parents:
diff changeset
2570 generate_conjoint_long_copy_core(aligned);
a61af66fc99e Initial load
duke
parents:
diff changeset
2571
a61af66fc99e Initial load
duke
parents:
diff changeset
2572 // O3, O4 are used as temp registers
a61af66fc99e Initial load
duke
parents:
diff changeset
2573 inc_counter_np(SharedRuntime::_jlong_array_copy_ctr, O3, O4);
a61af66fc99e Initial load
duke
parents:
diff changeset
2574 __ retl();
a61af66fc99e Initial load
duke
parents:
diff changeset
2575 __ delayed()->mov(G0, O0); // return 0
a61af66fc99e Initial load
duke
parents:
diff changeset
2576 return start;
a61af66fc99e Initial load
duke
parents:
diff changeset
2577 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2578
a61af66fc99e Initial load
duke
parents:
diff changeset
2579 // Generate stub for disjoint oop copy. If "aligned" is true, the
a61af66fc99e Initial load
duke
parents:
diff changeset
2580 // "from" and "to" addresses are assumed to be heapword aligned.
a61af66fc99e Initial load
duke
parents:
diff changeset
2581 //
a61af66fc99e Initial load
duke
parents:
diff changeset
2582 // Arguments for generated stub:
a61af66fc99e Initial load
duke
parents:
diff changeset
2583 // from: O0
a61af66fc99e Initial load
duke
parents:
diff changeset
2584 // to: O1
a61af66fc99e Initial load
duke
parents:
diff changeset
2585 // count: O2 treated as signed
a61af66fc99e Initial load
duke
parents:
diff changeset
2586 //
2324
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
2587 address generate_disjoint_oop_copy(bool aligned, address *entry, const char *name,
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
2588 bool dest_uninitialized = false) {
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2589
a61af66fc99e Initial load
duke
parents:
diff changeset
2590 const Register from = O0; // source array address
a61af66fc99e Initial load
duke
parents:
diff changeset
2591 const Register to = O1; // destination array address
a61af66fc99e Initial load
duke
parents:
diff changeset
2592 const Register count = O2; // elements count
a61af66fc99e Initial load
duke
parents:
diff changeset
2593
a61af66fc99e Initial load
duke
parents:
diff changeset
2594 __ align(CodeEntryAlignment);
a61af66fc99e Initial load
duke
parents:
diff changeset
2595 StubCodeMark mark(this, "StubRoutines", name);
a61af66fc99e Initial load
duke
parents:
diff changeset
2596 address start = __ pc();
a61af66fc99e Initial load
duke
parents:
diff changeset
2597
a61af66fc99e Initial load
duke
parents:
diff changeset
2598 assert_clean_int(count, O3); // Make sure 'count' is clean int.
a61af66fc99e Initial load
duke
parents:
diff changeset
2599
2313
d89a22843c62 7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents: 1972
diff changeset
2600 if (entry != NULL) {
d89a22843c62 7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents: 1972
diff changeset
2601 *entry = __ pc();
d89a22843c62 7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents: 1972
diff changeset
2602 // caller can pass a 64-bit byte count here
d89a22843c62 7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents: 1972
diff changeset
2603 BLOCK_COMMENT("Entry:");
d89a22843c62 7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents: 1972
diff changeset
2604 }
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2605
a61af66fc99e Initial load
duke
parents:
diff changeset
2606 // save arguments for barrier generation
a61af66fc99e Initial load
duke
parents:
diff changeset
2607 __ mov(to, G1);
a61af66fc99e Initial load
duke
parents:
diff changeset
2608 __ mov(count, G5);
2324
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
2609 gen_write_ref_array_pre_barrier(G1, G5, dest_uninitialized);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2610 #ifdef _LP64
113
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 16
diff changeset
2611 assert_clean_int(count, O3); // Make sure 'count' is clean int.
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 16
diff changeset
2612 if (UseCompressedOops) {
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 16
diff changeset
2613 generate_disjoint_int_copy_core(aligned);
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 16
diff changeset
2614 } else {
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 16
diff changeset
2615 generate_disjoint_long_copy_core(aligned);
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 16
diff changeset
2616 }
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2617 #else
a61af66fc99e Initial load
duke
parents:
diff changeset
2618 generate_disjoint_int_copy_core(aligned);
a61af66fc99e Initial load
duke
parents:
diff changeset
2619 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
2620 // O0 is used as temp register
a61af66fc99e Initial load
duke
parents:
diff changeset
2621 gen_write_ref_array_post_barrier(G1, G5, O0);
a61af66fc99e Initial load
duke
parents:
diff changeset
2622
a61af66fc99e Initial load
duke
parents:
diff changeset
2623 // O3, O4 are used as temp registers
a61af66fc99e Initial load
duke
parents:
diff changeset
2624 inc_counter_np(SharedRuntime::_oop_array_copy_ctr, O3, O4);
a61af66fc99e Initial load
duke
parents:
diff changeset
2625 __ retl();
a61af66fc99e Initial load
duke
parents:
diff changeset
2626 __ delayed()->mov(G0, O0); // return 0
a61af66fc99e Initial load
duke
parents:
diff changeset
2627 return start;
a61af66fc99e Initial load
duke
parents:
diff changeset
2628 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2629
a61af66fc99e Initial load
duke
parents:
diff changeset
2630 // Generate stub for conjoint oop copy. If "aligned" is true, the
a61af66fc99e Initial load
duke
parents:
diff changeset
2631 // "from" and "to" addresses are assumed to be heapword aligned.
a61af66fc99e Initial load
duke
parents:
diff changeset
2632 //
a61af66fc99e Initial load
duke
parents:
diff changeset
2633 // Arguments for generated stub:
a61af66fc99e Initial load
duke
parents:
diff changeset
2634 // from: O0
a61af66fc99e Initial load
duke
parents:
diff changeset
2635 // to: O1
a61af66fc99e Initial load
duke
parents:
diff changeset
2636 // count: O2 treated as signed
a61af66fc99e Initial load
duke
parents:
diff changeset
2637 //
2313
d89a22843c62 7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents: 1972
diff changeset
2638 address generate_conjoint_oop_copy(bool aligned, address nooverlap_target,
2324
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
2639 address *entry, const char *name,
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
2640 bool dest_uninitialized = false) {
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2641
a61af66fc99e Initial load
duke
parents:
diff changeset
2642 const Register from = O0; // source array address
a61af66fc99e Initial load
duke
parents:
diff changeset
2643 const Register to = O1; // destination array address
a61af66fc99e Initial load
duke
parents:
diff changeset
2644 const Register count = O2; // elements count
a61af66fc99e Initial load
duke
parents:
diff changeset
2645
a61af66fc99e Initial load
duke
parents:
diff changeset
2646 __ align(CodeEntryAlignment);
a61af66fc99e Initial load
duke
parents:
diff changeset
2647 StubCodeMark mark(this, "StubRoutines", name);
a61af66fc99e Initial load
duke
parents:
diff changeset
2648 address start = __ pc();
a61af66fc99e Initial load
duke
parents:
diff changeset
2649
a61af66fc99e Initial load
duke
parents:
diff changeset
2650 assert_clean_int(count, O3); // Make sure 'count' is clean int.
a61af66fc99e Initial load
duke
parents:
diff changeset
2651
2313
d89a22843c62 7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents: 1972
diff changeset
2652 if (entry != NULL) {
d89a22843c62 7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents: 1972
diff changeset
2653 *entry = __ pc();
d89a22843c62 7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents: 1972
diff changeset
2654 // caller can pass a 64-bit byte count here
d89a22843c62 7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents: 1972
diff changeset
2655 BLOCK_COMMENT("Entry:");
d89a22843c62 7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents: 1972
diff changeset
2656 }
d89a22843c62 7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents: 1972
diff changeset
2657
d89a22843c62 7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents: 1972
diff changeset
2658 array_overlap_test(nooverlap_target, LogBytesPerHeapOop);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2659
a61af66fc99e Initial load
duke
parents:
diff changeset
2660 // save arguments for barrier generation
a61af66fc99e Initial load
duke
parents:
diff changeset
2661 __ mov(to, G1);
a61af66fc99e Initial load
duke
parents:
diff changeset
2662 __ mov(count, G5);
2324
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
2663 gen_write_ref_array_pre_barrier(G1, G5, dest_uninitialized);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2664
a61af66fc99e Initial load
duke
parents:
diff changeset
2665 #ifdef _LP64
113
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 16
diff changeset
2666 if (UseCompressedOops) {
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 16
diff changeset
2667 generate_conjoint_int_copy_core(aligned);
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 16
diff changeset
2668 } else {
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 16
diff changeset
2669 generate_conjoint_long_copy_core(aligned);
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 16
diff changeset
2670 }
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2671 #else
a61af66fc99e Initial load
duke
parents:
diff changeset
2672 generate_conjoint_int_copy_core(aligned);
a61af66fc99e Initial load
duke
parents:
diff changeset
2673 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
2674
a61af66fc99e Initial load
duke
parents:
diff changeset
2675 // O0 is used as temp register
a61af66fc99e Initial load
duke
parents:
diff changeset
2676 gen_write_ref_array_post_barrier(G1, G5, O0);
a61af66fc99e Initial load
duke
parents:
diff changeset
2677
a61af66fc99e Initial load
duke
parents:
diff changeset
2678 // O3, O4 are used as temp registers
a61af66fc99e Initial load
duke
parents:
diff changeset
2679 inc_counter_np(SharedRuntime::_oop_array_copy_ctr, O3, O4);
a61af66fc99e Initial load
duke
parents:
diff changeset
2680 __ retl();
a61af66fc99e Initial load
duke
parents:
diff changeset
2681 __ delayed()->mov(G0, O0); // return 0
a61af66fc99e Initial load
duke
parents:
diff changeset
2682 return start;
a61af66fc99e Initial load
duke
parents:
diff changeset
2683 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2684
a61af66fc99e Initial load
duke
parents:
diff changeset
2685
a61af66fc99e Initial load
duke
parents:
diff changeset
2686 // Helper for generating a dynamic type check.
a61af66fc99e Initial load
duke
parents:
diff changeset
2687 // Smashes only the given temp registers.
a61af66fc99e Initial load
duke
parents:
diff changeset
2688 void generate_type_check(Register sub_klass,
a61af66fc99e Initial load
duke
parents:
diff changeset
2689 Register super_check_offset,
a61af66fc99e Initial load
duke
parents:
diff changeset
2690 Register super_klass,
a61af66fc99e Initial load
duke
parents:
diff changeset
2691 Register temp,
644
c517646eef23 6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents: 642
diff changeset
2692 Label& L_success) {
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2693 assert_different_registers(sub_klass, super_check_offset, super_klass, temp);
a61af66fc99e Initial load
duke
parents:
diff changeset
2694
a61af66fc99e Initial load
duke
parents:
diff changeset
2695 BLOCK_COMMENT("type_check:");
a61af66fc99e Initial load
duke
parents:
diff changeset
2696
644
c517646eef23 6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents: 642
diff changeset
2697 Label L_miss, L_pop_to_miss;
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2698
a61af66fc99e Initial load
duke
parents:
diff changeset
2699 assert_clean_int(super_check_offset, temp);
a61af66fc99e Initial load
duke
parents:
diff changeset
2700
644
c517646eef23 6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents: 642
diff changeset
2701 __ check_klass_subtype_fast_path(sub_klass, super_klass, temp, noreg,
c517646eef23 6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents: 642
diff changeset
2702 &L_success, &L_miss, NULL,
c517646eef23 6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents: 642
diff changeset
2703 super_check_offset);
c517646eef23 6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents: 642
diff changeset
2704
c517646eef23 6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents: 642
diff changeset
2705 BLOCK_COMMENT("type_check_slow_path:");
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2706 __ save_frame(0);
644
c517646eef23 6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents: 642
diff changeset
2707 __ check_klass_subtype_slow_path(sub_klass->after_save(),
c517646eef23 6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents: 642
diff changeset
2708 super_klass->after_save(),
c517646eef23 6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents: 642
diff changeset
2709 L0, L1, L2, L4,
c517646eef23 6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents: 642
diff changeset
2710 NULL, &L_pop_to_miss);
3839
3d42f82cd811 7063628: Use cbcond on T4
kvn
parents: 3781
diff changeset
2711 __ ba(L_success);
644
c517646eef23 6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents: 642
diff changeset
2712 __ delayed()->restore();
c517646eef23 6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents: 642
diff changeset
2713
c517646eef23 6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents: 642
diff changeset
2714 __ bind(L_pop_to_miss);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2715 __ restore();
a61af66fc99e Initial load
duke
parents:
diff changeset
2716
a61af66fc99e Initial load
duke
parents:
diff changeset
2717 // Fall through on failure!
a61af66fc99e Initial load
duke
parents:
diff changeset
2718 __ BIND(L_miss);
a61af66fc99e Initial load
duke
parents:
diff changeset
2719 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2720
a61af66fc99e Initial load
duke
parents:
diff changeset
2721
a61af66fc99e Initial load
duke
parents:
diff changeset
2722 // Generate stub for checked oop copy.
a61af66fc99e Initial load
duke
parents:
diff changeset
2723 //
a61af66fc99e Initial load
duke
parents:
diff changeset
2724 // Arguments for generated stub:
a61af66fc99e Initial load
duke
parents:
diff changeset
2725 // from: O0
a61af66fc99e Initial load
duke
parents:
diff changeset
2726 // to: O1
a61af66fc99e Initial load
duke
parents:
diff changeset
2727 // count: O2 treated as signed
a61af66fc99e Initial load
duke
parents:
diff changeset
2728 // ckoff: O3 (super_check_offset)
a61af66fc99e Initial load
duke
parents:
diff changeset
2729 // ckval: O4 (super_klass)
a61af66fc99e Initial load
duke
parents:
diff changeset
2730 // ret: O0 zero for success; (-1^K) where K is partial transfer count
a61af66fc99e Initial load
duke
parents:
diff changeset
2731 //
2324
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
2732 address generate_checkcast_copy(const char *name, address *entry, bool dest_uninitialized = false) {
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2733
a61af66fc99e Initial load
duke
parents:
diff changeset
2734 const Register O0_from = O0; // source array address
a61af66fc99e Initial load
duke
parents:
diff changeset
2735 const Register O1_to = O1; // destination array address
a61af66fc99e Initial load
duke
parents:
diff changeset
2736 const Register O2_count = O2; // elements count
a61af66fc99e Initial load
duke
parents:
diff changeset
2737 const Register O3_ckoff = O3; // super_check_offset
a61af66fc99e Initial load
duke
parents:
diff changeset
2738 const Register O4_ckval = O4; // super_klass
a61af66fc99e Initial load
duke
parents:
diff changeset
2739
a61af66fc99e Initial load
duke
parents:
diff changeset
2740 const Register O5_offset = O5; // loop var, with stride wordSize
a61af66fc99e Initial load
duke
parents:
diff changeset
2741 const Register G1_remain = G1; // loop var, with stride -1
a61af66fc99e Initial load
duke
parents:
diff changeset
2742 const Register G3_oop = G3; // actual oop copied
a61af66fc99e Initial load
duke
parents:
diff changeset
2743 const Register G4_klass = G4; // oop._klass
a61af66fc99e Initial load
duke
parents:
diff changeset
2744 const Register G5_super = G5; // oop._klass._primary_supers[ckval]
a61af66fc99e Initial load
duke
parents:
diff changeset
2745
a61af66fc99e Initial load
duke
parents:
diff changeset
2746 __ align(CodeEntryAlignment);
a61af66fc99e Initial load
duke
parents:
diff changeset
2747 StubCodeMark mark(this, "StubRoutines", name);
a61af66fc99e Initial load
duke
parents:
diff changeset
2748 address start = __ pc();
a61af66fc99e Initial load
duke
parents:
diff changeset
2749
a61af66fc99e Initial load
duke
parents:
diff changeset
2750 #ifdef ASSERT
644
c517646eef23 6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents: 642
diff changeset
2751 // We sometimes save a frame (see generate_type_check below).
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2752 // If this will cause trouble, let's fail now instead of later.
a61af66fc99e Initial load
duke
parents:
diff changeset
2753 __ save_frame(0);
a61af66fc99e Initial load
duke
parents:
diff changeset
2754 __ restore();
a61af66fc99e Initial load
duke
parents:
diff changeset
2755 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
2756
1844
75588558f1bf 6980792: Crash "exception happened outside interpreter, nmethods and vtable stubs (1)"
never
parents: 1794
diff changeset
2757 assert_clean_int(O2_count, G1); // Make sure 'count' is clean int.
75588558f1bf 6980792: Crash "exception happened outside interpreter, nmethods and vtable stubs (1)"
never
parents: 1794
diff changeset
2758
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2759 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
2760 // caller guarantees that the arrays really are different
a61af66fc99e Initial load
duke
parents:
diff changeset
2761 // otherwise, we would have to make conjoint checks
a61af66fc99e Initial load
duke
parents:
diff changeset
2762 { Label L;
a61af66fc99e Initial load
duke
parents:
diff changeset
2763 __ mov(O3, G1); // spill: overlap test smashes O3
a61af66fc99e Initial load
duke
parents:
diff changeset
2764 __ mov(O4, G4); // spill: overlap test smashes O4
113
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 16
diff changeset
2765 array_overlap_test(L, LogBytesPerHeapOop);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2766 __ stop("checkcast_copy within a single array");
a61af66fc99e Initial load
duke
parents:
diff changeset
2767 __ bind(L);
a61af66fc99e Initial load
duke
parents:
diff changeset
2768 __ mov(G1, O3);
a61af66fc99e Initial load
duke
parents:
diff changeset
2769 __ mov(G4, O4);
a61af66fc99e Initial load
duke
parents:
diff changeset
2770 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2771 #endif //ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
2772
2313
d89a22843c62 7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents: 1972
diff changeset
2773 if (entry != NULL) {
d89a22843c62 7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents: 1972
diff changeset
2774 *entry = __ pc();
d89a22843c62 7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents: 1972
diff changeset
2775 // caller can pass a 64-bit byte count here (from generic stub)
d89a22843c62 7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents: 1972
diff changeset
2776 BLOCK_COMMENT("Entry:");
d89a22843c62 7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents: 1972
diff changeset
2777 }
2324
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
2778 gen_write_ref_array_pre_barrier(O1_to, O2_count, dest_uninitialized);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2779
a61af66fc99e Initial load
duke
parents:
diff changeset
2780 Label load_element, store_element, do_card_marks, fail, done;
a61af66fc99e Initial load
duke
parents:
diff changeset
2781 __ addcc(O2_count, 0, G1_remain); // initialize loop index, and test it
a61af66fc99e Initial load
duke
parents:
diff changeset
2782 __ brx(Assembler::notZero, false, Assembler::pt, load_element);
a61af66fc99e Initial load
duke
parents:
diff changeset
2783 __ delayed()->mov(G0, O5_offset); // offset from start of arrays
a61af66fc99e Initial load
duke
parents:
diff changeset
2784
a61af66fc99e Initial load
duke
parents:
diff changeset
2785 // Empty array: Nothing to do.
a61af66fc99e Initial load
duke
parents:
diff changeset
2786 inc_counter_np(SharedRuntime::_checkcast_array_copy_ctr, O3, O4);
a61af66fc99e Initial load
duke
parents:
diff changeset
2787 __ retl();
a61af66fc99e Initial load
duke
parents:
diff changeset
2788 __ delayed()->set(0, O0); // return 0 on (trivial) success
a61af66fc99e Initial load
duke
parents:
diff changeset
2789
a61af66fc99e Initial load
duke
parents:
diff changeset
2790 // ======== begin loop ========
a61af66fc99e Initial load
duke
parents:
diff changeset
2791 // (Loop is rotated; its entry is load_element.)
a61af66fc99e Initial load
duke
parents:
diff changeset
2792 // Loop variables:
a61af66fc99e Initial load
duke
parents:
diff changeset
2793 // (O5 = 0; ; O5 += wordSize) --- offset from src, dest arrays
a61af66fc99e Initial load
duke
parents:
diff changeset
2794 // (O2 = len; O2 != 0; O2--) --- number of oops *remaining*
a61af66fc99e Initial load
duke
parents:
diff changeset
2795 // G3, G4, G5 --- current oop, oop.klass, oop.klass.super
1365
6476042f815c 6940701: Don't align loops in stubs for Niagara sparc
kvn
parents: 1364
diff changeset
2796 __ align(OptoLoopAlignment);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2797
644
c517646eef23 6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents: 642
diff changeset
2798 __ BIND(store_element);
c517646eef23 6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents: 642
diff changeset
2799 __ deccc(G1_remain); // decrement the count
113
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 16
diff changeset
2800 __ store_heap_oop(G3_oop, O1_to, O5_offset); // store the oop
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 16
diff changeset
2801 __ inc(O5_offset, heapOopSize); // step to next offset
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2802 __ brx(Assembler::zero, true, Assembler::pt, do_card_marks);
a61af66fc99e Initial load
duke
parents:
diff changeset
2803 __ delayed()->set(0, O0); // return -1 on success
a61af66fc99e Initial load
duke
parents:
diff changeset
2804
a61af66fc99e Initial load
duke
parents:
diff changeset
2805 // ======== loop entry is here ========
644
c517646eef23 6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents: 642
diff changeset
2806 __ BIND(load_element);
113
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 16
diff changeset
2807 __ load_heap_oop(O0_from, O5_offset, G3_oop); // load the oop
3839
3d42f82cd811 7063628: Use cbcond on T4
kvn
parents: 3781
diff changeset
2808 __ br_null_short(G3_oop, Assembler::pt, store_element);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2809
113
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 16
diff changeset
2810 __ load_klass(G3_oop, G4_klass); // query the object klass
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2811
a61af66fc99e Initial load
duke
parents:
diff changeset
2812 generate_type_check(G4_klass, O3_ckoff, O4_ckval, G5_super,
a61af66fc99e Initial load
duke
parents:
diff changeset
2813 // branch to this on success:
644
c517646eef23 6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents: 642
diff changeset
2814 store_element);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2815 // ======== end loop ========
a61af66fc99e Initial load
duke
parents:
diff changeset
2816
a61af66fc99e Initial load
duke
parents:
diff changeset
2817 // It was a real error; we must depend on the caller to finish the job.
a61af66fc99e Initial load
duke
parents:
diff changeset
2818 // Register G1 has number of *remaining* oops, O2 number of *total* oops.
a61af66fc99e Initial load
duke
parents:
diff changeset
2819 // Emit GC store barriers for the oops we have copied (O2 minus G1),
a61af66fc99e Initial load
duke
parents:
diff changeset
2820 // and report their number to the caller.
644
c517646eef23 6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents: 642
diff changeset
2821 __ BIND(fail);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2822 __ subcc(O2_count, G1_remain, O2_count);
a61af66fc99e Initial load
duke
parents:
diff changeset
2823 __ brx(Assembler::zero, false, Assembler::pt, done);
a61af66fc99e Initial load
duke
parents:
diff changeset
2824 __ delayed()->not1(O2_count, O0); // report (-1^K) to caller
a61af66fc99e Initial load
duke
parents:
diff changeset
2825
644
c517646eef23 6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents: 642
diff changeset
2826 __ BIND(do_card_marks);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2827 gen_write_ref_array_post_barrier(O1_to, O2_count, O3); // store check on O1[0..O2]
a61af66fc99e Initial load
duke
parents:
diff changeset
2828
644
c517646eef23 6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents: 642
diff changeset
2829 __ BIND(done);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2830 inc_counter_np(SharedRuntime::_checkcast_array_copy_ctr, O3, O4);
a61af66fc99e Initial load
duke
parents:
diff changeset
2831 __ retl();
a61af66fc99e Initial load
duke
parents:
diff changeset
2832 __ delayed()->nop(); // return value in 00
a61af66fc99e Initial load
duke
parents:
diff changeset
2833
a61af66fc99e Initial load
duke
parents:
diff changeset
2834 return start;
a61af66fc99e Initial load
duke
parents:
diff changeset
2835 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2836
a61af66fc99e Initial load
duke
parents:
diff changeset
2837
a61af66fc99e Initial load
duke
parents:
diff changeset
2838 // Generate 'unsafe' array copy stub
a61af66fc99e Initial load
duke
parents:
diff changeset
2839 // Though just as safe as the other stubs, it takes an unscaled
a61af66fc99e Initial load
duke
parents:
diff changeset
2840 // size_t argument instead of an element count.
a61af66fc99e Initial load
duke
parents:
diff changeset
2841 //
a61af66fc99e Initial load
duke
parents:
diff changeset
2842 // Arguments for generated stub:
a61af66fc99e Initial load
duke
parents:
diff changeset
2843 // from: O0
a61af66fc99e Initial load
duke
parents:
diff changeset
2844 // to: O1
a61af66fc99e Initial load
duke
parents:
diff changeset
2845 // count: O2 byte count, treated as ssize_t, can be zero
a61af66fc99e Initial load
duke
parents:
diff changeset
2846 //
a61af66fc99e Initial load
duke
parents:
diff changeset
2847 // Examines the alignment of the operands and dispatches
a61af66fc99e Initial load
duke
parents:
diff changeset
2848 // to a long, int, short, or byte copy loop.
a61af66fc99e Initial load
duke
parents:
diff changeset
2849 //
2313
d89a22843c62 7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents: 1972
diff changeset
2850 address generate_unsafe_copy(const char* name,
d89a22843c62 7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents: 1972
diff changeset
2851 address byte_copy_entry,
d89a22843c62 7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents: 1972
diff changeset
2852 address short_copy_entry,
d89a22843c62 7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents: 1972
diff changeset
2853 address int_copy_entry,
d89a22843c62 7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents: 1972
diff changeset
2854 address long_copy_entry) {
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2855
a61af66fc99e Initial load
duke
parents:
diff changeset
2856 const Register O0_from = O0; // source array address
a61af66fc99e Initial load
duke
parents:
diff changeset
2857 const Register O1_to = O1; // destination array address
a61af66fc99e Initial load
duke
parents:
diff changeset
2858 const Register O2_count = O2; // elements count
a61af66fc99e Initial load
duke
parents:
diff changeset
2859
a61af66fc99e Initial load
duke
parents:
diff changeset
2860 const Register G1_bits = G1; // test copy of low bits
a61af66fc99e Initial load
duke
parents:
diff changeset
2861
a61af66fc99e Initial load
duke
parents:
diff changeset
2862 __ align(CodeEntryAlignment);
a61af66fc99e Initial load
duke
parents:
diff changeset
2863 StubCodeMark mark(this, "StubRoutines", name);
a61af66fc99e Initial load
duke
parents:
diff changeset
2864 address start = __ pc();
a61af66fc99e Initial load
duke
parents:
diff changeset
2865
a61af66fc99e Initial load
duke
parents:
diff changeset
2866 // bump this on entry, not on exit:
a61af66fc99e Initial load
duke
parents:
diff changeset
2867 inc_counter_np(SharedRuntime::_unsafe_array_copy_ctr, G1, G3);
a61af66fc99e Initial load
duke
parents:
diff changeset
2868
a61af66fc99e Initial load
duke
parents:
diff changeset
2869 __ or3(O0_from, O1_to, G1_bits);
a61af66fc99e Initial load
duke
parents:
diff changeset
2870 __ or3(O2_count, G1_bits, G1_bits);
a61af66fc99e Initial load
duke
parents:
diff changeset
2871
a61af66fc99e Initial load
duke
parents:
diff changeset
2872 __ btst(BytesPerLong-1, G1_bits);
a61af66fc99e Initial load
duke
parents:
diff changeset
2873 __ br(Assembler::zero, true, Assembler::pt,
a61af66fc99e Initial load
duke
parents:
diff changeset
2874 long_copy_entry, relocInfo::runtime_call_type);
a61af66fc99e Initial load
duke
parents:
diff changeset
2875 // scale the count on the way out:
a61af66fc99e Initial load
duke
parents:
diff changeset
2876 __ delayed()->srax(O2_count, LogBytesPerLong, O2_count);
a61af66fc99e Initial load
duke
parents:
diff changeset
2877
a61af66fc99e Initial load
duke
parents:
diff changeset
2878 __ btst(BytesPerInt-1, G1_bits);
a61af66fc99e Initial load
duke
parents:
diff changeset
2879 __ br(Assembler::zero, true, Assembler::pt,
a61af66fc99e Initial load
duke
parents:
diff changeset
2880 int_copy_entry, relocInfo::runtime_call_type);
a61af66fc99e Initial load
duke
parents:
diff changeset
2881 // scale the count on the way out:
a61af66fc99e Initial load
duke
parents:
diff changeset
2882 __ delayed()->srax(O2_count, LogBytesPerInt, O2_count);
a61af66fc99e Initial load
duke
parents:
diff changeset
2883
a61af66fc99e Initial load
duke
parents:
diff changeset
2884 __ btst(BytesPerShort-1, G1_bits);
a61af66fc99e Initial load
duke
parents:
diff changeset
2885 __ br(Assembler::zero, true, Assembler::pt,
a61af66fc99e Initial load
duke
parents:
diff changeset
2886 short_copy_entry, relocInfo::runtime_call_type);
a61af66fc99e Initial load
duke
parents:
diff changeset
2887 // scale the count on the way out:
a61af66fc99e Initial load
duke
parents:
diff changeset
2888 __ delayed()->srax(O2_count, LogBytesPerShort, O2_count);
a61af66fc99e Initial load
duke
parents:
diff changeset
2889
a61af66fc99e Initial load
duke
parents:
diff changeset
2890 __ br(Assembler::always, false, Assembler::pt,
a61af66fc99e Initial load
duke
parents:
diff changeset
2891 byte_copy_entry, relocInfo::runtime_call_type);
a61af66fc99e Initial load
duke
parents:
diff changeset
2892 __ delayed()->nop();
a61af66fc99e Initial load
duke
parents:
diff changeset
2893
a61af66fc99e Initial load
duke
parents:
diff changeset
2894 return start;
a61af66fc99e Initial load
duke
parents:
diff changeset
2895 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2896
a61af66fc99e Initial load
duke
parents:
diff changeset
2897
a61af66fc99e Initial load
duke
parents:
diff changeset
2898 // Perform range checks on the proposed arraycopy.
a61af66fc99e Initial load
duke
parents:
diff changeset
2899 // Kills the two temps, but nothing else.
a61af66fc99e Initial load
duke
parents:
diff changeset
2900 // Also, clean the sign bits of src_pos and dst_pos.
a61af66fc99e Initial load
duke
parents:
diff changeset
2901 void arraycopy_range_checks(Register src, // source array oop (O0)
a61af66fc99e Initial load
duke
parents:
diff changeset
2902 Register src_pos, // source position (O1)
a61af66fc99e Initial load
duke
parents:
diff changeset
2903 Register dst, // destination array oo (O2)
a61af66fc99e Initial load
duke
parents:
diff changeset
2904 Register dst_pos, // destination position (O3)
a61af66fc99e Initial load
duke
parents:
diff changeset
2905 Register length, // length of copy (O4)
a61af66fc99e Initial load
duke
parents:
diff changeset
2906 Register temp1, Register temp2,
a61af66fc99e Initial load
duke
parents:
diff changeset
2907 Label& L_failed) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2908 BLOCK_COMMENT("arraycopy_range_checks:");
a61af66fc99e Initial load
duke
parents:
diff changeset
2909
a61af66fc99e Initial load
duke
parents:
diff changeset
2910 // if (src_pos + length > arrayOop(src)->length() ) FAIL;
a61af66fc99e Initial load
duke
parents:
diff changeset
2911
a61af66fc99e Initial load
duke
parents:
diff changeset
2912 const Register array_length = temp1; // scratch
a61af66fc99e Initial load
duke
parents:
diff changeset
2913 const Register end_pos = temp2; // scratch
a61af66fc99e Initial load
duke
parents:
diff changeset
2914
a61af66fc99e Initial load
duke
parents:
diff changeset
2915 // Note: This next instruction may be in the delay slot of a branch:
a61af66fc99e Initial load
duke
parents:
diff changeset
2916 __ add(length, src_pos, end_pos); // src_pos + length
a61af66fc99e Initial load
duke
parents:
diff changeset
2917 __ lduw(src, arrayOopDesc::length_offset_in_bytes(), array_length);
a61af66fc99e Initial load
duke
parents:
diff changeset
2918 __ cmp(end_pos, array_length);
a61af66fc99e Initial load
duke
parents:
diff changeset
2919 __ br(Assembler::greater, false, Assembler::pn, L_failed);
a61af66fc99e Initial load
duke
parents:
diff changeset
2920
a61af66fc99e Initial load
duke
parents:
diff changeset
2921 // if (dst_pos + length > arrayOop(dst)->length() ) FAIL;
a61af66fc99e Initial load
duke
parents:
diff changeset
2922 __ delayed()->add(length, dst_pos, end_pos); // dst_pos + length
a61af66fc99e Initial load
duke
parents:
diff changeset
2923 __ lduw(dst, arrayOopDesc::length_offset_in_bytes(), array_length);
a61af66fc99e Initial load
duke
parents:
diff changeset
2924 __ cmp(end_pos, array_length);
a61af66fc99e Initial load
duke
parents:
diff changeset
2925 __ br(Assembler::greater, false, Assembler::pn, L_failed);
a61af66fc99e Initial load
duke
parents:
diff changeset
2926
a61af66fc99e Initial load
duke
parents:
diff changeset
2927 // Have to clean up high 32-bits of 'src_pos' and 'dst_pos'.
a61af66fc99e Initial load
duke
parents:
diff changeset
2928 // Move with sign extension can be used since they are positive.
a61af66fc99e Initial load
duke
parents:
diff changeset
2929 __ delayed()->signx(src_pos, src_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
2930 __ signx(dst_pos, dst_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
2931
a61af66fc99e Initial load
duke
parents:
diff changeset
2932 BLOCK_COMMENT("arraycopy_range_checks done");
a61af66fc99e Initial load
duke
parents:
diff changeset
2933 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2934
a61af66fc99e Initial load
duke
parents:
diff changeset
2935
a61af66fc99e Initial load
duke
parents:
diff changeset
2936 //
a61af66fc99e Initial load
duke
parents:
diff changeset
2937 // Generate generic array copy stubs
a61af66fc99e Initial load
duke
parents:
diff changeset
2938 //
a61af66fc99e Initial load
duke
parents:
diff changeset
2939 // Input:
a61af66fc99e Initial load
duke
parents:
diff changeset
2940 // O0 - src oop
a61af66fc99e Initial load
duke
parents:
diff changeset
2941 // O1 - src_pos
a61af66fc99e Initial load
duke
parents:
diff changeset
2942 // O2 - dst oop
a61af66fc99e Initial load
duke
parents:
diff changeset
2943 // O3 - dst_pos
a61af66fc99e Initial load
duke
parents:
diff changeset
2944 // O4 - element count
a61af66fc99e Initial load
duke
parents:
diff changeset
2945 //
a61af66fc99e Initial load
duke
parents:
diff changeset
2946 // Output:
a61af66fc99e Initial load
duke
parents:
diff changeset
2947 // O0 == 0 - success
a61af66fc99e Initial load
duke
parents:
diff changeset
2948 // O0 == -1 - need to call System.arraycopy
a61af66fc99e Initial load
duke
parents:
diff changeset
2949 //
2313
d89a22843c62 7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents: 1972
diff changeset
2950 address generate_generic_copy(const char *name,
d89a22843c62 7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents: 1972
diff changeset
2951 address entry_jbyte_arraycopy,
d89a22843c62 7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents: 1972
diff changeset
2952 address entry_jshort_arraycopy,
d89a22843c62 7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents: 1972
diff changeset
2953 address entry_jint_arraycopy,
d89a22843c62 7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents: 1972
diff changeset
2954 address entry_oop_arraycopy,
d89a22843c62 7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents: 1972
diff changeset
2955 address entry_jlong_arraycopy,
d89a22843c62 7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents: 1972
diff changeset
2956 address entry_checkcast_arraycopy) {
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2957 Label L_failed, L_objArray;
a61af66fc99e Initial load
duke
parents:
diff changeset
2958
a61af66fc99e Initial load
duke
parents:
diff changeset
2959 // Input registers
a61af66fc99e Initial load
duke
parents:
diff changeset
2960 const Register src = O0; // source array oop
a61af66fc99e Initial load
duke
parents:
diff changeset
2961 const Register src_pos = O1; // source position
a61af66fc99e Initial load
duke
parents:
diff changeset
2962 const Register dst = O2; // destination array oop
a61af66fc99e Initial load
duke
parents:
diff changeset
2963 const Register dst_pos = O3; // destination position
a61af66fc99e Initial load
duke
parents:
diff changeset
2964 const Register length = O4; // elements count
a61af66fc99e Initial load
duke
parents:
diff changeset
2965
a61af66fc99e Initial load
duke
parents:
diff changeset
2966 // registers used as temp
a61af66fc99e Initial load
duke
parents:
diff changeset
2967 const Register G3_src_klass = G3; // source array klass
a61af66fc99e Initial load
duke
parents:
diff changeset
2968 const Register G4_dst_klass = G4; // destination array klass
a61af66fc99e Initial load
duke
parents:
diff changeset
2969 const Register G5_lh = G5; // layout handler
a61af66fc99e Initial load
duke
parents:
diff changeset
2970 const Register O5_temp = O5;
a61af66fc99e Initial load
duke
parents:
diff changeset
2971
a61af66fc99e Initial load
duke
parents:
diff changeset
2972 __ align(CodeEntryAlignment);
a61af66fc99e Initial load
duke
parents:
diff changeset
2973 StubCodeMark mark(this, "StubRoutines", name);
a61af66fc99e Initial load
duke
parents:
diff changeset
2974 address start = __ pc();
a61af66fc99e Initial load
duke
parents:
diff changeset
2975
a61af66fc99e Initial load
duke
parents:
diff changeset
2976 // bump this on entry, not on exit:
a61af66fc99e Initial load
duke
parents:
diff changeset
2977 inc_counter_np(SharedRuntime::_generic_array_copy_ctr, G1, G3);
a61af66fc99e Initial load
duke
parents:
diff changeset
2978
a61af66fc99e Initial load
duke
parents:
diff changeset
2979 // In principle, the int arguments could be dirty.
a61af66fc99e Initial load
duke
parents:
diff changeset
2980 //assert_clean_int(src_pos, G1);
a61af66fc99e Initial load
duke
parents:
diff changeset
2981 //assert_clean_int(dst_pos, G1);
a61af66fc99e Initial load
duke
parents:
diff changeset
2982 //assert_clean_int(length, G1);
a61af66fc99e Initial load
duke
parents:
diff changeset
2983
a61af66fc99e Initial load
duke
parents:
diff changeset
2984 //-----------------------------------------------------------------------
a61af66fc99e Initial load
duke
parents:
diff changeset
2985 // Assembler stubs will be used for this call to arraycopy
a61af66fc99e Initial load
duke
parents:
diff changeset
2986 // if the following conditions are met:
a61af66fc99e Initial load
duke
parents:
diff changeset
2987 //
a61af66fc99e Initial load
duke
parents:
diff changeset
2988 // (1) src and dst must not be null.
a61af66fc99e Initial load
duke
parents:
diff changeset
2989 // (2) src_pos must not be negative.
a61af66fc99e Initial load
duke
parents:
diff changeset
2990 // (3) dst_pos must not be negative.
a61af66fc99e Initial load
duke
parents:
diff changeset
2991 // (4) length must not be negative.
a61af66fc99e Initial load
duke
parents:
diff changeset
2992 // (5) src klass and dst klass should be the same and not NULL.
a61af66fc99e Initial load
duke
parents:
diff changeset
2993 // (6) src and dst should be arrays.
a61af66fc99e Initial load
duke
parents:
diff changeset
2994 // (7) src_pos + length must not exceed length of src.
a61af66fc99e Initial load
duke
parents:
diff changeset
2995 // (8) dst_pos + length must not exceed length of dst.
a61af66fc99e Initial load
duke
parents:
diff changeset
2996 BLOCK_COMMENT("arraycopy initial argument checks");
a61af66fc99e Initial load
duke
parents:
diff changeset
2997
a61af66fc99e Initial load
duke
parents:
diff changeset
2998 // if (src == NULL) return -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
2999 __ br_null(src, false, Assembler::pn, L_failed);
a61af66fc99e Initial load
duke
parents:
diff changeset
3000
a61af66fc99e Initial load
duke
parents:
diff changeset
3001 // if (src_pos < 0) return -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
3002 __ delayed()->tst(src_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
3003 __ br(Assembler::negative, false, Assembler::pn, L_failed);
a61af66fc99e Initial load
duke
parents:
diff changeset
3004 __ delayed()->nop();
a61af66fc99e Initial load
duke
parents:
diff changeset
3005
a61af66fc99e Initial load
duke
parents:
diff changeset
3006 // if (dst == NULL) return -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
3007 __ br_null(dst, false, Assembler::pn, L_failed);
a61af66fc99e Initial load
duke
parents:
diff changeset
3008
a61af66fc99e Initial load
duke
parents:
diff changeset
3009 // if (dst_pos < 0) return -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
3010 __ delayed()->tst(dst_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
3011 __ br(Assembler::negative, false, Assembler::pn, L_failed);
a61af66fc99e Initial load
duke
parents:
diff changeset
3012
a61af66fc99e Initial load
duke
parents:
diff changeset
3013 // if (length < 0) return -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
3014 __ delayed()->tst(length);
a61af66fc99e Initial load
duke
parents:
diff changeset
3015 __ br(Assembler::negative, false, Assembler::pn, L_failed);
a61af66fc99e Initial load
duke
parents:
diff changeset
3016
a61af66fc99e Initial load
duke
parents:
diff changeset
3017 BLOCK_COMMENT("arraycopy argument klass checks");
a61af66fc99e Initial load
duke
parents:
diff changeset
3018 // get src->klass()
6725
da91efe96a93 6964458: Reimplement class meta-data storage to use native memory
coleenp
parents: 6266
diff changeset
3019 if (UseCompressedKlassPointers) {
113
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 16
diff changeset
3020 __ delayed()->nop(); // ??? not good
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 16
diff changeset
3021 __ load_klass(src, G3_src_klass);
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 16
diff changeset
3022 } else {
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 16
diff changeset
3023 __ delayed()->ld_ptr(src, oopDesc::klass_offset_in_bytes(), G3_src_klass);
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 16
diff changeset
3024 }
0
a61af66fc99e Initial load
duke
parents:
diff changeset
3025
a61af66fc99e Initial load
duke
parents:
diff changeset
3026 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
3027 // assert(src->klass() != NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
3028 BLOCK_COMMENT("assert klasses not null");
a61af66fc99e Initial load
duke
parents:
diff changeset
3029 { Label L_a, L_b;
3839
3d42f82cd811 7063628: Use cbcond on T4
kvn
parents: 3781
diff changeset
3030 __ br_notnull_short(G3_src_klass, Assembler::pt, L_b); // it is broken if klass is NULL
0
a61af66fc99e Initial load
duke
parents:
diff changeset
3031 __ bind(L_a);
a61af66fc99e Initial load
duke
parents:
diff changeset
3032 __ stop("broken null klass");
a61af66fc99e Initial load
duke
parents:
diff changeset
3033 __ bind(L_b);
113
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 16
diff changeset
3034 __ load_klass(dst, G4_dst_klass);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
3035 __ br_null(G4_dst_klass, false, Assembler::pn, L_a); // this would be broken also
a61af66fc99e Initial load
duke
parents:
diff changeset
3036 __ delayed()->mov(G0, G4_dst_klass); // scribble the temp
a61af66fc99e Initial load
duke
parents:
diff changeset
3037 BLOCK_COMMENT("assert done");
a61af66fc99e Initial load
duke
parents:
diff changeset
3038 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3039 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
3040
a61af66fc99e Initial load
duke
parents:
diff changeset
3041 // Load layout helper
a61af66fc99e Initial load
duke
parents:
diff changeset
3042 //
a61af66fc99e Initial load
duke
parents:
diff changeset
3043 // |array_tag| | header_size | element_type | |log2_element_size|
a61af66fc99e Initial load
duke
parents:
diff changeset
3044 // 32 30 24 16 8 2 0
a61af66fc99e Initial load
duke
parents:
diff changeset
3045 //
a61af66fc99e Initial load
duke
parents:
diff changeset
3046 // array_tag: typeArray = 0x3, objArray = 0x2, non-array = 0x0
a61af66fc99e Initial load
duke
parents:
diff changeset
3047 //
a61af66fc99e Initial load
duke
parents:
diff changeset
3048
4762
069ab3f976d3 7118863: Move sizeof(klassOopDesc) into the *Klass::*_offset_in_bytes() functions
stefank
parents: 3961
diff changeset
3049 int lh_offset = in_bytes(Klass::layout_helper_offset());
0
a61af66fc99e Initial load
duke
parents:
diff changeset
3050
a61af66fc99e Initial load
duke
parents:
diff changeset
3051 // Load 32-bits signed value. Use br() instruction with it to check icc.
a61af66fc99e Initial load
duke
parents:
diff changeset
3052 __ lduw(G3_src_klass, lh_offset, G5_lh);
a61af66fc99e Initial load
duke
parents:
diff changeset
3053
6725
da91efe96a93 6964458: Reimplement class meta-data storage to use native memory
coleenp
parents: 6266
diff changeset
3054 if (UseCompressedKlassPointers) {
113
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 16
diff changeset
3055 __ load_klass(dst, G4_dst_klass);
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 16
diff changeset
3056 }
0
a61af66fc99e Initial load
duke
parents:
diff changeset
3057 // Handle objArrays completely differently...
a61af66fc99e Initial load
duke
parents:
diff changeset
3058 juint objArray_lh = Klass::array_layout_helper(T_OBJECT);
a61af66fc99e Initial load
duke
parents:
diff changeset
3059 __ set(objArray_lh, O5_temp);
a61af66fc99e Initial load
duke
parents:
diff changeset
3060 __ cmp(G5_lh, O5_temp);
a61af66fc99e Initial load
duke
parents:
diff changeset
3061 __ br(Assembler::equal, false, Assembler::pt, L_objArray);
6725
da91efe96a93 6964458: Reimplement class meta-data storage to use native memory
coleenp
parents: 6266
diff changeset
3062 if (UseCompressedKlassPointers) {
113
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 16
diff changeset
3063 __ delayed()->nop();
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 16
diff changeset
3064 } else {
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 16
diff changeset
3065 __ delayed()->ld_ptr(dst, oopDesc::klass_offset_in_bytes(), G4_dst_klass);
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 16
diff changeset
3066 }
0
a61af66fc99e Initial load
duke
parents:
diff changeset
3067
a61af66fc99e Initial load
duke
parents:
diff changeset
3068 // if (src->klass() != dst->klass()) return -1;
3839
3d42f82cd811 7063628: Use cbcond on T4
kvn
parents: 3781
diff changeset
3069 __ cmp_and_brx_short(G3_src_klass, G4_dst_klass, Assembler::notEqual, Assembler::pn, L_failed);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
3070
a61af66fc99e Initial load
duke
parents:
diff changeset
3071 // if (!src->is_Array()) return -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
3072 __ cmp(G5_lh, Klass::_lh_neutral_value); // < 0
a61af66fc99e Initial load
duke
parents:
diff changeset
3073 __ br(Assembler::greaterEqual, false, Assembler::pn, L_failed);
a61af66fc99e Initial load
duke
parents:
diff changeset
3074
a61af66fc99e Initial load
duke
parents:
diff changeset
3075 // At this point, it is known to be a typeArray (array_tag 0x3).
a61af66fc99e Initial load
duke
parents:
diff changeset
3076 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
3077 __ delayed()->nop();
a61af66fc99e Initial load
duke
parents:
diff changeset
3078 { Label L;
a61af66fc99e Initial load
duke
parents:
diff changeset
3079 jint lh_prim_tag_in_place = (Klass::_lh_array_tag_type_value << Klass::_lh_array_tag_shift);
a61af66fc99e Initial load
duke
parents:
diff changeset
3080 __ set(lh_prim_tag_in_place, O5_temp);
a61af66fc99e Initial load
duke
parents:
diff changeset
3081 __ cmp(G5_lh, O5_temp);
a61af66fc99e Initial load
duke
parents:
diff changeset
3082 __ br(Assembler::greaterEqual, false, Assembler::pt, L);
a61af66fc99e Initial load
duke
parents:
diff changeset
3083 __ delayed()->nop();
a61af66fc99e Initial load
duke
parents:
diff changeset
3084 __ stop("must be a primitive array");
a61af66fc99e Initial load
duke
parents:
diff changeset
3085 __ bind(L);
a61af66fc99e Initial load
duke
parents:
diff changeset
3086 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3087 #else
a61af66fc99e Initial load
duke
parents:
diff changeset
3088 __ delayed(); // match next insn to prev branch
a61af66fc99e Initial load
duke
parents:
diff changeset
3089 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
3090
a61af66fc99e Initial load
duke
parents:
diff changeset
3091 arraycopy_range_checks(src, src_pos, dst, dst_pos, length,
a61af66fc99e Initial load
duke
parents:
diff changeset
3092 O5_temp, G4_dst_klass, L_failed);
a61af66fc99e Initial load
duke
parents:
diff changeset
3093
a61af66fc99e Initial load
duke
parents:
diff changeset
3094 // typeArrayKlass
a61af66fc99e Initial load
duke
parents:
diff changeset
3095 //
a61af66fc99e Initial load
duke
parents:
diff changeset
3096 // src_addr = (src + array_header_in_bytes()) + (src_pos << log2elemsize);
a61af66fc99e Initial load
duke
parents:
diff changeset
3097 // dst_addr = (dst + array_header_in_bytes()) + (dst_pos << log2elemsize);
a61af66fc99e Initial load
duke
parents:
diff changeset
3098 //
a61af66fc99e Initial load
duke
parents:
diff changeset
3099
a61af66fc99e Initial load
duke
parents:
diff changeset
3100 const Register G4_offset = G4_dst_klass; // array offset
a61af66fc99e Initial load
duke
parents:
diff changeset
3101 const Register G3_elsize = G3_src_klass; // log2 element size
a61af66fc99e Initial load
duke
parents:
diff changeset
3102
a61af66fc99e Initial load
duke
parents:
diff changeset
3103 __ srl(G5_lh, Klass::_lh_header_size_shift, G4_offset);
a61af66fc99e Initial load
duke
parents:
diff changeset
3104 __ and3(G4_offset, Klass::_lh_header_size_mask, G4_offset); // array_offset
a61af66fc99e Initial load
duke
parents:
diff changeset
3105 __ add(src, G4_offset, src); // src array offset
a61af66fc99e Initial load
duke
parents:
diff changeset
3106 __ add(dst, G4_offset, dst); // dst array offset
a61af66fc99e Initial load
duke
parents:
diff changeset
3107 __ and3(G5_lh, Klass::_lh_log2_element_size_mask, G3_elsize); // log2 element size
a61af66fc99e Initial load
duke
parents:
diff changeset
3108
a61af66fc99e Initial load
duke
parents:
diff changeset
3109 // next registers should be set before the jump to corresponding stub
a61af66fc99e Initial load
duke
parents:
diff changeset
3110 const Register from = O0; // source array address
a61af66fc99e Initial load
duke
parents:
diff changeset
3111 const Register to = O1; // destination array address
a61af66fc99e Initial load
duke
parents:
diff changeset
3112 const Register count = O2; // elements count
a61af66fc99e Initial load
duke
parents:
diff changeset
3113
a61af66fc99e Initial load
duke
parents:
diff changeset
3114 // 'from', 'to', 'count' registers should be set in this order
a61af66fc99e Initial load
duke
parents:
diff changeset
3115 // since they are the same as 'src', 'src_pos', 'dst'.
a61af66fc99e Initial load
duke
parents:
diff changeset
3116
a61af66fc99e Initial load
duke
parents:
diff changeset
3117 BLOCK_COMMENT("scale indexes to element size");
a61af66fc99e Initial load
duke
parents:
diff changeset
3118 __ sll_ptr(src_pos, G3_elsize, src_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
3119 __ sll_ptr(dst_pos, G3_elsize, dst_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
3120 __ add(src, src_pos, from); // src_addr
a61af66fc99e Initial load
duke
parents:
diff changeset
3121 __ add(dst, dst_pos, to); // dst_addr
a61af66fc99e Initial load
duke
parents:
diff changeset
3122
a61af66fc99e Initial load
duke
parents:
diff changeset
3123 BLOCK_COMMENT("choose copy loop based on element size");
a61af66fc99e Initial load
duke
parents:
diff changeset
3124 __ cmp(G3_elsize, 0);
2313
d89a22843c62 7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents: 1972
diff changeset
3125 __ br(Assembler::equal, true, Assembler::pt, entry_jbyte_arraycopy);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
3126 __ delayed()->signx(length, count); // length
a61af66fc99e Initial load
duke
parents:
diff changeset
3127
a61af66fc99e Initial load
duke
parents:
diff changeset
3128 __ cmp(G3_elsize, LogBytesPerShort);
2313
d89a22843c62 7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents: 1972
diff changeset
3129 __ br(Assembler::equal, true, Assembler::pt, entry_jshort_arraycopy);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
3130 __ delayed()->signx(length, count); // length
a61af66fc99e Initial load
duke
parents:
diff changeset
3131
a61af66fc99e Initial load
duke
parents:
diff changeset
3132 __ cmp(G3_elsize, LogBytesPerInt);
2313
d89a22843c62 7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents: 1972
diff changeset
3133 __ br(Assembler::equal, true, Assembler::pt, entry_jint_arraycopy);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
3134 __ delayed()->signx(length, count); // length
a61af66fc99e Initial load
duke
parents:
diff changeset
3135 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
3136 { Label L;
3839
3d42f82cd811 7063628: Use cbcond on T4
kvn
parents: 3781
diff changeset
3137 __ cmp_and_br_short(G3_elsize, LogBytesPerLong, Assembler::equal, Assembler::pt, L);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
3138 __ stop("must be long copy, but elsize is wrong");
a61af66fc99e Initial load
duke
parents:
diff changeset
3139 __ bind(L);
a61af66fc99e Initial load
duke
parents:
diff changeset
3140 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3141 #endif
2313
d89a22843c62 7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents: 1972
diff changeset
3142 __ br(Assembler::always, false, Assembler::pt, entry_jlong_arraycopy);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
3143 __ delayed()->signx(length, count); // length
a61af66fc99e Initial load
duke
parents:
diff changeset
3144
a61af66fc99e Initial load
duke
parents:
diff changeset
3145 // objArrayKlass
a61af66fc99e Initial load
duke
parents:
diff changeset
3146 __ BIND(L_objArray);
a61af66fc99e Initial load
duke
parents:
diff changeset
3147 // live at this point: G3_src_klass, G4_dst_klass, src[_pos], dst[_pos], length
a61af66fc99e Initial load
duke
parents:
diff changeset
3148
a61af66fc99e Initial load
duke
parents:
diff changeset
3149 Label L_plain_copy, L_checkcast_copy;
a61af66fc99e Initial load
duke
parents:
diff changeset
3150 // test array classes for subtyping
a61af66fc99e Initial load
duke
parents:
diff changeset
3151 __ cmp(G3_src_klass, G4_dst_klass); // usual case is exact equality
a61af66fc99e Initial load
duke
parents:
diff changeset
3152 __ brx(Assembler::notEqual, true, Assembler::pn, L_checkcast_copy);
a61af66fc99e Initial load
duke
parents:
diff changeset
3153 __ delayed()->lduw(G4_dst_klass, lh_offset, O5_temp); // hoisted from below
a61af66fc99e Initial load
duke
parents:
diff changeset
3154
a61af66fc99e Initial load
duke
parents:
diff changeset
3155 // Identically typed arrays can be copied without element-wise checks.
a61af66fc99e Initial load
duke
parents:
diff changeset
3156 arraycopy_range_checks(src, src_pos, dst, dst_pos, length,
a61af66fc99e Initial load
duke
parents:
diff changeset
3157 O5_temp, G5_lh, L_failed);
a61af66fc99e Initial load
duke
parents:
diff changeset
3158
a61af66fc99e Initial load
duke
parents:
diff changeset
3159 __ add(src, arrayOopDesc::base_offset_in_bytes(T_OBJECT), src); //src offset
a61af66fc99e Initial load
duke
parents:
diff changeset
3160 __ add(dst, arrayOopDesc::base_offset_in_bytes(T_OBJECT), dst); //dst offset
113
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 16
diff changeset
3161 __ sll_ptr(src_pos, LogBytesPerHeapOop, src_pos);
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 16
diff changeset
3162 __ sll_ptr(dst_pos, LogBytesPerHeapOop, dst_pos);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
3163 __ add(src, src_pos, from); // src_addr
a61af66fc99e Initial load
duke
parents:
diff changeset
3164 __ add(dst, dst_pos, to); // dst_addr
a61af66fc99e Initial load
duke
parents:
diff changeset
3165 __ BIND(L_plain_copy);
2313
d89a22843c62 7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents: 1972
diff changeset
3166 __ br(Assembler::always, false, Assembler::pt, entry_oop_arraycopy);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
3167 __ delayed()->signx(length, count); // length
a61af66fc99e Initial load
duke
parents:
diff changeset
3168
a61af66fc99e Initial load
duke
parents:
diff changeset
3169 __ BIND(L_checkcast_copy);
a61af66fc99e Initial load
duke
parents:
diff changeset
3170 // live at this point: G3_src_klass, G4_dst_klass
a61af66fc99e Initial load
duke
parents:
diff changeset
3171 {
a61af66fc99e Initial load
duke
parents:
diff changeset
3172 // Before looking at dst.length, make sure dst is also an objArray.
a61af66fc99e Initial load
duke
parents:
diff changeset
3173 // lduw(G4_dst_klass, lh_offset, O5_temp); // hoisted to delay slot
a61af66fc99e Initial load
duke
parents:
diff changeset
3174 __ cmp(G5_lh, O5_temp);
a61af66fc99e Initial load
duke
parents:
diff changeset
3175 __ br(Assembler::notEqual, false, Assembler::pn, L_failed);
a61af66fc99e Initial load
duke
parents:
diff changeset
3176
a61af66fc99e Initial load
duke
parents:
diff changeset
3177 // It is safe to examine both src.length and dst.length.
a61af66fc99e Initial load
duke
parents:
diff changeset
3178 __ delayed(); // match next insn to prev branch
a61af66fc99e Initial load
duke
parents:
diff changeset
3179 arraycopy_range_checks(src, src_pos, dst, dst_pos, length,
a61af66fc99e Initial load
duke
parents:
diff changeset
3180 O5_temp, G5_lh, L_failed);
a61af66fc99e Initial load
duke
parents:
diff changeset
3181
a61af66fc99e Initial load
duke
parents:
diff changeset
3182 // Marshal the base address arguments now, freeing registers.
a61af66fc99e Initial load
duke
parents:
diff changeset
3183 __ add(src, arrayOopDesc::base_offset_in_bytes(T_OBJECT), src); //src offset
a61af66fc99e Initial load
duke
parents:
diff changeset
3184 __ add(dst, arrayOopDesc::base_offset_in_bytes(T_OBJECT), dst); //dst offset
113
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 16
diff changeset
3185 __ sll_ptr(src_pos, LogBytesPerHeapOop, src_pos);
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 16
diff changeset
3186 __ sll_ptr(dst_pos, LogBytesPerHeapOop, dst_pos);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
3187 __ add(src, src_pos, from); // src_addr
a61af66fc99e Initial load
duke
parents:
diff changeset
3188 __ add(dst, dst_pos, to); // dst_addr
a61af66fc99e Initial load
duke
parents:
diff changeset
3189 __ signx(length, count); // length (reloaded)
a61af66fc99e Initial load
duke
parents:
diff changeset
3190
a61af66fc99e Initial load
duke
parents:
diff changeset
3191 Register sco_temp = O3; // this register is free now
a61af66fc99e Initial load
duke
parents:
diff changeset
3192 assert_different_registers(from, to, count, sco_temp,
a61af66fc99e Initial load
duke
parents:
diff changeset
3193 G4_dst_klass, G3_src_klass);
a61af66fc99e Initial load
duke
parents:
diff changeset
3194
a61af66fc99e Initial load
duke
parents:
diff changeset
3195 // Generate the type check.
4762
069ab3f976d3 7118863: Move sizeof(klassOopDesc) into the *Klass::*_offset_in_bytes() functions
stefank
parents: 3961
diff changeset
3196 int sco_offset = in_bytes(Klass::super_check_offset_offset());
0
a61af66fc99e Initial load
duke
parents:
diff changeset
3197 __ lduw(G4_dst_klass, sco_offset, sco_temp);
a61af66fc99e Initial load
duke
parents:
diff changeset
3198 generate_type_check(G3_src_klass, sco_temp, G4_dst_klass,
a61af66fc99e Initial load
duke
parents:
diff changeset
3199 O5_temp, L_plain_copy);
a61af66fc99e Initial load
duke
parents:
diff changeset
3200
a61af66fc99e Initial load
duke
parents:
diff changeset
3201 // Fetch destination element klass from the objArrayKlass header.
4762
069ab3f976d3 7118863: Move sizeof(klassOopDesc) into the *Klass::*_offset_in_bytes() functions
stefank
parents: 3961
diff changeset
3202 int ek_offset = in_bytes(objArrayKlass::element_klass_offset());
0
a61af66fc99e Initial load
duke
parents:
diff changeset
3203
a61af66fc99e Initial load
duke
parents:
diff changeset
3204 // the checkcast_copy loop needs two extra arguments:
a61af66fc99e Initial load
duke
parents:
diff changeset
3205 __ ld_ptr(G4_dst_klass, ek_offset, O4); // dest elem klass
a61af66fc99e Initial load
duke
parents:
diff changeset
3206 // lduw(O4, sco_offset, O3); // sco of elem klass
a61af66fc99e Initial load
duke
parents:
diff changeset
3207
2313
d89a22843c62 7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents: 1972
diff changeset
3208 __ br(Assembler::always, false, Assembler::pt, entry_checkcast_arraycopy);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
3209 __ delayed()->lduw(O4, sco_offset, O3);
a61af66fc99e Initial load
duke
parents:
diff changeset
3210 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3211
a61af66fc99e Initial load
duke
parents:
diff changeset
3212 __ BIND(L_failed);
a61af66fc99e Initial load
duke
parents:
diff changeset
3213 __ retl();
a61af66fc99e Initial load
duke
parents:
diff changeset
3214 __ delayed()->sub(G0, 1, O0); // return -1
a61af66fc99e Initial load
duke
parents:
diff changeset
3215 return start;
a61af66fc99e Initial load
duke
parents:
diff changeset
3216 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3217
3892
baf763f388e6 7059037: Use BIS for zeroing on T4
kvn
parents: 3839
diff changeset
3218 //
baf763f388e6 7059037: Use BIS for zeroing on T4
kvn
parents: 3839
diff changeset
3219 // Generate stub for heap zeroing.
baf763f388e6 7059037: Use BIS for zeroing on T4
kvn
parents: 3839
diff changeset
3220 // "to" address is aligned to jlong (8 bytes).
baf763f388e6 7059037: Use BIS for zeroing on T4
kvn
parents: 3839
diff changeset
3221 //
baf763f388e6 7059037: Use BIS for zeroing on T4
kvn
parents: 3839
diff changeset
3222 // Arguments for generated stub:
baf763f388e6 7059037: Use BIS for zeroing on T4
kvn
parents: 3839
diff changeset
3223 // to: O0
baf763f388e6 7059037: Use BIS for zeroing on T4
kvn
parents: 3839
diff changeset
3224 // count: O1 treated as signed (count of HeapWord)
baf763f388e6 7059037: Use BIS for zeroing on T4
kvn
parents: 3839
diff changeset
3225 // count could be 0
baf763f388e6 7059037: Use BIS for zeroing on T4
kvn
parents: 3839
diff changeset
3226 //
baf763f388e6 7059037: Use BIS for zeroing on T4
kvn
parents: 3839
diff changeset
3227 address generate_zero_aligned_words(const char* name) {
baf763f388e6 7059037: Use BIS for zeroing on T4
kvn
parents: 3839
diff changeset
3228 __ align(CodeEntryAlignment);
baf763f388e6 7059037: Use BIS for zeroing on T4
kvn
parents: 3839
diff changeset
3229 StubCodeMark mark(this, "StubRoutines", name);
baf763f388e6 7059037: Use BIS for zeroing on T4
kvn
parents: 3839
diff changeset
3230 address start = __ pc();
baf763f388e6 7059037: Use BIS for zeroing on T4
kvn
parents: 3839
diff changeset
3231
baf763f388e6 7059037: Use BIS for zeroing on T4
kvn
parents: 3839
diff changeset
3232 const Register to = O0; // source array address
baf763f388e6 7059037: Use BIS for zeroing on T4
kvn
parents: 3839
diff changeset
3233 const Register count = O1; // HeapWords count
baf763f388e6 7059037: Use BIS for zeroing on T4
kvn
parents: 3839
diff changeset
3234 const Register temp = O2; // scratch
baf763f388e6 7059037: Use BIS for zeroing on T4
kvn
parents: 3839
diff changeset
3235
baf763f388e6 7059037: Use BIS for zeroing on T4
kvn
parents: 3839
diff changeset
3236 Label Ldone;
baf763f388e6 7059037: Use BIS for zeroing on T4
kvn
parents: 3839
diff changeset
3237 __ sllx(count, LogHeapWordSize, count); // to bytes count
baf763f388e6 7059037: Use BIS for zeroing on T4
kvn
parents: 3839
diff changeset
3238 // Use BIS for zeroing
baf763f388e6 7059037: Use BIS for zeroing on T4
kvn
parents: 3839
diff changeset
3239 __ bis_zeroing(to, count, temp, Ldone);
baf763f388e6 7059037: Use BIS for zeroing on T4
kvn
parents: 3839
diff changeset
3240 __ bind(Ldone);
baf763f388e6 7059037: Use BIS for zeroing on T4
kvn
parents: 3839
diff changeset
3241 __ retl();
baf763f388e6 7059037: Use BIS for zeroing on T4
kvn
parents: 3839
diff changeset
3242 __ delayed()->nop();
baf763f388e6 7059037: Use BIS for zeroing on T4
kvn
parents: 3839
diff changeset
3243 return start;
baf763f388e6 7059037: Use BIS for zeroing on T4
kvn
parents: 3839
diff changeset
3244 }
baf763f388e6 7059037: Use BIS for zeroing on T4
kvn
parents: 3839
diff changeset
3245
0
a61af66fc99e Initial load
duke
parents:
diff changeset
3246 void generate_arraycopy_stubs() {
2313
d89a22843c62 7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents: 1972
diff changeset
3247 address entry;
d89a22843c62 7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents: 1972
diff changeset
3248 address entry_jbyte_arraycopy;
d89a22843c62 7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents: 1972
diff changeset
3249 address entry_jshort_arraycopy;
d89a22843c62 7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents: 1972
diff changeset
3250 address entry_jint_arraycopy;
d89a22843c62 7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents: 1972
diff changeset
3251 address entry_oop_arraycopy;
d89a22843c62 7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents: 1972
diff changeset
3252 address entry_jlong_arraycopy;
d89a22843c62 7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents: 1972
diff changeset
3253 address entry_checkcast_arraycopy;
d89a22843c62 7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents: 1972
diff changeset
3254
2324
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
3255 //*** jbyte
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
3256 // Always need aligned and unaligned versions
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
3257 StubRoutines::_jbyte_disjoint_arraycopy = generate_disjoint_byte_copy(false, &entry,
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
3258 "jbyte_disjoint_arraycopy");
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
3259 StubRoutines::_jbyte_arraycopy = generate_conjoint_byte_copy(false, entry,
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
3260 &entry_jbyte_arraycopy,
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
3261 "jbyte_arraycopy");
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
3262 StubRoutines::_arrayof_jbyte_disjoint_arraycopy = generate_disjoint_byte_copy(true, &entry,
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
3263 "arrayof_jbyte_disjoint_arraycopy");
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
3264 StubRoutines::_arrayof_jbyte_arraycopy = generate_conjoint_byte_copy(true, entry, NULL,
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
3265 "arrayof_jbyte_arraycopy");
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
3266
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
3267 //*** jshort
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
3268 // Always need aligned and unaligned versions
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
3269 StubRoutines::_jshort_disjoint_arraycopy = generate_disjoint_short_copy(false, &entry,
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
3270 "jshort_disjoint_arraycopy");
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
3271 StubRoutines::_jshort_arraycopy = generate_conjoint_short_copy(false, entry,
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
3272 &entry_jshort_arraycopy,
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
3273 "jshort_arraycopy");
2313
d89a22843c62 7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents: 1972
diff changeset
3274 StubRoutines::_arrayof_jshort_disjoint_arraycopy = generate_disjoint_short_copy(true, &entry,
d89a22843c62 7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents: 1972
diff changeset
3275 "arrayof_jshort_disjoint_arraycopy");
d89a22843c62 7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents: 1972
diff changeset
3276 StubRoutines::_arrayof_jshort_arraycopy = generate_conjoint_short_copy(true, entry, NULL,
d89a22843c62 7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents: 1972
diff changeset
3277 "arrayof_jshort_arraycopy");
d89a22843c62 7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents: 1972
diff changeset
3278
2324
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
3279 //*** jint
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
3280 // Aligned versions
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
3281 StubRoutines::_arrayof_jint_disjoint_arraycopy = generate_disjoint_int_copy(true, &entry,
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
3282 "arrayof_jint_disjoint_arraycopy");
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
3283 StubRoutines::_arrayof_jint_arraycopy = generate_conjoint_int_copy(true, entry, &entry_jint_arraycopy,
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
3284 "arrayof_jint_arraycopy");
0
a61af66fc99e Initial load
duke
parents:
diff changeset
3285 #ifdef _LP64
2324
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
3286 // In 64 bit we need both aligned and unaligned versions of jint arraycopy.
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
3287 // entry_jint_arraycopy always points to the unaligned version (notice that we overwrite it).
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
3288 StubRoutines::_jint_disjoint_arraycopy = generate_disjoint_int_copy(false, &entry,
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
3289 "jint_disjoint_arraycopy");
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
3290 StubRoutines::_jint_arraycopy = generate_conjoint_int_copy(false, entry,
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
3291 &entry_jint_arraycopy,
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
3292 "jint_arraycopy");
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
3293 #else
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
3294 // In 32 bit jints are always HeapWordSize aligned, so always use the aligned version
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
3295 // (in fact in 32bit we always have a pre-loop part even in the aligned version,
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
3296 // because it uses 64-bit loads/stores, so the aligned flag is actually ignored).
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
3297 StubRoutines::_jint_disjoint_arraycopy = StubRoutines::_arrayof_jint_disjoint_arraycopy;
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
3298 StubRoutines::_jint_arraycopy = StubRoutines::_arrayof_jint_arraycopy;
0
a61af66fc99e Initial load
duke
parents:
diff changeset
3299 #endif
2313
d89a22843c62 7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents: 1972
diff changeset
3300
2324
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
3301
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
3302 //*** jlong
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
3303 // It is always aligned
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
3304 StubRoutines::_arrayof_jlong_disjoint_arraycopy = generate_disjoint_long_copy(true, &entry,
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
3305 "arrayof_jlong_disjoint_arraycopy");
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
3306 StubRoutines::_arrayof_jlong_arraycopy = generate_conjoint_long_copy(true, entry, &entry_jlong_arraycopy,
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
3307 "arrayof_jlong_arraycopy");
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
3308 StubRoutines::_jlong_disjoint_arraycopy = StubRoutines::_arrayof_jlong_disjoint_arraycopy;
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
3309 StubRoutines::_jlong_arraycopy = StubRoutines::_arrayof_jlong_arraycopy;
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
3310
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
3311
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
3312 //*** oops
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
3313 // Aligned versions
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
3314 StubRoutines::_arrayof_oop_disjoint_arraycopy = generate_disjoint_oop_copy(true, &entry,
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
3315 "arrayof_oop_disjoint_arraycopy");
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
3316 StubRoutines::_arrayof_oop_arraycopy = generate_conjoint_oop_copy(true, entry, &entry_oop_arraycopy,
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
3317 "arrayof_oop_arraycopy");
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
3318 // Aligned versions without pre-barriers
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
3319 StubRoutines::_arrayof_oop_disjoint_arraycopy_uninit = generate_disjoint_oop_copy(true, &entry,
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
3320 "arrayof_oop_disjoint_arraycopy_uninit",
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
3321 /*dest_uninitialized*/true);
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
3322 StubRoutines::_arrayof_oop_arraycopy_uninit = generate_conjoint_oop_copy(true, entry, NULL,
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
3323 "arrayof_oop_arraycopy_uninit",
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
3324 /*dest_uninitialized*/true);
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
3325 #ifdef _LP64
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
3326 if (UseCompressedOops) {
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
3327 // With compressed oops we need unaligned versions, notice that we overwrite entry_oop_arraycopy.
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
3328 StubRoutines::_oop_disjoint_arraycopy = generate_disjoint_oop_copy(false, &entry,
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
3329 "oop_disjoint_arraycopy");
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
3330 StubRoutines::_oop_arraycopy = generate_conjoint_oop_copy(false, entry, &entry_oop_arraycopy,
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
3331 "oop_arraycopy");
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
3332 // Unaligned versions without pre-barriers
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
3333 StubRoutines::_oop_disjoint_arraycopy_uninit = generate_disjoint_oop_copy(false, &entry,
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
3334 "oop_disjoint_arraycopy_uninit",
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
3335 /*dest_uninitialized*/true);
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
3336 StubRoutines::_oop_arraycopy_uninit = generate_conjoint_oop_copy(false, entry, NULL,
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
3337 "oop_arraycopy_uninit",
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
3338 /*dest_uninitialized*/true);
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
3339 } else
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
3340 #endif
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
3341 {
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
3342 // oop arraycopy is always aligned on 32bit and 64bit without compressed oops
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
3343 StubRoutines::_oop_disjoint_arraycopy = StubRoutines::_arrayof_oop_disjoint_arraycopy;
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
3344 StubRoutines::_oop_arraycopy = StubRoutines::_arrayof_oop_arraycopy;
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
3345 StubRoutines::_oop_disjoint_arraycopy_uninit = StubRoutines::_arrayof_oop_disjoint_arraycopy_uninit;
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
3346 StubRoutines::_oop_arraycopy_uninit = StubRoutines::_arrayof_oop_arraycopy_uninit;
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
3347 }
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
3348
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
3349 StubRoutines::_checkcast_arraycopy = generate_checkcast_copy("checkcast_arraycopy", &entry_checkcast_arraycopy);
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
3350 StubRoutines::_checkcast_arraycopy_uninit = generate_checkcast_copy("checkcast_arraycopy_uninit", NULL,
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
3351 /*dest_uninitialized*/true);
0ac769a57c64 6627983: G1: Bad oop deference during marking
iveresov
parents: 2313
diff changeset
3352
2313
d89a22843c62 7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents: 1972
diff changeset
3353 StubRoutines::_unsafe_arraycopy = generate_unsafe_copy("unsafe_arraycopy",
d89a22843c62 7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents: 1972
diff changeset
3354 entry_jbyte_arraycopy,
d89a22843c62 7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents: 1972
diff changeset
3355 entry_jshort_arraycopy,
d89a22843c62 7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents: 1972
diff changeset
3356 entry_jint_arraycopy,
d89a22843c62 7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents: 1972
diff changeset
3357 entry_jlong_arraycopy);
d89a22843c62 7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents: 1972
diff changeset
3358 StubRoutines::_generic_arraycopy = generate_generic_copy("generic_arraycopy",
d89a22843c62 7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents: 1972
diff changeset
3359 entry_jbyte_arraycopy,
d89a22843c62 7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents: 1972
diff changeset
3360 entry_jshort_arraycopy,
d89a22843c62 7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents: 1972
diff changeset
3361 entry_jint_arraycopy,
d89a22843c62 7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents: 1972
diff changeset
3362 entry_oop_arraycopy,
d89a22843c62 7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents: 1972
diff changeset
3363 entry_jlong_arraycopy,
d89a22843c62 7020521: arraycopy stubs place prebarriers incorrectly
iveresov
parents: 1972
diff changeset
3364 entry_checkcast_arraycopy);
1763
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
3365
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
3366 StubRoutines::_jbyte_fill = generate_fill(T_BYTE, false, "jbyte_fill");
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
3367 StubRoutines::_jshort_fill = generate_fill(T_SHORT, false, "jshort_fill");
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
3368 StubRoutines::_jint_fill = generate_fill(T_INT, false, "jint_fill");
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
3369 StubRoutines::_arrayof_jbyte_fill = generate_fill(T_BYTE, true, "arrayof_jbyte_fill");
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
3370 StubRoutines::_arrayof_jshort_fill = generate_fill(T_SHORT, true, "arrayof_jshort_fill");
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1655
diff changeset
3371 StubRoutines::_arrayof_jint_fill = generate_fill(T_INT, true, "arrayof_jint_fill");
3892
baf763f388e6 7059037: Use BIS for zeroing on T4
kvn
parents: 3839
diff changeset
3372
baf763f388e6 7059037: Use BIS for zeroing on T4
kvn
parents: 3839
diff changeset
3373 if (UseBlockZeroing) {
baf763f388e6 7059037: Use BIS for zeroing on T4
kvn
parents: 3839
diff changeset
3374 StubRoutines::_zero_aligned_words = generate_zero_aligned_words("zero_aligned_words");
baf763f388e6 7059037: Use BIS for zeroing on T4
kvn
parents: 3839
diff changeset
3375 }
0
a61af66fc99e Initial load
duke
parents:
diff changeset
3376 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3377
a61af66fc99e Initial load
duke
parents:
diff changeset
3378 void generate_initial() {
a61af66fc99e Initial load
duke
parents:
diff changeset
3379 // Generates all stubs and initializes the entry points
a61af66fc99e Initial load
duke
parents:
diff changeset
3380
a61af66fc99e Initial load
duke
parents:
diff changeset
3381 //------------------------------------------------------------------------------------------------------------------------
a61af66fc99e Initial load
duke
parents:
diff changeset
3382 // entry points that exist in all platforms
a61af66fc99e Initial load
duke
parents:
diff changeset
3383 // Note: This is code that could be shared among different platforms - however the benefit seems to be smaller than
a61af66fc99e Initial load
duke
parents:
diff changeset
3384 // the disadvantage of having a much more complicated generator structure. See also comment in stubRoutines.hpp.
a61af66fc99e Initial load
duke
parents:
diff changeset
3385 StubRoutines::_forward_exception_entry = generate_forward_exception();
a61af66fc99e Initial load
duke
parents:
diff changeset
3386
a61af66fc99e Initial load
duke
parents:
diff changeset
3387 StubRoutines::_call_stub_entry = generate_call_stub(StubRoutines::_call_stub_return_address);
a61af66fc99e Initial load
duke
parents:
diff changeset
3388 StubRoutines::_catch_exception_entry = generate_catch_exception();
a61af66fc99e Initial load
duke
parents:
diff changeset
3389
a61af66fc99e Initial load
duke
parents:
diff changeset
3390 //------------------------------------------------------------------------------------------------------------------------
a61af66fc99e Initial load
duke
parents:
diff changeset
3391 // entry points that are platform specific
a61af66fc99e Initial load
duke
parents:
diff changeset
3392 StubRoutines::Sparc::_test_stop_entry = generate_test_stop();
a61af66fc99e Initial load
duke
parents:
diff changeset
3393
a61af66fc99e Initial load
duke
parents:
diff changeset
3394 StubRoutines::Sparc::_stop_subroutine_entry = generate_stop_subroutine();
a61af66fc99e Initial load
duke
parents:
diff changeset
3395 StubRoutines::Sparc::_flush_callers_register_windows_entry = generate_flush_callers_register_windows();
a61af66fc99e Initial load
duke
parents:
diff changeset
3396
a61af66fc99e Initial load
duke
parents:
diff changeset
3397 #if !defined(COMPILER2) && !defined(_LP64)
a61af66fc99e Initial load
duke
parents:
diff changeset
3398 StubRoutines::_atomic_xchg_entry = generate_atomic_xchg();
a61af66fc99e Initial load
duke
parents:
diff changeset
3399 StubRoutines::_atomic_cmpxchg_entry = generate_atomic_cmpxchg();
a61af66fc99e Initial load
duke
parents:
diff changeset
3400 StubRoutines::_atomic_add_entry = generate_atomic_add();
a61af66fc99e Initial load
duke
parents:
diff changeset
3401 StubRoutines::_atomic_xchg_ptr_entry = StubRoutines::_atomic_xchg_entry;
a61af66fc99e Initial load
duke
parents:
diff changeset
3402 StubRoutines::_atomic_cmpxchg_ptr_entry = StubRoutines::_atomic_cmpxchg_entry;
a61af66fc99e Initial load
duke
parents:
diff changeset
3403 StubRoutines::_atomic_cmpxchg_long_entry = generate_atomic_cmpxchg_long();
a61af66fc99e Initial load
duke
parents:
diff changeset
3404 StubRoutines::_atomic_add_ptr_entry = StubRoutines::_atomic_add_entry;
a61af66fc99e Initial load
duke
parents:
diff changeset
3405 #endif // COMPILER2 !=> _LP64
3781
d83ac25d0304 7055355: JSR 292: crash while throwing WrongMethodTypeException
never
parents: 2324
diff changeset
3406
4743
dca455dea3a7 7116216: StackOverflow GC crash
bdelsart
parents: 3961
diff changeset
3407 // Build this early so it's available for the interpreter.
dca455dea3a7 7116216: StackOverflow GC crash
bdelsart
parents: 3961
diff changeset
3408 StubRoutines::_throw_StackOverflowError_entry = generate_throw_exception("StackOverflowError throw_exception", CAST_FROM_FN_PTR(address, SharedRuntime::throw_StackOverflowError));
0
a61af66fc99e Initial load
duke
parents:
diff changeset
3409 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3410
a61af66fc99e Initial load
duke
parents:
diff changeset
3411
a61af66fc99e Initial load
duke
parents:
diff changeset
3412 void generate_all() {
a61af66fc99e Initial load
duke
parents:
diff changeset
3413 // Generates all stubs and initializes the entry points
a61af66fc99e Initial load
duke
parents:
diff changeset
3414
642
660978a2a31a 6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents: 422
diff changeset
3415 // Generate partial_subtype_check first here since its code depends on
660978a2a31a 6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents: 422
diff changeset
3416 // UseZeroBaseCompressedOops which is defined after heap initialization.
660978a2a31a 6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents: 422
diff changeset
3417 StubRoutines::Sparc::_partial_subtype_check = generate_partial_subtype_check();
0
a61af66fc99e Initial load
duke
parents:
diff changeset
3418 // These entry points require SharedInfo::stack0 to be set up in non-core builds
3937
c565834fb592 7088020: SEGV in JNIHandleBlock::release_block
never
parents: 3903
diff changeset
3419 StubRoutines::_throw_AbstractMethodError_entry = generate_throw_exception("AbstractMethodError throw_exception", CAST_FROM_FN_PTR(address, SharedRuntime::throw_AbstractMethodError));
c565834fb592 7088020: SEGV in JNIHandleBlock::release_block
never
parents: 3903
diff changeset
3420 StubRoutines::_throw_IncompatibleClassChangeError_entry= generate_throw_exception("IncompatibleClassChangeError throw_exception", CAST_FROM_FN_PTR(address, SharedRuntime::throw_IncompatibleClassChangeError));
c565834fb592 7088020: SEGV in JNIHandleBlock::release_block
never
parents: 3903
diff changeset
3421 StubRoutines::_throw_NullPointerException_at_call_entry= generate_throw_exception("NullPointerException at call throw_exception", CAST_FROM_FN_PTR(address, SharedRuntime::throw_NullPointerException_at_call));
0
a61af66fc99e Initial load
duke
parents:
diff changeset
3422
a61af66fc99e Initial load
duke
parents:
diff changeset
3423 StubRoutines::_handler_for_unsafe_access_entry =
a61af66fc99e Initial load
duke
parents:
diff changeset
3424 generate_handler_for_unsafe_access();
a61af66fc99e Initial load
duke
parents:
diff changeset
3425
a61af66fc99e Initial load
duke
parents:
diff changeset
3426 // support for verify_oop (must happen after universe_init)
a61af66fc99e Initial load
duke
parents:
diff changeset
3427 StubRoutines::_verify_oop_subroutine_entry = generate_verify_oop_subroutine();
a61af66fc99e Initial load
duke
parents:
diff changeset
3428
a61af66fc99e Initial load
duke
parents:
diff changeset
3429 // arraycopy stubs used by compilers
a61af66fc99e Initial load
duke
parents:
diff changeset
3430 generate_arraycopy_stubs();
1174
ddb7834449d0 6849984: Value methods for platform dependent math functions constant fold incorrectly
never
parents: 727
diff changeset
3431
ddb7834449d0 6849984: Value methods for platform dependent math functions constant fold incorrectly
never
parents: 727
diff changeset
3432 // Don't initialize the platform math functions since sparc
ddb7834449d0 6849984: Value methods for platform dependent math functions constant fold incorrectly
never
parents: 727
diff changeset
3433 // doesn't have intrinsics for these operations.
0
a61af66fc99e Initial load
duke
parents:
diff changeset
3434 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3435
a61af66fc99e Initial load
duke
parents:
diff changeset
3436
a61af66fc99e Initial load
duke
parents:
diff changeset
3437 public:
a61af66fc99e Initial load
duke
parents:
diff changeset
3438 StubGenerator(CodeBuffer* code, bool all) : StubCodeGenerator(code) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3439 // replace the standard masm with a special one:
a61af66fc99e Initial load
duke
parents:
diff changeset
3440 _masm = new MacroAssembler(code);
a61af66fc99e Initial load
duke
parents:
diff changeset
3441
a61af66fc99e Initial load
duke
parents:
diff changeset
3442 _stub_count = !all ? 0x100 : 0x200;
a61af66fc99e Initial load
duke
parents:
diff changeset
3443 if (all) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3444 generate_all();
a61af66fc99e Initial load
duke
parents:
diff changeset
3445 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
3446 generate_initial();
a61af66fc99e Initial load
duke
parents:
diff changeset
3447 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3448
a61af66fc99e Initial load
duke
parents:
diff changeset
3449 // make sure this stub is available for all local calls
a61af66fc99e Initial load
duke
parents:
diff changeset
3450 if (_atomic_add_stub.is_unbound()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3451 // generate a second time, if necessary
a61af66fc99e Initial load
duke
parents:
diff changeset
3452 (void) generate_atomic_add();
a61af66fc99e Initial load
duke
parents:
diff changeset
3453 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3454 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3455
a61af66fc99e Initial load
duke
parents:
diff changeset
3456
a61af66fc99e Initial load
duke
parents:
diff changeset
3457 private:
a61af66fc99e Initial load
duke
parents:
diff changeset
3458 int _stub_count;
a61af66fc99e Initial load
duke
parents:
diff changeset
3459 void stub_prolog(StubCodeDesc* cdesc) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3460 # ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
3461 // put extra information in the stub code, to make it more readable
a61af66fc99e Initial load
duke
parents:
diff changeset
3462 #ifdef _LP64
a61af66fc99e Initial load
duke
parents:
diff changeset
3463 // Write the high part of the address
a61af66fc99e Initial load
duke
parents:
diff changeset
3464 // [RGV] Check if there is a dependency on the size of this prolog
a61af66fc99e Initial load
duke
parents:
diff changeset
3465 __ emit_data((intptr_t)cdesc >> 32, relocInfo::none);
a61af66fc99e Initial load
duke
parents:
diff changeset
3466 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
3467 __ emit_data((intptr_t)cdesc, relocInfo::none);
a61af66fc99e Initial load
duke
parents:
diff changeset
3468 __ emit_data(++_stub_count, relocInfo::none);
a61af66fc99e Initial load
duke
parents:
diff changeset
3469 # endif
a61af66fc99e Initial load
duke
parents:
diff changeset
3470 align(true);
a61af66fc99e Initial load
duke
parents:
diff changeset
3471 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3472
a61af66fc99e Initial load
duke
parents:
diff changeset
3473 void align(bool at_header = false) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3474 // %%%%% move this constant somewhere else
a61af66fc99e Initial load
duke
parents:
diff changeset
3475 // UltraSPARC cache line size is 8 instructions:
a61af66fc99e Initial load
duke
parents:
diff changeset
3476 const unsigned int icache_line_size = 32;
a61af66fc99e Initial load
duke
parents:
diff changeset
3477 const unsigned int icache_half_line_size = 16;
a61af66fc99e Initial load
duke
parents:
diff changeset
3478
a61af66fc99e Initial load
duke
parents:
diff changeset
3479 if (at_header) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3480 while ((intptr_t)(__ pc()) % icache_line_size != 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3481 __ emit_data(0, relocInfo::none);
a61af66fc99e Initial load
duke
parents:
diff changeset
3482 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3483 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
3484 while ((intptr_t)(__ pc()) % icache_half_line_size != 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3485 __ nop();
a61af66fc99e Initial load
duke
parents:
diff changeset
3486 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3487 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3488 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3489
a61af66fc99e Initial load
duke
parents:
diff changeset
3490 }; // end class declaration
a61af66fc99e Initial load
duke
parents:
diff changeset
3491
a61af66fc99e Initial load
duke
parents:
diff changeset
3492 void StubGenerator_generate(CodeBuffer* code, bool all) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3493 StubGenerator g(code, all);
a61af66fc99e Initial load
duke
parents:
diff changeset
3494 }