Mercurial > hg > graal-compiler
annotate src/cpu/sparc/vm/assembler_sparc.cpp @ 6812:988bf00cc564
7200261: G1: Liveness counting inconsistencies during marking verification
Summary: The clipping code in the routine that sets the bits for a range of cards, in the liveness accounting verification code was incorrect. It set all the bits in the card bitmap from the given starting index which would lead to spurious marking verification failures.
Reviewed-by: brutisso, jwilhelm, jmasa
author | johnc |
---|---|
date | Thu, 27 Sep 2012 15:44:01 -0700 |
parents | da91efe96a93 |
children | 2cb2f30450c7 |
rev | line source |
---|---|
0 | 1 /* |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
2 * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. |
0 | 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * | |
5 * This code is free software; you can redistribute it and/or modify it | |
6 * under the terms of the GNU General Public License version 2 only, as | |
7 * published by the Free Software Foundation. | |
8 * | |
9 * This code is distributed in the hope that it will be useful, but WITHOUT | |
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
12 * version 2 for more details (a copy is included in the LICENSE file that | |
13 * accompanied this code). | |
14 * | |
15 * You should have received a copy of the GNU General Public License version | |
16 * 2 along with this work; if not, write to the Free Software Foundation, | |
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
18 * | |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1513
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1513
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:
1513
diff
changeset
|
21 * questions. |
0 | 22 * |
23 */ | |
24 | |
1972 | 25 #include "precompiled.hpp" |
2076
7737fa7ec2b5
7006044: materialize cheap non-oop pointers on 64-bit SPARC
twisti
parents:
2008
diff
changeset
|
26 #include "asm/assembler.hpp" |
1972 | 27 #include "assembler_sparc.inline.hpp" |
28 #include "gc_interface/collectedHeap.inline.hpp" | |
29 #include "interpreter/interpreter.hpp" | |
30 #include "memory/cardTableModRefBS.hpp" | |
31 #include "memory/resourceArea.hpp" | |
32 #include "prims/methodHandles.hpp" | |
33 #include "runtime/biasedLocking.hpp" | |
34 #include "runtime/interfaceSupport.hpp" | |
35 #include "runtime/objectMonitor.hpp" | |
36 #include "runtime/os.hpp" | |
37 #include "runtime/sharedRuntime.hpp" | |
38 #include "runtime/stubRoutines.hpp" | |
39 #ifndef SERIALGC | |
40 #include "gc_implementation/g1/g1CollectedHeap.inline.hpp" | |
41 #include "gc_implementation/g1/g1SATBCardTableModRefBS.hpp" | |
42 #include "gc_implementation/g1/heapRegion.hpp" | |
43 #endif | |
0 | 44 |
3753
cba7b5c2d53f
7045514: SPARC assembly code for JSR 292 ricochet frames
never
parents:
3249
diff
changeset
|
45 #ifdef PRODUCT |
cba7b5c2d53f
7045514: SPARC assembly code for JSR 292 ricochet frames
never
parents:
3249
diff
changeset
|
46 #define BLOCK_COMMENT(str) /* nothing */ |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
4762
diff
changeset
|
47 #define STOP(error) stop(error) |
3753
cba7b5c2d53f
7045514: SPARC assembly code for JSR 292 ricochet frames
never
parents:
3249
diff
changeset
|
48 #else |
cba7b5c2d53f
7045514: SPARC assembly code for JSR 292 ricochet frames
never
parents:
3249
diff
changeset
|
49 #define BLOCK_COMMENT(str) block_comment(str) |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
4762
diff
changeset
|
50 #define STOP(error) block_comment(error); stop(error) |
3753
cba7b5c2d53f
7045514: SPARC assembly code for JSR 292 ricochet frames
never
parents:
3249
diff
changeset
|
51 #endif |
cba7b5c2d53f
7045514: SPARC assembly code for JSR 292 ricochet frames
never
parents:
3249
diff
changeset
|
52 |
727 | 53 // Convert the raw encoding form into the form expected by the |
54 // constructor for Address. | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
55 Address Address::make_raw(int base, int index, int scale, int disp, relocInfo::relocType disp_reloc) { |
727 | 56 assert(scale == 0, "not supported"); |
57 RelocationHolder rspec; | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
58 if (disp_reloc != relocInfo::none) { |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
59 rspec = Relocation::spec_simple(disp_reloc); |
0 | 60 } |
727 | 61 |
62 Register rindex = as_Register(index); | |
63 if (rindex != G0) { | |
64 Address madr(as_Register(base), rindex); | |
65 madr._rspec = rspec; | |
66 return madr; | |
67 } else { | |
68 Address madr(as_Register(base), disp); | |
69 madr._rspec = rspec; | |
70 return madr; | |
71 } | |
72 } | |
73 | |
74 Address Argument::address_in_frame() const { | |
75 // Warning: In LP64 mode disp will occupy more than 10 bits, but | |
76 // op codes such as ld or ldx, only access disp() to get | |
77 // their simm13 argument. | |
78 int disp = ((_number - Argument::n_register_parameters + frame::memory_parameter_word_sp_offset) * BytesPerWord) + STACK_BIAS; | |
79 if (is_in()) | |
80 return Address(FP, disp); // In argument. | |
81 else | |
82 return Address(SP, disp); // Out argument. | |
0 | 83 } |
84 | |
85 static const char* argumentNames[][2] = { | |
86 {"A0","P0"}, {"A1","P1"}, {"A2","P2"}, {"A3","P3"}, {"A4","P4"}, | |
87 {"A5","P5"}, {"A6","P6"}, {"A7","P7"}, {"A8","P8"}, {"A9","P9"}, | |
88 {"A(n>9)","P(n>9)"} | |
89 }; | |
90 | |
91 const char* Argument::name() const { | |
92 int nofArgs = sizeof argumentNames / sizeof argumentNames[0]; | |
93 int num = number(); | |
94 if (num >= nofArgs) num = nofArgs - 1; | |
95 return argumentNames[num][is_in() ? 1 : 0]; | |
96 } | |
97 | |
98 void Assembler::print_instruction(int inst) { | |
99 const char* s; | |
100 switch (inv_op(inst)) { | |
101 default: s = "????"; break; | |
102 case call_op: s = "call"; break; | |
103 case branch_op: | |
104 switch (inv_op2(inst)) { | |
105 case fb_op2: s = "fb"; break; | |
106 case fbp_op2: s = "fbp"; break; | |
107 case br_op2: s = "br"; break; | |
108 case bp_op2: s = "bp"; break; | |
109 case cb_op2: s = "cb"; break; | |
3839 | 110 case bpr_op2: { |
111 if (is_cbcond(inst)) { | |
112 s = is_cxb(inst) ? "cxb" : "cwb"; | |
113 } else { | |
114 s = "bpr"; | |
115 } | |
116 break; | |
117 } | |
0 | 118 default: s = "????"; break; |
119 } | |
120 } | |
121 ::tty->print("%s", s); | |
122 } | |
123 | |
124 | |
125 // Patch instruction inst at offset inst_pos to refer to dest_pos | |
126 // and return the resulting instruction. | |
127 // We should have pcs, not offsets, but since all is relative, it will work out | |
128 // OK. | |
129 int Assembler::patched_branch(int dest_pos, int inst, int inst_pos) { | |
130 | |
131 int m; // mask for displacement field | |
132 int v; // new value for displacement field | |
133 const int word_aligned_ones = -4; | |
134 switch (inv_op(inst)) { | |
135 default: ShouldNotReachHere(); | |
136 case call_op: m = wdisp(word_aligned_ones, 0, 30); v = wdisp(dest_pos, inst_pos, 30); break; | |
137 case branch_op: | |
138 switch (inv_op2(inst)) { | |
139 case fbp_op2: m = wdisp( word_aligned_ones, 0, 19); v = wdisp( dest_pos, inst_pos, 19); break; | |
140 case bp_op2: m = wdisp( word_aligned_ones, 0, 19); v = wdisp( dest_pos, inst_pos, 19); break; | |
141 case fb_op2: m = wdisp( word_aligned_ones, 0, 22); v = wdisp( dest_pos, inst_pos, 22); break; | |
142 case br_op2: m = wdisp( word_aligned_ones, 0, 22); v = wdisp( dest_pos, inst_pos, 22); break; | |
143 case cb_op2: m = wdisp( word_aligned_ones, 0, 22); v = wdisp( dest_pos, inst_pos, 22); break; | |
3839 | 144 case bpr_op2: { |
145 if (is_cbcond(inst)) { | |
146 m = wdisp10(word_aligned_ones, 0); | |
147 v = wdisp10(dest_pos, inst_pos); | |
148 } else { | |
149 m = wdisp16(word_aligned_ones, 0); | |
150 v = wdisp16(dest_pos, inst_pos); | |
151 } | |
152 break; | |
153 } | |
0 | 154 default: ShouldNotReachHere(); |
155 } | |
156 } | |
157 return inst & ~m | v; | |
158 } | |
159 | |
160 // Return the offset of the branch destionation of instruction inst | |
161 // at offset pos. | |
162 // Should have pcs, but since all is relative, it works out. | |
163 int Assembler::branch_destination(int inst, int pos) { | |
164 int r; | |
165 switch (inv_op(inst)) { | |
166 default: ShouldNotReachHere(); | |
167 case call_op: r = inv_wdisp(inst, pos, 30); break; | |
168 case branch_op: | |
169 switch (inv_op2(inst)) { | |
170 case fbp_op2: r = inv_wdisp( inst, pos, 19); break; | |
171 case bp_op2: r = inv_wdisp( inst, pos, 19); break; | |
172 case fb_op2: r = inv_wdisp( inst, pos, 22); break; | |
173 case br_op2: r = inv_wdisp( inst, pos, 22); break; | |
174 case cb_op2: r = inv_wdisp( inst, pos, 22); break; | |
3839 | 175 case bpr_op2: { |
176 if (is_cbcond(inst)) { | |
177 r = inv_wdisp10(inst, pos); | |
178 } else { | |
179 r = inv_wdisp16(inst, pos); | |
180 } | |
181 break; | |
182 } | |
0 | 183 default: ShouldNotReachHere(); |
184 } | |
185 } | |
186 return r; | |
187 } | |
188 | |
189 int AbstractAssembler::code_fill_byte() { | |
190 return 0x00; // illegal instruction 0x00000000 | |
191 } | |
192 | |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
193 Assembler::Condition Assembler::reg_cond_to_cc_cond(Assembler::RCondition in) { |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
194 switch (in) { |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
195 case rc_z: return equal; |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
196 case rc_lez: return lessEqual; |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
197 case rc_lz: return less; |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
198 case rc_nz: return notEqual; |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
199 case rc_gz: return greater; |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
200 case rc_gez: return greaterEqual; |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
201 default: |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
202 ShouldNotReachHere(); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
203 } |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
204 return equal; |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
205 } |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
206 |
0 | 207 // Generate a bunch 'o stuff (including v9's |
208 #ifndef PRODUCT | |
209 void Assembler::test_v9() { | |
210 add( G0, G1, G2 ); | |
211 add( G3, 0, G4 ); | |
212 | |
213 addcc( G5, G6, G7 ); | |
214 addcc( I0, 1, I1 ); | |
215 addc( I2, I3, I4 ); | |
216 addc( I5, -1, I6 ); | |
217 addccc( I7, L0, L1 ); | |
218 addccc( L2, (1 << 12) - 2, L3 ); | |
219 | |
220 Label lbl1, lbl2, lbl3; | |
221 | |
222 bind(lbl1); | |
223 | |
224 bpr( rc_z, true, pn, L4, pc(), relocInfo::oop_type ); | |
225 delayed()->nop(); | |
226 bpr( rc_lez, false, pt, L5, lbl1); | |
227 delayed()->nop(); | |
228 | |
229 fb( f_never, true, pc() + 4, relocInfo::none); | |
230 delayed()->nop(); | |
231 fb( f_notEqual, false, lbl2 ); | |
232 delayed()->nop(); | |
233 | |
234 fbp( f_notZero, true, fcc0, pn, pc() - 4, relocInfo::none); | |
235 delayed()->nop(); | |
236 fbp( f_lessOrGreater, false, fcc1, pt, lbl3 ); | |
237 delayed()->nop(); | |
238 | |
239 br( equal, true, pc() + 1024, relocInfo::none); | |
240 delayed()->nop(); | |
241 br( lessEqual, false, lbl1 ); | |
242 delayed()->nop(); | |
243 br( never, false, lbl1 ); | |
244 delayed()->nop(); | |
245 | |
246 bp( less, true, icc, pn, pc(), relocInfo::none); | |
247 delayed()->nop(); | |
248 bp( lessEqualUnsigned, false, xcc, pt, lbl2 ); | |
249 delayed()->nop(); | |
250 | |
251 call( pc(), relocInfo::none); | |
252 delayed()->nop(); | |
253 call( lbl3 ); | |
254 delayed()->nop(); | |
255 | |
256 | |
257 casa( L6, L7, O0 ); | |
258 casxa( O1, O2, O3, 0 ); | |
259 | |
260 udiv( O4, O5, O7 ); | |
261 udiv( G0, (1 << 12) - 1, G1 ); | |
262 sdiv( G1, G2, G3 ); | |
263 sdiv( G4, -((1 << 12) - 1), G5 ); | |
264 udivcc( G6, G7, I0 ); | |
265 udivcc( I1, -((1 << 12) - 2), I2 ); | |
266 sdivcc( I3, I4, I5 ); | |
267 sdivcc( I6, -((1 << 12) - 0), I7 ); | |
268 | |
269 done(); | |
270 retry(); | |
271 | |
272 fadd( FloatRegisterImpl::S, F0, F1, F2 ); | |
273 fsub( FloatRegisterImpl::D, F34, F0, F62 ); | |
274 | |
275 fcmp( FloatRegisterImpl::Q, fcc0, F0, F60); | |
276 fcmpe( FloatRegisterImpl::S, fcc1, F31, F30); | |
277 | |
278 ftox( FloatRegisterImpl::D, F2, F4 ); | |
279 ftoi( FloatRegisterImpl::Q, F4, F8 ); | |
280 | |
281 ftof( FloatRegisterImpl::S, FloatRegisterImpl::Q, F3, F12 ); | |
282 | |
283 fxtof( FloatRegisterImpl::S, F4, F5 ); | |
284 fitof( FloatRegisterImpl::D, F6, F8 ); | |
285 | |
286 fmov( FloatRegisterImpl::Q, F16, F20 ); | |
287 fneg( FloatRegisterImpl::S, F6, F7 ); | |
288 fabs( FloatRegisterImpl::D, F10, F12 ); | |
289 | |
290 fmul( FloatRegisterImpl::Q, F24, F28, F32 ); | |
291 fmul( FloatRegisterImpl::S, FloatRegisterImpl::D, F8, F9, F14 ); | |
292 fdiv( FloatRegisterImpl::S, F10, F11, F12 ); | |
293 | |
294 fsqrt( FloatRegisterImpl::S, F13, F14 ); | |
295 | |
296 flush( L0, L1 ); | |
297 flush( L2, -1 ); | |
298 | |
299 flushw(); | |
300 | |
301 illtrap( (1 << 22) - 2); | |
302 | |
303 impdep1( 17, (1 << 19) - 1 ); | |
304 impdep2( 3, 0 ); | |
305 | |
306 jmpl( L3, L4, L5 ); | |
307 delayed()->nop(); | |
308 jmpl( L6, -1, L7, Relocation::spec_simple(relocInfo::none)); | |
309 delayed()->nop(); | |
310 | |
311 | |
312 ldf( FloatRegisterImpl::S, O0, O1, F15 ); | |
313 ldf( FloatRegisterImpl::D, O2, -1, F14 ); | |
314 | |
315 | |
316 ldfsr( O3, O4 ); | |
317 ldfsr( O5, -1 ); | |
318 ldxfsr( O6, O7 ); | |
319 ldxfsr( I0, -1 ); | |
320 | |
321 ldfa( FloatRegisterImpl::D, I1, I2, 1, F16 ); | |
322 ldfa( FloatRegisterImpl::Q, I3, -1, F36 ); | |
323 | |
324 ldsb( I4, I5, I6 ); | |
325 ldsb( I7, -1, G0 ); | |
326 ldsh( G1, G3, G4 ); | |
327 ldsh( G5, -1, G6 ); | |
328 ldsw( G7, L0, L1 ); | |
329 ldsw( L2, -1, L3 ); | |
330 ldub( L4, L5, L6 ); | |
331 ldub( L7, -1, O0 ); | |
332 lduh( O1, O2, O3 ); | |
333 lduh( O4, -1, O5 ); | |
334 lduw( O6, O7, G0 ); | |
335 lduw( G1, -1, G2 ); | |
336 ldx( G3, G4, G5 ); | |
337 ldx( G6, -1, G7 ); | |
338 ldd( I0, I1, I2 ); | |
339 ldd( I3, -1, I4 ); | |
340 | |
341 ldsba( I5, I6, 2, I7 ); | |
342 ldsba( L0, -1, L1 ); | |
343 ldsha( L2, L3, 3, L4 ); | |
344 ldsha( L5, -1, L6 ); | |
345 ldswa( L7, O0, (1 << 8) - 1, O1 ); | |
346 ldswa( O2, -1, O3 ); | |
347 lduba( O4, O5, 0, O6 ); | |
348 lduba( O7, -1, I0 ); | |
349 lduha( I1, I2, 1, I3 ); | |
350 lduha( I4, -1, I5 ); | |
351 lduwa( I6, I7, 2, L0 ); | |
352 lduwa( L1, -1, L2 ); | |
353 ldxa( L3, L4, 3, L5 ); | |
354 ldxa( L6, -1, L7 ); | |
355 ldda( G0, G1, 4, G2 ); | |
356 ldda( G3, -1, G4 ); | |
357 | |
358 ldstub( G5, G6, G7 ); | |
359 ldstub( O0, -1, O1 ); | |
360 | |
361 ldstuba( O2, O3, 5, O4 ); | |
362 ldstuba( O5, -1, O6 ); | |
363 | |
364 and3( I0, L0, O0 ); | |
365 and3( G7, -1, O7 ); | |
366 andcc( L2, I2, G2 ); | |
367 andcc( L4, -1, G4 ); | |
368 andn( I5, I6, I7 ); | |
369 andn( I6, -1, I7 ); | |
370 andncc( I5, I6, I7 ); | |
371 andncc( I7, -1, I6 ); | |
372 or3( I5, I6, I7 ); | |
373 or3( I7, -1, I6 ); | |
374 orcc( I5, I6, I7 ); | |
375 orcc( I7, -1, I6 ); | |
376 orn( I5, I6, I7 ); | |
377 orn( I7, -1, I6 ); | |
378 orncc( I5, I6, I7 ); | |
379 orncc( I7, -1, I6 ); | |
380 xor3( I5, I6, I7 ); | |
381 xor3( I7, -1, I6 ); | |
382 xorcc( I5, I6, I7 ); | |
383 xorcc( I7, -1, I6 ); | |
384 xnor( I5, I6, I7 ); | |
385 xnor( I7, -1, I6 ); | |
386 xnorcc( I5, I6, I7 ); | |
387 xnorcc( I7, -1, I6 ); | |
388 | |
389 membar( Membar_mask_bits(StoreStore | LoadStore | StoreLoad | LoadLoad | Sync | MemIssue | Lookaside ) ); | |
390 membar( StoreStore ); | |
391 membar( LoadStore ); | |
392 membar( StoreLoad ); | |
393 membar( LoadLoad ); | |
394 membar( Sync ); | |
395 membar( MemIssue ); | |
396 membar( Lookaside ); | |
397 | |
398 fmov( FloatRegisterImpl::S, f_ordered, true, fcc2, F16, F17 ); | |
399 fmov( FloatRegisterImpl::D, rc_lz, L5, F18, F20 ); | |
400 | |
401 movcc( overflowClear, false, icc, I6, L4 ); | |
402 movcc( f_unorderedOrEqual, true, fcc2, (1 << 10) - 1, O0 ); | |
403 | |
404 movr( rc_nz, I5, I6, I7 ); | |
405 movr( rc_gz, L1, -1, L2 ); | |
406 | |
407 mulx( I5, I6, I7 ); | |
408 mulx( I7, -1, I6 ); | |
409 sdivx( I5, I6, I7 ); | |
410 sdivx( I7, -1, I6 ); | |
411 udivx( I5, I6, I7 ); | |
412 udivx( I7, -1, I6 ); | |
413 | |
414 umul( I5, I6, I7 ); | |
415 umul( I7, -1, I6 ); | |
416 smul( I5, I6, I7 ); | |
417 smul( I7, -1, I6 ); | |
418 umulcc( I5, I6, I7 ); | |
419 umulcc( I7, -1, I6 ); | |
420 smulcc( I5, I6, I7 ); | |
421 smulcc( I7, -1, I6 ); | |
422 | |
423 mulscc( I5, I6, I7 ); | |
424 mulscc( I7, -1, I6 ); | |
425 | |
426 nop(); | |
427 | |
428 | |
429 popc( G0, G1); | |
430 popc( -1, G2); | |
431 | |
432 prefetch( L1, L2, severalReads ); | |
433 prefetch( L3, -1, oneRead ); | |
434 prefetcha( O3, O2, 6, severalWritesAndPossiblyReads ); | |
435 prefetcha( G2, -1, oneWrite ); | |
436 | |
437 rett( I7, I7); | |
438 delayed()->nop(); | |
439 rett( G0, -1, relocInfo::none); | |
440 delayed()->nop(); | |
441 | |
442 save( I5, I6, I7 ); | |
443 save( I7, -1, I6 ); | |
444 restore( I5, I6, I7 ); | |
445 restore( I7, -1, I6 ); | |
446 | |
447 saved(); | |
448 restored(); | |
449 | |
450 sethi( 0xaaaaaaaa, I3, Relocation::spec_simple(relocInfo::none)); | |
451 | |
452 sll( I5, I6, I7 ); | |
453 sll( I7, 31, I6 ); | |
454 srl( I5, I6, I7 ); | |
455 srl( I7, 0, I6 ); | |
456 sra( I5, I6, I7 ); | |
457 sra( I7, 30, I6 ); | |
458 sllx( I5, I6, I7 ); | |
459 sllx( I7, 63, I6 ); | |
460 srlx( I5, I6, I7 ); | |
461 srlx( I7, 0, I6 ); | |
462 srax( I5, I6, I7 ); | |
463 srax( I7, 62, I6 ); | |
464 | |
465 sir( -1 ); | |
466 | |
467 stbar(); | |
468 | |
469 stf( FloatRegisterImpl::Q, F40, G0, I7 ); | |
470 stf( FloatRegisterImpl::S, F18, I3, -1 ); | |
471 | |
472 stfsr( L1, L2 ); | |
473 stfsr( I7, -1 ); | |
474 stxfsr( I6, I5 ); | |
475 stxfsr( L4, -1 ); | |
476 | |
477 stfa( FloatRegisterImpl::D, F22, I6, I7, 7 ); | |
478 stfa( FloatRegisterImpl::Q, F44, G0, -1 ); | |
479 | |
480 stb( L5, O2, I7 ); | |
481 stb( I7, I6, -1 ); | |
482 sth( L5, O2, I7 ); | |
483 sth( I7, I6, -1 ); | |
484 stw( L5, O2, I7 ); | |
485 stw( I7, I6, -1 ); | |
486 stx( L5, O2, I7 ); | |
487 stx( I7, I6, -1 ); | |
488 std( L5, O2, I7 ); | |
489 std( I7, I6, -1 ); | |
490 | |
491 stba( L5, O2, I7, 8 ); | |
492 stba( I7, I6, -1 ); | |
493 stha( L5, O2, I7, 9 ); | |
494 stha( I7, I6, -1 ); | |
495 stwa( L5, O2, I7, 0 ); | |
496 stwa( I7, I6, -1 ); | |
497 stxa( L5, O2, I7, 11 ); | |
498 stxa( I7, I6, -1 ); | |
499 stda( L5, O2, I7, 12 ); | |
500 stda( I7, I6, -1 ); | |
501 | |
502 sub( I5, I6, I7 ); | |
503 sub( I7, -1, I6 ); | |
504 subcc( I5, I6, I7 ); | |
505 subcc( I7, -1, I6 ); | |
506 subc( I5, I6, I7 ); | |
507 subc( I7, -1, I6 ); | |
508 subccc( I5, I6, I7 ); | |
509 subccc( I7, -1, I6 ); | |
510 | |
511 swap( I5, I6, I7 ); | |
512 swap( I7, -1, I6 ); | |
513 | |
514 swapa( G0, G1, 13, G2 ); | |
515 swapa( I7, -1, I6 ); | |
516 | |
517 taddcc( I5, I6, I7 ); | |
518 taddcc( I7, -1, I6 ); | |
519 taddcctv( I5, I6, I7 ); | |
520 taddcctv( I7, -1, I6 ); | |
521 | |
522 tsubcc( I5, I6, I7 ); | |
523 tsubcc( I7, -1, I6 ); | |
524 tsubcctv( I5, I6, I7 ); | |
525 tsubcctv( I7, -1, I6 ); | |
526 | |
527 trap( overflowClear, xcc, G0, G1 ); | |
528 trap( lessEqual, icc, I7, 17 ); | |
529 | |
530 bind(lbl2); | |
531 bind(lbl3); | |
532 | |
533 code()->decode(); | |
534 } | |
535 | |
536 // Generate a bunch 'o stuff unique to V8 | |
537 void Assembler::test_v8_onlys() { | |
538 Label lbl1; | |
539 | |
540 cb( cp_0or1or2, false, pc() - 4, relocInfo::none); | |
541 delayed()->nop(); | |
542 cb( cp_never, true, lbl1); | |
543 delayed()->nop(); | |
544 | |
545 cpop1(1, 2, 3, 4); | |
546 cpop2(5, 6, 7, 8); | |
547 | |
548 ldc( I0, I1, 31); | |
549 ldc( I2, -1, 0); | |
550 | |
551 lddc( I4, I4, 30); | |
552 lddc( I6, 0, 1 ); | |
553 | |
554 ldcsr( L0, L1, 0); | |
555 ldcsr( L1, (1 << 12) - 1, 17 ); | |
556 | |
557 stc( 31, L4, L5); | |
558 stc( 30, L6, -(1 << 12) ); | |
559 | |
560 stdc( 0, L7, G0); | |
561 stdc( 1, G1, 0 ); | |
562 | |
563 stcsr( 16, G2, G3); | |
564 stcsr( 17, G4, 1 ); | |
565 | |
566 stdcq( 4, G5, G6); | |
567 stdcq( 5, G7, -1 ); | |
568 | |
569 bind(lbl1); | |
570 | |
571 code()->decode(); | |
572 } | |
573 #endif | |
574 | |
575 // Implementation of MacroAssembler | |
576 | |
577 void MacroAssembler::null_check(Register reg, int offset) { | |
578 if (needs_explicit_null_check((intptr_t)offset)) { | |
579 // provoke OS NULL exception if reg = NULL by | |
580 // accessing M[reg] w/o changing any registers | |
581 ld_ptr(reg, 0, G0); | |
582 } | |
583 else { | |
584 // nothing to do, (later) access of M[reg + offset] | |
585 // will provoke OS NULL exception if reg = NULL | |
586 } | |
587 } | |
588 | |
589 // Ring buffer jumps | |
590 | |
591 #ifndef PRODUCT | |
592 void MacroAssembler::ret( bool trace ) { if (trace) { | |
593 mov(I7, O7); // traceable register | |
594 JMP(O7, 2 * BytesPerInstWord); | |
595 } else { | |
596 jmpl( I7, 2 * BytesPerInstWord, G0 ); | |
597 } | |
598 } | |
599 | |
600 void MacroAssembler::retl( bool trace ) { if (trace) JMP(O7, 2 * BytesPerInstWord); | |
601 else jmpl( O7, 2 * BytesPerInstWord, G0 ); } | |
602 #endif /* PRODUCT */ | |
603 | |
604 | |
605 void MacroAssembler::jmp2(Register r1, Register r2, const char* file, int line ) { | |
606 assert_not_delayed(); | |
607 // This can only be traceable if r1 & r2 are visible after a window save | |
608 if (TraceJumps) { | |
609 #ifndef PRODUCT | |
610 save_frame(0); | |
611 verify_thread(); | |
612 ld(G2_thread, in_bytes(JavaThread::jmp_ring_index_offset()), O0); | |
613 add(G2_thread, in_bytes(JavaThread::jmp_ring_offset()), O1); | |
614 sll(O0, exact_log2(4*sizeof(intptr_t)), O2); | |
615 add(O2, O1, O1); | |
616 | |
617 add(r1->after_save(), r2->after_save(), O2); | |
618 set((intptr_t)file, O3); | |
619 set(line, O4); | |
620 Label L; | |
621 // get nearby pc, store jmp target | |
622 call(L, relocInfo::none); // No relocation for call to pc+0x8 | |
623 delayed()->st(O2, O1, 0); | |
624 bind(L); | |
625 | |
626 // store nearby pc | |
627 st(O7, O1, sizeof(intptr_t)); | |
628 // store file | |
629 st(O3, O1, 2*sizeof(intptr_t)); | |
630 // store line | |
631 st(O4, O1, 3*sizeof(intptr_t)); | |
632 add(O0, 1, O0); | |
633 and3(O0, JavaThread::jump_ring_buffer_size - 1, O0); | |
634 st(O0, G2_thread, in_bytes(JavaThread::jmp_ring_index_offset())); | |
635 restore(); | |
636 #endif /* PRODUCT */ | |
637 } | |
638 jmpl(r1, r2, G0); | |
639 } | |
640 void MacroAssembler::jmp(Register r1, int offset, const char* file, int line ) { | |
641 assert_not_delayed(); | |
642 // This can only be traceable if r1 is visible after a window save | |
643 if (TraceJumps) { | |
644 #ifndef PRODUCT | |
645 save_frame(0); | |
646 verify_thread(); | |
647 ld(G2_thread, in_bytes(JavaThread::jmp_ring_index_offset()), O0); | |
648 add(G2_thread, in_bytes(JavaThread::jmp_ring_offset()), O1); | |
649 sll(O0, exact_log2(4*sizeof(intptr_t)), O2); | |
650 add(O2, O1, O1); | |
651 | |
652 add(r1->after_save(), offset, O2); | |
653 set((intptr_t)file, O3); | |
654 set(line, O4); | |
655 Label L; | |
656 // get nearby pc, store jmp target | |
657 call(L, relocInfo::none); // No relocation for call to pc+0x8 | |
658 delayed()->st(O2, O1, 0); | |
659 bind(L); | |
660 | |
661 // store nearby pc | |
662 st(O7, O1, sizeof(intptr_t)); | |
663 // store file | |
664 st(O3, O1, 2*sizeof(intptr_t)); | |
665 // store line | |
666 st(O4, O1, 3*sizeof(intptr_t)); | |
667 add(O0, 1, O0); | |
668 and3(O0, JavaThread::jump_ring_buffer_size - 1, O0); | |
669 st(O0, G2_thread, in_bytes(JavaThread::jmp_ring_index_offset())); | |
670 restore(); | |
671 #endif /* PRODUCT */ | |
672 } | |
673 jmp(r1, offset); | |
674 } | |
675 | |
676 // This code sequence is relocatable to any address, even on LP64. | |
1680
a64438a2b7e8
6958465: Sparc aten build24.0: openjdk-7.ea-b96 failed Error: Formal argument ... requires an lvalue
coleenp
parents:
1552
diff
changeset
|
677 void MacroAssembler::jumpl(const AddressLiteral& addrlit, Register temp, Register d, int offset, const char* file, int line) { |
0 | 678 assert_not_delayed(); |
679 // Force fixed length sethi because NativeJump and NativeFarCall don't handle | |
680 // variable length instruction streams. | |
727 | 681 patchable_sethi(addrlit, temp); |
682 Address a(temp, addrlit.low10() + offset); // Add the offset to the displacement. | |
0 | 683 if (TraceJumps) { |
684 #ifndef PRODUCT | |
685 // Must do the add here so relocation can find the remainder of the | |
686 // value to be relocated. | |
727 | 687 add(a.base(), a.disp(), a.base(), addrlit.rspec(offset)); |
0 | 688 save_frame(0); |
689 verify_thread(); | |
690 ld(G2_thread, in_bytes(JavaThread::jmp_ring_index_offset()), O0); | |
691 add(G2_thread, in_bytes(JavaThread::jmp_ring_offset()), O1); | |
692 sll(O0, exact_log2(4*sizeof(intptr_t)), O2); | |
693 add(O2, O1, O1); | |
694 | |
695 set((intptr_t)file, O3); | |
696 set(line, O4); | |
697 Label L; | |
698 | |
699 // get nearby pc, store jmp target | |
700 call(L, relocInfo::none); // No relocation for call to pc+0x8 | |
701 delayed()->st(a.base()->after_save(), O1, 0); | |
702 bind(L); | |
703 | |
704 // store nearby pc | |
705 st(O7, O1, sizeof(intptr_t)); | |
706 // store file | |
707 st(O3, O1, 2*sizeof(intptr_t)); | |
708 // store line | |
709 st(O4, O1, 3*sizeof(intptr_t)); | |
710 add(O0, 1, O0); | |
711 and3(O0, JavaThread::jump_ring_buffer_size - 1, O0); | |
712 st(O0, G2_thread, in_bytes(JavaThread::jmp_ring_index_offset())); | |
713 restore(); | |
714 jmpl(a.base(), G0, d); | |
715 #else | |
727 | 716 jmpl(a.base(), a.disp(), d); |
0 | 717 #endif /* PRODUCT */ |
718 } else { | |
727 | 719 jmpl(a.base(), a.disp(), d); |
0 | 720 } |
721 } | |
722 | |
1680
a64438a2b7e8
6958465: Sparc aten build24.0: openjdk-7.ea-b96 failed Error: Formal argument ... requires an lvalue
coleenp
parents:
1552
diff
changeset
|
723 void MacroAssembler::jump(const AddressLiteral& addrlit, Register temp, int offset, const char* file, int line) { |
727 | 724 jumpl(addrlit, temp, G0, offset, file, line); |
0 | 725 } |
726 | |
727 | |
728 // Convert to C varargs format | |
729 void MacroAssembler::set_varargs( Argument inArg, Register d ) { | |
730 // spill register-resident args to their memory slots | |
731 // (SPARC calling convention requires callers to have already preallocated these) | |
732 // Note that the inArg might in fact be an outgoing argument, | |
733 // if a leaf routine or stub does some tricky argument shuffling. | |
734 // This routine must work even though one of the saved arguments | |
735 // is in the d register (e.g., set_varargs(Argument(0, false), O0)). | |
736 for (Argument savePtr = inArg; | |
737 savePtr.is_register(); | |
738 savePtr = savePtr.successor()) { | |
739 st_ptr(savePtr.as_register(), savePtr.address_in_frame()); | |
740 } | |
741 // return the address of the first memory slot | |
727 | 742 Address a = inArg.address_in_frame(); |
743 add(a.base(), a.disp(), d); | |
0 | 744 } |
745 | |
746 // Conditional breakpoint (for assertion checks in assembly code) | |
747 void MacroAssembler::breakpoint_trap(Condition c, CC cc) { | |
748 trap(c, cc, G0, ST_RESERVED_FOR_USER_0); | |
749 } | |
750 | |
751 // We want to use ST_BREAKPOINT here, but the debugger is confused by it. | |
752 void MacroAssembler::breakpoint_trap() { | |
753 trap(ST_RESERVED_FOR_USER_0); | |
754 } | |
755 | |
756 // flush windows (except current) using flushw instruction if avail. | |
757 void MacroAssembler::flush_windows() { | |
758 if (VM_Version::v9_instructions_work()) flushw(); | |
759 else flush_windows_trap(); | |
760 } | |
761 | |
762 // Write serialization page so VM thread can do a pseudo remote membar | |
763 // We use the current thread pointer to calculate a thread specific | |
764 // offset to write to within the page. This minimizes bus traffic | |
765 // due to cache line collision. | |
766 void MacroAssembler::serialize_memory(Register thread, Register tmp1, Register tmp2) { | |
767 srl(thread, os::get_serialize_page_shift_count(), tmp2); | |
768 if (Assembler::is_simm13(os::vm_page_size())) { | |
769 and3(tmp2, (os::vm_page_size() - sizeof(int)), tmp2); | |
770 } | |
771 else { | |
772 set((os::vm_page_size() - sizeof(int)), tmp1); | |
773 and3(tmp2, tmp1, tmp2); | |
774 } | |
727 | 775 set(os::get_memory_serialize_page(), tmp1); |
0 | 776 st(G0, tmp1, tmp2); |
777 } | |
778 | |
779 | |
780 | |
781 void MacroAssembler::enter() { | |
782 Unimplemented(); | |
783 } | |
784 | |
785 void MacroAssembler::leave() { | |
786 Unimplemented(); | |
787 } | |
788 | |
789 void MacroAssembler::mult(Register s1, Register s2, Register d) { | |
790 if(VM_Version::v9_instructions_work()) { | |
791 mulx (s1, s2, d); | |
792 } else { | |
793 smul (s1, s2, d); | |
794 } | |
795 } | |
796 | |
797 void MacroAssembler::mult(Register s1, int simm13a, Register d) { | |
798 if(VM_Version::v9_instructions_work()) { | |
799 mulx (s1, simm13a, d); | |
800 } else { | |
801 smul (s1, simm13a, d); | |
802 } | |
803 } | |
804 | |
805 | |
806 #ifdef ASSERT | |
807 void MacroAssembler::read_ccr_v8_assert(Register ccr_save) { | |
808 const Register s1 = G3_scratch; | |
809 const Register s2 = G4_scratch; | |
810 Label get_psr_test; | |
811 // Get the condition codes the V8 way. | |
812 read_ccr_trap(s1); | |
813 mov(ccr_save, s2); | |
814 // This is a test of V8 which has icc but not xcc | |
815 // so mask off the xcc bits | |
816 and3(s2, 0xf, s2); | |
817 // Compare condition codes from the V8 and V9 ways. | |
818 subcc(s2, s1, G0); | |
819 br(Assembler::notEqual, true, Assembler::pt, get_psr_test); | |
820 delayed()->breakpoint_trap(); | |
821 bind(get_psr_test); | |
822 } | |
823 | |
824 void MacroAssembler::write_ccr_v8_assert(Register ccr_save) { | |
825 const Register s1 = G3_scratch; | |
826 const Register s2 = G4_scratch; | |
827 Label set_psr_test; | |
828 // Write out the saved condition codes the V8 way | |
829 write_ccr_trap(ccr_save, s1, s2); | |
830 // Read back the condition codes using the V9 instruction | |
831 rdccr(s1); | |
832 mov(ccr_save, s2); | |
833 // This is a test of V8 which has icc but not xcc | |
834 // so mask off the xcc bits | |
835 and3(s2, 0xf, s2); | |
836 and3(s1, 0xf, s1); | |
837 // Compare the V8 way with the V9 way. | |
838 subcc(s2, s1, G0); | |
839 br(Assembler::notEqual, true, Assembler::pt, set_psr_test); | |
840 delayed()->breakpoint_trap(); | |
841 bind(set_psr_test); | |
842 } | |
843 #else | |
844 #define read_ccr_v8_assert(x) | |
845 #define write_ccr_v8_assert(x) | |
846 #endif // ASSERT | |
847 | |
848 void MacroAssembler::read_ccr(Register ccr_save) { | |
849 if (VM_Version::v9_instructions_work()) { | |
850 rdccr(ccr_save); | |
851 // Test code sequence used on V8. Do not move above rdccr. | |
852 read_ccr_v8_assert(ccr_save); | |
853 } else { | |
854 read_ccr_trap(ccr_save); | |
855 } | |
856 } | |
857 | |
858 void MacroAssembler::write_ccr(Register ccr_save) { | |
859 if (VM_Version::v9_instructions_work()) { | |
860 // Test code sequence used on V8. Do not move below wrccr. | |
861 write_ccr_v8_assert(ccr_save); | |
862 wrccr(ccr_save); | |
863 } else { | |
864 const Register temp_reg1 = G3_scratch; | |
865 const Register temp_reg2 = G4_scratch; | |
866 write_ccr_trap(ccr_save, temp_reg1, temp_reg2); | |
867 } | |
868 } | |
869 | |
870 | |
871 // Calls to C land | |
872 | |
873 #ifdef ASSERT | |
874 // a hook for debugging | |
875 static Thread* reinitialize_thread() { | |
876 return ThreadLocalStorage::thread(); | |
877 } | |
878 #else | |
879 #define reinitialize_thread ThreadLocalStorage::thread | |
880 #endif | |
881 | |
882 #ifdef ASSERT | |
883 address last_get_thread = NULL; | |
884 #endif | |
885 | |
886 // call this when G2_thread is not known to be valid | |
887 void MacroAssembler::get_thread() { | |
888 save_frame(0); // to avoid clobbering O0 | |
889 mov(G1, L0); // avoid clobbering G1 | |
890 mov(G5_method, L1); // avoid clobbering G5 | |
891 mov(G3, L2); // avoid clobbering G3 also | |
892 mov(G4, L5); // avoid clobbering G4 | |
893 #ifdef ASSERT | |
727 | 894 AddressLiteral last_get_thread_addrlit(&last_get_thread); |
895 set(last_get_thread_addrlit, L3); | |
0 | 896 inc(L4, get_pc(L4) + 2 * BytesPerInstWord); // skip getpc() code + inc + st_ptr to point L4 at call |
727 | 897 st_ptr(L4, L3, 0); |
0 | 898 #endif |
899 call(CAST_FROM_FN_PTR(address, reinitialize_thread), relocInfo::runtime_call_type); | |
900 delayed()->nop(); | |
901 mov(L0, G1); | |
902 mov(L1, G5_method); | |
903 mov(L2, G3); | |
904 mov(L5, G4); | |
905 restore(O0, 0, G2_thread); | |
906 } | |
907 | |
908 static Thread* verify_thread_subroutine(Thread* gthread_value) { | |
909 Thread* correct_value = ThreadLocalStorage::thread(); | |
910 guarantee(gthread_value == correct_value, "G2_thread value must be the thread"); | |
911 return correct_value; | |
912 } | |
913 | |
914 void MacroAssembler::verify_thread() { | |
915 if (VerifyThread) { | |
916 // NOTE: this chops off the heads of the 64-bit O registers. | |
917 #ifdef CC_INTERP | |
918 save_frame(0); | |
919 #else | |
920 // make sure G2_thread contains the right value | |
921 save_frame_and_mov(0, Lmethod, Lmethod); // to avoid clobbering O0 (and propagate Lmethod for -Xprof) | |
922 mov(G1, L1); // avoid clobbering G1 | |
923 // G2 saved below | |
924 mov(G3, L3); // avoid clobbering G3 | |
925 mov(G4, L4); // avoid clobbering G4 | |
926 mov(G5_method, L5); // avoid clobbering G5_method | |
927 #endif /* CC_INTERP */ | |
928 #if defined(COMPILER2) && !defined(_LP64) | |
929 // Save & restore possible 64-bit Long arguments in G-regs | |
930 srlx(G1,32,L0); | |
931 srlx(G4,32,L6); | |
932 #endif | |
933 call(CAST_FROM_FN_PTR(address,verify_thread_subroutine), relocInfo::runtime_call_type); | |
934 delayed()->mov(G2_thread, O0); | |
935 | |
936 mov(L1, G1); // Restore G1 | |
937 // G2 restored below | |
938 mov(L3, G3); // restore G3 | |
939 mov(L4, G4); // restore G4 | |
940 mov(L5, G5_method); // restore G5_method | |
941 #if defined(COMPILER2) && !defined(_LP64) | |
942 // Save & restore possible 64-bit Long arguments in G-regs | |
943 sllx(L0,32,G2); // Move old high G1 bits high in G2 | |
2002 | 944 srl(G1, 0,G1); // Clear current high G1 bits |
0 | 945 or3 (G1,G2,G1); // Recover 64-bit G1 |
946 sllx(L6,32,G2); // Move old high G4 bits high in G2 | |
2002 | 947 srl(G4, 0,G4); // Clear current high G4 bits |
0 | 948 or3 (G4,G2,G4); // Recover 64-bit G4 |
949 #endif | |
950 restore(O0, 0, G2_thread); | |
951 } | |
952 } | |
953 | |
954 | |
955 void MacroAssembler::save_thread(const Register thread_cache) { | |
956 verify_thread(); | |
957 if (thread_cache->is_valid()) { | |
958 assert(thread_cache->is_local() || thread_cache->is_in(), "bad volatile"); | |
959 mov(G2_thread, thread_cache); | |
960 } | |
961 if (VerifyThread) { | |
962 // smash G2_thread, as if the VM were about to anyway | |
963 set(0x67676767, G2_thread); | |
964 } | |
965 } | |
966 | |
967 | |
968 void MacroAssembler::restore_thread(const Register thread_cache) { | |
969 if (thread_cache->is_valid()) { | |
970 assert(thread_cache->is_local() || thread_cache->is_in(), "bad volatile"); | |
971 mov(thread_cache, G2_thread); | |
972 verify_thread(); | |
973 } else { | |
974 // do it the slow way | |
975 get_thread(); | |
976 } | |
977 } | |
978 | |
979 | |
980 // %%% maybe get rid of [re]set_last_Java_frame | |
981 void MacroAssembler::set_last_Java_frame(Register last_java_sp, Register last_Java_pc) { | |
982 assert_not_delayed(); | |
727 | 983 Address flags(G2_thread, JavaThread::frame_anchor_offset() + |
984 JavaFrameAnchor::flags_offset()); | |
985 Address pc_addr(G2_thread, JavaThread::last_Java_pc_offset()); | |
0 | 986 |
987 // Always set last_Java_pc and flags first because once last_Java_sp is visible | |
988 // has_last_Java_frame is true and users will look at the rest of the fields. | |
989 // (Note: flags should always be zero before we get here so doesn't need to be set.) | |
990 | |
991 #ifdef ASSERT | |
992 // Verify that flags was zeroed on return to Java | |
993 Label PcOk; | |
994 save_frame(0); // to avoid clobbering O0 | |
995 ld_ptr(pc_addr, L0); | |
3839 | 996 br_null_short(L0, Assembler::pt, PcOk); |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
4762
diff
changeset
|
997 STOP("last_Java_pc not zeroed before leaving Java"); |
0 | 998 bind(PcOk); |
999 | |
1000 // Verify that flags was zeroed on return to Java | |
1001 Label FlagsOk; | |
1002 ld(flags, L0); | |
1003 tst(L0); | |
1004 br(Assembler::zero, false, Assembler::pt, FlagsOk); | |
1005 delayed() -> restore(); | |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
4762
diff
changeset
|
1006 STOP("flags not zeroed before leaving Java"); |
0 | 1007 bind(FlagsOk); |
1008 #endif /* ASSERT */ | |
1009 // | |
1010 // When returning from calling out from Java mode the frame anchor's last_Java_pc | |
1011 // will always be set to NULL. It is set here so that if we are doing a call to | |
1012 // native (not VM) that we capture the known pc and don't have to rely on the | |
1013 // native call having a standard frame linkage where we can find the pc. | |
1014 | |
1015 if (last_Java_pc->is_valid()) { | |
1016 st_ptr(last_Java_pc, pc_addr); | |
1017 } | |
1018 | |
1019 #ifdef _LP64 | |
1020 #ifdef ASSERT | |
1021 // Make sure that we have an odd stack | |
1022 Label StackOk; | |
1023 andcc(last_java_sp, 0x01, G0); | |
1024 br(Assembler::notZero, false, Assembler::pt, StackOk); | |
3839 | 1025 delayed()->nop(); |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
4762
diff
changeset
|
1026 STOP("Stack Not Biased in set_last_Java_frame"); |
0 | 1027 bind(StackOk); |
1028 #endif // ASSERT | |
1029 assert( last_java_sp != G4_scratch, "bad register usage in set_last_Java_frame"); | |
1030 add( last_java_sp, STACK_BIAS, G4_scratch ); | |
727 | 1031 st_ptr(G4_scratch, G2_thread, JavaThread::last_Java_sp_offset()); |
0 | 1032 #else |
727 | 1033 st_ptr(last_java_sp, G2_thread, JavaThread::last_Java_sp_offset()); |
0 | 1034 #endif // _LP64 |
1035 } | |
1036 | |
1037 void MacroAssembler::reset_last_Java_frame(void) { | |
1038 assert_not_delayed(); | |
1039 | |
727 | 1040 Address sp_addr(G2_thread, JavaThread::last_Java_sp_offset()); |
1041 Address pc_addr(G2_thread, JavaThread::frame_anchor_offset() + JavaFrameAnchor::last_Java_pc_offset()); | |
1042 Address flags (G2_thread, JavaThread::frame_anchor_offset() + JavaFrameAnchor::flags_offset()); | |
0 | 1043 |
1044 #ifdef ASSERT | |
1045 // check that it WAS previously set | |
1046 #ifdef CC_INTERP | |
1047 save_frame(0); | |
1048 #else | |
1049 save_frame_and_mov(0, Lmethod, Lmethod); // Propagate Lmethod to helper frame for -Xprof | |
1050 #endif /* CC_INTERP */ | |
1051 ld_ptr(sp_addr, L0); | |
1052 tst(L0); | |
1053 breakpoint_trap(Assembler::zero, Assembler::ptr_cc); | |
1054 restore(); | |
1055 #endif // ASSERT | |
1056 | |
1057 st_ptr(G0, sp_addr); | |
1058 // Always return last_Java_pc to zero | |
1059 st_ptr(G0, pc_addr); | |
1060 // Always null flags after return to Java | |
1061 st(G0, flags); | |
1062 } | |
1063 | |
1064 | |
1065 void MacroAssembler::call_VM_base( | |
1066 Register oop_result, | |
1067 Register thread_cache, | |
1068 Register last_java_sp, | |
1069 address entry_point, | |
1070 int number_of_arguments, | |
1071 bool check_exceptions) | |
1072 { | |
1073 assert_not_delayed(); | |
1074 | |
1075 // determine last_java_sp register | |
1076 if (!last_java_sp->is_valid()) { | |
1077 last_java_sp = SP; | |
1078 } | |
1079 // debugging support | |
1080 assert(number_of_arguments >= 0 , "cannot have negative number of arguments"); | |
1081 | |
1082 // 64-bit last_java_sp is biased! | |
1083 set_last_Java_frame(last_java_sp, noreg); | |
1084 if (VerifyThread) mov(G2_thread, O0); // about to be smashed; pass early | |
1085 save_thread(thread_cache); | |
1086 // do the call | |
1087 call(entry_point, relocInfo::runtime_call_type); | |
1088 if (!VerifyThread) | |
1089 delayed()->mov(G2_thread, O0); // pass thread as first argument | |
1090 else | |
1091 delayed()->nop(); // (thread already passed) | |
1092 restore_thread(thread_cache); | |
1093 reset_last_Java_frame(); | |
1094 | |
1095 // check for pending exceptions. use Gtemp as scratch register. | |
1096 if (check_exceptions) { | |
1097 check_and_forward_exception(Gtemp); | |
1098 } | |
1099 | |
3753
cba7b5c2d53f
7045514: SPARC assembly code for JSR 292 ricochet frames
never
parents:
3249
diff
changeset
|
1100 #ifdef ASSERT |
cba7b5c2d53f
7045514: SPARC assembly code for JSR 292 ricochet frames
never
parents:
3249
diff
changeset
|
1101 set(badHeapWordVal, G3); |
cba7b5c2d53f
7045514: SPARC assembly code for JSR 292 ricochet frames
never
parents:
3249
diff
changeset
|
1102 set(badHeapWordVal, G4); |
cba7b5c2d53f
7045514: SPARC assembly code for JSR 292 ricochet frames
never
parents:
3249
diff
changeset
|
1103 set(badHeapWordVal, G5); |
cba7b5c2d53f
7045514: SPARC assembly code for JSR 292 ricochet frames
never
parents:
3249
diff
changeset
|
1104 #endif |
cba7b5c2d53f
7045514: SPARC assembly code for JSR 292 ricochet frames
never
parents:
3249
diff
changeset
|
1105 |
0 | 1106 // get oop result if there is one and reset the value in the thread |
1107 if (oop_result->is_valid()) { | |
1108 get_vm_result(oop_result); | |
1109 } | |
1110 } | |
1111 | |
1112 void MacroAssembler::check_and_forward_exception(Register scratch_reg) | |
1113 { | |
1114 Label L; | |
1115 | |
1116 check_and_handle_popframe(scratch_reg); | |
1117 check_and_handle_earlyret(scratch_reg); | |
1118 | |
727 | 1119 Address exception_addr(G2_thread, Thread::pending_exception_offset()); |
0 | 1120 ld_ptr(exception_addr, scratch_reg); |
3839 | 1121 br_null_short(scratch_reg, pt, L); |
0 | 1122 // we use O7 linkage so that forward_exception_entry has the issuing PC |
1123 call(StubRoutines::forward_exception_entry(), relocInfo::runtime_call_type); | |
1124 delayed()->nop(); | |
1125 bind(L); | |
1126 } | |
1127 | |
1128 | |
1129 void MacroAssembler::check_and_handle_popframe(Register scratch_reg) { | |
1130 } | |
1131 | |
1132 | |
1133 void MacroAssembler::check_and_handle_earlyret(Register scratch_reg) { | |
1134 } | |
1135 | |
1136 | |
1137 void MacroAssembler::call_VM(Register oop_result, address entry_point, int number_of_arguments, bool check_exceptions) { | |
1138 call_VM_base(oop_result, noreg, noreg, entry_point, number_of_arguments, check_exceptions); | |
1139 } | |
1140 | |
1141 | |
1142 void MacroAssembler::call_VM(Register oop_result, address entry_point, Register arg_1, bool check_exceptions) { | |
1143 // O0 is reserved for the thread | |
1144 mov(arg_1, O1); | |
1145 call_VM(oop_result, entry_point, 1, check_exceptions); | |
1146 } | |
1147 | |
1148 | |
1149 void MacroAssembler::call_VM(Register oop_result, address entry_point, Register arg_1, Register arg_2, bool check_exceptions) { | |
1150 // O0 is reserved for the thread | |
1151 mov(arg_1, O1); | |
1152 mov(arg_2, O2); assert(arg_2 != O1, "smashed argument"); | |
1153 call_VM(oop_result, entry_point, 2, check_exceptions); | |
1154 } | |
1155 | |
1156 | |
1157 void MacroAssembler::call_VM(Register oop_result, address entry_point, Register arg_1, Register arg_2, Register arg_3, bool check_exceptions) { | |
1158 // O0 is reserved for the thread | |
1159 mov(arg_1, O1); | |
1160 mov(arg_2, O2); assert(arg_2 != O1, "smashed argument"); | |
1161 mov(arg_3, O3); assert(arg_3 != O1 && arg_3 != O2, "smashed argument"); | |
1162 call_VM(oop_result, entry_point, 3, check_exceptions); | |
1163 } | |
1164 | |
1165 | |
1166 | |
1167 // Note: The following call_VM overloadings are useful when a "save" | |
1168 // has already been performed by a stub, and the last Java frame is | |
1169 // the previous one. In that case, last_java_sp must be passed as FP | |
1170 // instead of SP. | |
1171 | |
1172 | |
1173 void MacroAssembler::call_VM(Register oop_result, Register last_java_sp, address entry_point, int number_of_arguments, bool check_exceptions) { | |
1174 call_VM_base(oop_result, noreg, last_java_sp, entry_point, number_of_arguments, check_exceptions); | |
1175 } | |
1176 | |
1177 | |
1178 void MacroAssembler::call_VM(Register oop_result, Register last_java_sp, address entry_point, Register arg_1, bool check_exceptions) { | |
1179 // O0 is reserved for the thread | |
1180 mov(arg_1, O1); | |
1181 call_VM(oop_result, last_java_sp, entry_point, 1, check_exceptions); | |
1182 } | |
1183 | |
1184 | |
1185 void MacroAssembler::call_VM(Register oop_result, Register last_java_sp, address entry_point, Register arg_1, Register arg_2, bool check_exceptions) { | |
1186 // O0 is reserved for the thread | |
1187 mov(arg_1, O1); | |
1188 mov(arg_2, O2); assert(arg_2 != O1, "smashed argument"); | |
1189 call_VM(oop_result, last_java_sp, entry_point, 2, check_exceptions); | |
1190 } | |
1191 | |
1192 | |
1193 void MacroAssembler::call_VM(Register oop_result, Register last_java_sp, address entry_point, Register arg_1, Register arg_2, Register arg_3, bool check_exceptions) { | |
1194 // O0 is reserved for the thread | |
1195 mov(arg_1, O1); | |
1196 mov(arg_2, O2); assert(arg_2 != O1, "smashed argument"); | |
1197 mov(arg_3, O3); assert(arg_3 != O1 && arg_3 != O2, "smashed argument"); | |
1198 call_VM(oop_result, last_java_sp, entry_point, 3, check_exceptions); | |
1199 } | |
1200 | |
1201 | |
1202 | |
1203 void MacroAssembler::call_VM_leaf_base(Register thread_cache, address entry_point, int number_of_arguments) { | |
1204 assert_not_delayed(); | |
1205 save_thread(thread_cache); | |
1206 // do the call | |
1207 call(entry_point, relocInfo::runtime_call_type); | |
1208 delayed()->nop(); | |
1209 restore_thread(thread_cache); | |
3753
cba7b5c2d53f
7045514: SPARC assembly code for JSR 292 ricochet frames
never
parents:
3249
diff
changeset
|
1210 #ifdef ASSERT |
cba7b5c2d53f
7045514: SPARC assembly code for JSR 292 ricochet frames
never
parents:
3249
diff
changeset
|
1211 set(badHeapWordVal, G3); |
cba7b5c2d53f
7045514: SPARC assembly code for JSR 292 ricochet frames
never
parents:
3249
diff
changeset
|
1212 set(badHeapWordVal, G4); |
cba7b5c2d53f
7045514: SPARC assembly code for JSR 292 ricochet frames
never
parents:
3249
diff
changeset
|
1213 set(badHeapWordVal, G5); |
cba7b5c2d53f
7045514: SPARC assembly code for JSR 292 ricochet frames
never
parents:
3249
diff
changeset
|
1214 #endif |
0 | 1215 } |
1216 | |
1217 | |
1218 void MacroAssembler::call_VM_leaf(Register thread_cache, address entry_point, int number_of_arguments) { | |
1219 call_VM_leaf_base(thread_cache, entry_point, number_of_arguments); | |
1220 } | |
1221 | |
1222 | |
1223 void MacroAssembler::call_VM_leaf(Register thread_cache, address entry_point, Register arg_1) { | |
1224 mov(arg_1, O0); | |
1225 call_VM_leaf(thread_cache, entry_point, 1); | |
1226 } | |
1227 | |
1228 | |
1229 void MacroAssembler::call_VM_leaf(Register thread_cache, address entry_point, Register arg_1, Register arg_2) { | |
1230 mov(arg_1, O0); | |
1231 mov(arg_2, O1); assert(arg_2 != O0, "smashed argument"); | |
1232 call_VM_leaf(thread_cache, entry_point, 2); | |
1233 } | |
1234 | |
1235 | |
1236 void MacroAssembler::call_VM_leaf(Register thread_cache, address entry_point, Register arg_1, Register arg_2, Register arg_3) { | |
1237 mov(arg_1, O0); | |
1238 mov(arg_2, O1); assert(arg_2 != O0, "smashed argument"); | |
1239 mov(arg_3, O2); assert(arg_3 != O0 && arg_3 != O1, "smashed argument"); | |
1240 call_VM_leaf(thread_cache, entry_point, 3); | |
1241 } | |
1242 | |
1243 | |
1244 void MacroAssembler::get_vm_result(Register oop_result) { | |
1245 verify_thread(); | |
727 | 1246 Address vm_result_addr(G2_thread, JavaThread::vm_result_offset()); |
0 | 1247 ld_ptr( vm_result_addr, oop_result); |
1248 st_ptr(G0, vm_result_addr); | |
1249 verify_oop(oop_result); | |
1250 } | |
1251 | |
1252 | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
1253 void MacroAssembler::get_vm_result_2(Register metadata_result) { |
0 | 1254 verify_thread(); |
727 | 1255 Address vm_result_addr_2(G2_thread, JavaThread::vm_result_2_offset()); |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
1256 ld_ptr(vm_result_addr_2, metadata_result); |
0 | 1257 st_ptr(G0, vm_result_addr_2); |
1258 } | |
1259 | |
1260 | |
1261 // We require that C code which does not return a value in vm_result will | |
1262 // leave it undisturbed. | |
1263 void MacroAssembler::set_vm_result(Register oop_result) { | |
1264 verify_thread(); | |
727 | 1265 Address vm_result_addr(G2_thread, JavaThread::vm_result_offset()); |
0 | 1266 verify_oop(oop_result); |
1267 | |
1268 # ifdef ASSERT | |
1269 // Check that we are not overwriting any other oop. | |
1270 #ifdef CC_INTERP | |
1271 save_frame(0); | |
1272 #else | |
1273 save_frame_and_mov(0, Lmethod, Lmethod); // Propagate Lmethod for -Xprof | |
1274 #endif /* CC_INTERP */ | |
1275 ld_ptr(vm_result_addr, L0); | |
1276 tst(L0); | |
1277 restore(); | |
1278 breakpoint_trap(notZero, Assembler::ptr_cc); | |
1279 // } | |
1280 # endif | |
1281 | |
1282 st_ptr(oop_result, vm_result_addr); | |
1283 } | |
1284 | |
1285 | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
1286 void MacroAssembler::ic_call(address entry, bool emit_delay) { |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
1287 RelocationHolder rspec = virtual_call_Relocation::spec(pc()); |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
1288 patchable_set((intptr_t)Universe::non_oop_word(), G5_inline_cache_reg); |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
1289 relocate(rspec); |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
1290 call(entry, relocInfo::none); |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
1291 if (emit_delay) { |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
1292 delayed()->nop(); |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
1293 } |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
1294 } |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
1295 |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
1296 |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
1297 void MacroAssembler::card_table_write(jbyte* byte_map_base, |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
1298 Register tmp, Register obj) { |
0 | 1299 #ifdef _LP64 |
1300 srlx(obj, CardTableModRefBS::card_shift, obj); | |
1301 #else | |
1302 srl(obj, CardTableModRefBS::card_shift, obj); | |
1303 #endif | |
727 | 1304 assert(tmp != obj, "need separate temp reg"); |
1305 set((address) byte_map_base, tmp); | |
1306 stb(G0, tmp, obj); | |
0 | 1307 } |
1308 | |
727 | 1309 |
1310 void MacroAssembler::internal_sethi(const AddressLiteral& addrlit, Register d, bool ForceRelocatable) { | |
0 | 1311 address save_pc; |
1312 int shiftcnt; | |
1313 #ifdef _LP64 | |
1314 # ifdef CHECK_DELAY | |
727 | 1315 assert_not_delayed((char*) "cannot put two instructions in delay slot"); |
0 | 1316 # endif |
1317 v9_dep(); | |
1318 save_pc = pc(); | |
727 | 1319 |
1320 int msb32 = (int) (addrlit.value() >> 32); | |
1321 int lsb32 = (int) (addrlit.value()); | |
1322 | |
1323 if (msb32 == 0 && lsb32 >= 0) { | |
1324 Assembler::sethi(lsb32, d, addrlit.rspec()); | |
0 | 1325 } |
727 | 1326 else if (msb32 == -1) { |
1327 Assembler::sethi(~lsb32, d, addrlit.rspec()); | |
1328 xor3(d, ~low10(~0), d); | |
0 | 1329 } |
1330 else { | |
727 | 1331 Assembler::sethi(msb32, d, addrlit.rspec()); // msb 22-bits |
1332 if (msb32 & 0x3ff) // Any bits? | |
1333 or3(d, msb32 & 0x3ff, d); // msb 32-bits are now in lsb 32 | |
1334 if (lsb32 & 0xFFFFFC00) { // done? | |
1335 if ((lsb32 >> 20) & 0xfff) { // Any bits set? | |
1336 sllx(d, 12, d); // Make room for next 12 bits | |
1337 or3(d, (lsb32 >> 20) & 0xfff, d); // Or in next 12 | |
1338 shiftcnt = 0; // We already shifted | |
0 | 1339 } |
1340 else | |
1341 shiftcnt = 12; | |
727 | 1342 if ((lsb32 >> 10) & 0x3ff) { |
1343 sllx(d, shiftcnt + 10, d); // Make room for last 10 bits | |
1344 or3(d, (lsb32 >> 10) & 0x3ff, d); // Or in next 10 | |
0 | 1345 shiftcnt = 0; |
1346 } | |
1347 else | |
1348 shiftcnt = 10; | |
727 | 1349 sllx(d, shiftcnt + 10, d); // Shift leaving disp field 0'd |
0 | 1350 } |
1351 else | |
727 | 1352 sllx(d, 32, d); |
0 | 1353 } |
727 | 1354 // Pad out the instruction sequence so it can be patched later. |
1355 if (ForceRelocatable || (addrlit.rtype() != relocInfo::none && | |
1356 addrlit.rtype() != relocInfo::runtime_call_type)) { | |
1357 while (pc() < (save_pc + (7 * BytesPerInstWord))) | |
0 | 1358 nop(); |
1359 } | |
1360 #else | |
727 | 1361 Assembler::sethi(addrlit.value(), d, addrlit.rspec()); |
0 | 1362 #endif |
727 | 1363 } |
1364 | |
1365 | |
1366 void MacroAssembler::sethi(const AddressLiteral& addrlit, Register d) { | |
1367 internal_sethi(addrlit, d, false); | |
0 | 1368 } |
1369 | |
727 | 1370 |
1371 void MacroAssembler::patchable_sethi(const AddressLiteral& addrlit, Register d) { | |
1372 internal_sethi(addrlit, d, true); | |
1373 } | |
1374 | |
1375 | |
2076
7737fa7ec2b5
7006044: materialize cheap non-oop pointers on 64-bit SPARC
twisti
parents:
2008
diff
changeset
|
1376 int MacroAssembler::insts_for_sethi(address a, bool worst_case) { |
0 | 1377 #ifdef _LP64 |
2076
7737fa7ec2b5
7006044: materialize cheap non-oop pointers on 64-bit SPARC
twisti
parents:
2008
diff
changeset
|
1378 if (worst_case) return 7; |
7737fa7ec2b5
7006044: materialize cheap non-oop pointers on 64-bit SPARC
twisti
parents:
2008
diff
changeset
|
1379 intptr_t iaddr = (intptr_t) a; |
7737fa7ec2b5
7006044: materialize cheap non-oop pointers on 64-bit SPARC
twisti
parents:
2008
diff
changeset
|
1380 int msb32 = (int) (iaddr >> 32); |
7737fa7ec2b5
7006044: materialize cheap non-oop pointers on 64-bit SPARC
twisti
parents:
2008
diff
changeset
|
1381 int lsb32 = (int) (iaddr); |
7737fa7ec2b5
7006044: materialize cheap non-oop pointers on 64-bit SPARC
twisti
parents:
2008
diff
changeset
|
1382 int count; |
7737fa7ec2b5
7006044: materialize cheap non-oop pointers on 64-bit SPARC
twisti
parents:
2008
diff
changeset
|
1383 if (msb32 == 0 && lsb32 >= 0) |
7737fa7ec2b5
7006044: materialize cheap non-oop pointers on 64-bit SPARC
twisti
parents:
2008
diff
changeset
|
1384 count = 1; |
7737fa7ec2b5
7006044: materialize cheap non-oop pointers on 64-bit SPARC
twisti
parents:
2008
diff
changeset
|
1385 else if (msb32 == -1) |
7737fa7ec2b5
7006044: materialize cheap non-oop pointers on 64-bit SPARC
twisti
parents:
2008
diff
changeset
|
1386 count = 2; |
0 | 1387 else { |
2076
7737fa7ec2b5
7006044: materialize cheap non-oop pointers on 64-bit SPARC
twisti
parents:
2008
diff
changeset
|
1388 count = 2; |
7737fa7ec2b5
7006044: materialize cheap non-oop pointers on 64-bit SPARC
twisti
parents:
2008
diff
changeset
|
1389 if (msb32 & 0x3ff) |
7737fa7ec2b5
7006044: materialize cheap non-oop pointers on 64-bit SPARC
twisti
parents:
2008
diff
changeset
|
1390 count++; |
7737fa7ec2b5
7006044: materialize cheap non-oop pointers on 64-bit SPARC
twisti
parents:
2008
diff
changeset
|
1391 if (lsb32 & 0xFFFFFC00 ) { |
7737fa7ec2b5
7006044: materialize cheap non-oop pointers on 64-bit SPARC
twisti
parents:
2008
diff
changeset
|
1392 if ((lsb32 >> 20) & 0xfff) count += 2; |
7737fa7ec2b5
7006044: materialize cheap non-oop pointers on 64-bit SPARC
twisti
parents:
2008
diff
changeset
|
1393 if ((lsb32 >> 10) & 0x3ff) count += 2; |
0 | 1394 } |
1395 } | |
2076
7737fa7ec2b5
7006044: materialize cheap non-oop pointers on 64-bit SPARC
twisti
parents:
2008
diff
changeset
|
1396 return count; |
0 | 1397 #else |
2076
7737fa7ec2b5
7006044: materialize cheap non-oop pointers on 64-bit SPARC
twisti
parents:
2008
diff
changeset
|
1398 return 1; |
0 | 1399 #endif |
1400 } | |
1401 | |
2076
7737fa7ec2b5
7006044: materialize cheap non-oop pointers on 64-bit SPARC
twisti
parents:
2008
diff
changeset
|
1402 int MacroAssembler::worst_case_insts_for_set() { |
7737fa7ec2b5
7006044: materialize cheap non-oop pointers on 64-bit SPARC
twisti
parents:
2008
diff
changeset
|
1403 return insts_for_sethi(NULL, true) + 1; |
0 | 1404 } |
1405 | |
727 | 1406 |
2076
7737fa7ec2b5
7006044: materialize cheap non-oop pointers on 64-bit SPARC
twisti
parents:
2008
diff
changeset
|
1407 // Keep in sync with MacroAssembler::insts_for_internal_set |
727 | 1408 void MacroAssembler::internal_set(const AddressLiteral& addrlit, Register d, bool ForceRelocatable) { |
1409 intptr_t value = addrlit.value(); | |
1410 | |
1411 if (!ForceRelocatable && addrlit.rspec().type() == relocInfo::none) { | |
0 | 1412 // can optimize |
727 | 1413 if (-4096 <= value && value <= 4095) { |
0 | 1414 or3(G0, value, d); // setsw (this leaves upper 32 bits sign-extended) |
1415 return; | |
1416 } | |
1417 if (inv_hi22(hi22(value)) == value) { | |
727 | 1418 sethi(addrlit, d); |
0 | 1419 return; |
1420 } | |
1421 } | |
727 | 1422 assert_not_delayed((char*) "cannot put two instructions in delay slot"); |
1423 internal_sethi(addrlit, d, ForceRelocatable); | |
1424 if (ForceRelocatable || addrlit.rspec().type() != relocInfo::none || addrlit.low10() != 0) { | |
1425 add(d, addrlit.low10(), d, addrlit.rspec()); | |
0 | 1426 } |
1427 } | |
1428 | |
2076
7737fa7ec2b5
7006044: materialize cheap non-oop pointers on 64-bit SPARC
twisti
parents:
2008
diff
changeset
|
1429 // Keep in sync with MacroAssembler::internal_set |
7737fa7ec2b5
7006044: materialize cheap non-oop pointers on 64-bit SPARC
twisti
parents:
2008
diff
changeset
|
1430 int MacroAssembler::insts_for_internal_set(intptr_t value) { |
7737fa7ec2b5
7006044: materialize cheap non-oop pointers on 64-bit SPARC
twisti
parents:
2008
diff
changeset
|
1431 // can optimize |
7737fa7ec2b5
7006044: materialize cheap non-oop pointers on 64-bit SPARC
twisti
parents:
2008
diff
changeset
|
1432 if (-4096 <= value && value <= 4095) { |
7737fa7ec2b5
7006044: materialize cheap non-oop pointers on 64-bit SPARC
twisti
parents:
2008
diff
changeset
|
1433 return 1; |
7737fa7ec2b5
7006044: materialize cheap non-oop pointers on 64-bit SPARC
twisti
parents:
2008
diff
changeset
|
1434 } |
7737fa7ec2b5
7006044: materialize cheap non-oop pointers on 64-bit SPARC
twisti
parents:
2008
diff
changeset
|
1435 if (inv_hi22(hi22(value)) == value) { |
7737fa7ec2b5
7006044: materialize cheap non-oop pointers on 64-bit SPARC
twisti
parents:
2008
diff
changeset
|
1436 return insts_for_sethi((address) value); |
7737fa7ec2b5
7006044: materialize cheap non-oop pointers on 64-bit SPARC
twisti
parents:
2008
diff
changeset
|
1437 } |
7737fa7ec2b5
7006044: materialize cheap non-oop pointers on 64-bit SPARC
twisti
parents:
2008
diff
changeset
|
1438 int count = insts_for_sethi((address) value); |
7737fa7ec2b5
7006044: materialize cheap non-oop pointers on 64-bit SPARC
twisti
parents:
2008
diff
changeset
|
1439 AddressLiteral al(value); |
7737fa7ec2b5
7006044: materialize cheap non-oop pointers on 64-bit SPARC
twisti
parents:
2008
diff
changeset
|
1440 if (al.low10() != 0) { |
7737fa7ec2b5
7006044: materialize cheap non-oop pointers on 64-bit SPARC
twisti
parents:
2008
diff
changeset
|
1441 count++; |
7737fa7ec2b5
7006044: materialize cheap non-oop pointers on 64-bit SPARC
twisti
parents:
2008
diff
changeset
|
1442 } |
7737fa7ec2b5
7006044: materialize cheap non-oop pointers on 64-bit SPARC
twisti
parents:
2008
diff
changeset
|
1443 return count; |
7737fa7ec2b5
7006044: materialize cheap non-oop pointers on 64-bit SPARC
twisti
parents:
2008
diff
changeset
|
1444 } |
7737fa7ec2b5
7006044: materialize cheap non-oop pointers on 64-bit SPARC
twisti
parents:
2008
diff
changeset
|
1445 |
727 | 1446 void MacroAssembler::set(const AddressLiteral& al, Register d) { |
1447 internal_set(al, d, false); | |
1448 } | |
1449 | |
1450 void MacroAssembler::set(intptr_t value, Register d) { | |
1451 AddressLiteral al(value); | |
1452 internal_set(al, d, false); | |
0 | 1453 } |
1454 | |
727 | 1455 void MacroAssembler::set(address addr, Register d, RelocationHolder const& rspec) { |
1456 AddressLiteral al(addr, rspec); | |
1457 internal_set(al, d, false); | |
1458 } | |
1459 | |
1460 void MacroAssembler::patchable_set(const AddressLiteral& al, Register d) { | |
1461 internal_set(al, d, true); | |
1462 } | |
1463 | |
1464 void MacroAssembler::patchable_set(intptr_t value, Register d) { | |
1465 AddressLiteral al(value); | |
1466 internal_set(al, d, true); | |
1467 } | |
0 | 1468 |
1469 | |
1470 void MacroAssembler::set64(jlong value, Register d, Register tmp) { | |
1471 assert_not_delayed(); | |
1472 v9_dep(); | |
1473 | |
1474 int hi = (int)(value >> 32); | |
1475 int lo = (int)(value & ~0); | |
1476 // (Matcher::isSimpleConstant64 knows about the following optimizations.) | |
1477 if (Assembler::is_simm13(lo) && value == lo) { | |
1478 or3(G0, lo, d); | |
1479 } else if (hi == 0) { | |
1480 Assembler::sethi(lo, d); // hardware version zero-extends to upper 32 | |
1481 if (low10(lo) != 0) | |
1482 or3(d, low10(lo), d); | |
1483 } | |
1484 else if (hi == -1) { | |
1485 Assembler::sethi(~lo, d); // hardware version zero-extends to upper 32 | |
1486 xor3(d, low10(lo) ^ ~low10(~0), d); | |
1487 } | |
1488 else if (lo == 0) { | |
1489 if (Assembler::is_simm13(hi)) { | |
1490 or3(G0, hi, d); | |
1491 } else { | |
1492 Assembler::sethi(hi, d); // hardware version zero-extends to upper 32 | |
1493 if (low10(hi) != 0) | |
1494 or3(d, low10(hi), d); | |
1495 } | |
1496 sllx(d, 32, d); | |
1497 } | |
1498 else { | |
1499 Assembler::sethi(hi, tmp); | |
1500 Assembler::sethi(lo, d); // macro assembler version sign-extends | |
1501 if (low10(hi) != 0) | |
1502 or3 (tmp, low10(hi), tmp); | |
1503 if (low10(lo) != 0) | |
1504 or3 ( d, low10(lo), d); | |
1505 sllx(tmp, 32, tmp); | |
1506 or3 (d, tmp, d); | |
1507 } | |
1508 } | |
1509 | |
2076
7737fa7ec2b5
7006044: materialize cheap non-oop pointers on 64-bit SPARC
twisti
parents:
2008
diff
changeset
|
1510 int MacroAssembler::insts_for_set64(jlong value) { |
2008 | 1511 v9_dep(); |
1512 | |
2076
7737fa7ec2b5
7006044: materialize cheap non-oop pointers on 64-bit SPARC
twisti
parents:
2008
diff
changeset
|
1513 int hi = (int) (value >> 32); |
7737fa7ec2b5
7006044: materialize cheap non-oop pointers on 64-bit SPARC
twisti
parents:
2008
diff
changeset
|
1514 int lo = (int) (value & ~0); |
2008 | 1515 int count = 0; |
1516 | |
1517 // (Matcher::isSimpleConstant64 knows about the following optimizations.) | |
1518 if (Assembler::is_simm13(lo) && value == lo) { | |
1519 count++; | |
1520 } else if (hi == 0) { | |
1521 count++; | |
1522 if (low10(lo) != 0) | |
1523 count++; | |
1524 } | |
1525 else if (hi == -1) { | |
1526 count += 2; | |
1527 } | |
1528 else if (lo == 0) { | |
1529 if (Assembler::is_simm13(hi)) { | |
1530 count++; | |
1531 } else { | |
1532 count++; | |
1533 if (low10(hi) != 0) | |
1534 count++; | |
1535 } | |
1536 count++; | |
1537 } | |
1538 else { | |
1539 count += 2; | |
1540 if (low10(hi) != 0) | |
1541 count++; | |
1542 if (low10(lo) != 0) | |
1543 count++; | |
1544 count += 2; | |
1545 } | |
1546 return count; | |
1547 } | |
1548 | |
0 | 1549 // compute size in bytes of sparc frame, given |
1550 // number of extraWords | |
1551 int MacroAssembler::total_frame_size_in_bytes(int extraWords) { | |
1552 | |
1553 int nWords = frame::memory_parameter_word_sp_offset; | |
1554 | |
1555 nWords += extraWords; | |
1556 | |
1557 if (nWords & 1) ++nWords; // round up to double-word | |
1558 | |
1559 return nWords * BytesPerWord; | |
1560 } | |
1561 | |
1562 | |
1563 // save_frame: given number of "extra" words in frame, | |
1564 // issue approp. save instruction (p 200, v8 manual) | |
1565 | |
3753
cba7b5c2d53f
7045514: SPARC assembly code for JSR 292 ricochet frames
never
parents:
3249
diff
changeset
|
1566 void MacroAssembler::save_frame(int extraWords) { |
0 | 1567 int delta = -total_frame_size_in_bytes(extraWords); |
1568 if (is_simm13(delta)) { | |
1569 save(SP, delta, SP); | |
1570 } else { | |
1571 set(delta, G3_scratch); | |
1572 save(SP, G3_scratch, SP); | |
1573 } | |
1574 } | |
1575 | |
1576 | |
1577 void MacroAssembler::save_frame_c1(int size_in_bytes) { | |
1578 if (is_simm13(-size_in_bytes)) { | |
1579 save(SP, -size_in_bytes, SP); | |
1580 } else { | |
1581 set(-size_in_bytes, G3_scratch); | |
1582 save(SP, G3_scratch, SP); | |
1583 } | |
1584 } | |
1585 | |
1586 | |
1587 void MacroAssembler::save_frame_and_mov(int extraWords, | |
1588 Register s1, Register d1, | |
1589 Register s2, Register d2) { | |
1590 assert_not_delayed(); | |
1591 | |
1592 // The trick here is to use precisely the same memory word | |
1593 // that trap handlers also use to save the register. | |
1594 // This word cannot be used for any other purpose, but | |
1595 // it works fine to save the register's value, whether or not | |
1596 // an interrupt flushes register windows at any given moment! | |
1597 Address s1_addr; | |
1598 if (s1->is_valid() && (s1->is_in() || s1->is_local())) { | |
1599 s1_addr = s1->address_in_saved_window(); | |
1600 st_ptr(s1, s1_addr); | |
1601 } | |
1602 | |
1603 Address s2_addr; | |
1604 if (s2->is_valid() && (s2->is_in() || s2->is_local())) { | |
1605 s2_addr = s2->address_in_saved_window(); | |
1606 st_ptr(s2, s2_addr); | |
1607 } | |
1608 | |
1609 save_frame(extraWords); | |
1610 | |
1611 if (s1_addr.base() == SP) { | |
1612 ld_ptr(s1_addr.after_save(), d1); | |
1613 } else if (s1->is_valid()) { | |
1614 mov(s1->after_save(), d1); | |
1615 } | |
1616 | |
1617 if (s2_addr.base() == SP) { | |
1618 ld_ptr(s2_addr.after_save(), d2); | |
1619 } else if (s2->is_valid()) { | |
1620 mov(s2->after_save(), d2); | |
1621 } | |
1622 } | |
1623 | |
1624 | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
1625 AddressLiteral MacroAssembler::allocate_metadata_address(Metadata* obj) { |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
1626 assert(oop_recorder() != NULL, "this assembler needs a Recorder"); |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
1627 int index = oop_recorder()->allocate_metadata_index(obj); |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
1628 RelocationHolder rspec = metadata_Relocation::spec(index); |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
1629 return AddressLiteral((address)obj, rspec); |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
1630 } |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
1631 |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
1632 AddressLiteral MacroAssembler::constant_metadata_address(Metadata* obj) { |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
1633 assert(oop_recorder() != NULL, "this assembler needs a Recorder"); |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
1634 int index = oop_recorder()->find_index(obj); |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
1635 RelocationHolder rspec = metadata_Relocation::spec(index); |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
1636 return AddressLiteral((address)obj, rspec); |
0 | 1637 } |
1638 | |
1639 | |
727 | 1640 AddressLiteral MacroAssembler::constant_oop_address(jobject obj) { |
0 | 1641 assert(oop_recorder() != NULL, "this assembler needs an OopRecorder"); |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
1642 assert(Universe::heap()->is_in_reserved(JNIHandles::resolve(obj)), "not an oop"); |
0 | 1643 int oop_index = oop_recorder()->find_index(obj); |
727 | 1644 return AddressLiteral(obj, oop_Relocation::spec(oop_index)); |
0 | 1645 } |
1646 | |
164
c436414a719e
6703890: Compressed Oops: add LoadNKlass node to generate narrow oops (32-bits) compare instructions
kvn
parents:
124
diff
changeset
|
1647 void MacroAssembler::set_narrow_oop(jobject obj, Register d) { |
c436414a719e
6703890: Compressed Oops: add LoadNKlass node to generate narrow oops (32-bits) compare instructions
kvn
parents:
124
diff
changeset
|
1648 assert(oop_recorder() != NULL, "this assembler needs an OopRecorder"); |
c436414a719e
6703890: Compressed Oops: add LoadNKlass node to generate narrow oops (32-bits) compare instructions
kvn
parents:
124
diff
changeset
|
1649 int oop_index = oop_recorder()->find_index(obj); |
c436414a719e
6703890: Compressed Oops: add LoadNKlass node to generate narrow oops (32-bits) compare instructions
kvn
parents:
124
diff
changeset
|
1650 RelocationHolder rspec = oop_Relocation::spec(oop_index); |
c436414a719e
6703890: Compressed Oops: add LoadNKlass node to generate narrow oops (32-bits) compare instructions
kvn
parents:
124
diff
changeset
|
1651 |
c436414a719e
6703890: Compressed Oops: add LoadNKlass node to generate narrow oops (32-bits) compare instructions
kvn
parents:
124
diff
changeset
|
1652 assert_not_delayed(); |
c436414a719e
6703890: Compressed Oops: add LoadNKlass node to generate narrow oops (32-bits) compare instructions
kvn
parents:
124
diff
changeset
|
1653 // Relocation with special format (see relocInfo_sparc.hpp). |
c436414a719e
6703890: Compressed Oops: add LoadNKlass node to generate narrow oops (32-bits) compare instructions
kvn
parents:
124
diff
changeset
|
1654 relocate(rspec, 1); |
c436414a719e
6703890: Compressed Oops: add LoadNKlass node to generate narrow oops (32-bits) compare instructions
kvn
parents:
124
diff
changeset
|
1655 // Assembler::sethi(0x3fffff, d); |
c436414a719e
6703890: Compressed Oops: add LoadNKlass node to generate narrow oops (32-bits) compare instructions
kvn
parents:
124
diff
changeset
|
1656 emit_long( op(branch_op) | rd(d) | op2(sethi_op2) | hi22(0x3fffff) ); |
c436414a719e
6703890: Compressed Oops: add LoadNKlass node to generate narrow oops (32-bits) compare instructions
kvn
parents:
124
diff
changeset
|
1657 // Don't add relocation for 'add'. Do patching during 'sethi' processing. |
c436414a719e
6703890: Compressed Oops: add LoadNKlass node to generate narrow oops (32-bits) compare instructions
kvn
parents:
124
diff
changeset
|
1658 add(d, 0x3ff, d); |
c436414a719e
6703890: Compressed Oops: add LoadNKlass node to generate narrow oops (32-bits) compare instructions
kvn
parents:
124
diff
changeset
|
1659 |
c436414a719e
6703890: Compressed Oops: add LoadNKlass node to generate narrow oops (32-bits) compare instructions
kvn
parents:
124
diff
changeset
|
1660 } |
c436414a719e
6703890: Compressed Oops: add LoadNKlass node to generate narrow oops (32-bits) compare instructions
kvn
parents:
124
diff
changeset
|
1661 |
0 | 1662 |
1663 void MacroAssembler::align(int modulus) { | |
1664 while (offset() % modulus != 0) nop(); | |
1665 } | |
1666 | |
1667 | |
1668 void MacroAssembler::safepoint() { | |
1669 relocate(breakpoint_Relocation::spec(breakpoint_Relocation::safepoint)); | |
1670 } | |
1671 | |
1672 | |
1673 void RegistersForDebugging::print(outputStream* s) { | |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
4762
diff
changeset
|
1674 FlagSetting fs(Debugging, true); |
0 | 1675 int j; |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
4762
diff
changeset
|
1676 for (j = 0; j < 8; ++j) { |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
4762
diff
changeset
|
1677 if (j != 6) { s->print("i%d = ", j); os::print_location(s, i[j]); } |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
4762
diff
changeset
|
1678 else { s->print( "fp = " ); os::print_location(s, i[j]); } |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
4762
diff
changeset
|
1679 } |
0 | 1680 s->cr(); |
1681 | |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
4762
diff
changeset
|
1682 for (j = 0; j < 8; ++j) { |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
4762
diff
changeset
|
1683 s->print("l%d = ", j); os::print_location(s, l[j]); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
4762
diff
changeset
|
1684 } |
0 | 1685 s->cr(); |
1686 | |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
4762
diff
changeset
|
1687 for (j = 0; j < 8; ++j) { |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
4762
diff
changeset
|
1688 if (j != 6) { s->print("o%d = ", j); os::print_location(s, o[j]); } |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
4762
diff
changeset
|
1689 else { s->print( "sp = " ); os::print_location(s, o[j]); } |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
4762
diff
changeset
|
1690 } |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
4762
diff
changeset
|
1691 s->cr(); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
4762
diff
changeset
|
1692 |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
4762
diff
changeset
|
1693 for (j = 0; j < 8; ++j) { |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
4762
diff
changeset
|
1694 s->print("g%d = ", j); os::print_location(s, g[j]); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
4762
diff
changeset
|
1695 } |
0 | 1696 s->cr(); |
1697 | |
1698 // print out floats with compression | |
1699 for (j = 0; j < 32; ) { | |
1700 jfloat val = f[j]; | |
1701 int last = j; | |
1702 for ( ; last+1 < 32; ++last ) { | |
1703 char b1[1024], b2[1024]; | |
1704 sprintf(b1, "%f", val); | |
1705 sprintf(b2, "%f", f[last+1]); | |
1706 if (strcmp(b1, b2)) | |
1707 break; | |
1708 } | |
1709 s->print("f%d", j); | |
1710 if ( j != last ) s->print(" - f%d", last); | |
1711 s->print(" = %f", val); | |
1712 s->fill_to(25); | |
1713 s->print_cr(" (0x%x)", val); | |
1714 j = last + 1; | |
1715 } | |
1716 s->cr(); | |
1717 | |
1718 // and doubles (evens only) | |
1719 for (j = 0; j < 32; ) { | |
1720 jdouble val = d[j]; | |
1721 int last = j; | |
1722 for ( ; last+1 < 32; ++last ) { | |
1723 char b1[1024], b2[1024]; | |
1724 sprintf(b1, "%f", val); | |
1725 sprintf(b2, "%f", d[last+1]); | |
1726 if (strcmp(b1, b2)) | |
1727 break; | |
1728 } | |
1729 s->print("d%d", 2 * j); | |
1730 if ( j != last ) s->print(" - d%d", last); | |
1731 s->print(" = %f", val); | |
1732 s->fill_to(30); | |
1733 s->print("(0x%x)", *(int*)&val); | |
1734 s->fill_to(42); | |
1735 s->print_cr("(0x%x)", *(1 + (int*)&val)); | |
1736 j = last + 1; | |
1737 } | |
1738 s->cr(); | |
1739 } | |
1740 | |
1741 void RegistersForDebugging::save_registers(MacroAssembler* a) { | |
1742 a->sub(FP, round_to(sizeof(RegistersForDebugging), sizeof(jdouble)) - STACK_BIAS, O0); | |
1743 a->flush_windows(); | |
1744 int i; | |
1745 for (i = 0; i < 8; ++i) { | |
1746 a->ld_ptr(as_iRegister(i)->address_in_saved_window().after_save(), L1); a->st_ptr( L1, O0, i_offset(i)); | |
1747 a->ld_ptr(as_lRegister(i)->address_in_saved_window().after_save(), L1); a->st_ptr( L1, O0, l_offset(i)); | |
1748 a->st_ptr(as_oRegister(i)->after_save(), O0, o_offset(i)); | |
1749 a->st_ptr(as_gRegister(i)->after_save(), O0, g_offset(i)); | |
1750 } | |
1751 for (i = 0; i < 32; ++i) { | |
1752 a->stf(FloatRegisterImpl::S, as_FloatRegister(i), O0, f_offset(i)); | |
1753 } | |
1754 for (i = 0; i < (VM_Version::v9_instructions_work() ? 64 : 32); i += 2) { | |
1755 a->stf(FloatRegisterImpl::D, as_FloatRegister(i), O0, d_offset(i)); | |
1756 } | |
1757 } | |
1758 | |
1759 void RegistersForDebugging::restore_registers(MacroAssembler* a, Register r) { | |
1760 for (int i = 1; i < 8; ++i) { | |
1761 a->ld_ptr(r, g_offset(i), as_gRegister(i)); | |
1762 } | |
1763 for (int j = 0; j < 32; ++j) { | |
1764 a->ldf(FloatRegisterImpl::S, O0, f_offset(j), as_FloatRegister(j)); | |
1765 } | |
1766 for (int k = 0; k < (VM_Version::v9_instructions_work() ? 64 : 32); k += 2) { | |
1767 a->ldf(FloatRegisterImpl::D, O0, d_offset(k), as_FloatRegister(k)); | |
1768 } | |
1769 } | |
1770 | |
1771 | |
1772 // pushes double TOS element of FPU stack on CPU stack; pops from FPU stack | |
1773 void MacroAssembler::push_fTOS() { | |
1774 // %%%%%% need to implement this | |
1775 } | |
1776 | |
1777 // pops double TOS element from CPU stack and pushes on FPU stack | |
1778 void MacroAssembler::pop_fTOS() { | |
1779 // %%%%%% need to implement this | |
1780 } | |
1781 | |
1782 void MacroAssembler::empty_FPU_stack() { | |
1783 // %%%%%% need to implement this | |
1784 } | |
1785 | |
1786 void MacroAssembler::_verify_oop(Register reg, const char* msg, const char * file, int line) { | |
1787 // plausibility check for oops | |
1788 if (!VerifyOops) return; | |
1789 | |
1790 if (reg == G0) return; // always NULL, which is always an oop | |
1791 | |
3753
cba7b5c2d53f
7045514: SPARC assembly code for JSR 292 ricochet frames
never
parents:
3249
diff
changeset
|
1792 BLOCK_COMMENT("verify_oop {"); |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
1793 char buffer[64]; |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
1794 #ifdef COMPILER1 |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
1795 if (CommentedAssembly) { |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
1796 snprintf(buffer, sizeof(buffer), "verify_oop at %d", offset()); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
1797 block_comment(buffer); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
1798 } |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
1799 #endif |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
1800 |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
1801 int len = strlen(file) + strlen(msg) + 1 + 4; |
0 | 1802 sprintf(buffer, "%d", line); |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
1803 len += strlen(buffer); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
1804 sprintf(buffer, " at offset %d ", offset()); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
1805 len += strlen(buffer); |
0 | 1806 char * real_msg = new char[len]; |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
1807 sprintf(real_msg, "%s%s(%s:%d)", msg, buffer, file, line); |
0 | 1808 |
1809 // Call indirectly to solve generation ordering problem | |
727 | 1810 AddressLiteral a(StubRoutines::verify_oop_subroutine_entry_address()); |
0 | 1811 |
1812 // Make some space on stack above the current register window. | |
1813 // Enough to hold 8 64-bit registers. | |
1814 add(SP,-8*8,SP); | |
1815 | |
1816 // Save some 64-bit registers; a normal 'save' chops the heads off | |
1817 // of 64-bit longs in the 32-bit build. | |
1818 stx(O0,SP,frame::register_save_words*wordSize+STACK_BIAS+0*8); | |
1819 stx(O1,SP,frame::register_save_words*wordSize+STACK_BIAS+1*8); | |
1820 mov(reg,O0); // Move arg into O0; arg might be in O7 which is about to be crushed | |
1821 stx(O7,SP,frame::register_save_words*wordSize+STACK_BIAS+7*8); | |
1822 | |
3898 | 1823 // Size of set() should stay the same |
1824 patchable_set((intptr_t)real_msg, O1); | |
0 | 1825 // Load address to call to into O7 |
1826 load_ptr_contents(a, O7); | |
1827 // Register call to verify_oop_subroutine | |
1828 callr(O7, G0); | |
1829 delayed()->nop(); | |
1830 // recover frame size | |
1831 add(SP, 8*8,SP); | |
3753
cba7b5c2d53f
7045514: SPARC assembly code for JSR 292 ricochet frames
never
parents:
3249
diff
changeset
|
1832 BLOCK_COMMENT("} verify_oop"); |
0 | 1833 } |
1834 | |
1835 void MacroAssembler::_verify_oop_addr(Address addr, const char* msg, const char * file, int line) { | |
1836 // plausibility check for oops | |
1837 if (!VerifyOops) return; | |
1838 | |
1839 char buffer[64]; | |
1840 sprintf(buffer, "%d", line); | |
1841 int len = strlen(file) + strlen(msg) + 1 + 4 + strlen(buffer); | |
1842 sprintf(buffer, " at SP+%d ", addr.disp()); | |
1843 len += strlen(buffer); | |
1844 char * real_msg = new char[len]; | |
1845 sprintf(real_msg, "%s at SP+%d (%s:%d)", msg, addr.disp(), file, line); | |
1846 | |
1847 // Call indirectly to solve generation ordering problem | |
727 | 1848 AddressLiteral a(StubRoutines::verify_oop_subroutine_entry_address()); |
0 | 1849 |
1850 // Make some space on stack above the current register window. | |
1851 // Enough to hold 8 64-bit registers. | |
1852 add(SP,-8*8,SP); | |
1853 | |
1854 // Save some 64-bit registers; a normal 'save' chops the heads off | |
1855 // of 64-bit longs in the 32-bit build. | |
1856 stx(O0,SP,frame::register_save_words*wordSize+STACK_BIAS+0*8); | |
1857 stx(O1,SP,frame::register_save_words*wordSize+STACK_BIAS+1*8); | |
1858 ld_ptr(addr.base(), addr.disp() + 8*8, O0); // Load arg into O0; arg might be in O7 which is about to be crushed | |
1859 stx(O7,SP,frame::register_save_words*wordSize+STACK_BIAS+7*8); | |
1860 | |
3898 | 1861 // Size of set() should stay the same |
1862 patchable_set((intptr_t)real_msg, O1); | |
0 | 1863 // Load address to call to into O7 |
1864 load_ptr_contents(a, O7); | |
1865 // Register call to verify_oop_subroutine | |
1866 callr(O7, G0); | |
1867 delayed()->nop(); | |
1868 // recover frame size | |
1869 add(SP, 8*8,SP); | |
1870 } | |
1871 | |
1872 // side-door communication with signalHandler in os_solaris.cpp | |
1873 address MacroAssembler::_verify_oop_implicit_branch[3] = { NULL }; | |
1874 | |
1875 // This macro is expanded just once; it creates shared code. Contract: | |
1876 // receives an oop in O0. Must restore O0 & O7 from TLS. Must not smash ANY | |
1877 // registers, including flags. May not use a register 'save', as this blows | |
1878 // the high bits of the O-regs if they contain Long values. Acts as a 'leaf' | |
1879 // call. | |
1880 void MacroAssembler::verify_oop_subroutine() { | |
1881 assert( VM_Version::v9_instructions_work(), "VerifyOops not supported for V8" ); | |
1882 | |
1883 // Leaf call; no frame. | |
1884 Label succeed, fail, null_or_fail; | |
1885 | |
1886 // O0 and O7 were saved already (O0 in O0's TLS home, O7 in O5's TLS home). | |
1887 // O0 is now the oop to be checked. O7 is the return address. | |
1888 Register O0_obj = O0; | |
1889 | |
1890 // Save some more registers for temps. | |
1891 stx(O2,SP,frame::register_save_words*wordSize+STACK_BIAS+2*8); | |
1892 stx(O3,SP,frame::register_save_words*wordSize+STACK_BIAS+3*8); | |
1893 stx(O4,SP,frame::register_save_words*wordSize+STACK_BIAS+4*8); | |
1894 stx(O5,SP,frame::register_save_words*wordSize+STACK_BIAS+5*8); | |
1895 | |
1896 // Save flags | |
1897 Register O5_save_flags = O5; | |
1898 rdccr( O5_save_flags ); | |
1899 | |
1900 { // count number of verifies | |
1901 Register O2_adr = O2; | |
1902 Register O3_accum = O3; | |
727 | 1903 inc_counter(StubRoutines::verify_oop_count_addr(), O2_adr, O3_accum); |
0 | 1904 } |
1905 | |
1906 Register O2_mask = O2; | |
1907 Register O3_bits = O3; | |
1908 Register O4_temp = O4; | |
1909 | |
1910 // mark lower end of faulting range | |
1911 assert(_verify_oop_implicit_branch[0] == NULL, "set once"); | |
1912 _verify_oop_implicit_branch[0] = pc(); | |
1913 | |
1914 // We can't check the mark oop because it could be in the process of | |
1915 // locking or unlocking while this is running. | |
1916 set(Universe::verify_oop_mask (), O2_mask); | |
1917 set(Universe::verify_oop_bits (), O3_bits); | |
1918 | |
1919 // assert((obj & oop_mask) == oop_bits); | |
1920 and3(O0_obj, O2_mask, O4_temp); | |
3839 | 1921 cmp_and_brx_short(O4_temp, O3_bits, notEqual, pn, null_or_fail); |
0 | 1922 |
1923 if ((NULL_WORD & Universe::verify_oop_mask()) == Universe::verify_oop_bits()) { | |
1924 // the null_or_fail case is useless; must test for null separately | |
3839 | 1925 br_null_short(O0_obj, pn, succeed); |
0 | 1926 } |
1927 | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
1928 // Check the Klass* of this object for being in the right area of memory. |
0 | 1929 // Cannot do the load in the delay above slot in case O0 is null |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
1930 load_klass(O0_obj, O0_obj); |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
1931 // assert((klass != NULL) |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
1932 br_null_short(O0_obj, pn, fail); |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
1933 // TODO: Future assert that klass is lower 4g memory for UseCompressedKlassPointers |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
1934 |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
1935 wrccr( O5_save_flags ); // Restore CCR's |
0 | 1936 |
1937 // mark upper end of faulting range | |
1938 _verify_oop_implicit_branch[1] = pc(); | |
1939 | |
1940 //----------------------- | |
1941 // all tests pass | |
1942 bind(succeed); | |
1943 | |
1944 // Restore prior 64-bit registers | |
1945 ldx(SP,frame::register_save_words*wordSize+STACK_BIAS+0*8,O0); | |
1946 ldx(SP,frame::register_save_words*wordSize+STACK_BIAS+1*8,O1); | |
1947 ldx(SP,frame::register_save_words*wordSize+STACK_BIAS+2*8,O2); | |
1948 ldx(SP,frame::register_save_words*wordSize+STACK_BIAS+3*8,O3); | |
1949 ldx(SP,frame::register_save_words*wordSize+STACK_BIAS+4*8,O4); | |
1950 ldx(SP,frame::register_save_words*wordSize+STACK_BIAS+5*8,O5); | |
1951 | |
1952 retl(); // Leaf return; restore prior O7 in delay slot | |
1953 delayed()->ldx(SP,frame::register_save_words*wordSize+STACK_BIAS+7*8,O7); | |
1954 | |
1955 //----------------------- | |
1956 bind(null_or_fail); // nulls are less common but OK | |
1957 br_null(O0_obj, false, pt, succeed); | |
1958 delayed()->wrccr( O5_save_flags ); // Restore CCR's | |
1959 | |
1960 //----------------------- | |
1961 // report failure: | |
1962 bind(fail); | |
1963 _verify_oop_implicit_branch[2] = pc(); | |
1964 | |
1965 wrccr( O5_save_flags ); // Restore CCR's | |
1966 | |
1967 save_frame(::round_to(sizeof(RegistersForDebugging) / BytesPerWord, 2)); | |
1968 | |
1969 // stop_subroutine expects message pointer in I1. | |
1970 mov(I1, O1); | |
1971 | |
1972 // Restore prior 64-bit registers | |
1973 ldx(FP,frame::register_save_words*wordSize+STACK_BIAS+0*8,I0); | |
1974 ldx(FP,frame::register_save_words*wordSize+STACK_BIAS+1*8,I1); | |
1975 ldx(FP,frame::register_save_words*wordSize+STACK_BIAS+2*8,I2); | |
1976 ldx(FP,frame::register_save_words*wordSize+STACK_BIAS+3*8,I3); | |
1977 ldx(FP,frame::register_save_words*wordSize+STACK_BIAS+4*8,I4); | |
1978 ldx(FP,frame::register_save_words*wordSize+STACK_BIAS+5*8,I5); | |
1979 | |
1980 // factor long stop-sequence into subroutine to save space | |
1981 assert(StubRoutines::Sparc::stop_subroutine_entry_address(), "hasn't been generated yet"); | |
1982 | |
1983 // call indirectly to solve generation ordering problem | |
727 | 1984 AddressLiteral al(StubRoutines::Sparc::stop_subroutine_entry_address()); |
1985 load_ptr_contents(al, O5); | |
0 | 1986 jmpl(O5, 0, O7); |
1987 delayed()->nop(); | |
1988 } | |
1989 | |
1990 | |
1991 void MacroAssembler::stop(const char* msg) { | |
1992 // save frame first to get O7 for return address | |
1993 // add one word to size in case struct is odd number of words long | |
1994 // It must be doubleword-aligned for storing doubles into it. | |
1995 | |
1996 save_frame(::round_to(sizeof(RegistersForDebugging) / BytesPerWord, 2)); | |
1997 | |
1998 // stop_subroutine expects message pointer in I1. | |
3898 | 1999 // Size of set() should stay the same |
2000 patchable_set((intptr_t)msg, O1); | |
0 | 2001 |
2002 // factor long stop-sequence into subroutine to save space | |
2003 assert(StubRoutines::Sparc::stop_subroutine_entry_address(), "hasn't been generated yet"); | |
2004 | |
2005 // call indirectly to solve generation ordering problem | |
727 | 2006 AddressLiteral a(StubRoutines::Sparc::stop_subroutine_entry_address()); |
0 | 2007 load_ptr_contents(a, O5); |
2008 jmpl(O5, 0, O7); | |
2009 delayed()->nop(); | |
2010 | |
2011 breakpoint_trap(); // make stop actually stop rather than writing | |
2012 // unnoticeable results in the output files. | |
2013 | |
2014 // restore(); done in callee to save space! | |
2015 } | |
2016 | |
2017 | |
2018 void MacroAssembler::warn(const char* msg) { | |
2019 save_frame(::round_to(sizeof(RegistersForDebugging) / BytesPerWord, 2)); | |
2020 RegistersForDebugging::save_registers(this); | |
2021 mov(O0, L0); | |
3898 | 2022 // Size of set() should stay the same |
2023 patchable_set((intptr_t)msg, O0); | |
0 | 2024 call( CAST_FROM_FN_PTR(address, warning) ); |
2025 delayed()->nop(); | |
2026 // ret(); | |
2027 // delayed()->restore(); | |
2028 RegistersForDebugging::restore_registers(this, L0); | |
2029 restore(); | |
2030 } | |
2031 | |
2032 | |
2033 void MacroAssembler::untested(const char* what) { | |
2034 // We must be able to turn interactive prompting off | |
2035 // in order to run automated test scripts on the VM | |
2036 // Use the flag ShowMessageBoxOnError | |
2037 | |
2038 char* b = new char[1024]; | |
2039 sprintf(b, "untested: %s", what); | |
2040 | |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
4762
diff
changeset
|
2041 if (ShowMessageBoxOnError) { STOP(b); } |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
4762
diff
changeset
|
2042 else { warn(b); } |
0 | 2043 } |
2044 | |
2045 | |
2046 void MacroAssembler::stop_subroutine() { | |
2047 RegistersForDebugging::save_registers(this); | |
2048 | |
2049 // for the sake of the debugger, stick a PC on the current frame | |
2050 // (this assumes that the caller has performed an extra "save") | |
2051 mov(I7, L7); | |
2052 add(O7, -7 * BytesPerInt, I7); | |
2053 | |
2054 save_frame(); // one more save to free up another O7 register | |
2055 mov(I0, O1); // addr of reg save area | |
2056 | |
2057 // We expect pointer to message in I1. Caller must set it up in O1 | |
2058 mov(I1, O0); // get msg | |
2059 call (CAST_FROM_FN_PTR(address, MacroAssembler::debug), relocInfo::runtime_call_type); | |
2060 delayed()->nop(); | |
2061 | |
2062 restore(); | |
2063 | |
2064 RegistersForDebugging::restore_registers(this, O0); | |
2065 | |
2066 save_frame(0); | |
2067 call(CAST_FROM_FN_PTR(address,breakpoint)); | |
2068 delayed()->nop(); | |
2069 restore(); | |
2070 | |
2071 mov(L7, I7); | |
2072 retl(); | |
2073 delayed()->restore(); // see stop above | |
2074 } | |
2075 | |
2076 | |
2077 void MacroAssembler::debug(char* msg, RegistersForDebugging* regs) { | |
2078 if ( ShowMessageBoxOnError ) { | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
2079 JavaThread* thread = JavaThread::current(); |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
2080 JavaThreadState saved_state = thread->thread_state(); |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
2081 thread->set_thread_state(_thread_in_vm); |
0 | 2082 { |
2083 // In order to get locks work, we need to fake a in_VM state | |
2084 ttyLocker ttyl; | |
2085 ::tty->print_cr("EXECUTION STOPPED: %s\n", msg); | |
2086 if (CountBytecodes || TraceBytecodes || StopInterpreterAt) { | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
2087 BytecodeCounter::print(); |
0 | 2088 } |
2089 if (os::message_box(msg, "Execution stopped, print registers?")) | |
2090 regs->print(::tty); | |
2091 } | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
2092 BREAKPOINT; |
0 | 2093 ThreadStateTransition::transition(JavaThread::current(), _thread_in_vm, saved_state); |
2094 } | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
2095 else { |
0 | 2096 ::tty->print_cr("=============== DEBUG MESSAGE: %s ================\n", msg); |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
2097 } |
3753
cba7b5c2d53f
7045514: SPARC assembly code for JSR 292 ricochet frames
never
parents:
3249
diff
changeset
|
2098 assert(false, err_msg("DEBUG MESSAGE: %s", msg)); |
0 | 2099 } |
2100 | |
2101 #ifndef PRODUCT | |
2102 void MacroAssembler::test() { | |
2103 ResourceMark rm; | |
2104 | |
2105 CodeBuffer cb("test", 10000, 10000); | |
2106 MacroAssembler* a = new MacroAssembler(&cb); | |
2107 VM_Version::allow_all(); | |
2108 a->test_v9(); | |
2109 a->test_v8_onlys(); | |
2110 VM_Version::revert(); | |
2111 | |
2112 StubRoutines::Sparc::test_stop_entry()(); | |
2113 } | |
2114 #endif | |
2115 | |
2116 | |
2117 void MacroAssembler::calc_mem_param_words(Register Rparam_words, Register Rresult) { | |
2118 subcc( Rparam_words, Argument::n_register_parameters, Rresult); // how many mem words? | |
2119 Label no_extras; | |
2120 br( negative, true, pt, no_extras ); // if neg, clear reg | |
727 | 2121 delayed()->set(0, Rresult); // annuled, so only if taken |
0 | 2122 bind( no_extras ); |
2123 } | |
2124 | |
2125 | |
2126 void MacroAssembler::calc_frame_size(Register Rextra_words, Register Rresult) { | |
2127 #ifdef _LP64 | |
2128 add(Rextra_words, frame::memory_parameter_word_sp_offset, Rresult); | |
2129 #else | |
2130 add(Rextra_words, frame::memory_parameter_word_sp_offset + 1, Rresult); | |
2131 #endif | |
2132 bclr(1, Rresult); | |
2133 sll(Rresult, LogBytesPerWord, Rresult); // Rresult has total frame bytes | |
2134 } | |
2135 | |
2136 | |
2137 void MacroAssembler::calc_frame_size_and_save(Register Rextra_words, Register Rresult) { | |
2138 calc_frame_size(Rextra_words, Rresult); | |
2139 neg(Rresult); | |
2140 save(SP, Rresult, SP); | |
2141 } | |
2142 | |
2143 | |
2144 // --------------------------------------------------------- | |
2145 Assembler::RCondition cond2rcond(Assembler::Condition c) { | |
2146 switch (c) { | |
2147 /*case zero: */ | |
2148 case Assembler::equal: return Assembler::rc_z; | |
2149 case Assembler::lessEqual: return Assembler::rc_lez; | |
2150 case Assembler::less: return Assembler::rc_lz; | |
2151 /*case notZero:*/ | |
2152 case Assembler::notEqual: return Assembler::rc_nz; | |
2153 case Assembler::greater: return Assembler::rc_gz; | |
2154 case Assembler::greaterEqual: return Assembler::rc_gez; | |
2155 } | |
2156 ShouldNotReachHere(); | |
2157 return Assembler::rc_z; | |
2158 } | |
2159 | |
3839 | 2160 // compares (32 bit) register with zero and branches. NOT FOR USE WITH 64-bit POINTERS |
2161 void MacroAssembler::cmp_zero_and_br(Condition c, Register s1, Label& L, bool a, Predict p) { | |
0 | 2162 tst(s1); |
2163 br (c, a, p, L); | |
2164 } | |
2165 | |
2166 // Compares a pointer register with zero and branches on null. | |
2167 // Does a test & branch on 32-bit systems and a register-branch on 64-bit. | |
2168 void MacroAssembler::br_null( Register s1, bool a, Predict p, Label& L ) { | |
2169 assert_not_delayed(); | |
2170 #ifdef _LP64 | |
2171 bpr( rc_z, a, p, s1, L ); | |
2172 #else | |
2173 tst(s1); | |
2174 br ( zero, a, p, L ); | |
2175 #endif | |
2176 } | |
2177 | |
2178 void MacroAssembler::br_notnull( Register s1, bool a, Predict p, Label& L ) { | |
2179 assert_not_delayed(); | |
2180 #ifdef _LP64 | |
2181 bpr( rc_nz, a, p, s1, L ); | |
2182 #else | |
2183 tst(s1); | |
2184 br ( notZero, a, p, L ); | |
2185 #endif | |
2186 } | |
2187 | |
3839 | 2188 // Compare registers and branch with nop in delay slot or cbcond without delay slot. |
2189 | |
2190 // Compare integer (32 bit) values (icc only). | |
2191 void MacroAssembler::cmp_and_br_short(Register s1, Register s2, Condition c, | |
2192 Predict p, Label& L) { | |
2193 assert_not_delayed(); | |
2194 if (use_cbcond(L)) { | |
2195 Assembler::cbcond(c, icc, s1, s2, L); | |
2196 } else { | |
2197 cmp(s1, s2); | |
2198 br(c, false, p, L); | |
2199 delayed()->nop(); | |
2200 } | |
2201 } | |
2202 | |
2203 // Compare integer (32 bit) values (icc only). | |
2204 void MacroAssembler::cmp_and_br_short(Register s1, int simm13a, Condition c, | |
2205 Predict p, Label& L) { | |
2206 assert_not_delayed(); | |
2207 if (is_simm(simm13a,5) && use_cbcond(L)) { | |
2208 Assembler::cbcond(c, icc, s1, simm13a, L); | |
2209 } else { | |
2210 cmp(s1, simm13a); | |
2211 br(c, false, p, L); | |
2212 delayed()->nop(); | |
2213 } | |
2214 } | |
2215 | |
2216 // Branch that tests xcc in LP64 and icc in !LP64 | |
2217 void MacroAssembler::cmp_and_brx_short(Register s1, Register s2, Condition c, | |
2218 Predict p, Label& L) { | |
2219 assert_not_delayed(); | |
2220 if (use_cbcond(L)) { | |
2221 Assembler::cbcond(c, ptr_cc, s1, s2, L); | |
2222 } else { | |
2223 cmp(s1, s2); | |
2224 brx(c, false, p, L); | |
2225 delayed()->nop(); | |
2226 } | |
2227 } | |
2228 | |
2229 // Branch that tests xcc in LP64 and icc in !LP64 | |
2230 void MacroAssembler::cmp_and_brx_short(Register s1, int simm13a, Condition c, | |
2231 Predict p, Label& L) { | |
2232 assert_not_delayed(); | |
2233 if (is_simm(simm13a,5) && use_cbcond(L)) { | |
2234 Assembler::cbcond(c, ptr_cc, s1, simm13a, L); | |
2235 } else { | |
2236 cmp(s1, simm13a); | |
2237 brx(c, false, p, L); | |
2238 delayed()->nop(); | |
2239 } | |
2240 } | |
2241 | |
2242 // Short branch version for compares a pointer with zero. | |
2243 | |
2244 void MacroAssembler::br_null_short(Register s1, Predict p, Label& L) { | |
2245 assert_not_delayed(); | |
2246 if (use_cbcond(L)) { | |
2247 Assembler::cbcond(zero, ptr_cc, s1, 0, L); | |
2248 return; | |
2249 } | |
2250 br_null(s1, false, p, L); | |
2251 delayed()->nop(); | |
2252 } | |
2253 | |
2254 void MacroAssembler::br_notnull_short(Register s1, Predict p, Label& L) { | |
2255 assert_not_delayed(); | |
2256 if (use_cbcond(L)) { | |
2257 Assembler::cbcond(notZero, ptr_cc, s1, 0, L); | |
2258 return; | |
2259 } | |
2260 br_notnull(s1, false, p, L); | |
2261 delayed()->nop(); | |
2262 } | |
2263 | |
2264 // Unconditional short branch | |
2265 void MacroAssembler::ba_short(Label& L) { | |
2266 if (use_cbcond(L)) { | |
2267 Assembler::cbcond(equal, icc, G0, G0, L); | |
2268 return; | |
2269 } | |
2270 br(always, false, pt, L); | |
2271 delayed()->nop(); | |
2272 } | |
0 | 2273 |
2274 // instruction sequences factored across compiler & interpreter | |
2275 | |
2276 | |
2277 void MacroAssembler::lcmp( Register Ra_hi, Register Ra_low, | |
2278 Register Rb_hi, Register Rb_low, | |
2279 Register Rresult) { | |
2280 | |
2281 Label check_low_parts, done; | |
2282 | |
2283 cmp(Ra_hi, Rb_hi ); // compare hi parts | |
2284 br(equal, true, pt, check_low_parts); | |
2285 delayed()->cmp(Ra_low, Rb_low); // test low parts | |
2286 | |
2287 // And, with an unsigned comparison, it does not matter if the numbers | |
2288 // are negative or not. | |
2289 // E.g., -2 cmp -1: the low parts are 0xfffffffe and 0xffffffff. | |
2290 // The second one is bigger (unsignedly). | |
2291 | |
2292 // Other notes: The first move in each triplet can be unconditional | |
2293 // (and therefore probably prefetchable). | |
2294 // And the equals case for the high part does not need testing, | |
2295 // since that triplet is reached only after finding the high halves differ. | |
2296 | |
2297 if (VM_Version::v9_instructions_work()) { | |
3839 | 2298 mov(-1, Rresult); |
2299 ba(done); delayed()-> movcc(greater, false, icc, 1, Rresult); | |
2300 } else { | |
0 | 2301 br(less, true, pt, done); delayed()-> set(-1, Rresult); |
2302 br(greater, true, pt, done); delayed()-> set( 1, Rresult); | |
2303 } | |
2304 | |
2305 bind( check_low_parts ); | |
2306 | |
2307 if (VM_Version::v9_instructions_work()) { | |
2308 mov( -1, Rresult); | |
2309 movcc(equal, false, icc, 0, Rresult); | |
2310 movcc(greaterUnsigned, false, icc, 1, Rresult); | |
3839 | 2311 } else { |
2312 set(-1, Rresult); | |
0 | 2313 br(equal, true, pt, done); delayed()->set( 0, Rresult); |
2314 br(greaterUnsigned, true, pt, done); delayed()->set( 1, Rresult); | |
2315 } | |
2316 bind( done ); | |
2317 } | |
2318 | |
2319 void MacroAssembler::lneg( Register Rhi, Register Rlow ) { | |
2320 subcc( G0, Rlow, Rlow ); | |
2321 subc( G0, Rhi, Rhi ); | |
2322 } | |
2323 | |
2324 void MacroAssembler::lshl( Register Rin_high, Register Rin_low, | |
2325 Register Rcount, | |
2326 Register Rout_high, Register Rout_low, | |
2327 Register Rtemp ) { | |
2328 | |
2329 | |
2330 Register Ralt_count = Rtemp; | |
2331 Register Rxfer_bits = Rtemp; | |
2332 | |
2333 assert( Ralt_count != Rin_high | |
2334 && Ralt_count != Rin_low | |
2335 && Ralt_count != Rcount | |
2336 && Rxfer_bits != Rin_low | |
2337 && Rxfer_bits != Rin_high | |
2338 && Rxfer_bits != Rcount | |
2339 && Rxfer_bits != Rout_low | |
2340 && Rout_low != Rin_high, | |
2341 "register alias checks"); | |
2342 | |
2343 Label big_shift, done; | |
2344 | |
2345 // This code can be optimized to use the 64 bit shifts in V9. | |
2346 // Here we use the 32 bit shifts. | |
2347 | |
3839 | 2348 and3( Rcount, 0x3f, Rcount); // take least significant 6 bits |
2349 subcc(Rcount, 31, Ralt_count); | |
0 | 2350 br(greater, true, pn, big_shift); |
3839 | 2351 delayed()->dec(Ralt_count); |
0 | 2352 |
2353 // shift < 32 bits, Ralt_count = Rcount-31 | |
2354 | |
2355 // We get the transfer bits by shifting right by 32-count the low | |
2356 // register. This is done by shifting right by 31-count and then by one | |
2357 // more to take care of the special (rare) case where count is zero | |
2358 // (shifting by 32 would not work). | |
2359 | |
3839 | 2360 neg(Ralt_count); |
0 | 2361 |
2362 // The order of the next two instructions is critical in the case where | |
2363 // Rin and Rout are the same and should not be reversed. | |
2364 | |
3839 | 2365 srl(Rin_low, Ralt_count, Rxfer_bits); // shift right by 31-count |
0 | 2366 if (Rcount != Rout_low) { |
3839 | 2367 sll(Rin_low, Rcount, Rout_low); // low half |
0 | 2368 } |
3839 | 2369 sll(Rin_high, Rcount, Rout_high); |
0 | 2370 if (Rcount == Rout_low) { |
3839 | 2371 sll(Rin_low, Rcount, Rout_low); // low half |
0 | 2372 } |
3839 | 2373 srl(Rxfer_bits, 1, Rxfer_bits ); // shift right by one more |
2374 ba(done); | |
2375 delayed()->or3(Rout_high, Rxfer_bits, Rout_high); // new hi value: or in shifted old hi part and xfer from low | |
0 | 2376 |
2377 // shift >= 32 bits, Ralt_count = Rcount-32 | |
2378 bind(big_shift); | |
3839 | 2379 sll(Rin_low, Ralt_count, Rout_high ); |
2380 clr(Rout_low); | |
0 | 2381 |
2382 bind(done); | |
2383 } | |
2384 | |
2385 | |
2386 void MacroAssembler::lshr( Register Rin_high, Register Rin_low, | |
2387 Register Rcount, | |
2388 Register Rout_high, Register Rout_low, | |
2389 Register Rtemp ) { | |
2390 | |
2391 Register Ralt_count = Rtemp; | |
2392 Register Rxfer_bits = Rtemp; | |
2393 | |
2394 assert( Ralt_count != Rin_high | |
2395 && Ralt_count != Rin_low | |
2396 && Ralt_count != Rcount | |
2397 && Rxfer_bits != Rin_low | |
2398 && Rxfer_bits != Rin_high | |
2399 && Rxfer_bits != Rcount | |
2400 && Rxfer_bits != Rout_high | |
2401 && Rout_high != Rin_low, | |
2402 "register alias checks"); | |
2403 | |
2404 Label big_shift, done; | |
2405 | |
2406 // This code can be optimized to use the 64 bit shifts in V9. | |
2407 // Here we use the 32 bit shifts. | |
2408 | |
3839 | 2409 and3( Rcount, 0x3f, Rcount); // take least significant 6 bits |
2410 subcc(Rcount, 31, Ralt_count); | |
0 | 2411 br(greater, true, pn, big_shift); |
2412 delayed()->dec(Ralt_count); | |
2413 | |
2414 // shift < 32 bits, Ralt_count = Rcount-31 | |
2415 | |
2416 // We get the transfer bits by shifting left by 32-count the high | |
2417 // register. This is done by shifting left by 31-count and then by one | |
2418 // more to take care of the special (rare) case where count is zero | |
2419 // (shifting by 32 would not work). | |
2420 | |
3839 | 2421 neg(Ralt_count); |
0 | 2422 if (Rcount != Rout_low) { |
3839 | 2423 srl(Rin_low, Rcount, Rout_low); |
0 | 2424 } |
2425 | |
2426 // The order of the next two instructions is critical in the case where | |
2427 // Rin and Rout are the same and should not be reversed. | |
2428 | |
3839 | 2429 sll(Rin_high, Ralt_count, Rxfer_bits); // shift left by 31-count |
2430 sra(Rin_high, Rcount, Rout_high ); // high half | |
2431 sll(Rxfer_bits, 1, Rxfer_bits); // shift left by one more | |
0 | 2432 if (Rcount == Rout_low) { |
3839 | 2433 srl(Rin_low, Rcount, Rout_low); |
0 | 2434 } |
3839 | 2435 ba(done); |
2436 delayed()->or3(Rout_low, Rxfer_bits, Rout_low); // new low value: or shifted old low part and xfer from high | |
0 | 2437 |
2438 // shift >= 32 bits, Ralt_count = Rcount-32 | |
2439 bind(big_shift); | |
2440 | |
3839 | 2441 sra(Rin_high, Ralt_count, Rout_low); |
2442 sra(Rin_high, 31, Rout_high); // sign into hi | |
0 | 2443 |
2444 bind( done ); | |
2445 } | |
2446 | |
2447 | |
2448 | |
2449 void MacroAssembler::lushr( Register Rin_high, Register Rin_low, | |
2450 Register Rcount, | |
2451 Register Rout_high, Register Rout_low, | |
2452 Register Rtemp ) { | |
2453 | |
2454 Register Ralt_count = Rtemp; | |
2455 Register Rxfer_bits = Rtemp; | |
2456 | |
2457 assert( Ralt_count != Rin_high | |
2458 && Ralt_count != Rin_low | |
2459 && Ralt_count != Rcount | |
2460 && Rxfer_bits != Rin_low | |
2461 && Rxfer_bits != Rin_high | |
2462 && Rxfer_bits != Rcount | |
2463 && Rxfer_bits != Rout_high | |
2464 && Rout_high != Rin_low, | |
2465 "register alias checks"); | |
2466 | |
2467 Label big_shift, done; | |
2468 | |
2469 // This code can be optimized to use the 64 bit shifts in V9. | |
2470 // Here we use the 32 bit shifts. | |
2471 | |
3839 | 2472 and3( Rcount, 0x3f, Rcount); // take least significant 6 bits |
2473 subcc(Rcount, 31, Ralt_count); | |
0 | 2474 br(greater, true, pn, big_shift); |
2475 delayed()->dec(Ralt_count); | |
2476 | |
2477 // shift < 32 bits, Ralt_count = Rcount-31 | |
2478 | |
2479 // We get the transfer bits by shifting left by 32-count the high | |
2480 // register. This is done by shifting left by 31-count and then by one | |
2481 // more to take care of the special (rare) case where count is zero | |
2482 // (shifting by 32 would not work). | |
2483 | |
3839 | 2484 neg(Ralt_count); |
0 | 2485 if (Rcount != Rout_low) { |
3839 | 2486 srl(Rin_low, Rcount, Rout_low); |
0 | 2487 } |
2488 | |
2489 // The order of the next two instructions is critical in the case where | |
2490 // Rin and Rout are the same and should not be reversed. | |
2491 | |
3839 | 2492 sll(Rin_high, Ralt_count, Rxfer_bits); // shift left by 31-count |
2493 srl(Rin_high, Rcount, Rout_high ); // high half | |
2494 sll(Rxfer_bits, 1, Rxfer_bits); // shift left by one more | |
0 | 2495 if (Rcount == Rout_low) { |
3839 | 2496 srl(Rin_low, Rcount, Rout_low); |
0 | 2497 } |
3839 | 2498 ba(done); |
2499 delayed()->or3(Rout_low, Rxfer_bits, Rout_low); // new low value: or shifted old low part and xfer from high | |
0 | 2500 |
2501 // shift >= 32 bits, Ralt_count = Rcount-32 | |
2502 bind(big_shift); | |
2503 | |
3839 | 2504 srl(Rin_high, Ralt_count, Rout_low); |
2505 clr(Rout_high); | |
0 | 2506 |
2507 bind( done ); | |
2508 } | |
2509 | |
2510 #ifdef _LP64 | |
2511 void MacroAssembler::lcmp( Register Ra, Register Rb, Register Rresult) { | |
2512 cmp(Ra, Rb); | |
3839 | 2513 mov(-1, Rresult); |
0 | 2514 movcc(equal, false, xcc, 0, Rresult); |
2515 movcc(greater, false, xcc, 1, Rresult); | |
2516 } | |
2517 #endif | |
2518 | |
2519 | |
2258
28bf941f445e
7018378: JSR 292: _bound_int_mh produces wrong result on 64-bit SPARC
twisti
parents:
2127
diff
changeset
|
2520 void MacroAssembler::load_sized_value(Address src, Register dst, size_t size_in_bytes, bool is_signed) { |
1503 | 2521 switch (size_in_bytes) { |
2258
28bf941f445e
7018378: JSR 292: _bound_int_mh produces wrong result on 64-bit SPARC
twisti
parents:
2127
diff
changeset
|
2522 case 8: ld_long(src, dst); break; |
28bf941f445e
7018378: JSR 292: _bound_int_mh produces wrong result on 64-bit SPARC
twisti
parents:
2127
diff
changeset
|
2523 case 4: ld( src, dst); break; |
28bf941f445e
7018378: JSR 292: _bound_int_mh produces wrong result on 64-bit SPARC
twisti
parents:
2127
diff
changeset
|
2524 case 2: is_signed ? ldsh(src, dst) : lduh(src, dst); break; |
28bf941f445e
7018378: JSR 292: _bound_int_mh produces wrong result on 64-bit SPARC
twisti
parents:
2127
diff
changeset
|
2525 case 1: is_signed ? ldsb(src, dst) : ldub(src, dst); break; |
28bf941f445e
7018378: JSR 292: _bound_int_mh produces wrong result on 64-bit SPARC
twisti
parents:
2127
diff
changeset
|
2526 default: ShouldNotReachHere(); |
28bf941f445e
7018378: JSR 292: _bound_int_mh produces wrong result on 64-bit SPARC
twisti
parents:
2127
diff
changeset
|
2527 } |
28bf941f445e
7018378: JSR 292: _bound_int_mh produces wrong result on 64-bit SPARC
twisti
parents:
2127
diff
changeset
|
2528 } |
28bf941f445e
7018378: JSR 292: _bound_int_mh produces wrong result on 64-bit SPARC
twisti
parents:
2127
diff
changeset
|
2529 |
28bf941f445e
7018378: JSR 292: _bound_int_mh produces wrong result on 64-bit SPARC
twisti
parents:
2127
diff
changeset
|
2530 void MacroAssembler::store_sized_value(Register src, Address dst, size_t size_in_bytes) { |
28bf941f445e
7018378: JSR 292: _bound_int_mh produces wrong result on 64-bit SPARC
twisti
parents:
2127
diff
changeset
|
2531 switch (size_in_bytes) { |
28bf941f445e
7018378: JSR 292: _bound_int_mh produces wrong result on 64-bit SPARC
twisti
parents:
2127
diff
changeset
|
2532 case 8: st_long(src, dst); break; |
28bf941f445e
7018378: JSR 292: _bound_int_mh produces wrong result on 64-bit SPARC
twisti
parents:
2127
diff
changeset
|
2533 case 4: st( src, dst); break; |
28bf941f445e
7018378: JSR 292: _bound_int_mh produces wrong result on 64-bit SPARC
twisti
parents:
2127
diff
changeset
|
2534 case 2: sth( src, dst); break; |
28bf941f445e
7018378: JSR 292: _bound_int_mh produces wrong result on 64-bit SPARC
twisti
parents:
2127
diff
changeset
|
2535 case 1: stb( src, dst); break; |
28bf941f445e
7018378: JSR 292: _bound_int_mh produces wrong result on 64-bit SPARC
twisti
parents:
2127
diff
changeset
|
2536 default: ShouldNotReachHere(); |
1503 | 2537 } |
2538 } | |
2539 | |
2540 | |
0 | 2541 void MacroAssembler::float_cmp( bool is_float, int unordered_result, |
2542 FloatRegister Fa, FloatRegister Fb, | |
2543 Register Rresult) { | |
2544 | |
2545 fcmp(is_float ? FloatRegisterImpl::S : FloatRegisterImpl::D, fcc0, Fa, Fb); | |
2546 | |
2547 Condition lt = unordered_result == -1 ? f_unorderedOrLess : f_less; | |
2548 Condition eq = f_equal; | |
2549 Condition gt = unordered_result == 1 ? f_unorderedOrGreater : f_greater; | |
2550 | |
2551 if (VM_Version::v9_instructions_work()) { | |
2552 | |
3839 | 2553 mov(-1, Rresult); |
2554 movcc(eq, true, fcc0, 0, Rresult); | |
2555 movcc(gt, true, fcc0, 1, Rresult); | |
0 | 2556 |
2557 } else { | |
2558 Label done; | |
2559 | |
3839 | 2560 set( -1, Rresult ); |
0 | 2561 //fb(lt, true, pn, done); delayed()->set( -1, Rresult ); |
2562 fb( eq, true, pn, done); delayed()->set( 0, Rresult ); | |
2563 fb( gt, true, pn, done); delayed()->set( 1, Rresult ); | |
2564 | |
2565 bind (done); | |
2566 } | |
2567 } | |
2568 | |
2569 | |
2570 void MacroAssembler::fneg( FloatRegisterImpl::Width w, FloatRegister s, FloatRegister d) | |
2571 { | |
2572 if (VM_Version::v9_instructions_work()) { | |
2573 Assembler::fneg(w, s, d); | |
2574 } else { | |
2575 if (w == FloatRegisterImpl::S) { | |
2576 Assembler::fneg(w, s, d); | |
2577 } else if (w == FloatRegisterImpl::D) { | |
2578 // number() does a sanity check on the alignment. | |
2579 assert(((s->encoding(FloatRegisterImpl::D) & 1) == 0) && | |
2580 ((d->encoding(FloatRegisterImpl::D) & 1) == 0), "float register alignment check"); | |
2581 | |
2582 Assembler::fneg(FloatRegisterImpl::S, s, d); | |
2583 Assembler::fmov(FloatRegisterImpl::S, s->successor(), d->successor()); | |
2584 } else { | |
2585 assert(w == FloatRegisterImpl::Q, "Invalid float register width"); | |
2586 | |
2587 // number() does a sanity check on the alignment. | |
2588 assert(((s->encoding(FloatRegisterImpl::D) & 3) == 0) && | |
2589 ((d->encoding(FloatRegisterImpl::D) & 3) == 0), "float register alignment check"); | |
2590 | |
2591 Assembler::fneg(FloatRegisterImpl::S, s, d); | |
2592 Assembler::fmov(FloatRegisterImpl::S, s->successor(), d->successor()); | |
2593 Assembler::fmov(FloatRegisterImpl::S, s->successor()->successor(), d->successor()->successor()); | |
2594 Assembler::fmov(FloatRegisterImpl::S, s->successor()->successor()->successor(), d->successor()->successor()->successor()); | |
2595 } | |
2596 } | |
2597 } | |
2598 | |
2599 void MacroAssembler::fmov( FloatRegisterImpl::Width w, FloatRegister s, FloatRegister d) | |
2600 { | |
2601 if (VM_Version::v9_instructions_work()) { | |
2602 Assembler::fmov(w, s, d); | |
2603 } else { | |
2604 if (w == FloatRegisterImpl::S) { | |
2605 Assembler::fmov(w, s, d); | |
2606 } else if (w == FloatRegisterImpl::D) { | |
2607 // number() does a sanity check on the alignment. | |
2608 assert(((s->encoding(FloatRegisterImpl::D) & 1) == 0) && | |
2609 ((d->encoding(FloatRegisterImpl::D) & 1) == 0), "float register alignment check"); | |
2610 | |
2611 Assembler::fmov(FloatRegisterImpl::S, s, d); | |
2612 Assembler::fmov(FloatRegisterImpl::S, s->successor(), d->successor()); | |
2613 } else { | |
2614 assert(w == FloatRegisterImpl::Q, "Invalid float register width"); | |
2615 | |
2616 // number() does a sanity check on the alignment. | |
2617 assert(((s->encoding(FloatRegisterImpl::D) & 3) == 0) && | |
2618 ((d->encoding(FloatRegisterImpl::D) & 3) == 0), "float register alignment check"); | |
2619 | |
2620 Assembler::fmov(FloatRegisterImpl::S, s, d); | |
2621 Assembler::fmov(FloatRegisterImpl::S, s->successor(), d->successor()); | |
2622 Assembler::fmov(FloatRegisterImpl::S, s->successor()->successor(), d->successor()->successor()); | |
2623 Assembler::fmov(FloatRegisterImpl::S, s->successor()->successor()->successor(), d->successor()->successor()->successor()); | |
2624 } | |
2625 } | |
2626 } | |
2627 | |
2628 void MacroAssembler::fabs( FloatRegisterImpl::Width w, FloatRegister s, FloatRegister d) | |
2629 { | |
2630 if (VM_Version::v9_instructions_work()) { | |
2631 Assembler::fabs(w, s, d); | |
2632 } else { | |
2633 if (w == FloatRegisterImpl::S) { | |
2634 Assembler::fabs(w, s, d); | |
2635 } else if (w == FloatRegisterImpl::D) { | |
2636 // number() does a sanity check on the alignment. | |
2637 assert(((s->encoding(FloatRegisterImpl::D) & 1) == 0) && | |
2638 ((d->encoding(FloatRegisterImpl::D) & 1) == 0), "float register alignment check"); | |
2639 | |
2640 Assembler::fabs(FloatRegisterImpl::S, s, d); | |
2641 Assembler::fmov(FloatRegisterImpl::S, s->successor(), d->successor()); | |
2642 } else { | |
2643 assert(w == FloatRegisterImpl::Q, "Invalid float register width"); | |
2644 | |
2645 // number() does a sanity check on the alignment. | |
2646 assert(((s->encoding(FloatRegisterImpl::D) & 3) == 0) && | |
2647 ((d->encoding(FloatRegisterImpl::D) & 3) == 0), "float register alignment check"); | |
2648 | |
2649 Assembler::fabs(FloatRegisterImpl::S, s, d); | |
2650 Assembler::fmov(FloatRegisterImpl::S, s->successor(), d->successor()); | |
2651 Assembler::fmov(FloatRegisterImpl::S, s->successor()->successor(), d->successor()->successor()); | |
2652 Assembler::fmov(FloatRegisterImpl::S, s->successor()->successor()->successor(), d->successor()->successor()->successor()); | |
2653 } | |
2654 } | |
2655 } | |
2656 | |
2657 void MacroAssembler::save_all_globals_into_locals() { | |
2658 mov(G1,L1); | |
2659 mov(G2,L2); | |
2660 mov(G3,L3); | |
2661 mov(G4,L4); | |
2662 mov(G5,L5); | |
2663 mov(G6,L6); | |
2664 mov(G7,L7); | |
2665 } | |
2666 | |
2667 void MacroAssembler::restore_globals_from_locals() { | |
2668 mov(L1,G1); | |
2669 mov(L2,G2); | |
2670 mov(L3,G3); | |
2671 mov(L4,G4); | |
2672 mov(L5,G5); | |
2673 mov(L6,G6); | |
2674 mov(L7,G7); | |
2675 } | |
2676 | |
2677 // Use for 64 bit operation. | |
2678 void MacroAssembler::casx_under_lock(Register top_ptr_reg, Register top_reg, Register ptr_reg, address lock_addr, bool use_call_vm) | |
2679 { | |
2680 // store ptr_reg as the new top value | |
2681 #ifdef _LP64 | |
2682 casx(top_ptr_reg, top_reg, ptr_reg); | |
2683 #else | |
2684 cas_under_lock(top_ptr_reg, top_reg, ptr_reg, lock_addr, use_call_vm); | |
2685 #endif // _LP64 | |
2686 } | |
2687 | |
2688 // [RGV] This routine does not handle 64 bit operations. | |
2689 // use casx_under_lock() or casx directly!!! | |
2690 void MacroAssembler::cas_under_lock(Register top_ptr_reg, Register top_reg, Register ptr_reg, address lock_addr, bool use_call_vm) | |
2691 { | |
2692 // store ptr_reg as the new top value | |
2693 if (VM_Version::v9_instructions_work()) { | |
2694 cas(top_ptr_reg, top_reg, ptr_reg); | |
2695 } else { | |
2696 | |
2697 // If the register is not an out nor global, it is not visible | |
2698 // after the save. Allocate a register for it, save its | |
2699 // value in the register save area (the save may not flush | |
2700 // registers to the save area). | |
2701 | |
2702 Register top_ptr_reg_after_save; | |
2703 Register top_reg_after_save; | |
2704 Register ptr_reg_after_save; | |
2705 | |
2706 if (top_ptr_reg->is_out() || top_ptr_reg->is_global()) { | |
2707 top_ptr_reg_after_save = top_ptr_reg->after_save(); | |
2708 } else { | |
2709 Address reg_save_addr = top_ptr_reg->address_in_saved_window(); | |
2710 top_ptr_reg_after_save = L0; | |
2711 st(top_ptr_reg, reg_save_addr); | |
2712 } | |
2713 | |
2714 if (top_reg->is_out() || top_reg->is_global()) { | |
2715 top_reg_after_save = top_reg->after_save(); | |
2716 } else { | |
2717 Address reg_save_addr = top_reg->address_in_saved_window(); | |
2718 top_reg_after_save = L1; | |
2719 st(top_reg, reg_save_addr); | |
2720 } | |
2721 | |
2722 if (ptr_reg->is_out() || ptr_reg->is_global()) { | |
2723 ptr_reg_after_save = ptr_reg->after_save(); | |
2724 } else { | |
2725 Address reg_save_addr = ptr_reg->address_in_saved_window(); | |
2726 ptr_reg_after_save = L2; | |
2727 st(ptr_reg, reg_save_addr); | |
2728 } | |
2729 | |
2730 const Register& lock_reg = L3; | |
2731 const Register& lock_ptr_reg = L4; | |
2732 const Register& value_reg = L5; | |
2733 const Register& yield_reg = L6; | |
2734 const Register& yieldall_reg = L7; | |
2735 | |
2736 save_frame(); | |
2737 | |
2738 if (top_ptr_reg_after_save == L0) { | |
2739 ld(top_ptr_reg->address_in_saved_window().after_save(), top_ptr_reg_after_save); | |
2740 } | |
2741 | |
2742 if (top_reg_after_save == L1) { | |
2743 ld(top_reg->address_in_saved_window().after_save(), top_reg_after_save); | |
2744 } | |
2745 | |
2746 if (ptr_reg_after_save == L2) { | |
2747 ld(ptr_reg->address_in_saved_window().after_save(), ptr_reg_after_save); | |
2748 } | |
2749 | |
2750 Label(retry_get_lock); | |
2751 Label(not_same); | |
2752 Label(dont_yield); | |
2753 | |
2754 assert(lock_addr, "lock_address should be non null for v8"); | |
2755 set((intptr_t)lock_addr, lock_ptr_reg); | |
2756 // Initialize yield counter | |
2757 mov(G0,yield_reg); | |
2758 mov(G0, yieldall_reg); | |
2759 set(StubRoutines::Sparc::locked, lock_reg); | |
2760 | |
2761 bind(retry_get_lock); | |
3839 | 2762 cmp_and_br_short(yield_reg, V8AtomicOperationUnderLockSpinCount, Assembler::less, Assembler::pt, dont_yield); |
0 | 2763 |
2764 if(use_call_vm) { | |
2765 Untested("Need to verify global reg consistancy"); | |
2766 call_VM(noreg, CAST_FROM_FN_PTR(address, SharedRuntime::yield_all), yieldall_reg); | |
2767 } else { | |
2768 // Save the regs and make space for a C call | |
2769 save(SP, -96, SP); | |
2770 save_all_globals_into_locals(); | |
2771 call(CAST_FROM_FN_PTR(address,os::yield_all)); | |
2772 delayed()->mov(yieldall_reg, O0); | |
2773 restore_globals_from_locals(); | |
2774 restore(); | |
2775 } | |
2776 | |
2777 // reset the counter | |
2778 mov(G0,yield_reg); | |
2779 add(yieldall_reg, 1, yieldall_reg); | |
2780 | |
2781 bind(dont_yield); | |
2782 // try to get lock | |
2783 swap(lock_ptr_reg, 0, lock_reg); | |
2784 | |
2785 // did we get the lock? | |
2786 cmp(lock_reg, StubRoutines::Sparc::unlocked); | |
2787 br(Assembler::notEqual, true, Assembler::pn, retry_get_lock); | |
2788 delayed()->add(yield_reg,1,yield_reg); | |
2789 | |
2790 // yes, got lock. do we have the same top? | |
2791 ld(top_ptr_reg_after_save, 0, value_reg); | |
3839 | 2792 cmp_and_br_short(value_reg, top_reg_after_save, Assembler::notEqual, Assembler::pn, not_same); |
0 | 2793 |
2794 // yes, same top. | |
2795 st(ptr_reg_after_save, top_ptr_reg_after_save, 0); | |
2796 membar(Assembler::StoreStore); | |
2797 | |
2798 bind(not_same); | |
2799 mov(value_reg, ptr_reg_after_save); | |
2800 st(lock_reg, lock_ptr_reg, 0); // unlock | |
2801 | |
2802 restore(); | |
2803 } | |
2804 } | |
2805 | |
665
c89f86385056
6814659: separable cleanups and subroutines for 6655638
jrose
parents:
644
diff
changeset
|
2806 RegisterOrConstant MacroAssembler::delayed_value_impl(intptr_t* delayed_value_addr, |
c89f86385056
6814659: separable cleanups and subroutines for 6655638
jrose
parents:
644
diff
changeset
|
2807 Register tmp, |
c89f86385056
6814659: separable cleanups and subroutines for 6655638
jrose
parents:
644
diff
changeset
|
2808 int offset) { |
622
56aae7be60d4
6812678: macro assembler needs delayed binding of a few constants (for 6655638)
jrose
parents:
420
diff
changeset
|
2809 intptr_t value = *delayed_value_addr; |
56aae7be60d4
6812678: macro assembler needs delayed binding of a few constants (for 6655638)
jrose
parents:
420
diff
changeset
|
2810 if (value != 0) |
665
c89f86385056
6814659: separable cleanups and subroutines for 6655638
jrose
parents:
644
diff
changeset
|
2811 return RegisterOrConstant(value + offset); |
622
56aae7be60d4
6812678: macro assembler needs delayed binding of a few constants (for 6655638)
jrose
parents:
420
diff
changeset
|
2812 |
56aae7be60d4
6812678: macro assembler needs delayed binding of a few constants (for 6655638)
jrose
parents:
420
diff
changeset
|
2813 // load indirectly to solve generation ordering problem |
727 | 2814 AddressLiteral a(delayed_value_addr); |
622
56aae7be60d4
6812678: macro assembler needs delayed binding of a few constants (for 6655638)
jrose
parents:
420
diff
changeset
|
2815 load_ptr_contents(a, tmp); |
56aae7be60d4
6812678: macro assembler needs delayed binding of a few constants (for 6655638)
jrose
parents:
420
diff
changeset
|
2816 |
56aae7be60d4
6812678: macro assembler needs delayed binding of a few constants (for 6655638)
jrose
parents:
420
diff
changeset
|
2817 #ifdef ASSERT |
56aae7be60d4
6812678: macro assembler needs delayed binding of a few constants (for 6655638)
jrose
parents:
420
diff
changeset
|
2818 tst(tmp); |
56aae7be60d4
6812678: macro assembler needs delayed binding of a few constants (for 6655638)
jrose
parents:
420
diff
changeset
|
2819 breakpoint_trap(zero, xcc); |
56aae7be60d4
6812678: macro assembler needs delayed binding of a few constants (for 6655638)
jrose
parents:
420
diff
changeset
|
2820 #endif |
56aae7be60d4
6812678: macro assembler needs delayed binding of a few constants (for 6655638)
jrose
parents:
420
diff
changeset
|
2821 |
56aae7be60d4
6812678: macro assembler needs delayed binding of a few constants (for 6655638)
jrose
parents:
420
diff
changeset
|
2822 if (offset != 0) |
56aae7be60d4
6812678: macro assembler needs delayed binding of a few constants (for 6655638)
jrose
parents:
420
diff
changeset
|
2823 add(tmp, offset, tmp); |
56aae7be60d4
6812678: macro assembler needs delayed binding of a few constants (for 6655638)
jrose
parents:
420
diff
changeset
|
2824 |
665
c89f86385056
6814659: separable cleanups and subroutines for 6655638
jrose
parents:
644
diff
changeset
|
2825 return RegisterOrConstant(tmp); |
622
56aae7be60d4
6812678: macro assembler needs delayed binding of a few constants (for 6655638)
jrose
parents:
420
diff
changeset
|
2826 } |
56aae7be60d4
6812678: macro assembler needs delayed binding of a few constants (for 6655638)
jrose
parents:
420
diff
changeset
|
2827 |
56aae7be60d4
6812678: macro assembler needs delayed binding of a few constants (for 6655638)
jrose
parents:
420
diff
changeset
|
2828 |
1503 | 2829 RegisterOrConstant MacroAssembler::regcon_andn_ptr(RegisterOrConstant s1, RegisterOrConstant s2, RegisterOrConstant d, Register temp) { |
2830 assert(d.register_or_noreg() != G0, "lost side effect"); | |
2831 if ((s2.is_constant() && s2.as_constant() == 0) || | |
2832 (s2.is_register() && s2.as_register() == G0)) { | |
2833 // Do nothing, just move value. | |
2834 if (s1.is_register()) { | |
2835 if (d.is_constant()) d = temp; | |
2836 mov(s1.as_register(), d.as_register()); | |
2837 return d; | |
2838 } else { | |
2839 return s1; | |
2840 } | |
2841 } | |
2842 | |
2843 if (s1.is_register()) { | |
2844 assert_different_registers(s1.as_register(), temp); | |
2845 if (d.is_constant()) d = temp; | |
2846 andn(s1.as_register(), ensure_simm13_or_reg(s2, temp), d.as_register()); | |
2847 return d; | |
623
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
2848 } else { |
1503 | 2849 if (s2.is_register()) { |
2850 assert_different_registers(s2.as_register(), temp); | |
2851 if (d.is_constant()) d = temp; | |
2852 set(s1.as_constant(), temp); | |
2853 andn(temp, s2.as_register(), d.as_register()); | |
2854 return d; | |
2855 } else { | |
2856 intptr_t res = s1.as_constant() & ~s2.as_constant(); | |
2857 return res; | |
2858 } | |
623
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
2859 } |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
2860 } |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
2861 |
1503 | 2862 RegisterOrConstant MacroAssembler::regcon_inc_ptr(RegisterOrConstant s1, RegisterOrConstant s2, RegisterOrConstant d, Register temp) { |
2863 assert(d.register_or_noreg() != G0, "lost side effect"); | |
2864 if ((s2.is_constant() && s2.as_constant() == 0) || | |
2865 (s2.is_register() && s2.as_register() == G0)) { | |
2866 // Do nothing, just move value. | |
2867 if (s1.is_register()) { | |
2868 if (d.is_constant()) d = temp; | |
2869 mov(s1.as_register(), d.as_register()); | |
2870 return d; | |
2871 } else { | |
2872 return s1; | |
2873 } | |
2874 } | |
2875 | |
2876 if (s1.is_register()) { | |
2877 assert_different_registers(s1.as_register(), temp); | |
2878 if (d.is_constant()) d = temp; | |
2879 add(s1.as_register(), ensure_simm13_or_reg(s2, temp), d.as_register()); | |
2880 return d; | |
623
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
2881 } else { |
1503 | 2882 if (s2.is_register()) { |
2883 assert_different_registers(s2.as_register(), temp); | |
2884 if (d.is_constant()) d = temp; | |
2885 add(s2.as_register(), ensure_simm13_or_reg(s1, temp), d.as_register()); | |
2886 return d; | |
2887 } else { | |
2888 intptr_t res = s1.as_constant() + s2.as_constant(); | |
2889 return res; | |
2890 } | |
2891 } | |
2892 } | |
2893 | |
2894 RegisterOrConstant MacroAssembler::regcon_sll_ptr(RegisterOrConstant s1, RegisterOrConstant s2, RegisterOrConstant d, Register temp) { | |
2895 assert(d.register_or_noreg() != G0, "lost side effect"); | |
2896 if (!is_simm13(s2.constant_or_zero())) | |
2897 s2 = (s2.as_constant() & 0xFF); | |
2898 if ((s2.is_constant() && s2.as_constant() == 0) || | |
2899 (s2.is_register() && s2.as_register() == G0)) { | |
2900 // Do nothing, just move value. | |
2901 if (s1.is_register()) { | |
2902 if (d.is_constant()) d = temp; | |
2903 mov(s1.as_register(), d.as_register()); | |
2904 return d; | |
2905 } else { | |
2906 return s1; | |
2907 } | |
2908 } | |
2909 | |
2910 if (s1.is_register()) { | |
2911 assert_different_registers(s1.as_register(), temp); | |
2912 if (d.is_constant()) d = temp; | |
2913 sll_ptr(s1.as_register(), ensure_simm13_or_reg(s2, temp), d.as_register()); | |
2914 return d; | |
2915 } else { | |
2916 if (s2.is_register()) { | |
2917 assert_different_registers(s2.as_register(), temp); | |
2918 if (d.is_constant()) d = temp; | |
2919 set(s1.as_constant(), temp); | |
2920 sll_ptr(temp, s2.as_register(), d.as_register()); | |
2921 return d; | |
2922 } else { | |
2923 intptr_t res = s1.as_constant() << s2.as_constant(); | |
2924 return res; | |
2925 } | |
623
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
2926 } |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
2927 } |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
2928 |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
2929 |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
2930 // Look up the method for a megamorphic invokeinterface call. |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
2931 // The target method is determined by <intf_klass, itable_index>. |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
2932 // The receiver klass is in recv_klass. |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
2933 // On success, the result will be in method_result, and execution falls through. |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
2934 // On failure, execution transfers to the given label. |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
2935 void MacroAssembler::lookup_interface_method(Register recv_klass, |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
2936 Register intf_klass, |
665
c89f86385056
6814659: separable cleanups and subroutines for 6655638
jrose
parents:
644
diff
changeset
|
2937 RegisterOrConstant itable_index, |
623
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
2938 Register method_result, |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
2939 Register scan_temp, |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
2940 Register sethi_temp, |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
2941 Label& L_no_such_interface) { |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
2942 assert_different_registers(recv_klass, intf_klass, method_result, scan_temp); |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
2943 assert(itable_index.is_constant() || itable_index.as_register() == method_result, |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
2944 "caller must use same register for non-constant itable index as for method"); |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
2945 |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
2946 // Compute start of first itableOffsetEntry (which is at the end of the vtable) |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
2947 int vtable_base = InstanceKlass::vtable_start_offset() * wordSize; |
623
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
2948 int scan_step = itableOffsetEntry::size() * wordSize; |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
2949 int vte_size = vtableEntry::size() * wordSize; |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
2950 |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
2951 lduw(recv_klass, InstanceKlass::vtable_length_offset() * wordSize, scan_temp); |
623
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
2952 // %%% We should store the aligned, prescaled offset in the klassoop. |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
2953 // Then the next several instructions would fold away. |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
2954 |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
2955 int round_to_unit = ((HeapWordsPerLong > 1) ? BytesPerLong : 0); |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
2956 int itb_offset = vtable_base; |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
2957 if (round_to_unit != 0) { |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
2958 // hoist first instruction of round_to(scan_temp, BytesPerLong): |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
2959 itb_offset += round_to_unit - wordSize; |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
2960 } |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
2961 int itb_scale = exact_log2(vtableEntry::size() * wordSize); |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
2962 sll(scan_temp, itb_scale, scan_temp); |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
2963 add(scan_temp, itb_offset, scan_temp); |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
2964 if (round_to_unit != 0) { |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
2965 // Round up to align_object_offset boundary |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
2966 // see code for InstanceKlass::start_of_itable! |
623
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
2967 // Was: round_to(scan_temp, BytesPerLong); |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
2968 // Hoisted: add(scan_temp, BytesPerLong-1, scan_temp); |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
2969 and3(scan_temp, -round_to_unit, scan_temp); |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
2970 } |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
2971 add(recv_klass, scan_temp, scan_temp); |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
2972 |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
2973 // Adjust recv_klass by scaled itable_index, so we can free itable_index. |
665
c89f86385056
6814659: separable cleanups and subroutines for 6655638
jrose
parents:
644
diff
changeset
|
2974 RegisterOrConstant itable_offset = itable_index; |
1503 | 2975 itable_offset = regcon_sll_ptr(itable_index, exact_log2(itableMethodEntry::size() * wordSize), itable_offset); |
2976 itable_offset = regcon_inc_ptr(itable_offset, itableMethodEntry::method_offset_in_bytes(), itable_offset); | |
1006
dcf03e02b020
6879902: CTW failure jdk6_18/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp:845
twisti
parents:
986
diff
changeset
|
2977 add(recv_klass, ensure_simm13_or_reg(itable_offset, sethi_temp), recv_klass); |
623
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
2978 |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
2979 // for (scan = klass->itable(); scan->interface() != NULL; scan += scan_step) { |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
2980 // if (scan->interface() == intf) { |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
2981 // result = (klass + scan->offset() + itable_index); |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
2982 // } |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
2983 // } |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
2984 Label search, found_method; |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
2985 |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
2986 for (int peel = 1; peel >= 0; peel--) { |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
2987 // %%%% Could load both offset and interface in one ldx, if they were |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
2988 // in the opposite order. This would save a load. |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
2989 ld_ptr(scan_temp, itableOffsetEntry::interface_offset_in_bytes(), method_result); |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
2990 |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
2991 // Check that this entry is non-null. A null entry means that |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
2992 // the receiver class doesn't implement the interface, and wasn't the |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
2993 // same as when the caller was compiled. |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
2994 bpr(Assembler::rc_z, false, Assembler::pn, method_result, L_no_such_interface); |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
2995 delayed()->cmp(method_result, intf_klass); |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
2996 |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
2997 if (peel) { |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
2998 brx(Assembler::equal, false, Assembler::pt, found_method); |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
2999 } else { |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
3000 brx(Assembler::notEqual, false, Assembler::pn, search); |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
3001 // (invert the test to fall through to found_method...) |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
3002 } |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
3003 delayed()->add(scan_temp, scan_step, scan_temp); |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
3004 |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
3005 if (!peel) break; |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
3006 |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
3007 bind(search); |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
3008 } |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
3009 |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
3010 bind(found_method); |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
3011 |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
3012 // Got a hit. |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
3013 int ito_offset = itableOffsetEntry::offset_offset_in_bytes(); |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
3014 // scan_temp[-scan_step] points to the vtable offset we need |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
3015 ito_offset -= scan_step; |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
3016 lduw(scan_temp, ito_offset, scan_temp); |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
3017 ld_ptr(recv_klass, scan_temp, method_result); |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
3018 } |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
3019 |
9adddb8c0fc8
6812831: factor duplicated assembly code for megamorphic invokeinterface (for 6655638)
jrose
parents:
622
diff
changeset
|
3020 |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
4762
diff
changeset
|
3021 // virtual method calling |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
4762
diff
changeset
|
3022 void MacroAssembler::lookup_virtual_method(Register recv_klass, |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
4762
diff
changeset
|
3023 RegisterOrConstant vtable_index, |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
4762
diff
changeset
|
3024 Register method_result) { |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
4762
diff
changeset
|
3025 assert_different_registers(recv_klass, method_result, vtable_index.register_or_noreg()); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
4762
diff
changeset
|
3026 Register sethi_temp = method_result; |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
3027 const int base = (InstanceKlass::vtable_start_offset() * wordSize + |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
4762
diff
changeset
|
3028 // method pointer offset within the vtable entry: |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
4762
diff
changeset
|
3029 vtableEntry::method_offset_in_bytes()); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
4762
diff
changeset
|
3030 RegisterOrConstant vtable_offset = vtable_index; |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
4762
diff
changeset
|
3031 // Each of the following three lines potentially generates an instruction. |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
4762
diff
changeset
|
3032 // But the total number of address formation instructions will always be |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
4762
diff
changeset
|
3033 // at most two, and will often be zero. In any case, it will be optimal. |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
4762
diff
changeset
|
3034 // If vtable_index is a register, we will have (sll_ptr N,x; inc_ptr B,x; ld_ptr k,x). |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
4762
diff
changeset
|
3035 // If vtable_index is a constant, we will have at most (set B+X<<N,t; ld_ptr k,t). |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
4762
diff
changeset
|
3036 vtable_offset = regcon_sll_ptr(vtable_index, exact_log2(vtableEntry::size() * wordSize), vtable_offset); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
4762
diff
changeset
|
3037 vtable_offset = regcon_inc_ptr(vtable_offset, base, vtable_offset, sethi_temp); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
4762
diff
changeset
|
3038 Address vtable_entry_addr(recv_klass, ensure_simm13_or_reg(vtable_offset, sethi_temp)); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
4762
diff
changeset
|
3039 ld_ptr(vtable_entry_addr, method_result); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
4762
diff
changeset
|
3040 } |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
4762
diff
changeset
|
3041 |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
4762
diff
changeset
|
3042 |
644
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3043 void MacroAssembler::check_klass_subtype(Register sub_klass, |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3044 Register super_klass, |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3045 Register temp_reg, |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3046 Register temp2_reg, |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3047 Label& L_success) { |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3048 Register sub_2 = sub_klass; |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3049 Register sup_2 = super_klass; |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3050 if (!sub_2->is_global()) sub_2 = L0; |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3051 if (!sup_2->is_global()) sup_2 = L1; |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
4762
diff
changeset
|
3052 bool did_save = false; |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
4762
diff
changeset
|
3053 if (temp_reg == noreg || temp2_reg == noreg) { |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
4762
diff
changeset
|
3054 temp_reg = L2; |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
4762
diff
changeset
|
3055 temp2_reg = L3; |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
4762
diff
changeset
|
3056 save_frame_and_mov(0, sub_klass, sub_2, super_klass, sup_2); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
4762
diff
changeset
|
3057 sub_klass = sub_2; |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
4762
diff
changeset
|
3058 super_klass = sup_2; |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
4762
diff
changeset
|
3059 did_save = true; |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
4762
diff
changeset
|
3060 } |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
4762
diff
changeset
|
3061 Label L_failure, L_pop_to_failure, L_pop_to_success; |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
4762
diff
changeset
|
3062 check_klass_subtype_fast_path(sub_klass, super_klass, |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
4762
diff
changeset
|
3063 temp_reg, temp2_reg, |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
4762
diff
changeset
|
3064 (did_save ? &L_pop_to_success : &L_success), |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
4762
diff
changeset
|
3065 (did_save ? &L_pop_to_failure : &L_failure), NULL); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
4762
diff
changeset
|
3066 |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
4762
diff
changeset
|
3067 if (!did_save) |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
4762
diff
changeset
|
3068 save_frame_and_mov(0, sub_klass, sub_2, super_klass, sup_2); |
644
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3069 check_klass_subtype_slow_path(sub_2, sup_2, |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3070 L2, L3, L4, L5, |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3071 NULL, &L_pop_to_failure); |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3072 |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3073 // on success: |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
4762
diff
changeset
|
3074 bind(L_pop_to_success); |
644
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3075 restore(); |
3839 | 3076 ba_short(L_success); |
644
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3077 |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3078 // on failure: |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3079 bind(L_pop_to_failure); |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3080 restore(); |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3081 bind(L_failure); |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3082 } |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3083 |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3084 |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3085 void MacroAssembler::check_klass_subtype_fast_path(Register sub_klass, |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3086 Register super_klass, |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3087 Register temp_reg, |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3088 Register temp2_reg, |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3089 Label* L_success, |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3090 Label* L_failure, |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3091 Label* L_slow_path, |
3839 | 3092 RegisterOrConstant super_check_offset) { |
4762
069ab3f976d3
7118863: Move sizeof(klassOopDesc) into the *Klass::*_offset_in_bytes() functions
stefank
parents:
3938
diff
changeset
|
3093 int sc_offset = in_bytes(Klass::secondary_super_cache_offset()); |
069ab3f976d3
7118863: Move sizeof(klassOopDesc) into the *Klass::*_offset_in_bytes() functions
stefank
parents:
3938
diff
changeset
|
3094 int sco_offset = in_bytes(Klass::super_check_offset_offset()); |
644
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3095 |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3096 bool must_load_sco = (super_check_offset.constant_or_zero() == -1); |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3097 bool need_slow_path = (must_load_sco || |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3098 super_check_offset.constant_or_zero() == sco_offset); |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3099 |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3100 assert_different_registers(sub_klass, super_klass, temp_reg); |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3101 if (super_check_offset.is_register()) { |
1503 | 3102 assert_different_registers(sub_klass, super_klass, temp_reg, |
644
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3103 super_check_offset.as_register()); |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3104 } else if (must_load_sco) { |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3105 assert(temp2_reg != noreg, "supply either a temp or a register offset"); |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3106 } |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3107 |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3108 Label L_fallthrough; |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3109 int label_nulls = 0; |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3110 if (L_success == NULL) { L_success = &L_fallthrough; label_nulls++; } |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3111 if (L_failure == NULL) { L_failure = &L_fallthrough; label_nulls++; } |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3112 if (L_slow_path == NULL) { L_slow_path = &L_fallthrough; label_nulls++; } |
3839 | 3113 assert(label_nulls <= 1 || |
644
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3114 (L_slow_path == &L_fallthrough && label_nulls <= 2 && !need_slow_path), |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3115 "at most one NULL in the batch, usually"); |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3116 |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3117 // If the pointers are equal, we are done (e.g., String[] elements). |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3118 // This self-check enables sharing of secondary supertype arrays among |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3119 // non-primary types such as array-of-interface. Otherwise, each such |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3120 // type would need its own customized SSA. |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3121 // We move this check to the front of the fast path because many |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3122 // type checks are in fact trivially successful in this manner, |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3123 // so we get a nicely predicted branch right at the start of the check. |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3124 cmp(super_klass, sub_klass); |
3839 | 3125 brx(Assembler::equal, false, Assembler::pn, *L_success); |
3126 delayed()->nop(); | |
644
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3127 |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3128 // Check the supertype display: |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3129 if (must_load_sco) { |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3130 // The super check offset is always positive... |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3131 lduw(super_klass, sco_offset, temp2_reg); |
665
c89f86385056
6814659: separable cleanups and subroutines for 6655638
jrose
parents:
644
diff
changeset
|
3132 super_check_offset = RegisterOrConstant(temp2_reg); |
1503 | 3133 // super_check_offset is register. |
3134 assert_different_registers(sub_klass, super_klass, temp_reg, super_check_offset.as_register()); | |
644
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3135 } |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3136 ld_ptr(sub_klass, super_check_offset, temp_reg); |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3137 cmp(super_klass, temp_reg); |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3138 |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3139 // This check has worked decisively for primary supers. |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3140 // Secondary supers are sought in the super_cache ('super_cache_addr'). |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3141 // (Secondary supers are interfaces and very deeply nested subtypes.) |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3142 // This works in the same check above because of a tricky aliasing |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3143 // between the super_cache and the primary super display elements. |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3144 // (The 'super_check_addr' can address either, as the case requires.) |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3145 // Note that the cache is updated below if it does not help us find |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3146 // what we need immediately. |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3147 // So if it was a primary super, we can just fail immediately. |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3148 // Otherwise, it's the slow path for us (no success at this point). |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3149 |
3839 | 3150 // Hacked ba(), which may only be used just before L_fallthrough. |
3151 #define FINAL_JUMP(label) \ | |
3152 if (&(label) != &L_fallthrough) { \ | |
3153 ba(label); delayed()->nop(); \ | |
3154 } | |
3155 | |
644
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3156 if (super_check_offset.is_register()) { |
3839 | 3157 brx(Assembler::equal, false, Assembler::pn, *L_success); |
3158 delayed()->cmp(super_check_offset.as_register(), sc_offset); | |
644
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3159 |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3160 if (L_failure == &L_fallthrough) { |
3839 | 3161 brx(Assembler::equal, false, Assembler::pt, *L_slow_path); |
644
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3162 delayed()->nop(); |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3163 } else { |
3839 | 3164 brx(Assembler::notEqual, false, Assembler::pn, *L_failure); |
3165 delayed()->nop(); | |
3166 FINAL_JUMP(*L_slow_path); | |
644
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3167 } |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3168 } else if (super_check_offset.as_constant() == sc_offset) { |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3169 // Need a slow path; fast failure is impossible. |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3170 if (L_slow_path == &L_fallthrough) { |
3839 | 3171 brx(Assembler::equal, false, Assembler::pt, *L_success); |
3172 delayed()->nop(); | |
644
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3173 } else { |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3174 brx(Assembler::notEqual, false, Assembler::pn, *L_slow_path); |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3175 delayed()->nop(); |
3839 | 3176 FINAL_JUMP(*L_success); |
644
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3177 } |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3178 } else { |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3179 // No slow path; it's a fast decision. |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3180 if (L_failure == &L_fallthrough) { |
3839 | 3181 brx(Assembler::equal, false, Assembler::pt, *L_success); |
3182 delayed()->nop(); | |
644
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3183 } else { |
3839 | 3184 brx(Assembler::notEqual, false, Assembler::pn, *L_failure); |
3185 delayed()->nop(); | |
3186 FINAL_JUMP(*L_success); | |
644
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3187 } |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3188 } |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3189 |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3190 bind(L_fallthrough); |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3191 |
3839 | 3192 #undef FINAL_JUMP |
644
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3193 } |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3194 |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3195 |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3196 void MacroAssembler::check_klass_subtype_slow_path(Register sub_klass, |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3197 Register super_klass, |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3198 Register count_temp, |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3199 Register scan_temp, |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3200 Register scratch_reg, |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3201 Register coop_reg, |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3202 Label* L_success, |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3203 Label* L_failure) { |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3204 assert_different_registers(sub_klass, super_klass, |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3205 count_temp, scan_temp, scratch_reg, coop_reg); |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3206 |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3207 Label L_fallthrough, L_loop; |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3208 int label_nulls = 0; |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3209 if (L_success == NULL) { L_success = &L_fallthrough; label_nulls++; } |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3210 if (L_failure == NULL) { L_failure = &L_fallthrough; label_nulls++; } |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3211 assert(label_nulls <= 1, "at most one NULL in the batch"); |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3212 |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3213 // a couple of useful fields in sub_klass: |
4762
069ab3f976d3
7118863: Move sizeof(klassOopDesc) into the *Klass::*_offset_in_bytes() functions
stefank
parents:
3938
diff
changeset
|
3214 int ss_offset = in_bytes(Klass::secondary_supers_offset()); |
069ab3f976d3
7118863: Move sizeof(klassOopDesc) into the *Klass::*_offset_in_bytes() functions
stefank
parents:
3938
diff
changeset
|
3215 int sc_offset = in_bytes(Klass::secondary_super_cache_offset()); |
644
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3216 |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3217 // Do a linear scan of the secondary super-klass chain. |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3218 // This code is rarely used, so simplicity is a virtue here. |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3219 |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3220 #ifndef PRODUCT |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3221 int* pst_counter = &SharedRuntime::_partial_subtype_ctr; |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3222 inc_counter((address) pst_counter, count_temp, scan_temp); |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3223 #endif |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3224 |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3225 // We will consult the secondary-super array. |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3226 ld_ptr(sub_klass, ss_offset, scan_temp); |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3227 |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3228 Register search_key = super_klass; |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3229 |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3230 // Load the array length. (Positive movl does right thing on LP64.) |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
3231 lduw(scan_temp, Array<Klass*>::length_offset_in_bytes(), count_temp); |
644
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3232 |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3233 // Check for empty secondary super list |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3234 tst(count_temp); |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3235 |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
3236 // In the array of super classes elements are pointer sized. |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
3237 int element_size = wordSize; |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
3238 |
644
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3239 // Top of search loop |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3240 bind(L_loop); |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3241 br(Assembler::equal, false, Assembler::pn, *L_failure); |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
3242 delayed()->add(scan_temp, element_size, scan_temp); |
644
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3243 |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3244 // Skip the array header in all array accesses. |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
3245 int elem_offset = Array<Klass*>::base_offset_in_bytes(); |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
3246 elem_offset -= element_size; // the scan pointer was pre-incremented also |
644
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3247 |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3248 // Load next super to check |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3249 ld_ptr( scan_temp, elem_offset, scratch_reg ); |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3250 |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3251 // Look for Rsuper_klass on Rsub_klass's secondary super-class-overflow list |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3252 cmp(scratch_reg, search_key); |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3253 |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3254 // A miss means we are NOT a subtype and need to keep looping |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3255 brx(Assembler::notEqual, false, Assembler::pn, L_loop); |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3256 delayed()->deccc(count_temp); // decrement trip counter in delay slot |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3257 |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3258 // Success. Cache the super we found and proceed in triumph. |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3259 st_ptr(super_klass, sub_klass, sc_offset); |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3260 |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3261 if (L_success != &L_fallthrough) { |
3839 | 3262 ba(*L_success); |
644
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3263 delayed()->nop(); |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3264 } |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3265 |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3266 bind(L_fallthrough); |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3267 } |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3268 |
c517646eef23
6813212: factor duplicated assembly code for general subclass check (for 6655638)
jrose
parents:
642
diff
changeset
|
3269 |
710 | 3270 RegisterOrConstant MacroAssembler::argument_offset(RegisterOrConstant arg_slot, |
3753
cba7b5c2d53f
7045514: SPARC assembly code for JSR 292 ricochet frames
never
parents:
3249
diff
changeset
|
3271 Register temp_reg, |
710 | 3272 int extra_slot_offset) { |
3273 // cf. TemplateTable::prepare_invoke(), if (load_receiver). | |
1506 | 3274 int stackElementSize = Interpreter::stackElementSize; |
1503 | 3275 int offset = extra_slot_offset * stackElementSize; |
710 | 3276 if (arg_slot.is_constant()) { |
3277 offset += arg_slot.as_constant() * stackElementSize; | |
3278 return offset; | |
3279 } else { | |
3753
cba7b5c2d53f
7045514: SPARC assembly code for JSR 292 ricochet frames
never
parents:
3249
diff
changeset
|
3280 assert(temp_reg != noreg, "must specify"); |
cba7b5c2d53f
7045514: SPARC assembly code for JSR 292 ricochet frames
never
parents:
3249
diff
changeset
|
3281 sll_ptr(arg_slot.as_register(), exact_log2(stackElementSize), temp_reg); |
710 | 3282 if (offset != 0) |
3753
cba7b5c2d53f
7045514: SPARC assembly code for JSR 292 ricochet frames
never
parents:
3249
diff
changeset
|
3283 add(temp_reg, offset, temp_reg); |
cba7b5c2d53f
7045514: SPARC assembly code for JSR 292 ricochet frames
never
parents:
3249
diff
changeset
|
3284 return temp_reg; |
710 | 3285 } |
3286 } | |
3287 | |
3288 | |
1503 | 3289 Address MacroAssembler::argument_address(RegisterOrConstant arg_slot, |
3753
cba7b5c2d53f
7045514: SPARC assembly code for JSR 292 ricochet frames
never
parents:
3249
diff
changeset
|
3290 Register temp_reg, |
1503 | 3291 int extra_slot_offset) { |
3753
cba7b5c2d53f
7045514: SPARC assembly code for JSR 292 ricochet frames
never
parents:
3249
diff
changeset
|
3292 return Address(Gargs, argument_offset(arg_slot, temp_reg, extra_slot_offset)); |
1503 | 3293 } |
3294 | |
710 | 3295 |
420
a1980da045cc
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
356
diff
changeset
|
3296 void MacroAssembler::biased_locking_enter(Register obj_reg, Register mark_reg, |
a1980da045cc
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
356
diff
changeset
|
3297 Register temp_reg, |
0 | 3298 Label& done, Label* slow_case, |
3299 BiasedLockingCounters* counters) { | |
3300 assert(UseBiasedLocking, "why call this otherwise?"); | |
3301 | |
3302 if (PrintBiasedLockingStatistics) { | |
3303 assert_different_registers(obj_reg, mark_reg, temp_reg, O7); | |
3304 if (counters == NULL) | |
3305 counters = BiasedLocking::counters(); | |
3306 } | |
3307 | |
3308 Label cas_label; | |
3309 | |
3310 // Biased locking | |
3311 // See whether the lock is currently biased toward our thread and | |
3312 // whether the epoch is still valid | |
3313 // Note that the runtime guarantees sufficient alignment of JavaThread | |
3314 // pointers to allow age to be placed into low bits | |
3315 assert(markOopDesc::age_shift == markOopDesc::lock_bits + markOopDesc::biased_lock_bits, "biased locking makes assumptions about bit layout"); | |
3316 and3(mark_reg, markOopDesc::biased_lock_mask_in_place, temp_reg); | |
3839 | 3317 cmp_and_brx_short(temp_reg, markOopDesc::biased_lock_pattern, Assembler::notEqual, Assembler::pn, cas_label); |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
3318 |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
3319 load_klass(obj_reg, temp_reg); |
4762
069ab3f976d3
7118863: Move sizeof(klassOopDesc) into the *Klass::*_offset_in_bytes() functions
stefank
parents:
3938
diff
changeset
|
3320 ld_ptr(Address(temp_reg, Klass::prototype_header_offset()), temp_reg); |
0 | 3321 or3(G2_thread, temp_reg, temp_reg); |
3322 xor3(mark_reg, temp_reg, temp_reg); | |
3323 andcc(temp_reg, ~((int) markOopDesc::age_mask_in_place), temp_reg); | |
3324 if (counters != NULL) { | |
3325 cond_inc(Assembler::equal, (address) counters->biased_lock_entry_count_addr(), mark_reg, temp_reg); | |
3326 // Reload mark_reg as we may need it later | |
727 | 3327 ld_ptr(Address(obj_reg, oopDesc::mark_offset_in_bytes()), mark_reg); |
0 | 3328 } |
3329 brx(Assembler::equal, true, Assembler::pt, done); | |
3330 delayed()->nop(); | |
3331 | |
3332 Label try_revoke_bias; | |
3333 Label try_rebias; | |
727 | 3334 Address mark_addr = Address(obj_reg, oopDesc::mark_offset_in_bytes()); |
0 | 3335 assert(mark_addr.disp() == 0, "cas must take a zero displacement"); |
3336 | |
3337 // At this point we know that the header has the bias pattern and | |
3338 // that we are not the bias owner in the current epoch. We need to | |
3339 // figure out more details about the state of the header in order to | |
3340 // know what operations can be legally performed on the object's | |
3341 // header. | |
3342 | |
3343 // If the low three bits in the xor result aren't clear, that means | |
3344 // the prototype header is no longer biased and we have to revoke | |
3345 // the bias on this object. | |
3346 btst(markOopDesc::biased_lock_mask_in_place, temp_reg); | |
3347 brx(Assembler::notZero, false, Assembler::pn, try_revoke_bias); | |
3348 | |
3349 // Biasing is still enabled for this data type. See whether the | |
3350 // epoch of the current bias is still valid, meaning that the epoch | |
3351 // bits of the mark word are equal to the epoch bits of the | |
3352 // prototype header. (Note that the prototype header's epoch bits | |
3353 // only change at a safepoint.) If not, attempt to rebias the object | |
3354 // toward the current thread. Note that we must be absolutely sure | |
3355 // that the current epoch is invalid in order to do this because | |
3356 // otherwise the manipulations it performs on the mark word are | |
3357 // illegal. | |
3358 delayed()->btst(markOopDesc::epoch_mask_in_place, temp_reg); | |
3359 brx(Assembler::notZero, false, Assembler::pn, try_rebias); | |
3360 | |
3361 // The epoch of the current bias is still valid but we know nothing | |
3362 // about the owner; it might be set or it might be clear. Try to | |
3363 // acquire the bias of the object using an atomic operation. If this | |
3364 // fails we will go in to the runtime to revoke the object's bias. | |
3365 // Note that we first construct the presumed unbiased header so we | |
3366 // don't accidentally blow away another thread's valid bias. | |
3367 delayed()->and3(mark_reg, | |
3368 markOopDesc::biased_lock_mask_in_place | markOopDesc::age_mask_in_place | markOopDesc::epoch_mask_in_place, | |
3369 mark_reg); | |
3370 or3(G2_thread, mark_reg, temp_reg); | |
420
a1980da045cc
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
356
diff
changeset
|
3371 casn(mark_addr.base(), mark_reg, temp_reg); |
0 | 3372 // If the biasing toward our thread failed, this means that |
3373 // another thread succeeded in biasing it toward itself and we | |
3374 // need to revoke that bias. The revocation will occur in the | |
3375 // interpreter runtime in the slow case. | |
3376 cmp(mark_reg, temp_reg); | |
3377 if (counters != NULL) { | |
3378 cond_inc(Assembler::zero, (address) counters->anonymously_biased_lock_entry_count_addr(), mark_reg, temp_reg); | |
3379 } | |
3380 if (slow_case != NULL) { | |
3381 brx(Assembler::notEqual, true, Assembler::pn, *slow_case); | |
3382 delayed()->nop(); | |
3383 } | |
3839 | 3384 ba_short(done); |
0 | 3385 |
3386 bind(try_rebias); | |
3387 // At this point we know the epoch has expired, meaning that the | |
3388 // current "bias owner", if any, is actually invalid. Under these | |
3389 // circumstances _only_, we are allowed to use the current header's | |
3390 // value as the comparison value when doing the cas to acquire the | |
3391 // bias in the current epoch. In other words, we allow transfer of | |
3392 // the bias from one thread to another directly in this situation. | |
3393 // | |
3394 // FIXME: due to a lack of registers we currently blow away the age | |
3395 // bits in this situation. Should attempt to preserve them. | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
3396 load_klass(obj_reg, temp_reg); |
4762
069ab3f976d3
7118863: Move sizeof(klassOopDesc) into the *Klass::*_offset_in_bytes() functions
stefank
parents:
3938
diff
changeset
|
3397 ld_ptr(Address(temp_reg, Klass::prototype_header_offset()), temp_reg); |
0 | 3398 or3(G2_thread, temp_reg, temp_reg); |
420
a1980da045cc
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
356
diff
changeset
|
3399 casn(mark_addr.base(), mark_reg, temp_reg); |
0 | 3400 // If the biasing toward our thread failed, this means that |
3401 // another thread succeeded in biasing it toward itself and we | |
3402 // need to revoke that bias. The revocation will occur in the | |
3403 // interpreter runtime in the slow case. | |
3404 cmp(mark_reg, temp_reg); | |
3405 if (counters != NULL) { | |
3406 cond_inc(Assembler::zero, (address) counters->rebiased_lock_entry_count_addr(), mark_reg, temp_reg); | |
3407 } | |
3408 if (slow_case != NULL) { | |
3409 brx(Assembler::notEqual, true, Assembler::pn, *slow_case); | |
3410 delayed()->nop(); | |
3411 } | |
3839 | 3412 ba_short(done); |
0 | 3413 |
3414 bind(try_revoke_bias); | |
3415 // The prototype mark in the klass doesn't have the bias bit set any | |
3416 // more, indicating that objects of this data type are not supposed | |
3417 // to be biased any more. We are going to try to reset the mark of | |
3418 // this object to the prototype value and fall through to the | |
3419 // CAS-based locking scheme. Note that if our CAS fails, it means | |
3420 // that another thread raced us for the privilege of revoking the | |
3421 // bias of this particular object, so it's okay to continue in the | |
3422 // normal locking code. | |
3423 // | |
3424 // FIXME: due to a lack of registers we currently blow away the age | |
3425 // bits in this situation. Should attempt to preserve them. | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
3426 load_klass(obj_reg, temp_reg); |
4762
069ab3f976d3
7118863: Move sizeof(klassOopDesc) into the *Klass::*_offset_in_bytes() functions
stefank
parents:
3938
diff
changeset
|
3427 ld_ptr(Address(temp_reg, Klass::prototype_header_offset()), temp_reg); |
420
a1980da045cc
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
356
diff
changeset
|
3428 casn(mark_addr.base(), mark_reg, temp_reg); |
0 | 3429 // Fall through to the normal CAS-based lock, because no matter what |
3430 // the result of the above CAS, some thread must have succeeded in | |
3431 // removing the bias bit from the object's header. | |
3432 if (counters != NULL) { | |
3433 cmp(mark_reg, temp_reg); | |
3434 cond_inc(Assembler::zero, (address) counters->revoked_lock_entry_count_addr(), mark_reg, temp_reg); | |
3435 } | |
3436 | |
3437 bind(cas_label); | |
3438 } | |
3439 | |
3440 void MacroAssembler::biased_locking_exit (Address mark_addr, Register temp_reg, Label& done, | |
3441 bool allow_delay_slot_filling) { | |
3442 // Check for biased locking unlock case, which is a no-op | |
3443 // Note: we do not have to check the thread ID for two reasons. | |
3444 // First, the interpreter checks for IllegalMonitorStateException at | |
3445 // a higher level. Second, if the bias was revoked while we held the | |
3446 // lock, the object could not be rebiased toward another thread, so | |
3447 // the bias bit would be clear. | |
3448 ld_ptr(mark_addr, temp_reg); | |
3449 and3(temp_reg, markOopDesc::biased_lock_mask_in_place, temp_reg); | |
3450 cmp(temp_reg, markOopDesc::biased_lock_pattern); | |
3451 brx(Assembler::equal, allow_delay_slot_filling, Assembler::pt, done); | |
3452 delayed(); | |
3453 if (!allow_delay_slot_filling) { | |
3454 nop(); | |
3455 } | |
3456 } | |
3457 | |
3458 | |
3459 // CASN -- 32-64 bit switch hitter similar to the synthetic CASN provided by | |
3460 // Solaris/SPARC's "as". Another apt name would be cas_ptr() | |
3461 | |
3462 void MacroAssembler::casn (Register addr_reg, Register cmp_reg, Register set_reg ) { | |
3839 | 3463 casx_under_lock (addr_reg, cmp_reg, set_reg, (address)StubRoutines::Sparc::atomic_memory_operation_lock_addr()); |
0 | 3464 } |
3465 | |
3466 | |
3467 | |
3468 // compiler_lock_object() and compiler_unlock_object() are direct transliterations | |
3469 // of i486.ad fast_lock() and fast_unlock(). See those methods for detailed comments. | |
3470 // The code could be tightened up considerably. | |
3471 // | |
3472 // box->dhw disposition - post-conditions at DONE_LABEL. | |
3473 // - Successful inflated lock: box->dhw != 0. | |
3474 // Any non-zero value suffices. | |
3475 // Consider G2_thread, rsp, boxReg, or unused_mark() | |
3476 // - Successful Stack-lock: box->dhw == mark. | |
3477 // box->dhw must contain the displaced mark word value | |
3478 // - Failure -- icc.ZFlag == 0 and box->dhw is undefined. | |
3479 // The slow-path fast_enter() and slow_enter() operators | |
3480 // are responsible for setting box->dhw = NonZero (typically ::unused_mark). | |
3481 // - Biased: box->dhw is undefined | |
3482 // | |
3483 // SPARC refworkload performance - specifically jetstream and scimark - are | |
3484 // extremely sensitive to the size of the code emitted by compiler_lock_object | |
3485 // and compiler_unlock_object. Critically, the key factor is code size, not path | |
3486 // length. (Simply experiments to pad CLO with unexecuted NOPs demonstrte the | |
3487 // effect). | |
3488 | |
3489 | |
420
a1980da045cc
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
356
diff
changeset
|
3490 void MacroAssembler::compiler_lock_object(Register Roop, Register Rmark, |
a1980da045cc
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
356
diff
changeset
|
3491 Register Rbox, Register Rscratch, |
a1980da045cc
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
356
diff
changeset
|
3492 BiasedLockingCounters* counters, |
a1980da045cc
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
356
diff
changeset
|
3493 bool try_bias) { |
727 | 3494 Address mark_addr(Roop, oopDesc::mark_offset_in_bytes()); |
0 | 3495 |
3496 verify_oop(Roop); | |
3497 Label done ; | |
3498 | |
3499 if (counters != NULL) { | |
3500 inc_counter((address) counters->total_entry_count_addr(), Rmark, Rscratch); | |
3501 } | |
3502 | |
3503 if (EmitSync & 1) { | |
3839 | 3504 mov(3, Rscratch); |
3505 st_ptr(Rscratch, Rbox, BasicLock::displaced_header_offset_in_bytes()); | |
3506 cmp(SP, G0); | |
0 | 3507 return ; |
3508 } | |
3509 | |
3510 if (EmitSync & 2) { | |
3511 | |
3512 // Fetch object's markword | |
3513 ld_ptr(mark_addr, Rmark); | |
3514 | |
420
a1980da045cc
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
356
diff
changeset
|
3515 if (try_bias) { |
0 | 3516 biased_locking_enter(Roop, Rmark, Rscratch, done, NULL, counters); |
3517 } | |
3518 | |
3519 // Save Rbox in Rscratch to be used for the cas operation | |
3520 mov(Rbox, Rscratch); | |
3521 | |
3522 // set Rmark to markOop | markOopDesc::unlocked_value | |
3523 or3(Rmark, markOopDesc::unlocked_value, Rmark); | |
3524 | |
3525 // Initialize the box. (Must happen before we update the object mark!) | |
3526 st_ptr(Rmark, Rbox, BasicLock::displaced_header_offset_in_bytes()); | |
3527 | |
3528 // compare object markOop with Rmark and if equal exchange Rscratch with object markOop | |
3529 assert(mark_addr.disp() == 0, "cas must take a zero displacement"); | |
3530 casx_under_lock(mark_addr.base(), Rmark, Rscratch, | |
3531 (address)StubRoutines::Sparc::atomic_memory_operation_lock_addr()); | |
3532 | |
3533 // if compare/exchange succeeded we found an unlocked object and we now have locked it | |
3534 // hence we are done | |
3535 cmp(Rmark, Rscratch); | |
3536 #ifdef _LP64 | |
3537 sub(Rscratch, STACK_BIAS, Rscratch); | |
3538 #endif | |
3539 brx(Assembler::equal, false, Assembler::pt, done); | |
3540 delayed()->sub(Rscratch, SP, Rscratch); //pull next instruction into delay slot | |
3541 | |
3542 // we did not find an unlocked object so see if this is a recursive case | |
3543 // sub(Rscratch, SP, Rscratch); | |
3544 assert(os::vm_page_size() > 0xfff, "page size too small - change the constant"); | |
3545 andcc(Rscratch, 0xfffff003, Rscratch); | |
3546 st_ptr(Rscratch, Rbox, BasicLock::displaced_header_offset_in_bytes()); | |
3839 | 3547 bind (done); |
0 | 3548 return ; |
3549 } | |
3550 | |
3551 Label Egress ; | |
3552 | |
3553 if (EmitSync & 256) { | |
3554 Label IsInflated ; | |
3555 | |
3839 | 3556 ld_ptr(mark_addr, Rmark); // fetch obj->mark |
0 | 3557 // Triage: biased, stack-locked, neutral, inflated |
420
a1980da045cc
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
356
diff
changeset
|
3558 if (try_bias) { |
0 | 3559 biased_locking_enter(Roop, Rmark, Rscratch, done, NULL, counters); |
3560 // Invariant: if control reaches this point in the emitted stream | |
3561 // then Rmark has not been modified. | |
3562 } | |
3563 | |
3564 // Store mark into displaced mark field in the on-stack basic-lock "box" | |
3565 // Critically, this must happen before the CAS | |
3566 // Maximize the ST-CAS distance to minimize the ST-before-CAS penalty. | |
3839 | 3567 st_ptr(Rmark, Rbox, BasicLock::displaced_header_offset_in_bytes()); |
3568 andcc(Rmark, 2, G0); | |
3569 brx(Assembler::notZero, false, Assembler::pn, IsInflated); | |
3570 delayed()-> | |
0 | 3571 |
3572 // Try stack-lock acquisition. | |
3573 // Beware: the 1st instruction is in a delay slot | |
3839 | 3574 mov(Rbox, Rscratch); |
3575 or3(Rmark, markOopDesc::unlocked_value, Rmark); | |
3576 assert(mark_addr.disp() == 0, "cas must take a zero displacement"); | |
3577 casn(mark_addr.base(), Rmark, Rscratch); | |
3578 cmp(Rmark, Rscratch); | |
3579 brx(Assembler::equal, false, Assembler::pt, done); | |
0 | 3580 delayed()->sub(Rscratch, SP, Rscratch); |
3581 | |
3582 // Stack-lock attempt failed - check for recursive stack-lock. | |
3583 // See the comments below about how we might remove this case. | |
3584 #ifdef _LP64 | |
3839 | 3585 sub(Rscratch, STACK_BIAS, Rscratch); |
0 | 3586 #endif |
3587 assert(os::vm_page_size() > 0xfff, "page size too small - change the constant"); | |
3839 | 3588 andcc(Rscratch, 0xfffff003, Rscratch); |
3589 br(Assembler::always, false, Assembler::pt, done); | |
3590 delayed()-> st_ptr(Rscratch, Rbox, BasicLock::displaced_header_offset_in_bytes()); | |
3591 | |
3592 bind(IsInflated); | |
0 | 3593 if (EmitSync & 64) { |
3594 // If m->owner != null goto IsLocked | |
3595 // Pessimistic form: Test-and-CAS vs CAS | |
3596 // The optimistic form avoids RTS->RTO cache line upgrades. | |
3839 | 3597 ld_ptr(Rmark, ObjectMonitor::owner_offset_in_bytes() - 2, Rscratch); |
3598 andcc(Rscratch, Rscratch, G0); | |
3599 brx(Assembler::notZero, false, Assembler::pn, done); | |
3600 delayed()->nop(); | |
0 | 3601 // m->owner == null : it's unlocked. |
3602 } | |
3603 | |
3604 // Try to CAS m->owner from null to Self | |
3605 // Invariant: if we acquire the lock then _recursions should be 0. | |
3839 | 3606 add(Rmark, ObjectMonitor::owner_offset_in_bytes()-2, Rmark); |
3607 mov(G2_thread, Rscratch); | |
3608 casn(Rmark, G0, Rscratch); | |
3609 cmp(Rscratch, G0); | |
0 | 3610 // Intentional fall-through into done |
3611 } else { | |
3612 // Aggressively avoid the Store-before-CAS penalty | |
3613 // Defer the store into box->dhw until after the CAS | |
3614 Label IsInflated, Recursive ; | |
3615 | |
3616 // Anticipate CAS -- Avoid RTS->RTO upgrade | |
3839 | 3617 // prefetch (mark_addr, Assembler::severalWritesAndPossiblyReads); |
3618 | |
3619 ld_ptr(mark_addr, Rmark); // fetch obj->mark | |
0 | 3620 // Triage: biased, stack-locked, neutral, inflated |
3621 | |
420
a1980da045cc
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
356
diff
changeset
|
3622 if (try_bias) { |
0 | 3623 biased_locking_enter(Roop, Rmark, Rscratch, done, NULL, counters); |
3624 // Invariant: if control reaches this point in the emitted stream | |
3625 // then Rmark has not been modified. | |
3626 } | |
3839 | 3627 andcc(Rmark, 2, G0); |
3628 brx(Assembler::notZero, false, Assembler::pn, IsInflated); | |
0 | 3629 delayed()-> // Beware - dangling delay-slot |
3630 | |
3631 // Try stack-lock acquisition. | |
3632 // Transiently install BUSY (0) encoding in the mark word. | |
3633 // if the CAS of 0 into the mark was successful then we execute: | |
3634 // ST box->dhw = mark -- save fetched mark in on-stack basiclock box | |
3635 // ST obj->mark = box -- overwrite transient 0 value | |
3636 // This presumes TSO, of course. | |
3637 | |
3839 | 3638 mov(0, Rscratch); |
3639 or3(Rmark, markOopDesc::unlocked_value, Rmark); | |
3640 assert(mark_addr.disp() == 0, "cas must take a zero displacement"); | |
3641 casn(mark_addr.base(), Rmark, Rscratch); | |
3642 // prefetch (mark_addr, Assembler::severalWritesAndPossiblyReads); | |
3643 cmp(Rscratch, Rmark); | |
3644 brx(Assembler::notZero, false, Assembler::pn, Recursive); | |
3645 delayed()->st_ptr(Rmark, Rbox, BasicLock::displaced_header_offset_in_bytes()); | |
0 | 3646 if (counters != NULL) { |
3647 cond_inc(Assembler::equal, (address) counters->fast_path_entry_count_addr(), Rmark, Rscratch); | |
3648 } | |
3839 | 3649 ba(done); |
3650 delayed()->st_ptr(Rbox, mark_addr); | |
3651 | |
3652 bind(Recursive); | |
0 | 3653 // Stack-lock attempt failed - check for recursive stack-lock. |
3654 // Tests show that we can remove the recursive case with no impact | |
3655 // on refworkload 0.83. If we need to reduce the size of the code | |
3656 // emitted by compiler_lock_object() the recursive case is perfect | |
3657 // candidate. | |
3658 // | |
3659 // A more extreme idea is to always inflate on stack-lock recursion. | |
3660 // This lets us eliminate the recursive checks in compiler_lock_object | |
3661 // and compiler_unlock_object and the (box->dhw == 0) encoding. | |
3662 // A brief experiment - requiring changes to synchronizer.cpp, interpreter, | |
3663 // and showed a performance *increase*. In the same experiment I eliminated | |
3664 // the fast-path stack-lock code from the interpreter and always passed | |
3665 // control to the "slow" operators in synchronizer.cpp. | |
3666 | |
3667 // RScratch contains the fetched obj->mark value from the failed CASN. | |
3668 #ifdef _LP64 | |
3839 | 3669 sub(Rscratch, STACK_BIAS, Rscratch); |
0 | 3670 #endif |
3671 sub(Rscratch, SP, Rscratch); | |
3672 assert(os::vm_page_size() > 0xfff, "page size too small - change the constant"); | |
3839 | 3673 andcc(Rscratch, 0xfffff003, Rscratch); |
0 | 3674 if (counters != NULL) { |
3675 // Accounting needs the Rscratch register | |
3839 | 3676 st_ptr(Rscratch, Rbox, BasicLock::displaced_header_offset_in_bytes()); |
0 | 3677 cond_inc(Assembler::equal, (address) counters->fast_path_entry_count_addr(), Rmark, Rscratch); |
3839 | 3678 ba_short(done); |
0 | 3679 } else { |
3839 | 3680 ba(done); |
3681 delayed()->st_ptr(Rscratch, Rbox, BasicLock::displaced_header_offset_in_bytes()); | |
0 | 3682 } |
3683 | |
3839 | 3684 bind (IsInflated); |
0 | 3685 if (EmitSync & 64) { |
3686 // If m->owner != null goto IsLocked | |
3687 // Test-and-CAS vs CAS | |
3688 // Pessimistic form avoids futile (doomed) CAS attempts | |
3689 // The optimistic form avoids RTS->RTO cache line upgrades. | |
3839 | 3690 ld_ptr(Rmark, ObjectMonitor::owner_offset_in_bytes() - 2, Rscratch); |
3691 andcc(Rscratch, Rscratch, G0); | |
3692 brx(Assembler::notZero, false, Assembler::pn, done); | |
3693 delayed()->nop(); | |
0 | 3694 // m->owner == null : it's unlocked. |
3695 } | |
3696 | |
3697 // Try to CAS m->owner from null to Self | |
3698 // Invariant: if we acquire the lock then _recursions should be 0. | |
3839 | 3699 add(Rmark, ObjectMonitor::owner_offset_in_bytes()-2, Rmark); |
3700 mov(G2_thread, Rscratch); | |
3701 casn(Rmark, G0, Rscratch); | |
3702 cmp(Rscratch, G0); | |
0 | 3703 // ST box->displaced_header = NonZero. |
3704 // Any non-zero value suffices: | |
3705 // unused_mark(), G2_thread, RBox, RScratch, rsp, etc. | |
3839 | 3706 st_ptr(Rbox, Rbox, BasicLock::displaced_header_offset_in_bytes()); |
0 | 3707 // Intentional fall-through into done |
3708 } | |
3709 | |
3839 | 3710 bind (done); |
0 | 3711 } |
3712 | |
420
a1980da045cc
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
356
diff
changeset
|
3713 void MacroAssembler::compiler_unlock_object(Register Roop, Register Rmark, |
a1980da045cc
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
356
diff
changeset
|
3714 Register Rbox, Register Rscratch, |
a1980da045cc
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
356
diff
changeset
|
3715 bool try_bias) { |
727 | 3716 Address mark_addr(Roop, oopDesc::mark_offset_in_bytes()); |
0 | 3717 |
3718 Label done ; | |
3719 | |
3720 if (EmitSync & 4) { | |
3839 | 3721 cmp(SP, G0); |
0 | 3722 return ; |
3723 } | |
3724 | |
3725 if (EmitSync & 8) { | |
420
a1980da045cc
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
356
diff
changeset
|
3726 if (try_bias) { |
0 | 3727 biased_locking_exit(mark_addr, Rscratch, done); |
3728 } | |
3729 | |
3730 // Test first if it is a fast recursive unlock | |
3731 ld_ptr(Rbox, BasicLock::displaced_header_offset_in_bytes(), Rmark); | |
3839 | 3732 br_null_short(Rmark, Assembler::pt, done); |
0 | 3733 |
3734 // Check if it is still a light weight lock, this is is true if we see | |
3735 // the stack address of the basicLock in the markOop of the object | |
3736 assert(mark_addr.disp() == 0, "cas must take a zero displacement"); | |
3737 casx_under_lock(mark_addr.base(), Rbox, Rmark, | |
3738 (address)StubRoutines::Sparc::atomic_memory_operation_lock_addr()); | |
3839 | 3739 ba(done); |
0 | 3740 delayed()->cmp(Rbox, Rmark); |
3839 | 3741 bind(done); |
0 | 3742 return ; |
3743 } | |
3744 | |
3745 // Beware ... If the aggregate size of the code emitted by CLO and CUO is | |
3746 // is too large performance rolls abruptly off a cliff. | |
3747 // This could be related to inlining policies, code cache management, or | |
3748 // I$ effects. | |
3749 Label LStacked ; | |
3750 | |
420
a1980da045cc
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
356
diff
changeset
|
3751 if (try_bias) { |
0 | 3752 // TODO: eliminate redundant LDs of obj->mark |
3753 biased_locking_exit(mark_addr, Rscratch, done); | |
3754 } | |
3755 | |
3839 | 3756 ld_ptr(Roop, oopDesc::mark_offset_in_bytes(), Rmark); |
3757 ld_ptr(Rbox, BasicLock::displaced_header_offset_in_bytes(), Rscratch); | |
3758 andcc(Rscratch, Rscratch, G0); | |
3759 brx(Assembler::zero, false, Assembler::pn, done); | |
3760 delayed()->nop(); // consider: relocate fetch of mark, above, into this DS | |
3761 andcc(Rmark, 2, G0); | |
3762 brx(Assembler::zero, false, Assembler::pt, LStacked); | |
3763 delayed()->nop(); | |
0 | 3764 |
3765 // It's inflated | |
3766 // Conceptually we need a #loadstore|#storestore "release" MEMBAR before | |
3767 // the ST of 0 into _owner which releases the lock. This prevents loads | |
3768 // and stores within the critical section from reordering (floating) | |
3769 // past the store that releases the lock. But TSO is a strong memory model | |
3770 // and that particular flavor of barrier is a noop, so we can safely elide it. | |
3771 // Note that we use 1-0 locking by default for the inflated case. We | |
3772 // close the resultant (and rare) race by having contented threads in | |
3773 // monitorenter periodically poll _owner. | |
3839 | 3774 ld_ptr(Rmark, ObjectMonitor::owner_offset_in_bytes() - 2, Rscratch); |
3775 ld_ptr(Rmark, ObjectMonitor::recursions_offset_in_bytes() - 2, Rbox); | |
3776 xor3(Rscratch, G2_thread, Rscratch); | |
3777 orcc(Rbox, Rscratch, Rbox); | |
3778 brx(Assembler::notZero, false, Assembler::pn, done); | |
0 | 3779 delayed()-> |
3839 | 3780 ld_ptr(Rmark, ObjectMonitor::EntryList_offset_in_bytes() - 2, Rscratch); |
3781 ld_ptr(Rmark, ObjectMonitor::cxq_offset_in_bytes() - 2, Rbox); | |
3782 orcc(Rbox, Rscratch, G0); | |
0 | 3783 if (EmitSync & 65536) { |
3784 Label LSucc ; | |
3839 | 3785 brx(Assembler::notZero, false, Assembler::pn, LSucc); |
3786 delayed()->nop(); | |
3787 ba(done); | |
3788 delayed()->st_ptr(G0, Rmark, ObjectMonitor::owner_offset_in_bytes() - 2); | |
3789 | |
3790 bind(LSucc); | |
3791 st_ptr(G0, Rmark, ObjectMonitor::owner_offset_in_bytes() - 2); | |
3792 if (os::is_MP()) { membar (StoreLoad); } | |
3793 ld_ptr(Rmark, ObjectMonitor::succ_offset_in_bytes() - 2, Rscratch); | |
3794 andcc(Rscratch, Rscratch, G0); | |
3795 brx(Assembler::notZero, false, Assembler::pt, done); | |
3796 delayed()->andcc(G0, G0, G0); | |
3797 add(Rmark, ObjectMonitor::owner_offset_in_bytes()-2, Rmark); | |
3798 mov(G2_thread, Rscratch); | |
3799 casn(Rmark, G0, Rscratch); | |
0 | 3800 // invert icc.zf and goto done |
3839 | 3801 br_notnull(Rscratch, false, Assembler::pt, done); |
3802 delayed()->cmp(G0, G0); | |
3803 ba(done); | |
3804 delayed()->cmp(G0, 1); | |
0 | 3805 } else { |
3839 | 3806 brx(Assembler::notZero, false, Assembler::pn, done); |
3807 delayed()->nop(); | |
3808 ba(done); | |
3809 delayed()->st_ptr(G0, Rmark, ObjectMonitor::owner_offset_in_bytes() - 2); | |
0 | 3810 } |
3811 | |
3839 | 3812 bind (LStacked); |
0 | 3813 // Consider: we could replace the expensive CAS in the exit |
3814 // path with a simple ST of the displaced mark value fetched from | |
3815 // the on-stack basiclock box. That admits a race where a thread T2 | |
3816 // in the slow lock path -- inflating with monitor M -- could race a | |
3817 // thread T1 in the fast unlock path, resulting in a missed wakeup for T2. | |
3818 // More precisely T1 in the stack-lock unlock path could "stomp" the | |
3819 // inflated mark value M installed by T2, resulting in an orphan | |
3820 // object monitor M and T2 becoming stranded. We can remedy that situation | |
3821 // by having T2 periodically poll the object's mark word using timed wait | |
3822 // operations. If T2 discovers that a stomp has occurred it vacates | |
3823 // the monitor M and wakes any other threads stranded on the now-orphan M. | |
3824 // In addition the monitor scavenger, which performs deflation, | |
3825 // would also need to check for orpan monitors and stranded threads. | |
3826 // | |
3827 // Finally, inflation is also used when T2 needs to assign a hashCode | |
3828 // to O and O is stack-locked by T1. The "stomp" race could cause | |
3829 // an assigned hashCode value to be lost. We can avoid that condition | |
3830 // and provide the necessary hashCode stability invariants by ensuring | |
3831 // that hashCode generation is idempotent between copying GCs. | |
3832 // For example we could compute the hashCode of an object O as | |
3833 // O's heap address XOR some high quality RNG value that is refreshed | |
3834 // at GC-time. The monitor scavenger would install the hashCode | |
3835 // found in any orphan monitors. Again, the mechanism admits a | |
3836 // lost-update "stomp" WAW race but detects and recovers as needed. | |
3837 // | |
3838 // A prototype implementation showed excellent results, although | |
3839 // the scavenger and timeout code was rather involved. | |
3840 | |
3839 | 3841 casn(mark_addr.base(), Rbox, Rscratch); |
3842 cmp(Rbox, Rscratch); | |
0 | 3843 // Intentional fall through into done ... |
3844 | |
3839 | 3845 bind(done); |
0 | 3846 } |
3847 | |
3848 | |
3849 | |
3850 void MacroAssembler::print_CPU_state() { | |
3851 // %%%%% need to implement this | |
3852 } | |
3853 | |
3854 void MacroAssembler::verify_FPU(int stack_depth, const char* s) { | |
3855 // %%%%% need to implement this | |
3856 } | |
3857 | |
3858 void MacroAssembler::push_IU_state() { | |
3859 // %%%%% need to implement this | |
3860 } | |
3861 | |
3862 | |
3863 void MacroAssembler::pop_IU_state() { | |
3864 // %%%%% need to implement this | |
3865 } | |
3866 | |
3867 | |
3868 void MacroAssembler::push_FPU_state() { | |
3869 // %%%%% need to implement this | |
3870 } | |
3871 | |
3872 | |
3873 void MacroAssembler::pop_FPU_state() { | |
3874 // %%%%% need to implement this | |
3875 } | |
3876 | |
3877 | |
3878 void MacroAssembler::push_CPU_state() { | |
3879 // %%%%% need to implement this | |
3880 } | |
3881 | |
3882 | |
3883 void MacroAssembler::pop_CPU_state() { | |
3884 // %%%%% need to implement this | |
3885 } | |
3886 | |
3887 | |
3888 | |
3889 void MacroAssembler::verify_tlab() { | |
3890 #ifdef ASSERT | |
3891 if (UseTLAB && VerifyOops) { | |
3892 Label next, next2, ok; | |
3893 Register t1 = L0; | |
3894 Register t2 = L1; | |
3895 Register t3 = L2; | |
3896 | |
3897 save_frame(0); | |
3898 ld_ptr(G2_thread, in_bytes(JavaThread::tlab_top_offset()), t1); | |
3899 ld_ptr(G2_thread, in_bytes(JavaThread::tlab_start_offset()), t2); | |
3900 or3(t1, t2, t3); | |
3839 | 3901 cmp_and_br_short(t1, t2, Assembler::greaterEqual, Assembler::pn, next); |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
4762
diff
changeset
|
3902 STOP("assert(top >= start)"); |
0 | 3903 should_not_reach_here(); |
3904 | |
3905 bind(next); | |
3906 ld_ptr(G2_thread, in_bytes(JavaThread::tlab_top_offset()), t1); | |
3907 ld_ptr(G2_thread, in_bytes(JavaThread::tlab_end_offset()), t2); | |
3908 or3(t3, t2, t3); | |
3839 | 3909 cmp_and_br_short(t1, t2, Assembler::lessEqual, Assembler::pn, next2); |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
4762
diff
changeset
|
3910 STOP("assert(top <= end)"); |
0 | 3911 should_not_reach_here(); |
3912 | |
3913 bind(next2); | |
3914 and3(t3, MinObjAlignmentInBytesMask, t3); | |
3839 | 3915 cmp_and_br_short(t3, 0, Assembler::lessEqual, Assembler::pn, ok); |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
4762
diff
changeset
|
3916 STOP("assert(aligned)"); |
0 | 3917 should_not_reach_here(); |
3918 | |
3919 bind(ok); | |
3920 restore(); | |
3921 } | |
3922 #endif | |
3923 } | |
3924 | |
3925 | |
3926 void MacroAssembler::eden_allocate( | |
3927 Register obj, // result: pointer to object after successful allocation | |
3928 Register var_size_in_bytes, // object size in bytes if unknown at compile time; invalid otherwise | |
3929 int con_size_in_bytes, // object size in bytes if known at compile time | |
3930 Register t1, // temp register | |
3931 Register t2, // temp register | |
3932 Label& slow_case // continuation point if fast allocation fails | |
3933 ){ | |
3934 // make sure arguments make sense | |
3935 assert_different_registers(obj, var_size_in_bytes, t1, t2); | |
3936 assert(0 <= con_size_in_bytes && Assembler::is_simm13(con_size_in_bytes), "illegal object size"); | |
3937 assert((con_size_in_bytes & MinObjAlignmentInBytesMask) == 0, "object size is not multiple of alignment"); | |
3938 | |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
3939 if (CMSIncrementalMode || !Universe::heap()->supports_inline_contig_alloc()) { |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
3940 // No allocation in the shared eden. |
3839 | 3941 ba_short(slow_case); |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
3942 } else { |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
3943 // get eden boundaries |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
3944 // note: we need both top & top_addr! |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
3945 const Register top_addr = t1; |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
3946 const Register end = t2; |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
3947 |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
3948 CollectedHeap* ch = Universe::heap(); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
3949 set((intx)ch->top_addr(), top_addr); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
3950 intx delta = (intx)ch->end_addr() - (intx)ch->top_addr(); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
3951 ld_ptr(top_addr, delta, end); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
3952 ld_ptr(top_addr, 0, obj); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
3953 |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
3954 // try to allocate |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
3955 Label retry; |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
3956 bind(retry); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
3957 #ifdef ASSERT |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
3958 // make sure eden top is properly aligned |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
3959 { |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
3960 Label L; |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
3961 btst(MinObjAlignmentInBytesMask, obj); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
3962 br(Assembler::zero, false, Assembler::pt, L); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
3963 delayed()->nop(); |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
4762
diff
changeset
|
3964 STOP("eden top is not properly aligned"); |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
3965 bind(L); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
3966 } |
0 | 3967 #endif // ASSERT |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
3968 const Register free = end; |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
3969 sub(end, obj, free); // compute amount of free space |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
3970 if (var_size_in_bytes->is_valid()) { |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
3971 // size is unknown at compile time |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
3972 cmp(free, var_size_in_bytes); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
3973 br(Assembler::lessUnsigned, false, Assembler::pn, slow_case); // if there is not enough space go the slow case |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
3974 delayed()->add(obj, var_size_in_bytes, end); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
3975 } else { |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
3976 // size is known at compile time |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
3977 cmp(free, con_size_in_bytes); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
3978 br(Assembler::lessUnsigned, false, Assembler::pn, slow_case); // if there is not enough space go the slow case |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
3979 delayed()->add(obj, con_size_in_bytes, end); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
3980 } |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
3981 // Compare obj with the value at top_addr; if still equal, swap the value of |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
3982 // end with the value at top_addr. If not equal, read the value at top_addr |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
3983 // into end. |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
3984 casx_under_lock(top_addr, obj, end, (address)StubRoutines::Sparc::atomic_memory_operation_lock_addr()); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
3985 // if someone beat us on the allocation, try again, otherwise continue |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
3986 cmp(obj, end); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
3987 brx(Assembler::notEqual, false, Assembler::pn, retry); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
3988 delayed()->mov(end, obj); // nop if successfull since obj == end |
0 | 3989 |
3990 #ifdef ASSERT | |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
3991 // make sure eden top is properly aligned |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
3992 { |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
3993 Label L; |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
3994 const Register top_addr = t1; |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
3995 |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
3996 set((intx)ch->top_addr(), top_addr); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
3997 ld_ptr(top_addr, 0, top_addr); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
3998 btst(MinObjAlignmentInBytesMask, top_addr); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
3999 br(Assembler::zero, false, Assembler::pt, L); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4000 delayed()->nop(); |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
4762
diff
changeset
|
4001 STOP("eden top is not properly aligned"); |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4002 bind(L); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4003 } |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4004 #endif // ASSERT |
0 | 4005 } |
4006 } | |
4007 | |
4008 | |
4009 void MacroAssembler::tlab_allocate( | |
4010 Register obj, // result: pointer to object after successful allocation | |
4011 Register var_size_in_bytes, // object size in bytes if unknown at compile time; invalid otherwise | |
4012 int con_size_in_bytes, // object size in bytes if known at compile time | |
4013 Register t1, // temp register | |
4014 Label& slow_case // continuation point if fast allocation fails | |
4015 ){ | |
4016 // make sure arguments make sense | |
4017 assert_different_registers(obj, var_size_in_bytes, t1); | |
4018 assert(0 <= con_size_in_bytes && is_simm13(con_size_in_bytes), "illegal object size"); | |
4019 assert((con_size_in_bytes & MinObjAlignmentInBytesMask) == 0, "object size is not multiple of alignment"); | |
4020 | |
4021 const Register free = t1; | |
4022 | |
4023 verify_tlab(); | |
4024 | |
4025 ld_ptr(G2_thread, in_bytes(JavaThread::tlab_top_offset()), obj); | |
4026 | |
4027 // calculate amount of free space | |
4028 ld_ptr(G2_thread, in_bytes(JavaThread::tlab_end_offset()), free); | |
4029 sub(free, obj, free); | |
4030 | |
4031 Label done; | |
4032 if (var_size_in_bytes == noreg) { | |
4033 cmp(free, con_size_in_bytes); | |
4034 } else { | |
4035 cmp(free, var_size_in_bytes); | |
4036 } | |
4037 br(Assembler::less, false, Assembler::pn, slow_case); | |
4038 // calculate the new top pointer | |
4039 if (var_size_in_bytes == noreg) { | |
4040 delayed()->add(obj, con_size_in_bytes, free); | |
4041 } else { | |
4042 delayed()->add(obj, var_size_in_bytes, free); | |
4043 } | |
4044 | |
4045 bind(done); | |
4046 | |
4047 #ifdef ASSERT | |
4048 // make sure new free pointer is properly aligned | |
4049 { | |
4050 Label L; | |
4051 btst(MinObjAlignmentInBytesMask, free); | |
4052 br(Assembler::zero, false, Assembler::pt, L); | |
4053 delayed()->nop(); | |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
4762
diff
changeset
|
4054 STOP("updated TLAB free is not properly aligned"); |
0 | 4055 bind(L); |
4056 } | |
4057 #endif // ASSERT | |
4058 | |
4059 // update the tlab top pointer | |
4060 st_ptr(free, G2_thread, in_bytes(JavaThread::tlab_top_offset())); | |
4061 verify_tlab(); | |
4062 } | |
4063 | |
4064 | |
4065 void MacroAssembler::tlab_refill(Label& retry, Label& try_eden, Label& slow_case) { | |
4066 Register top = O0; | |
4067 Register t1 = G1; | |
4068 Register t2 = G3; | |
4069 Register t3 = O1; | |
4070 assert_different_registers(top, t1, t2, t3, G4, G5 /* preserve G4 and G5 */); | |
4071 Label do_refill, discard_tlab; | |
4072 | |
4073 if (CMSIncrementalMode || !Universe::heap()->supports_inline_contig_alloc()) { | |
4074 // No allocation in the shared eden. | |
3839 | 4075 ba_short(slow_case); |
0 | 4076 } |
4077 | |
4078 ld_ptr(G2_thread, in_bytes(JavaThread::tlab_top_offset()), top); | |
4079 ld_ptr(G2_thread, in_bytes(JavaThread::tlab_end_offset()), t1); | |
4080 ld_ptr(G2_thread, in_bytes(JavaThread::tlab_refill_waste_limit_offset()), t2); | |
4081 | |
4082 // calculate amount of free space | |
4083 sub(t1, top, t1); | |
4084 srl_ptr(t1, LogHeapWordSize, t1); | |
4085 | |
4086 // Retain tlab and allocate object in shared space if | |
4087 // the amount free in the tlab is too large to discard. | |
4088 cmp(t1, t2); | |
4089 brx(Assembler::lessEqual, false, Assembler::pt, discard_tlab); | |
4090 | |
4091 // increment waste limit to prevent getting stuck on this slow path | |
4092 delayed()->add(t2, ThreadLocalAllocBuffer::refill_waste_limit_increment(), t2); | |
4093 st_ptr(t2, G2_thread, in_bytes(JavaThread::tlab_refill_waste_limit_offset())); | |
4094 if (TLABStats) { | |
4095 // increment number of slow_allocations | |
4096 ld(G2_thread, in_bytes(JavaThread::tlab_slow_allocations_offset()), t2); | |
4097 add(t2, 1, t2); | |
4098 stw(t2, G2_thread, in_bytes(JavaThread::tlab_slow_allocations_offset())); | |
4099 } | |
3839 | 4100 ba_short(try_eden); |
0 | 4101 |
4102 bind(discard_tlab); | |
4103 if (TLABStats) { | |
4104 // increment number of refills | |
4105 ld(G2_thread, in_bytes(JavaThread::tlab_number_of_refills_offset()), t2); | |
4106 add(t2, 1, t2); | |
4107 stw(t2, G2_thread, in_bytes(JavaThread::tlab_number_of_refills_offset())); | |
4108 // accumulate wastage | |
4109 ld(G2_thread, in_bytes(JavaThread::tlab_fast_refill_waste_offset()), t2); | |
4110 add(t2, t1, t2); | |
4111 stw(t2, G2_thread, in_bytes(JavaThread::tlab_fast_refill_waste_offset())); | |
4112 } | |
4113 | |
4114 // if tlab is currently allocated (top or end != null) then | |
4115 // fill [top, end + alignment_reserve) with array object | |
3839 | 4116 br_null_short(top, Assembler::pn, do_refill); |
0 | 4117 |
4118 set((intptr_t)markOopDesc::prototype()->copy_set_hash(0x2), t2); | |
4119 st_ptr(t2, top, oopDesc::mark_offset_in_bytes()); // set up the mark word | |
4120 // set klass to intArrayKlass | |
4121 sub(t1, typeArrayOopDesc::header_size(T_INT), t1); | |
4122 add(t1, ThreadLocalAllocBuffer::alignment_reserve(), t1); | |
4123 sll_ptr(t1, log2_intptr(HeapWordSize/sizeof(jint)), t1); | |
4124 st(t1, top, arrayOopDesc::length_offset_in_bytes()); | |
167
feeb96a45707
6696264: assert("narrow oop can never be zero") for GCBasher & ParNewGC
coleenp
parents:
164
diff
changeset
|
4125 set((intptr_t)Universe::intArrayKlassObj_addr(), t2); |
feeb96a45707
6696264: assert("narrow oop can never be zero") for GCBasher & ParNewGC
coleenp
parents:
164
diff
changeset
|
4126 ld_ptr(t2, 0, t2); |
feeb96a45707
6696264: assert("narrow oop can never be zero") for GCBasher & ParNewGC
coleenp
parents:
164
diff
changeset
|
4127 // store klass last. concurrent gcs assumes klass length is valid if |
feeb96a45707
6696264: assert("narrow oop can never be zero") for GCBasher & ParNewGC
coleenp
parents:
164
diff
changeset
|
4128 // klass field is not null. |
feeb96a45707
6696264: assert("narrow oop can never be zero") for GCBasher & ParNewGC
coleenp
parents:
164
diff
changeset
|
4129 store_klass(t2, top); |
0 | 4130 verify_oop(top); |
4131 | |
2100
b1a2afa37ec4
7003271: Hotspot should track cumulative Java heap bytes allocated on a per-thread basis
phh
parents:
2008
diff
changeset
|
4132 ld_ptr(G2_thread, in_bytes(JavaThread::tlab_start_offset()), t1); |
b1a2afa37ec4
7003271: Hotspot should track cumulative Java heap bytes allocated on a per-thread basis
phh
parents:
2008
diff
changeset
|
4133 sub(top, t1, t1); // size of tlab's allocated portion |
2127
5577848f5923
7011463: Sparc MacroAssembler::incr_allocated_bytes() needs a RegisterOrConstant argument
phh
parents:
2102
diff
changeset
|
4134 incr_allocated_bytes(t1, t2, t3); |
2100
b1a2afa37ec4
7003271: Hotspot should track cumulative Java heap bytes allocated on a per-thread basis
phh
parents:
2008
diff
changeset
|
4135 |
0 | 4136 // refill the tlab with an eden allocation |
4137 bind(do_refill); | |
4138 ld_ptr(G2_thread, in_bytes(JavaThread::tlab_size_offset()), t1); | |
4139 sll_ptr(t1, LogHeapWordSize, t1); | |
2100
b1a2afa37ec4
7003271: Hotspot should track cumulative Java heap bytes allocated on a per-thread basis
phh
parents:
2008
diff
changeset
|
4140 // allocate new tlab, address returned in top |
0 | 4141 eden_allocate(top, t1, 0, t2, t3, slow_case); |
4142 | |
4143 st_ptr(top, G2_thread, in_bytes(JavaThread::tlab_start_offset())); | |
4144 st_ptr(top, G2_thread, in_bytes(JavaThread::tlab_top_offset())); | |
4145 #ifdef ASSERT | |
4146 // check that tlab_size (t1) is still valid | |
4147 { | |
4148 Label ok; | |
4149 ld_ptr(G2_thread, in_bytes(JavaThread::tlab_size_offset()), t2); | |
4150 sll_ptr(t2, LogHeapWordSize, t2); | |
3839 | 4151 cmp_and_br_short(t1, t2, Assembler::equal, Assembler::pt, ok); |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
4762
diff
changeset
|
4152 STOP("assert(t1 == tlab_size)"); |
0 | 4153 should_not_reach_here(); |
4154 | |
4155 bind(ok); | |
4156 } | |
4157 #endif // ASSERT | |
4158 add(top, t1, top); // t1 is tlab_size | |
4159 sub(top, ThreadLocalAllocBuffer::alignment_reserve_in_bytes(), top); | |
4160 st_ptr(top, G2_thread, in_bytes(JavaThread::tlab_end_offset())); | |
4161 verify_tlab(); | |
3839 | 4162 ba_short(retry); |
0 | 4163 } |
4164 | |
2127
5577848f5923
7011463: Sparc MacroAssembler::incr_allocated_bytes() needs a RegisterOrConstant argument
phh
parents:
2102
diff
changeset
|
4165 void MacroAssembler::incr_allocated_bytes(RegisterOrConstant size_in_bytes, |
5577848f5923
7011463: Sparc MacroAssembler::incr_allocated_bytes() needs a RegisterOrConstant argument
phh
parents:
2102
diff
changeset
|
4166 Register t1, Register t2) { |
2100
b1a2afa37ec4
7003271: Hotspot should track cumulative Java heap bytes allocated on a per-thread basis
phh
parents:
2008
diff
changeset
|
4167 // Bump total bytes allocated by this thread |
b1a2afa37ec4
7003271: Hotspot should track cumulative Java heap bytes allocated on a per-thread basis
phh
parents:
2008
diff
changeset
|
4168 assert(t1->is_global(), "must be global reg"); // so all 64 bits are saved on a context switch |
2127
5577848f5923
7011463: Sparc MacroAssembler::incr_allocated_bytes() needs a RegisterOrConstant argument
phh
parents:
2102
diff
changeset
|
4169 assert_different_registers(size_in_bytes.register_or_noreg(), t1, t2); |
2100
b1a2afa37ec4
7003271: Hotspot should track cumulative Java heap bytes allocated on a per-thread basis
phh
parents:
2008
diff
changeset
|
4170 // v8 support has gone the way of the dodo |
b1a2afa37ec4
7003271: Hotspot should track cumulative Java heap bytes allocated on a per-thread basis
phh
parents:
2008
diff
changeset
|
4171 ldx(G2_thread, in_bytes(JavaThread::allocated_bytes_offset()), t1); |
2127
5577848f5923
7011463: Sparc MacroAssembler::incr_allocated_bytes() needs a RegisterOrConstant argument
phh
parents:
2102
diff
changeset
|
4172 add(t1, ensure_simm13_or_reg(size_in_bytes, t2), t1); |
2100
b1a2afa37ec4
7003271: Hotspot should track cumulative Java heap bytes allocated on a per-thread basis
phh
parents:
2008
diff
changeset
|
4173 stx(t1, G2_thread, in_bytes(JavaThread::allocated_bytes_offset())); |
b1a2afa37ec4
7003271: Hotspot should track cumulative Java heap bytes allocated on a per-thread basis
phh
parents:
2008
diff
changeset
|
4174 } |
b1a2afa37ec4
7003271: Hotspot should track cumulative Java heap bytes allocated on a per-thread basis
phh
parents:
2008
diff
changeset
|
4175 |
0 | 4176 Assembler::Condition MacroAssembler::negate_condition(Assembler::Condition cond) { |
4177 switch (cond) { | |
4178 // Note some conditions are synonyms for others | |
4179 case Assembler::never: return Assembler::always; | |
4180 case Assembler::zero: return Assembler::notZero; | |
4181 case Assembler::lessEqual: return Assembler::greater; | |
4182 case Assembler::less: return Assembler::greaterEqual; | |
4183 case Assembler::lessEqualUnsigned: return Assembler::greaterUnsigned; | |
4184 case Assembler::lessUnsigned: return Assembler::greaterEqualUnsigned; | |
4185 case Assembler::negative: return Assembler::positive; | |
4186 case Assembler::overflowSet: return Assembler::overflowClear; | |
4187 case Assembler::always: return Assembler::never; | |
4188 case Assembler::notZero: return Assembler::zero; | |
4189 case Assembler::greater: return Assembler::lessEqual; | |
4190 case Assembler::greaterEqual: return Assembler::less; | |
4191 case Assembler::greaterUnsigned: return Assembler::lessEqualUnsigned; | |
4192 case Assembler::greaterEqualUnsigned: return Assembler::lessUnsigned; | |
4193 case Assembler::positive: return Assembler::negative; | |
4194 case Assembler::overflowClear: return Assembler::overflowSet; | |
4195 } | |
4196 | |
4197 ShouldNotReachHere(); return Assembler::overflowClear; | |
4198 } | |
4199 | |
4200 void MacroAssembler::cond_inc(Assembler::Condition cond, address counter_ptr, | |
4201 Register Rtmp1, Register Rtmp2 /*, Register Rtmp3, Register Rtmp4 */) { | |
4202 Condition negated_cond = negate_condition(cond); | |
4203 Label L; | |
4204 brx(negated_cond, false, Assembler::pt, L); | |
4205 delayed()->nop(); | |
4206 inc_counter(counter_ptr, Rtmp1, Rtmp2); | |
4207 bind(L); | |
4208 } | |
4209 | |
727 | 4210 void MacroAssembler::inc_counter(address counter_addr, Register Rtmp1, Register Rtmp2) { |
4211 AddressLiteral addrlit(counter_addr); | |
4212 sethi(addrlit, Rtmp1); // Move hi22 bits into temporary register. | |
4213 Address addr(Rtmp1, addrlit.low10()); // Build an address with low10 bits. | |
4214 ld(addr, Rtmp2); | |
0 | 4215 inc(Rtmp2); |
727 | 4216 st(Rtmp2, addr); |
4217 } | |
4218 | |
4219 void MacroAssembler::inc_counter(int* counter_addr, Register Rtmp1, Register Rtmp2) { | |
4220 inc_counter((address) counter_addr, Rtmp1, Rtmp2); | |
0 | 4221 } |
4222 | |
4223 SkipIfEqual::SkipIfEqual( | |
4224 MacroAssembler* masm, Register temp, const bool* flag_addr, | |
4225 Assembler::Condition condition) { | |
4226 _masm = masm; | |
727 | 4227 AddressLiteral flag(flag_addr); |
4228 _masm->sethi(flag, temp); | |
4229 _masm->ldub(temp, flag.low10(), temp); | |
0 | 4230 _masm->tst(temp); |
4231 _masm->br(condition, false, Assembler::pt, _label); | |
4232 _masm->delayed()->nop(); | |
4233 } | |
4234 | |
4235 SkipIfEqual::~SkipIfEqual() { | |
4236 _masm->bind(_label); | |
4237 } | |
4238 | |
4239 | |
4240 // Writes to stack successive pages until offset reached to check for | |
4241 // stack overflow + shadow pages. This clobbers tsp and scratch. | |
4242 void MacroAssembler::bang_stack_size(Register Rsize, Register Rtsp, | |
4243 Register Rscratch) { | |
4244 // Use stack pointer in temp stack pointer | |
4245 mov(SP, Rtsp); | |
4246 | |
4247 // Bang stack for total size given plus stack shadow page size. | |
4248 // Bang one page at a time because a large size can overflow yellow and | |
4249 // red zones (the bang will fail but stack overflow handling can't tell that | |
4250 // it was a stack overflow bang vs a regular segv). | |
4251 int offset = os::vm_page_size(); | |
4252 Register Roffset = Rscratch; | |
4253 | |
4254 Label loop; | |
4255 bind(loop); | |
4256 set((-offset)+STACK_BIAS, Rscratch); | |
4257 st(G0, Rtsp, Rscratch); | |
4258 set(offset, Roffset); | |
4259 sub(Rsize, Roffset, Rsize); | |
4260 cmp(Rsize, G0); | |
4261 br(Assembler::greater, false, Assembler::pn, loop); | |
4262 delayed()->sub(Rtsp, Roffset, Rtsp); | |
4263 | |
4264 // Bang down shadow pages too. | |
4265 // The -1 because we already subtracted 1 page. | |
4266 for (int i = 0; i< StackShadowPages-1; i++) { | |
4267 set((-i*offset)+STACK_BIAS, Rscratch); | |
4268 st(G0, Rtsp, Rscratch); | |
4269 } | |
4270 } | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
4271 |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4272 /////////////////////////////////////////////////////////////////////////////////// |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4273 #ifndef SERIALGC |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4274 |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
4275 static address satb_log_enqueue_with_frame = NULL; |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
4276 static u_char* satb_log_enqueue_with_frame_end = NULL; |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
4277 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
4278 static address satb_log_enqueue_frameless = NULL; |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
4279 static u_char* satb_log_enqueue_frameless_end = NULL; |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4280 |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4281 static int EnqueueCodeSize = 128 DEBUG_ONLY( + 256); // Instructions? |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4282 |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4283 static void generate_satb_log_enqueue(bool with_frame) { |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4284 BufferBlob* bb = BufferBlob::create("enqueue_with_frame", EnqueueCodeSize); |
1748 | 4285 CodeBuffer buf(bb); |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4286 MacroAssembler masm(&buf); |
3839 | 4287 |
4288 #define __ masm. | |
4289 | |
4290 address start = __ pc(); | |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4291 Register pre_val; |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4292 |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4293 Label refill, restart; |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4294 if (with_frame) { |
3839 | 4295 __ save_frame(0); |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4296 pre_val = I0; // Was O0 before the save. |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4297 } else { |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4298 pre_val = O0; |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4299 } |
3888
4fe626cbf0bf
7066841: remove MacroAssembler::br_on_reg_cond() on sparc
johnc
parents:
3839
diff
changeset
|
4300 |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4301 int satb_q_index_byte_offset = |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4302 in_bytes(JavaThread::satb_mark_queue_offset() + |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4303 PtrQueue::byte_offset_of_index()); |
3888
4fe626cbf0bf
7066841: remove MacroAssembler::br_on_reg_cond() on sparc
johnc
parents:
3839
diff
changeset
|
4304 |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4305 int satb_q_buf_byte_offset = |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4306 in_bytes(JavaThread::satb_mark_queue_offset() + |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4307 PtrQueue::byte_offset_of_buf()); |
3888
4fe626cbf0bf
7066841: remove MacroAssembler::br_on_reg_cond() on sparc
johnc
parents:
3839
diff
changeset
|
4308 |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4309 assert(in_bytes(PtrQueue::byte_width_of_index()) == sizeof(intptr_t) && |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4310 in_bytes(PtrQueue::byte_width_of_buf()) == sizeof(intptr_t), |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4311 "check sizes in assembly below"); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4312 |
3839 | 4313 __ bind(restart); |
3888
4fe626cbf0bf
7066841: remove MacroAssembler::br_on_reg_cond() on sparc
johnc
parents:
3839
diff
changeset
|
4314 |
4fe626cbf0bf
7066841: remove MacroAssembler::br_on_reg_cond() on sparc
johnc
parents:
3839
diff
changeset
|
4315 // Load the index into the SATB buffer. PtrQueue::_index is a size_t |
4fe626cbf0bf
7066841: remove MacroAssembler::br_on_reg_cond() on sparc
johnc
parents:
3839
diff
changeset
|
4316 // so ld_ptr is appropriate. |
3839 | 4317 __ ld_ptr(G2_thread, satb_q_index_byte_offset, L0); |
4318 | |
3888
4fe626cbf0bf
7066841: remove MacroAssembler::br_on_reg_cond() on sparc
johnc
parents:
3839
diff
changeset
|
4319 // index == 0? |
4fe626cbf0bf
7066841: remove MacroAssembler::br_on_reg_cond() on sparc
johnc
parents:
3839
diff
changeset
|
4320 __ cmp_and_brx_short(L0, G0, Assembler::equal, Assembler::pn, refill); |
4fe626cbf0bf
7066841: remove MacroAssembler::br_on_reg_cond() on sparc
johnc
parents:
3839
diff
changeset
|
4321 |
4fe626cbf0bf
7066841: remove MacroAssembler::br_on_reg_cond() on sparc
johnc
parents:
3839
diff
changeset
|
4322 __ ld_ptr(G2_thread, satb_q_buf_byte_offset, L1); |
3839 | 4323 __ sub(L0, oopSize, L0); |
4324 | |
4325 __ st_ptr(pre_val, L1, L0); // [_buf + index] := I0 | |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4326 if (!with_frame) { |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4327 // Use return-from-leaf |
3839 | 4328 __ retl(); |
4329 __ delayed()->st_ptr(L0, G2_thread, satb_q_index_byte_offset); | |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4330 } else { |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4331 // Not delayed. |
3839 | 4332 __ st_ptr(L0, G2_thread, satb_q_index_byte_offset); |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4333 } |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4334 if (with_frame) { |
3839 | 4335 __ ret(); |
4336 __ delayed()->restore(); | |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4337 } |
3839 | 4338 __ bind(refill); |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4339 |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4340 address handle_zero = |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4341 CAST_FROM_FN_PTR(address, |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4342 &SATBMarkQueueSet::handle_zero_index_for_thread); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4343 // This should be rare enough that we can afford to save all the |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4344 // scratch registers that the calling context might be using. |
3839 | 4345 __ mov(G1_scratch, L0); |
4346 __ mov(G3_scratch, L1); | |
4347 __ mov(G4, L2); | |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4348 // We need the value of O0 above (for the write into the buffer), so we |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4349 // save and restore it. |
3839 | 4350 __ mov(O0, L3); |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4351 // Since the call will overwrite O7, we save and restore that, as well. |
3839 | 4352 __ mov(O7, L4); |
4353 __ call_VM_leaf(L5, handle_zero, G2_thread); | |
4354 __ mov(L0, G1_scratch); | |
4355 __ mov(L1, G3_scratch); | |
4356 __ mov(L2, G4); | |
4357 __ mov(L3, O0); | |
4358 __ br(Assembler::always, /*annul*/false, Assembler::pt, restart); | |
4359 __ delayed()->mov(L4, O7); | |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4360 |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4361 if (with_frame) { |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4362 satb_log_enqueue_with_frame = start; |
3839 | 4363 satb_log_enqueue_with_frame_end = __ pc(); |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4364 } else { |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4365 satb_log_enqueue_frameless = start; |
3839 | 4366 satb_log_enqueue_frameless_end = __ pc(); |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4367 } |
3839 | 4368 |
4369 #undef __ | |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4370 } |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4371 |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4372 static inline void generate_satb_log_enqueue_if_necessary(bool with_frame) { |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4373 if (with_frame) { |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4374 if (satb_log_enqueue_with_frame == 0) { |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4375 generate_satb_log_enqueue(with_frame); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4376 assert(satb_log_enqueue_with_frame != 0, "postcondition."); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4377 if (G1SATBPrintStubs) { |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4378 tty->print_cr("Generated with-frame satb enqueue:"); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4379 Disassembler::decode((u_char*)satb_log_enqueue_with_frame, |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4380 satb_log_enqueue_with_frame_end, |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4381 tty); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4382 } |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4383 } |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4384 } else { |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4385 if (satb_log_enqueue_frameless == 0) { |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4386 generate_satb_log_enqueue(with_frame); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4387 assert(satb_log_enqueue_frameless != 0, "postcondition."); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4388 if (G1SATBPrintStubs) { |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4389 tty->print_cr("Generated frameless satb enqueue:"); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4390 Disassembler::decode((u_char*)satb_log_enqueue_frameless, |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4391 satb_log_enqueue_frameless_end, |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4392 tty); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4393 } |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4394 } |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4395 } |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4396 } |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4397 |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
4398 void MacroAssembler::g1_write_barrier_pre(Register obj, |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
4399 Register index, |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
4400 int offset, |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
4401 Register pre_val, |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
4402 Register tmp, |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
4403 bool preserve_o_regs) { |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4404 Label filtered; |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
4405 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
4406 if (obj == noreg) { |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
4407 // We are not loading the previous value so make |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
4408 // sure that we don't trash the value in pre_val |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
4409 // with the code below. |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
4410 assert_different_registers(pre_val, tmp); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
4411 } else { |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
4412 // We will be loading the previous value |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
4413 // in this code so... |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
4414 assert(offset == 0 || index == noreg, "choose one"); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
4415 assert(pre_val == noreg, "check this code"); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
4416 } |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
4417 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
4418 // Is marking active? |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4419 if (in_bytes(PtrQueue::byte_width_of_active()) == 4) { |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4420 ld(G2, |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4421 in_bytes(JavaThread::satb_mark_queue_offset() + |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4422 PtrQueue::byte_offset_of_active()), |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4423 tmp); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4424 } else { |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4425 guarantee(in_bytes(PtrQueue::byte_width_of_active()) == 1, |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4426 "Assumption"); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4427 ldsb(G2, |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4428 in_bytes(JavaThread::satb_mark_queue_offset() + |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4429 PtrQueue::byte_offset_of_active()), |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4430 tmp); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4431 } |
845
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
794
diff
changeset
|
4432 |
3888
4fe626cbf0bf
7066841: remove MacroAssembler::br_on_reg_cond() on sparc
johnc
parents:
3839
diff
changeset
|
4433 // Is marking active? |
4fe626cbf0bf
7066841: remove MacroAssembler::br_on_reg_cond() on sparc
johnc
parents:
3839
diff
changeset
|
4434 cmp_and_br_short(tmp, G0, Assembler::equal, Assembler::pt, filtered); |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4435 |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
4436 // Do we need to load the previous value? |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
4437 if (obj != noreg) { |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
4438 // Load the previous value... |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
4439 if (index == noreg) { |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
4440 if (Assembler::is_simm13(offset)) { |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
4441 load_heap_oop(obj, offset, tmp); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
4442 } else { |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
4443 set(offset, tmp); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
4444 load_heap_oop(obj, tmp, tmp); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
4445 } |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4446 } else { |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
4447 load_heap_oop(obj, index, tmp); |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4448 } |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
4449 // Previous value has been loaded into tmp |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
4450 pre_val = tmp; |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4451 } |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4452 |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
4453 assert(pre_val != noreg, "must have a real register"); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
4454 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
4455 // Is the previous value null? |
3888
4fe626cbf0bf
7066841: remove MacroAssembler::br_on_reg_cond() on sparc
johnc
parents:
3839
diff
changeset
|
4456 cmp_and_brx_short(pre_val, G0, Assembler::equal, Assembler::pt, filtered); |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4457 |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4458 // OK, it's not filtered, so we'll need to call enqueue. In the normal |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
4459 // case, pre_val will be a scratch G-reg, but there are some cases in |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
4460 // which it's an O-reg. In the first case, do a normal call. In the |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
4461 // latter, do a save here and call the frameless version. |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4462 |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4463 guarantee(pre_val->is_global() || pre_val->is_out(), |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4464 "Or we need to think harder."); |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
4465 |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4466 if (pre_val->is_global() && !preserve_o_regs) { |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
4467 generate_satb_log_enqueue_if_necessary(true); // with frame |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
4468 |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4469 call(satb_log_enqueue_with_frame); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4470 delayed()->mov(pre_val, O0); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4471 } else { |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
4472 generate_satb_log_enqueue_if_necessary(false); // frameless |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
4473 |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4474 save_frame(0); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4475 call(satb_log_enqueue_frameless); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4476 delayed()->mov(pre_val->after_save(), O0); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4477 restore(); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4478 } |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4479 |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4480 bind(filtered); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4481 } |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4482 |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4483 static address dirty_card_log_enqueue = 0; |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4484 static u_char* dirty_card_log_enqueue_end = 0; |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4485 |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4486 // This gets to assume that o0 contains the object address. |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4487 static void generate_dirty_card_log_enqueue(jbyte* byte_map_base) { |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4488 BufferBlob* bb = BufferBlob::create("dirty_card_enqueue", EnqueueCodeSize*2); |
1748 | 4489 CodeBuffer buf(bb); |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4490 MacroAssembler masm(&buf); |
3839 | 4491 #define __ masm. |
4492 address start = __ pc(); | |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4493 |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4494 Label not_already_dirty, restart, refill; |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4495 |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4496 #ifdef _LP64 |
3839 | 4497 __ srlx(O0, CardTableModRefBS::card_shift, O0); |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4498 #else |
3839 | 4499 __ srl(O0, CardTableModRefBS::card_shift, O0); |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4500 #endif |
727 | 4501 AddressLiteral addrlit(byte_map_base); |
3839 | 4502 __ set(addrlit, O1); // O1 := <card table base> |
4503 __ ldub(O0, O1, O2); // O2 := [O0 + O1] | |
4504 | |
3888
4fe626cbf0bf
7066841: remove MacroAssembler::br_on_reg_cond() on sparc
johnc
parents:
3839
diff
changeset
|
4505 assert(CardTableModRefBS::dirty_card_val() == 0, "otherwise check this code"); |
4fe626cbf0bf
7066841: remove MacroAssembler::br_on_reg_cond() on sparc
johnc
parents:
3839
diff
changeset
|
4506 __ cmp_and_br_short(O2, G0, Assembler::notEqual, Assembler::pt, not_already_dirty); |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4507 |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4508 // We didn't take the branch, so we're already dirty: return. |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4509 // Use return-from-leaf |
3839 | 4510 __ retl(); |
4511 __ delayed()->nop(); | |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4512 |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4513 // Not dirty. |
3839 | 4514 __ bind(not_already_dirty); |
3888
4fe626cbf0bf
7066841: remove MacroAssembler::br_on_reg_cond() on sparc
johnc
parents:
3839
diff
changeset
|
4515 |
4fe626cbf0bf
7066841: remove MacroAssembler::br_on_reg_cond() on sparc
johnc
parents:
3839
diff
changeset
|
4516 // Get O0 + O1 into a reg by itself |
4fe626cbf0bf
7066841: remove MacroAssembler::br_on_reg_cond() on sparc
johnc
parents:
3839
diff
changeset
|
4517 __ add(O0, O1, O3); |
4fe626cbf0bf
7066841: remove MacroAssembler::br_on_reg_cond() on sparc
johnc
parents:
3839
diff
changeset
|
4518 |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4519 // First, dirty it. |
3839 | 4520 __ stb(G0, O3, G0); // [cardPtr] := 0 (i.e., dirty). |
3888
4fe626cbf0bf
7066841: remove MacroAssembler::br_on_reg_cond() on sparc
johnc
parents:
3839
diff
changeset
|
4521 |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4522 int dirty_card_q_index_byte_offset = |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4523 in_bytes(JavaThread::dirty_card_queue_offset() + |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4524 PtrQueue::byte_offset_of_index()); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4525 int dirty_card_q_buf_byte_offset = |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4526 in_bytes(JavaThread::dirty_card_queue_offset() + |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4527 PtrQueue::byte_offset_of_buf()); |
3839 | 4528 __ bind(restart); |
3888
4fe626cbf0bf
7066841: remove MacroAssembler::br_on_reg_cond() on sparc
johnc
parents:
3839
diff
changeset
|
4529 |
4fe626cbf0bf
7066841: remove MacroAssembler::br_on_reg_cond() on sparc
johnc
parents:
3839
diff
changeset
|
4530 // Load the index into the update buffer. PtrQueue::_index is |
4fe626cbf0bf
7066841: remove MacroAssembler::br_on_reg_cond() on sparc
johnc
parents:
3839
diff
changeset
|
4531 // a size_t so ld_ptr is appropriate here. |
3839 | 4532 __ ld_ptr(G2_thread, dirty_card_q_index_byte_offset, L0); |
4533 | |
3888
4fe626cbf0bf
7066841: remove MacroAssembler::br_on_reg_cond() on sparc
johnc
parents:
3839
diff
changeset
|
4534 // index == 0? |
4fe626cbf0bf
7066841: remove MacroAssembler::br_on_reg_cond() on sparc
johnc
parents:
3839
diff
changeset
|
4535 __ cmp_and_brx_short(L0, G0, Assembler::equal, Assembler::pn, refill); |
4fe626cbf0bf
7066841: remove MacroAssembler::br_on_reg_cond() on sparc
johnc
parents:
3839
diff
changeset
|
4536 |
4fe626cbf0bf
7066841: remove MacroAssembler::br_on_reg_cond() on sparc
johnc
parents:
3839
diff
changeset
|
4537 __ ld_ptr(G2_thread, dirty_card_q_buf_byte_offset, L1); |
3839 | 4538 __ sub(L0, oopSize, L0); |
4539 | |
4540 __ st_ptr(O3, L1, L0); // [_buf + index] := I0 | |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4541 // Use return-from-leaf |
3839 | 4542 __ retl(); |
4543 __ delayed()->st_ptr(L0, G2_thread, dirty_card_q_index_byte_offset); | |
4544 | |
4545 __ bind(refill); | |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4546 address handle_zero = |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4547 CAST_FROM_FN_PTR(address, |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4548 &DirtyCardQueueSet::handle_zero_index_for_thread); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4549 // This should be rare enough that we can afford to save all the |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4550 // scratch registers that the calling context might be using. |
3839 | 4551 __ mov(G1_scratch, L3); |
4552 __ mov(G3_scratch, L5); | |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4553 // We need the value of O3 above (for the write into the buffer), so we |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4554 // save and restore it. |
3839 | 4555 __ mov(O3, L6); |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4556 // Since the call will overwrite O7, we save and restore that, as well. |
3839 | 4557 __ mov(O7, L4); |
4558 | |
4559 __ call_VM_leaf(L7_thread_cache, handle_zero, G2_thread); | |
4560 __ mov(L3, G1_scratch); | |
4561 __ mov(L5, G3_scratch); | |
4562 __ mov(L6, O3); | |
4563 __ br(Assembler::always, /*annul*/false, Assembler::pt, restart); | |
4564 __ delayed()->mov(L4, O7); | |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4565 |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4566 dirty_card_log_enqueue = start; |
3839 | 4567 dirty_card_log_enqueue_end = __ pc(); |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4568 // XXX Should have a guarantee here about not going off the end! |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4569 // Does it already do so? Do an experiment... |
3839 | 4570 |
4571 #undef __ | |
4572 | |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4573 } |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4574 |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4575 static inline void |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4576 generate_dirty_card_log_enqueue_if_necessary(jbyte* byte_map_base) { |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4577 if (dirty_card_log_enqueue == 0) { |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4578 generate_dirty_card_log_enqueue(byte_map_base); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4579 assert(dirty_card_log_enqueue != 0, "postcondition."); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4580 if (G1SATBPrintStubs) { |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4581 tty->print_cr("Generated dirty_card enqueue:"); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4582 Disassembler::decode((u_char*)dirty_card_log_enqueue, |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4583 dirty_card_log_enqueue_end, |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4584 tty); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4585 } |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4586 } |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4587 } |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4588 |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4589 |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4590 void MacroAssembler::g1_write_barrier_post(Register store_addr, Register new_val, Register tmp) { |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4591 |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4592 Label filtered; |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4593 MacroAssembler* post_filter_masm = this; |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4594 |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4595 if (new_val == G0) return; |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4596 |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4597 G1SATBCardTableModRefBS* bs = (G1SATBCardTableModRefBS*) Universe::heap()->barrier_set(); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4598 assert(bs->kind() == BarrierSet::G1SATBCT || |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4599 bs->kind() == BarrierSet::G1SATBCTLogging, "wrong barrier"); |
3888
4fe626cbf0bf
7066841: remove MacroAssembler::br_on_reg_cond() on sparc
johnc
parents:
3839
diff
changeset
|
4600 |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4601 if (G1RSBarrierRegionFilter) { |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4602 xor3(store_addr, new_val, tmp); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4603 #ifdef _LP64 |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4604 srlx(tmp, HeapRegion::LogOfHRGrainBytes, tmp); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4605 #else |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4606 srl(tmp, HeapRegion::LogOfHRGrainBytes, tmp); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4607 #endif |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2357
diff
changeset
|
4608 |
3888
4fe626cbf0bf
7066841: remove MacroAssembler::br_on_reg_cond() on sparc
johnc
parents:
3839
diff
changeset
|
4609 // XXX Should I predict this taken or not? Does it matter? |
4fe626cbf0bf
7066841: remove MacroAssembler::br_on_reg_cond() on sparc
johnc
parents:
3839
diff
changeset
|
4610 cmp_and_brx_short(tmp, G0, Assembler::equal, Assembler::pt, filtered); |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4611 } |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4612 |
794 | 4613 // If the "store_addr" register is an "in" or "local" register, move it to |
4614 // a scratch reg so we can pass it as an argument. | |
4615 bool use_scr = !(store_addr->is_global() || store_addr->is_out()); | |
4616 // Pick a scratch register different from "tmp". | |
4617 Register scr = (tmp == G1_scratch ? G3_scratch : G1_scratch); | |
4618 // Make sure we use up the delay slot! | |
4619 if (use_scr) { | |
4620 post_filter_masm->mov(store_addr, scr); | |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4621 } else { |
794 | 4622 post_filter_masm->nop(); |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4623 } |
794 | 4624 generate_dirty_card_log_enqueue_if_necessary(bs->byte_map_base); |
4625 save_frame(0); | |
4626 call(dirty_card_log_enqueue); | |
4627 if (use_scr) { | |
4628 delayed()->mov(scr, O0); | |
4629 } else { | |
4630 delayed()->mov(store_addr->after_save(), O0); | |
4631 } | |
4632 restore(); | |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4633 |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4634 bind(filtered); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4635 } |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4636 |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4637 #endif // SERIALGC |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4638 /////////////////////////////////////////////////////////////////////////////////// |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4639 |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4640 void MacroAssembler::card_write_barrier_post(Register store_addr, Register new_val, Register tmp) { |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4641 // If we're writing constant NULL, we can skip the write barrier. |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4642 if (new_val == G0) return; |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4643 CardTableModRefBS* bs = (CardTableModRefBS*) Universe::heap()->barrier_set(); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4644 assert(bs->kind() == BarrierSet::CardTableModRef || |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4645 bs->kind() == BarrierSet::CardTableExtension, "wrong barrier"); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4646 card_table_write(bs->byte_map_base, tmp, store_addr); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4647 } |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
124
diff
changeset
|
4648 |
164
c436414a719e
6703890: Compressed Oops: add LoadNKlass node to generate narrow oops (32-bits) compare instructions
kvn
parents:
124
diff
changeset
|
4649 void MacroAssembler::load_klass(Register src_oop, Register klass) { |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
4650 // The number of bytes in this code is used by |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
4651 // MachCallDynamicJavaNode::ret_addr_offset() |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
4652 // if this changes, change that. |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
4653 if (UseCompressedKlassPointers) { |
164
c436414a719e
6703890: Compressed Oops: add LoadNKlass node to generate narrow oops (32-bits) compare instructions
kvn
parents:
124
diff
changeset
|
4654 lduw(src_oop, oopDesc::klass_offset_in_bytes(), klass); |
c436414a719e
6703890: Compressed Oops: add LoadNKlass node to generate narrow oops (32-bits) compare instructions
kvn
parents:
124
diff
changeset
|
4655 decode_heap_oop_not_null(klass); |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
4656 } else { |
164
c436414a719e
6703890: Compressed Oops: add LoadNKlass node to generate narrow oops (32-bits) compare instructions
kvn
parents:
124
diff
changeset
|
4657 ld_ptr(src_oop, oopDesc::klass_offset_in_bytes(), klass); |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
4658 } |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
4659 } |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
4660 |
164
c436414a719e
6703890: Compressed Oops: add LoadNKlass node to generate narrow oops (32-bits) compare instructions
kvn
parents:
124
diff
changeset
|
4661 void MacroAssembler::store_klass(Register klass, Register dst_oop) { |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
4662 if (UseCompressedKlassPointers) { |
164
c436414a719e
6703890: Compressed Oops: add LoadNKlass node to generate narrow oops (32-bits) compare instructions
kvn
parents:
124
diff
changeset
|
4663 assert(dst_oop != klass, "not enough registers"); |
c436414a719e
6703890: Compressed Oops: add LoadNKlass node to generate narrow oops (32-bits) compare instructions
kvn
parents:
124
diff
changeset
|
4664 encode_heap_oop_not_null(klass); |
167
feeb96a45707
6696264: assert("narrow oop can never be zero") for GCBasher & ParNewGC
coleenp
parents:
164
diff
changeset
|
4665 st(klass, dst_oop, oopDesc::klass_offset_in_bytes()); |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
4666 } else { |
164
c436414a719e
6703890: Compressed Oops: add LoadNKlass node to generate narrow oops (32-bits) compare instructions
kvn
parents:
124
diff
changeset
|
4667 st_ptr(klass, dst_oop, oopDesc::klass_offset_in_bytes()); |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
4668 } |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
4669 } |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
4670 |
167
feeb96a45707
6696264: assert("narrow oop can never be zero") for GCBasher & ParNewGC
coleenp
parents:
164
diff
changeset
|
4671 void MacroAssembler::store_klass_gap(Register s, Register d) { |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
4672 if (UseCompressedKlassPointers) { |
167
feeb96a45707
6696264: assert("narrow oop can never be zero") for GCBasher & ParNewGC
coleenp
parents:
164
diff
changeset
|
4673 assert(s != d, "not enough registers"); |
feeb96a45707
6696264: assert("narrow oop can never be zero") for GCBasher & ParNewGC
coleenp
parents:
164
diff
changeset
|
4674 st(s, d, oopDesc::klass_gap_offset_in_bytes()); |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
4675 } |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
4676 } |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
4677 |
727 | 4678 void MacroAssembler::load_heap_oop(const Address& s, Register d) { |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
4679 if (UseCompressedOops) { |
727 | 4680 lduw(s, d); |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
4681 decode_heap_oop(d); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
4682 } else { |
727 | 4683 ld_ptr(s, d); |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
4684 } |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
4685 } |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
4686 |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
4687 void MacroAssembler::load_heap_oop(Register s1, Register s2, Register d) { |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
4688 if (UseCompressedOops) { |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
4689 lduw(s1, s2, d); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
4690 decode_heap_oop(d, d); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
4691 } else { |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
4692 ld_ptr(s1, s2, d); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
4693 } |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
4694 } |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
4695 |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
4696 void MacroAssembler::load_heap_oop(Register s1, int simm13a, Register d) { |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
4697 if (UseCompressedOops) { |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
4698 lduw(s1, simm13a, d); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
4699 decode_heap_oop(d, d); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
4700 } else { |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
4701 ld_ptr(s1, simm13a, d); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
4702 } |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
4703 } |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
4704 |
1846 | 4705 void MacroAssembler::load_heap_oop(Register s1, RegisterOrConstant s2, Register d) { |
4706 if (s2.is_constant()) load_heap_oop(s1, s2.as_constant(), d); | |
4707 else load_heap_oop(s1, s2.as_register(), d); | |
4708 } | |
4709 | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
4710 void MacroAssembler::store_heap_oop(Register d, Register s1, Register s2) { |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
4711 if (UseCompressedOops) { |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
4712 assert(s1 != d && s2 != d, "not enough registers"); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
4713 encode_heap_oop(d); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
4714 st(d, s1, s2); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
4715 } else { |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
4716 st_ptr(d, s1, s2); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
4717 } |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
4718 } |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
4719 |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
4720 void MacroAssembler::store_heap_oop(Register d, Register s1, int simm13a) { |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
4721 if (UseCompressedOops) { |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
4722 assert(s1 != d, "not enough registers"); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
4723 encode_heap_oop(d); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
4724 st(d, s1, simm13a); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
4725 } else { |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
4726 st_ptr(d, s1, simm13a); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
4727 } |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
4728 } |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
4729 |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
4730 void MacroAssembler::store_heap_oop(Register d, const Address& a, int offset) { |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
4731 if (UseCompressedOops) { |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
4732 assert(a.base() != d, "not enough registers"); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
4733 encode_heap_oop(d); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
4734 st(d, a, offset); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
4735 } else { |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
4736 st_ptr(d, a, offset); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
4737 } |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
4738 } |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
4739 |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
4740 |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
4741 void MacroAssembler::encode_heap_oop(Register src, Register dst) { |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
4742 assert (UseCompressedOops, "must be compressed"); |
642
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
623
diff
changeset
|
4743 assert (Universe::heap() != NULL, "java heap should be initialized"); |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
623
diff
changeset
|
4744 assert (LogMinObjAlignmentInBytes == Universe::narrow_oop_shift(), "decode alg wrong"); |
178
6d172e3548cb
6695819: verify_oopx rax: broken oop in decode_heap_oop
coleenp
parents:
124
diff
changeset
|
4745 verify_oop(src); |
642
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
623
diff
changeset
|
4746 if (Universe::narrow_oop_base() == NULL) { |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
623
diff
changeset
|
4747 srlx(src, LogMinObjAlignmentInBytes, dst); |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
623
diff
changeset
|
4748 return; |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
623
diff
changeset
|
4749 } |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
4750 Label done; |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
4751 if (src == dst) { |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
4752 // optimize for frequent case src == dst |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
4753 bpr(rc_nz, true, Assembler::pt, src, done); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
4754 delayed() -> sub(src, G6_heapbase, dst); // annuled if not taken |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
4755 bind(done); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
4756 srlx(src, LogMinObjAlignmentInBytes, dst); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
4757 } else { |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
4758 bpr(rc_z, false, Assembler::pn, src, done); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
4759 delayed() -> mov(G0, dst); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
4760 // could be moved before branch, and annulate delay, |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
4761 // but may add some unneeded work decoding null |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
4762 sub(src, G6_heapbase, dst); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
4763 srlx(dst, LogMinObjAlignmentInBytes, dst); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
4764 bind(done); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
4765 } |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
4766 } |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
4767 |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
4768 |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
4769 void MacroAssembler::encode_heap_oop_not_null(Register r) { |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
4770 assert (UseCompressedOops, "must be compressed"); |
642
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
623
diff
changeset
|
4771 assert (Universe::heap() != NULL, "java heap should be initialized"); |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
623
diff
changeset
|
4772 assert (LogMinObjAlignmentInBytes == Universe::narrow_oop_shift(), "decode alg wrong"); |
178
6d172e3548cb
6695819: verify_oopx rax: broken oop in decode_heap_oop
coleenp
parents:
124
diff
changeset
|
4773 verify_oop(r); |
642
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
623
diff
changeset
|
4774 if (Universe::narrow_oop_base() != NULL) |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
623
diff
changeset
|
4775 sub(r, G6_heapbase, r); |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
4776 srlx(r, LogMinObjAlignmentInBytes, r); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
4777 } |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
4778 |
124
b130b98db9cf
6689060: Escape Analysis does not work with Compressed Oops
kvn
parents:
113
diff
changeset
|
4779 void MacroAssembler::encode_heap_oop_not_null(Register src, Register dst) { |
b130b98db9cf
6689060: Escape Analysis does not work with Compressed Oops
kvn
parents:
113
diff
changeset
|
4780 assert (UseCompressedOops, "must be compressed"); |
642
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
623
diff
changeset
|
4781 assert (Universe::heap() != NULL, "java heap should be initialized"); |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
623
diff
changeset
|
4782 assert (LogMinObjAlignmentInBytes == Universe::narrow_oop_shift(), "decode alg wrong"); |
178
6d172e3548cb
6695819: verify_oopx rax: broken oop in decode_heap_oop
coleenp
parents:
124
diff
changeset
|
4783 verify_oop(src); |
642
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
623
diff
changeset
|
4784 if (Universe::narrow_oop_base() == NULL) { |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
623
diff
changeset
|
4785 srlx(src, LogMinObjAlignmentInBytes, dst); |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
623
diff
changeset
|
4786 } else { |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
623
diff
changeset
|
4787 sub(src, G6_heapbase, dst); |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
623
diff
changeset
|
4788 srlx(dst, LogMinObjAlignmentInBytes, dst); |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
623
diff
changeset
|
4789 } |
124
b130b98db9cf
6689060: Escape Analysis does not work with Compressed Oops
kvn
parents:
113
diff
changeset
|
4790 } |
b130b98db9cf
6689060: Escape Analysis does not work with Compressed Oops
kvn
parents:
113
diff
changeset
|
4791 |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
4792 // Same algorithm as oops.inline.hpp decode_heap_oop. |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
4793 void MacroAssembler::decode_heap_oop(Register src, Register dst) { |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
4794 assert (UseCompressedOops, "must be compressed"); |
642
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
623
diff
changeset
|
4795 assert (Universe::heap() != NULL, "java heap should be initialized"); |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
623
diff
changeset
|
4796 assert (LogMinObjAlignmentInBytes == Universe::narrow_oop_shift(), "decode alg wrong"); |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
4797 sllx(src, LogMinObjAlignmentInBytes, dst); |
642
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
623
diff
changeset
|
4798 if (Universe::narrow_oop_base() != NULL) { |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
623
diff
changeset
|
4799 Label done; |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
623
diff
changeset
|
4800 bpr(rc_nz, true, Assembler::pt, dst, done); |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
623
diff
changeset
|
4801 delayed() -> add(dst, G6_heapbase, dst); // annuled if not taken |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
623
diff
changeset
|
4802 bind(done); |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
623
diff
changeset
|
4803 } |
178
6d172e3548cb
6695819: verify_oopx rax: broken oop in decode_heap_oop
coleenp
parents:
124
diff
changeset
|
4804 verify_oop(dst); |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
4805 } |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
4806 |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
4807 void MacroAssembler::decode_heap_oop_not_null(Register r) { |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
4808 // Do not add assert code to this unless you change vtableStubs_sparc.cpp |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
4809 // pd_code_size_limit. |
178
6d172e3548cb
6695819: verify_oopx rax: broken oop in decode_heap_oop
coleenp
parents:
124
diff
changeset
|
4810 // Also do not verify_oop as this is called by verify_oop. |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
4811 assert (UseCompressedOops, "must be compressed"); |
642
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
623
diff
changeset
|
4812 assert (Universe::heap() != NULL, "java heap should be initialized"); |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
623
diff
changeset
|
4813 assert (LogMinObjAlignmentInBytes == Universe::narrow_oop_shift(), "decode alg wrong"); |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
4814 sllx(r, LogMinObjAlignmentInBytes, r); |
642
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
623
diff
changeset
|
4815 if (Universe::narrow_oop_base() != NULL) |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
623
diff
changeset
|
4816 add(r, G6_heapbase, r); |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
4817 } |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
4818 |
124
b130b98db9cf
6689060: Escape Analysis does not work with Compressed Oops
kvn
parents:
113
diff
changeset
|
4819 void MacroAssembler::decode_heap_oop_not_null(Register src, Register dst) { |
b130b98db9cf
6689060: Escape Analysis does not work with Compressed Oops
kvn
parents:
113
diff
changeset
|
4820 // Do not add assert code to this unless you change vtableStubs_sparc.cpp |
b130b98db9cf
6689060: Escape Analysis does not work with Compressed Oops
kvn
parents:
113
diff
changeset
|
4821 // pd_code_size_limit. |
178
6d172e3548cb
6695819: verify_oopx rax: broken oop in decode_heap_oop
coleenp
parents:
124
diff
changeset
|
4822 // Also do not verify_oop as this is called by verify_oop. |
124
b130b98db9cf
6689060: Escape Analysis does not work with Compressed Oops
kvn
parents:
113
diff
changeset
|
4823 assert (UseCompressedOops, "must be compressed"); |
642
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
623
diff
changeset
|
4824 assert (Universe::heap() != NULL, "java heap should be initialized"); |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
623
diff
changeset
|
4825 assert (LogMinObjAlignmentInBytes == Universe::narrow_oop_shift(), "decode alg wrong"); |
124
b130b98db9cf
6689060: Escape Analysis does not work with Compressed Oops
kvn
parents:
113
diff
changeset
|
4826 sllx(src, LogMinObjAlignmentInBytes, dst); |
642
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
623
diff
changeset
|
4827 if (Universe::narrow_oop_base() != NULL) |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
623
diff
changeset
|
4828 add(dst, G6_heapbase, dst); |
124
b130b98db9cf
6689060: Escape Analysis does not work with Compressed Oops
kvn
parents:
113
diff
changeset
|
4829 } |
b130b98db9cf
6689060: Escape Analysis does not work with Compressed Oops
kvn
parents:
113
diff
changeset
|
4830 |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
4831 void MacroAssembler::reinit_heapbase() { |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
4832 if (UseCompressedOops) { |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
4833 // call indirectly to solve generation ordering problem |
727 | 4834 AddressLiteral base(Universe::narrow_oop_base_addr()); |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
4835 load_ptr_contents(base, G6_heapbase); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
4836 } |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
4837 } |
986
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
845
diff
changeset
|
4838 |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
845
diff
changeset
|
4839 // Compare char[] arrays aligned to 4 bytes. |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
845
diff
changeset
|
4840 void MacroAssembler::char_arrays_equals(Register ary1, Register ary2, |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
845
diff
changeset
|
4841 Register limit, Register result, |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
845
diff
changeset
|
4842 Register chr1, Register chr2, Label& Ldone) { |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
845
diff
changeset
|
4843 Label Lvector, Lloop; |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
845
diff
changeset
|
4844 assert(chr1 == result, "should be the same"); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
845
diff
changeset
|
4845 |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
845
diff
changeset
|
4846 // Note: limit contains number of bytes (2*char_elements) != 0. |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
845
diff
changeset
|
4847 andcc(limit, 0x2, chr1); // trailing character ? |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
845
diff
changeset
|
4848 br(Assembler::zero, false, Assembler::pt, Lvector); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
845
diff
changeset
|
4849 delayed()->nop(); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
845
diff
changeset
|
4850 |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
845
diff
changeset
|
4851 // compare the trailing char |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
845
diff
changeset
|
4852 sub(limit, sizeof(jchar), limit); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
845
diff
changeset
|
4853 lduh(ary1, limit, chr1); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
845
diff
changeset
|
4854 lduh(ary2, limit, chr2); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
845
diff
changeset
|
4855 cmp(chr1, chr2); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
845
diff
changeset
|
4856 br(Assembler::notEqual, true, Assembler::pt, Ldone); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
845
diff
changeset
|
4857 delayed()->mov(G0, result); // not equal |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
845
diff
changeset
|
4858 |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
845
diff
changeset
|
4859 // only one char ? |
3839 | 4860 cmp_zero_and_br(zero, limit, Ldone, true, Assembler::pn); |
986
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
845
diff
changeset
|
4861 delayed()->add(G0, 1, result); // zero-length arrays are equal |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
845
diff
changeset
|
4862 |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
845
diff
changeset
|
4863 // word by word compare, dont't need alignment check |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
845
diff
changeset
|
4864 bind(Lvector); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
845
diff
changeset
|
4865 // Shift ary1 and ary2 to the end of the arrays, negate limit |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
845
diff
changeset
|
4866 add(ary1, limit, ary1); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
845
diff
changeset
|
4867 add(ary2, limit, ary2); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
845
diff
changeset
|
4868 neg(limit, limit); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
845
diff
changeset
|
4869 |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
845
diff
changeset
|
4870 lduw(ary1, limit, chr1); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
845
diff
changeset
|
4871 bind(Lloop); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
845
diff
changeset
|
4872 lduw(ary2, limit, chr2); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
845
diff
changeset
|
4873 cmp(chr1, chr2); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
845
diff
changeset
|
4874 br(Assembler::notEqual, true, Assembler::pt, Ldone); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
845
diff
changeset
|
4875 delayed()->mov(G0, result); // not equal |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
845
diff
changeset
|
4876 inccc(limit, 2*sizeof(jchar)); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
845
diff
changeset
|
4877 // annul LDUW if branch is not taken to prevent access past end of array |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
845
diff
changeset
|
4878 br(Assembler::notZero, true, Assembler::pt, Lloop); |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
845
diff
changeset
|
4879 delayed()->lduw(ary1, limit, chr1); // hoisted |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
845
diff
changeset
|
4880 |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
845
diff
changeset
|
4881 // Caller should set it: |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
845
diff
changeset
|
4882 // add(G0, 1, result); // equals |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
845
diff
changeset
|
4883 } |
3892 | 4884 |
4885 // Use BIS for zeroing (count is in bytes). | |
4886 void MacroAssembler::bis_zeroing(Register to, Register count, Register temp, Label& Ldone) { | |
4887 assert(UseBlockZeroing && VM_Version::has_block_zeroing(), "only works with BIS zeroing"); | |
4888 Register end = count; | |
4889 int cache_line_size = VM_Version::prefetch_data_size(); | |
4890 // Minimum count when BIS zeroing can be used since | |
4891 // it needs membar which is expensive. | |
4892 int block_zero_size = MAX2(cache_line_size*3, (int)BlockZeroingLowLimit); | |
4893 | |
4894 Label small_loop; | |
4895 // Check if count is negative (dead code) or zero. | |
4896 // Note, count uses 64bit in 64 bit VM. | |
4897 cmp_and_brx_short(count, 0, Assembler::lessEqual, Assembler::pn, Ldone); | |
4898 | |
4899 // Use BIS zeroing only for big arrays since it requires membar. | |
4900 if (Assembler::is_simm13(block_zero_size)) { // < 4096 | |
4901 cmp(count, block_zero_size); | |
4902 } else { | |
4903 set(block_zero_size, temp); | |
4904 cmp(count, temp); | |
4905 } | |
4906 br(Assembler::lessUnsigned, false, Assembler::pt, small_loop); | |
4907 delayed()->add(to, count, end); | |
4908 | |
4909 // Note: size is >= three (32 bytes) cache lines. | |
4910 | |
4911 // Clean the beginning of space up to next cache line. | |
4912 for (int offs = 0; offs < cache_line_size; offs += 8) { | |
4913 stx(G0, to, offs); | |
4914 } | |
4915 | |
4916 // align to next cache line | |
4917 add(to, cache_line_size, to); | |
4918 and3(to, -cache_line_size, to); | |
4919 | |
4920 // Note: size left >= two (32 bytes) cache lines. | |
4921 | |
4922 // BIS should not be used to zero tail (64 bytes) | |
4923 // to avoid zeroing a header of the following object. | |
4924 sub(end, (cache_line_size*2)-8, end); | |
4925 | |
4926 Label bis_loop; | |
4927 bind(bis_loop); | |
4928 stxa(G0, to, G0, Assembler::ASI_ST_BLKINIT_PRIMARY); | |
4929 add(to, cache_line_size, to); | |
4930 cmp_and_brx_short(to, end, Assembler::lessUnsigned, Assembler::pt, bis_loop); | |
4931 | |
4932 // BIS needs membar. | |
4933 membar(Assembler::StoreLoad); | |
4934 | |
4935 add(end, (cache_line_size*2)-8, end); // restore end | |
4936 cmp_and_brx_short(to, end, Assembler::greaterEqualUnsigned, Assembler::pn, Ldone); | |
4937 | |
4938 // Clean the tail. | |
4939 bind(small_loop); | |
4940 stx(G0, to, 0); | |
4941 add(to, 8, to); | |
4942 cmp_and_brx_short(to, end, Assembler::lessUnsigned, Assembler::pt, small_loop); | |
4943 nop(); // Separate short branches | |
4944 } |