annotate src/cpu/sparc/vm/stubGenerator_sparc.cpp @ 1708:a03ae377b2e8

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