annotate src/cpu/sparc/vm/stubGenerator_sparc.cpp @ 2368:dde920245681

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