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