Mercurial > hg > graal-jvmci-8
annotate src/cpu/sparc/vm/templateTable_sparc.cpp @ 2368:dde920245681
6896099: Integrate CMS heap ergo with default heap sizing ergo
6627787: CMS: JVM refuses to start up with -Xms16m -Xmx16m
7000125: CMS: Anti-monotone young gen sizing with respect to maximum whole heap size specification
7027529: CMS: retire CMSUseOldDefaults flag
Summary: Simplify CMS heap sizing code, relying on ergonomic initial sizing consistent with other collectors for the most part, controlling only young gen sizing to rein in pause times. Make CMS young gen sizing default statically cpu-dependant. Remove inconsistencies wrt generation sizing and policy code, allowing for the fixing for 6627787 and 7000125. For 7027529, retire the flag CMSUseOldDefaults which had been introduced as a bridge from JDK 5 to JDK 6 a number of years ago.
Reviewed-by: brutisso, poonam
author | ysr |
---|---|
date | Wed, 16 Mar 2011 10:37:08 -0700 |
parents | 856ecff79cf7 |
children | 8033953d67ff |
rev | line source |
---|---|
0 | 1 /* |
2100
b1a2afa37ec4
7003271: Hotspot should track cumulative Java heap bytes allocated on a per-thread basis
phh
parents:
1972
diff
changeset
|
2 * Copyright (c) 1997, 2011, 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:
1506
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1506
diff
changeset
|
20 * or visit www.oracle.com if you need additional information or have any |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1506
diff
changeset
|
21 * questions. |
0 | 22 * |
23 */ | |
24 | |
1972 | 25 #include "precompiled.hpp" |
26 #include "interpreter/interpreter.hpp" | |
27 #include "interpreter/interpreterRuntime.hpp" | |
28 #include "interpreter/templateTable.hpp" | |
29 #include "memory/universe.inline.hpp" | |
30 #include "oops/methodDataOop.hpp" | |
31 #include "oops/objArrayKlass.hpp" | |
32 #include "oops/oop.inline.hpp" | |
33 #include "prims/methodHandles.hpp" | |
34 #include "runtime/sharedRuntime.hpp" | |
35 #include "runtime/stubRoutines.hpp" | |
36 #include "runtime/synchronizer.hpp" | |
0 | 37 |
38 #ifndef CC_INTERP | |
39 #define __ _masm-> | |
40 | |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
41 // Misc helpers |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
42 |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
43 // Do an oop store like *(base + index + offset) = val |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
44 // index can be noreg, |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
45 static void do_oop_store(InterpreterMacroAssembler* _masm, |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
46 Register base, |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
47 Register index, |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
48 int offset, |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
49 Register val, |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
50 Register tmp, |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
51 BarrierSet::Name barrier, |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
52 bool precise) { |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
53 assert(tmp != val && tmp != base && tmp != index, "register collision"); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
54 assert(index == noreg || offset == 0, "only one offset"); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
55 switch (barrier) { |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
56 #ifndef SERIALGC |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
57 case BarrierSet::G1SATBCT: |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
58 case BarrierSet::G1SATBCTLogging: |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
59 { |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
60 __ g1_write_barrier_pre( base, index, offset, tmp, /*preserve_o_regs*/true); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
61 if (index == noreg ) { |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
62 assert(Assembler::is_simm13(offset), "fix this code"); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
63 __ store_heap_oop(val, base, offset); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
64 } else { |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
65 __ store_heap_oop(val, base, index); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
66 } |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
67 |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
68 // No need for post barrier if storing NULL |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
69 if (val != G0) { |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
70 if (precise) { |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
71 if (index == noreg) { |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
72 __ add(base, offset, base); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
73 } else { |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
74 __ add(base, index, base); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
75 } |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
76 } |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
77 __ g1_write_barrier_post(base, val, tmp); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
78 } |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
79 } |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
80 break; |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
81 #endif // SERIALGC |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
82 case BarrierSet::CardTableModRef: |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
83 case BarrierSet::CardTableExtension: |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
84 { |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
85 if (index == noreg ) { |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
86 assert(Assembler::is_simm13(offset), "fix this code"); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
87 __ store_heap_oop(val, base, offset); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
88 } else { |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
89 __ store_heap_oop(val, base, index); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
90 } |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
91 // No need for post barrier if storing NULL |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
92 if (val != G0) { |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
93 if (precise) { |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
94 if (index == noreg) { |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
95 __ add(base, offset, base); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
96 } else { |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
97 __ add(base, index, base); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
98 } |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
99 } |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
100 __ card_write_barrier_post(base, val, tmp); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
101 } |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
102 } |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
103 break; |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
104 case BarrierSet::ModRef: |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
105 case BarrierSet::Other: |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
106 ShouldNotReachHere(); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
107 break; |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
108 default : |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
109 ShouldNotReachHere(); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
110 |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
111 } |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
112 } |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
113 |
0 | 114 |
115 //---------------------------------------------------------------------------------------------------- | |
116 // Platform-dependent initialization | |
117 | |
118 void TemplateTable::pd_initialize() { | |
119 // (none) | |
120 } | |
121 | |
122 | |
123 //---------------------------------------------------------------------------------------------------- | |
124 // Condition conversion | |
125 Assembler::Condition ccNot(TemplateTable::Condition cc) { | |
126 switch (cc) { | |
127 case TemplateTable::equal : return Assembler::notEqual; | |
128 case TemplateTable::not_equal : return Assembler::equal; | |
129 case TemplateTable::less : return Assembler::greaterEqual; | |
130 case TemplateTable::less_equal : return Assembler::greater; | |
131 case TemplateTable::greater : return Assembler::lessEqual; | |
132 case TemplateTable::greater_equal: return Assembler::less; | |
133 } | |
134 ShouldNotReachHere(); | |
135 return Assembler::zero; | |
136 } | |
137 | |
138 //---------------------------------------------------------------------------------------------------- | |
139 // Miscelaneous helper routines | |
140 | |
141 | |
142 Address TemplateTable::at_bcp(int offset) { | |
143 assert(_desc->uses_bcp(), "inconsistent uses_bcp information"); | |
727 | 144 return Address(Lbcp, offset); |
0 | 145 } |
146 | |
147 | |
148 void TemplateTable::patch_bytecode(Bytecodes::Code bc, Register Rbyte_code, | |
149 Register Rscratch, | |
150 bool load_bc_into_scratch /*=true*/) { | |
151 // With sharing on, may need to test methodOop flag. | |
152 if (!RewriteBytecodes) return; | |
153 if (load_bc_into_scratch) __ set(bc, Rbyte_code); | |
154 Label patch_done; | |
155 if (JvmtiExport::can_post_breakpoint()) { | |
156 Label fast_patch; | |
157 __ ldub(at_bcp(0), Rscratch); | |
158 __ cmp(Rscratch, Bytecodes::_breakpoint); | |
159 __ br(Assembler::notEqual, false, Assembler::pt, fast_patch); | |
160 __ delayed()->nop(); // don't bother to hoist the stb here | |
161 // perform the quickening, slowly, in the bowels of the breakpoint table | |
162 __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::set_original_bytecode_at), Lmethod, Lbcp, Rbyte_code); | |
163 __ ba(false, patch_done); | |
164 __ delayed()->nop(); | |
165 __ bind(fast_patch); | |
166 } | |
167 #ifdef ASSERT | |
168 Bytecodes::Code orig_bytecode = Bytecodes::java_code(bc); | |
169 Label okay; | |
170 __ ldub(at_bcp(0), Rscratch); | |
171 __ cmp(Rscratch, orig_bytecode); | |
172 __ br(Assembler::equal, false, Assembler::pt, okay); | |
173 __ delayed() ->cmp(Rscratch, Rbyte_code); | |
174 __ br(Assembler::equal, false, Assembler::pt, okay); | |
175 __ delayed()->nop(); | |
176 __ stop("Rewriting wrong bytecode location"); | |
177 __ bind(okay); | |
178 #endif | |
179 __ stb(Rbyte_code, at_bcp(0)); | |
180 __ bind(patch_done); | |
181 } | |
182 | |
183 //---------------------------------------------------------------------------------------------------- | |
184 // Individual instructions | |
185 | |
186 void TemplateTable::nop() { | |
187 transition(vtos, vtos); | |
188 // nothing to do | |
189 } | |
190 | |
191 void TemplateTable::shouldnotreachhere() { | |
192 transition(vtos, vtos); | |
193 __ stop("shouldnotreachhere bytecode"); | |
194 } | |
195 | |
196 void TemplateTable::aconst_null() { | |
197 transition(vtos, atos); | |
198 __ clr(Otos_i); | |
199 } | |
200 | |
201 | |
202 void TemplateTable::iconst(int value) { | |
203 transition(vtos, itos); | |
204 __ set(value, Otos_i); | |
205 } | |
206 | |
207 | |
208 void TemplateTable::lconst(int value) { | |
209 transition(vtos, ltos); | |
210 assert(value >= 0, "check this code"); | |
211 #ifdef _LP64 | |
212 __ set(value, Otos_l); | |
213 #else | |
214 __ set(value, Otos_l2); | |
215 __ clr( Otos_l1); | |
216 #endif | |
217 } | |
218 | |
219 | |
220 void TemplateTable::fconst(int value) { | |
221 transition(vtos, ftos); | |
222 static float zero = 0.0, one = 1.0, two = 2.0; | |
223 float* p; | |
224 switch( value ) { | |
225 default: ShouldNotReachHere(); | |
226 case 0: p = &zero; break; | |
227 case 1: p = &one; break; | |
228 case 2: p = &two; break; | |
229 } | |
727 | 230 AddressLiteral a(p); |
231 __ sethi(a, G3_scratch); | |
232 __ ldf(FloatRegisterImpl::S, G3_scratch, a.low10(), Ftos_f); | |
0 | 233 } |
234 | |
235 | |
236 void TemplateTable::dconst(int value) { | |
237 transition(vtos, dtos); | |
238 static double zero = 0.0, one = 1.0; | |
239 double* p; | |
240 switch( value ) { | |
241 default: ShouldNotReachHere(); | |
242 case 0: p = &zero; break; | |
243 case 1: p = &one; break; | |
244 } | |
727 | 245 AddressLiteral a(p); |
246 __ sethi(a, G3_scratch); | |
247 __ ldf(FloatRegisterImpl::D, G3_scratch, a.low10(), Ftos_d); | |
0 | 248 } |
249 | |
250 | |
251 // %%%%% Should factore most snippet templates across platforms | |
252 | |
253 void TemplateTable::bipush() { | |
254 transition(vtos, itos); | |
255 __ ldsb( at_bcp(1), Otos_i ); | |
256 } | |
257 | |
258 void TemplateTable::sipush() { | |
259 transition(vtos, itos); | |
260 __ get_2_byte_integer_at_bcp(1, G3_scratch, Otos_i, InterpreterMacroAssembler::Signed); | |
261 } | |
262 | |
263 void TemplateTable::ldc(bool wide) { | |
264 transition(vtos, vtos); | |
265 Label call_ldc, notInt, notString, notClass, exit; | |
266 | |
267 if (wide) { | |
268 __ get_2_byte_integer_at_bcp(1, G3_scratch, O1, InterpreterMacroAssembler::Unsigned); | |
269 } else { | |
270 __ ldub(Lbcp, 1, O1); | |
271 } | |
272 __ get_cpool_and_tags(O0, O2); | |
273 | |
274 const int base_offset = constantPoolOopDesc::header_size() * wordSize; | |
275 const int tags_offset = typeArrayOopDesc::header_size(T_BYTE) * wordSize; | |
276 | |
277 // get type from tags | |
278 __ add(O2, tags_offset, O2); | |
279 __ ldub(O2, O1, O2); | |
280 __ cmp(O2, JVM_CONSTANT_UnresolvedString); // unresolved string? If so, must resolve | |
281 __ brx(Assembler::equal, true, Assembler::pt, call_ldc); | |
282 __ delayed()->nop(); | |
283 | |
284 __ cmp(O2, JVM_CONSTANT_UnresolvedClass); // unresolved class? If so, must resolve | |
285 __ brx(Assembler::equal, true, Assembler::pt, call_ldc); | |
286 __ delayed()->nop(); | |
287 | |
288 __ cmp(O2, JVM_CONSTANT_UnresolvedClassInError); // unresolved class in error state | |
289 __ brx(Assembler::equal, true, Assembler::pn, call_ldc); | |
290 __ delayed()->nop(); | |
291 | |
292 __ cmp(O2, JVM_CONSTANT_Class); // need to call vm to get java mirror of the class | |
293 __ brx(Assembler::notEqual, true, Assembler::pt, notClass); | |
294 __ delayed()->add(O0, base_offset, O0); | |
295 | |
296 __ bind(call_ldc); | |
297 __ set(wide, O1); | |
298 call_VM(Otos_i, CAST_FROM_FN_PTR(address, InterpreterRuntime::ldc), O1); | |
299 __ push(atos); | |
300 __ ba(false, exit); | |
301 __ delayed()->nop(); | |
302 | |
303 __ bind(notClass); | |
304 // __ add(O0, base_offset, O0); | |
305 __ sll(O1, LogBytesPerWord, O1); | |
306 __ cmp(O2, JVM_CONSTANT_Integer); | |
307 __ brx(Assembler::notEqual, true, Assembler::pt, notInt); | |
308 __ delayed()->cmp(O2, JVM_CONSTANT_String); | |
309 __ ld(O0, O1, Otos_i); | |
310 __ push(itos); | |
311 __ ba(false, exit); | |
312 __ delayed()->nop(); | |
313 | |
314 __ bind(notInt); | |
315 // __ cmp(O2, JVM_CONSTANT_String); | |
316 __ brx(Assembler::notEqual, true, Assembler::pt, notString); | |
317 __ delayed()->ldf(FloatRegisterImpl::S, O0, O1, Ftos_f); | |
318 __ ld_ptr(O0, O1, Otos_i); | |
319 __ verify_oop(Otos_i); | |
320 __ push(atos); | |
321 __ ba(false, exit); | |
322 __ delayed()->nop(); | |
323 | |
324 __ bind(notString); | |
325 // __ ldf(FloatRegisterImpl::S, O0, O1, Ftos_f); | |
326 __ push(ftos); | |
327 | |
328 __ bind(exit); | |
329 } | |
330 | |
1602 | 331 // Fast path for caching oop constants. |
332 // %%% We should use this to handle Class and String constants also. | |
333 // %%% It will simplify the ldc/primitive path considerably. | |
334 void TemplateTable::fast_aldc(bool wide) { | |
335 transition(vtos, atos); | |
336 | |
337 if (!EnableMethodHandles) { | |
338 // We should not encounter this bytecode if !EnableMethodHandles. | |
339 // The verifier will stop it. However, if we get past the verifier, | |
340 // this will stop the thread in a reasonable way, without crashing the JVM. | |
341 __ call_VM(noreg, CAST_FROM_FN_PTR(address, | |
342 InterpreterRuntime::throw_IncompatibleClassChangeError)); | |
343 // the call_VM checks for exception, so we should never return here. | |
344 __ should_not_reach_here(); | |
345 return; | |
346 } | |
347 | |
348 Register Rcache = G3_scratch; | |
349 Register Rscratch = G4_scratch; | |
350 | |
351 resolve_cache_and_index(f1_oop, Otos_i, Rcache, Rscratch, wide ? sizeof(u2) : sizeof(u1)); | |
352 | |
353 __ verify_oop(Otos_i); | |
1913
3b2dea75431e
6984311: JSR 292 needs optional bootstrap method parameters
jrose
parents:
1846
diff
changeset
|
354 |
3b2dea75431e
6984311: JSR 292 needs optional bootstrap method parameters
jrose
parents:
1846
diff
changeset
|
355 Label L_done; |
3b2dea75431e
6984311: JSR 292 needs optional bootstrap method parameters
jrose
parents:
1846
diff
changeset
|
356 const Register Rcon_klass = G3_scratch; // same as Rcache |
3b2dea75431e
6984311: JSR 292 needs optional bootstrap method parameters
jrose
parents:
1846
diff
changeset
|
357 const Register Rarray_klass = G4_scratch; // same as Rscratch |
3b2dea75431e
6984311: JSR 292 needs optional bootstrap method parameters
jrose
parents:
1846
diff
changeset
|
358 __ load_klass(Otos_i, Rcon_klass); |
3b2dea75431e
6984311: JSR 292 needs optional bootstrap method parameters
jrose
parents:
1846
diff
changeset
|
359 AddressLiteral array_klass_addr((address)Universe::systemObjArrayKlassObj_addr()); |
3b2dea75431e
6984311: JSR 292 needs optional bootstrap method parameters
jrose
parents:
1846
diff
changeset
|
360 __ load_contents(array_klass_addr, Rarray_klass); |
3b2dea75431e
6984311: JSR 292 needs optional bootstrap method parameters
jrose
parents:
1846
diff
changeset
|
361 __ cmp(Rarray_klass, Rcon_klass); |
3b2dea75431e
6984311: JSR 292 needs optional bootstrap method parameters
jrose
parents:
1846
diff
changeset
|
362 __ brx(Assembler::notEqual, false, Assembler::pt, L_done); |
3b2dea75431e
6984311: JSR 292 needs optional bootstrap method parameters
jrose
parents:
1846
diff
changeset
|
363 __ delayed()->nop(); |
3b2dea75431e
6984311: JSR 292 needs optional bootstrap method parameters
jrose
parents:
1846
diff
changeset
|
364 __ ld(Address(Otos_i, arrayOopDesc::length_offset_in_bytes()), Rcon_klass); |
3b2dea75431e
6984311: JSR 292 needs optional bootstrap method parameters
jrose
parents:
1846
diff
changeset
|
365 __ tst(Rcon_klass); |
3b2dea75431e
6984311: JSR 292 needs optional bootstrap method parameters
jrose
parents:
1846
diff
changeset
|
366 __ brx(Assembler::zero, true, Assembler::pt, L_done); |
3b2dea75431e
6984311: JSR 292 needs optional bootstrap method parameters
jrose
parents:
1846
diff
changeset
|
367 __ delayed()->clr(Otos_i); // executed only if branch is taken |
3b2dea75431e
6984311: JSR 292 needs optional bootstrap method parameters
jrose
parents:
1846
diff
changeset
|
368 |
3b2dea75431e
6984311: JSR 292 needs optional bootstrap method parameters
jrose
parents:
1846
diff
changeset
|
369 // Load the exception from the system-array which wraps it: |
3b2dea75431e
6984311: JSR 292 needs optional bootstrap method parameters
jrose
parents:
1846
diff
changeset
|
370 __ load_heap_oop(Otos_i, arrayOopDesc::base_offset_in_bytes(T_OBJECT), Otos_i); |
3b2dea75431e
6984311: JSR 292 needs optional bootstrap method parameters
jrose
parents:
1846
diff
changeset
|
371 __ throw_if_not_x(Assembler::never, Interpreter::throw_exception_entry(), G3_scratch); |
3b2dea75431e
6984311: JSR 292 needs optional bootstrap method parameters
jrose
parents:
1846
diff
changeset
|
372 |
3b2dea75431e
6984311: JSR 292 needs optional bootstrap method parameters
jrose
parents:
1846
diff
changeset
|
373 __ bind(L_done); |
1602 | 374 } |
375 | |
0 | 376 void TemplateTable::ldc2_w() { |
377 transition(vtos, vtos); | |
378 Label retry, resolved, Long, exit; | |
379 | |
380 __ bind(retry); | |
381 __ get_2_byte_integer_at_bcp(1, G3_scratch, O1, InterpreterMacroAssembler::Unsigned); | |
382 __ get_cpool_and_tags(O0, O2); | |
383 | |
384 const int base_offset = constantPoolOopDesc::header_size() * wordSize; | |
385 const int tags_offset = typeArrayOopDesc::header_size(T_BYTE) * wordSize; | |
386 // get type from tags | |
387 __ add(O2, tags_offset, O2); | |
388 __ ldub(O2, O1, O2); | |
389 | |
390 __ sll(O1, LogBytesPerWord, O1); | |
391 __ add(O0, O1, G3_scratch); | |
392 | |
393 __ cmp(O2, JVM_CONSTANT_Double); | |
394 __ brx(Assembler::notEqual, false, Assembler::pt, Long); | |
395 __ delayed()->nop(); | |
396 // A double can be placed at word-aligned locations in the constant pool. | |
397 // Check out Conversions.java for an example. | |
398 // Also constantPoolOopDesc::header_size() is 20, which makes it very difficult | |
399 // to double-align double on the constant pool. SG, 11/7/97 | |
400 #ifdef _LP64 | |
401 __ ldf(FloatRegisterImpl::D, G3_scratch, base_offset, Ftos_d); | |
402 #else | |
403 FloatRegister f = Ftos_d; | |
404 __ ldf(FloatRegisterImpl::S, G3_scratch, base_offset, f); | |
405 __ ldf(FloatRegisterImpl::S, G3_scratch, base_offset + sizeof(jdouble)/2, | |
406 f->successor()); | |
407 #endif | |
408 __ push(dtos); | |
409 __ ba(false, exit); | |
410 __ delayed()->nop(); | |
411 | |
412 __ bind(Long); | |
413 #ifdef _LP64 | |
414 __ ldx(G3_scratch, base_offset, Otos_l); | |
415 #else | |
416 __ ld(G3_scratch, base_offset, Otos_l); | |
417 __ ld(G3_scratch, base_offset + sizeof(jlong)/2, Otos_l->successor()); | |
418 #endif | |
419 __ push(ltos); | |
420 | |
421 __ bind(exit); | |
422 } | |
423 | |
424 | |
425 void TemplateTable::locals_index(Register reg, int offset) { | |
426 __ ldub( at_bcp(offset), reg ); | |
427 } | |
428 | |
429 | |
430 void TemplateTable::locals_index_wide(Register reg) { | |
431 // offset is 2, not 1, because Lbcp points to wide prefix code | |
432 __ get_2_byte_integer_at_bcp(2, G4_scratch, reg, InterpreterMacroAssembler::Unsigned); | |
433 } | |
434 | |
435 void TemplateTable::iload() { | |
436 transition(vtos, itos); | |
437 // Rewrite iload,iload pair into fast_iload2 | |
438 // iload,caload pair into fast_icaload | |
439 if (RewriteFrequentPairs) { | |
440 Label rewrite, done; | |
441 | |
442 // get next byte | |
443 __ ldub(at_bcp(Bytecodes::length_for(Bytecodes::_iload)), G3_scratch); | |
444 | |
445 // if _iload, wait to rewrite to iload2. We only want to rewrite the | |
446 // last two iloads in a pair. Comparing against fast_iload means that | |
447 // the next bytecode is neither an iload or a caload, and therefore | |
448 // an iload pair. | |
449 __ cmp(G3_scratch, (int)Bytecodes::_iload); | |
450 __ br(Assembler::equal, false, Assembler::pn, done); | |
451 __ delayed()->nop(); | |
452 | |
453 __ cmp(G3_scratch, (int)Bytecodes::_fast_iload); | |
454 __ br(Assembler::equal, false, Assembler::pn, rewrite); | |
455 __ delayed()->set(Bytecodes::_fast_iload2, G4_scratch); | |
456 | |
457 __ cmp(G3_scratch, (int)Bytecodes::_caload); | |
458 __ br(Assembler::equal, false, Assembler::pn, rewrite); | |
459 __ delayed()->set(Bytecodes::_fast_icaload, G4_scratch); | |
460 | |
461 __ set(Bytecodes::_fast_iload, G4_scratch); // don't check again | |
462 // rewrite | |
463 // G4_scratch: fast bytecode | |
464 __ bind(rewrite); | |
465 patch_bytecode(Bytecodes::_iload, G4_scratch, G3_scratch, false); | |
466 __ bind(done); | |
467 } | |
468 | |
469 // Get the local value into tos | |
470 locals_index(G3_scratch); | |
471 __ access_local_int( G3_scratch, Otos_i ); | |
472 } | |
473 | |
474 void TemplateTable::fast_iload2() { | |
475 transition(vtos, itos); | |
476 locals_index(G3_scratch); | |
477 __ access_local_int( G3_scratch, Otos_i ); | |
478 __ push_i(); | |
479 locals_index(G3_scratch, 3); // get next bytecode's local index. | |
480 __ access_local_int( G3_scratch, Otos_i ); | |
481 } | |
482 | |
483 void TemplateTable::fast_iload() { | |
484 transition(vtos, itos); | |
485 locals_index(G3_scratch); | |
486 __ access_local_int( G3_scratch, Otos_i ); | |
487 } | |
488 | |
489 void TemplateTable::lload() { | |
490 transition(vtos, ltos); | |
491 locals_index(G3_scratch); | |
492 __ access_local_long( G3_scratch, Otos_l ); | |
493 } | |
494 | |
495 | |
496 void TemplateTable::fload() { | |
497 transition(vtos, ftos); | |
498 locals_index(G3_scratch); | |
499 __ access_local_float( G3_scratch, Ftos_f ); | |
500 } | |
501 | |
502 | |
503 void TemplateTable::dload() { | |
504 transition(vtos, dtos); | |
505 locals_index(G3_scratch); | |
506 __ access_local_double( G3_scratch, Ftos_d ); | |
507 } | |
508 | |
509 | |
510 void TemplateTable::aload() { | |
511 transition(vtos, atos); | |
512 locals_index(G3_scratch); | |
513 __ access_local_ptr( G3_scratch, Otos_i); | |
514 } | |
515 | |
516 | |
517 void TemplateTable::wide_iload() { | |
518 transition(vtos, itos); | |
519 locals_index_wide(G3_scratch); | |
520 __ access_local_int( G3_scratch, Otos_i ); | |
521 } | |
522 | |
523 | |
524 void TemplateTable::wide_lload() { | |
525 transition(vtos, ltos); | |
526 locals_index_wide(G3_scratch); | |
527 __ access_local_long( G3_scratch, Otos_l ); | |
528 } | |
529 | |
530 | |
531 void TemplateTable::wide_fload() { | |
532 transition(vtos, ftos); | |
533 locals_index_wide(G3_scratch); | |
534 __ access_local_float( G3_scratch, Ftos_f ); | |
535 } | |
536 | |
537 | |
538 void TemplateTable::wide_dload() { | |
539 transition(vtos, dtos); | |
540 locals_index_wide(G3_scratch); | |
541 __ access_local_double( G3_scratch, Ftos_d ); | |
542 } | |
543 | |
544 | |
545 void TemplateTable::wide_aload() { | |
546 transition(vtos, atos); | |
547 locals_index_wide(G3_scratch); | |
548 __ access_local_ptr( G3_scratch, Otos_i ); | |
549 __ verify_oop(Otos_i); | |
550 } | |
551 | |
552 | |
553 void TemplateTable::iaload() { | |
554 transition(itos, itos); | |
555 // Otos_i: index | |
556 // tos: array | |
557 __ index_check(O2, Otos_i, LogBytesPerInt, G3_scratch, O3); | |
558 __ ld(O3, arrayOopDesc::base_offset_in_bytes(T_INT), Otos_i); | |
559 } | |
560 | |
561 | |
562 void TemplateTable::laload() { | |
563 transition(itos, ltos); | |
564 // Otos_i: index | |
565 // O2: array | |
566 __ index_check(O2, Otos_i, LogBytesPerLong, G3_scratch, O3); | |
567 __ ld_long(O3, arrayOopDesc::base_offset_in_bytes(T_LONG), Otos_l); | |
568 } | |
569 | |
570 | |
571 void TemplateTable::faload() { | |
572 transition(itos, ftos); | |
573 // Otos_i: index | |
574 // O2: array | |
575 __ index_check(O2, Otos_i, LogBytesPerInt, G3_scratch, O3); | |
576 __ ldf(FloatRegisterImpl::S, O3, arrayOopDesc::base_offset_in_bytes(T_FLOAT), Ftos_f); | |
577 } | |
578 | |
579 | |
580 void TemplateTable::daload() { | |
581 transition(itos, dtos); | |
582 // Otos_i: index | |
583 // O2: array | |
584 __ index_check(O2, Otos_i, LogBytesPerLong, G3_scratch, O3); | |
585 __ ldf(FloatRegisterImpl::D, O3, arrayOopDesc::base_offset_in_bytes(T_DOUBLE), Ftos_d); | |
586 } | |
587 | |
588 | |
589 void TemplateTable::aaload() { | |
590 transition(itos, atos); | |
591 // Otos_i: index | |
592 // tos: array | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
593 __ index_check(O2, Otos_i, UseCompressedOops ? 2 : LogBytesPerWord, G3_scratch, O3); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
594 __ load_heap_oop(O3, arrayOopDesc::base_offset_in_bytes(T_OBJECT), Otos_i); |
0 | 595 __ verify_oop(Otos_i); |
596 } | |
597 | |
598 | |
599 void TemplateTable::baload() { | |
600 transition(itos, itos); | |
601 // Otos_i: index | |
602 // tos: array | |
603 __ index_check(O2, Otos_i, 0, G3_scratch, O3); | |
604 __ ldsb(O3, arrayOopDesc::base_offset_in_bytes(T_BYTE), Otos_i); | |
605 } | |
606 | |
607 | |
608 void TemplateTable::caload() { | |
609 transition(itos, itos); | |
610 // Otos_i: index | |
611 // tos: array | |
612 __ index_check(O2, Otos_i, LogBytesPerShort, G3_scratch, O3); | |
613 __ lduh(O3, arrayOopDesc::base_offset_in_bytes(T_CHAR), Otos_i); | |
614 } | |
615 | |
616 void TemplateTable::fast_icaload() { | |
617 transition(vtos, itos); | |
618 // Otos_i: index | |
619 // tos: array | |
620 locals_index(G3_scratch); | |
621 __ access_local_int( G3_scratch, Otos_i ); | |
622 __ index_check(O2, Otos_i, LogBytesPerShort, G3_scratch, O3); | |
623 __ lduh(O3, arrayOopDesc::base_offset_in_bytes(T_CHAR), Otos_i); | |
624 } | |
625 | |
626 | |
627 void TemplateTable::saload() { | |
628 transition(itos, itos); | |
629 // Otos_i: index | |
630 // tos: array | |
631 __ index_check(O2, Otos_i, LogBytesPerShort, G3_scratch, O3); | |
632 __ ldsh(O3, arrayOopDesc::base_offset_in_bytes(T_SHORT), Otos_i); | |
633 } | |
634 | |
635 | |
636 void TemplateTable::iload(int n) { | |
637 transition(vtos, itos); | |
638 __ ld( Llocals, Interpreter::local_offset_in_bytes(n), Otos_i ); | |
639 } | |
640 | |
641 | |
642 void TemplateTable::lload(int n) { | |
643 transition(vtos, ltos); | |
644 assert(n+1 < Argument::n_register_parameters, "would need more code"); | |
645 __ load_unaligned_long(Llocals, Interpreter::local_offset_in_bytes(n+1), Otos_l); | |
646 } | |
647 | |
648 | |
649 void TemplateTable::fload(int n) { | |
650 transition(vtos, ftos); | |
651 assert(n < Argument::n_register_parameters, "would need more code"); | |
652 __ ldf( FloatRegisterImpl::S, Llocals, Interpreter::local_offset_in_bytes(n), Ftos_f ); | |
653 } | |
654 | |
655 | |
656 void TemplateTable::dload(int n) { | |
657 transition(vtos, dtos); | |
658 FloatRegister dst = Ftos_d; | |
659 __ load_unaligned_double(Llocals, Interpreter::local_offset_in_bytes(n+1), dst); | |
660 } | |
661 | |
662 | |
663 void TemplateTable::aload(int n) { | |
664 transition(vtos, atos); | |
665 __ ld_ptr( Llocals, Interpreter::local_offset_in_bytes(n), Otos_i ); | |
666 } | |
667 | |
668 | |
669 void TemplateTable::aload_0() { | |
670 transition(vtos, atos); | |
671 | |
672 // According to bytecode histograms, the pairs: | |
673 // | |
674 // _aload_0, _fast_igetfield (itos) | |
675 // _aload_0, _fast_agetfield (atos) | |
676 // _aload_0, _fast_fgetfield (ftos) | |
677 // | |
678 // occur frequently. If RewriteFrequentPairs is set, the (slow) _aload_0 | |
679 // bytecode checks the next bytecode and then rewrites the current | |
680 // bytecode into a pair bytecode; otherwise it rewrites the current | |
681 // bytecode into _fast_aload_0 that doesn't do the pair check anymore. | |
682 // | |
683 if (RewriteFrequentPairs) { | |
684 Label rewrite, done; | |
685 | |
686 // get next byte | |
687 __ ldub(at_bcp(Bytecodes::length_for(Bytecodes::_aload_0)), G3_scratch); | |
688 | |
689 // do actual aload_0 | |
690 aload(0); | |
691 | |
692 // if _getfield then wait with rewrite | |
693 __ cmp(G3_scratch, (int)Bytecodes::_getfield); | |
694 __ br(Assembler::equal, false, Assembler::pn, done); | |
695 __ delayed()->nop(); | |
696 | |
697 // if _igetfield then rewrite to _fast_iaccess_0 | |
698 assert(Bytecodes::java_code(Bytecodes::_fast_iaccess_0) == Bytecodes::_aload_0, "adjust fast bytecode def"); | |
699 __ cmp(G3_scratch, (int)Bytecodes::_fast_igetfield); | |
700 __ br(Assembler::equal, false, Assembler::pn, rewrite); | |
701 __ delayed()->set(Bytecodes::_fast_iaccess_0, G4_scratch); | |
702 | |
703 // if _agetfield then rewrite to _fast_aaccess_0 | |
704 assert(Bytecodes::java_code(Bytecodes::_fast_aaccess_0) == Bytecodes::_aload_0, "adjust fast bytecode def"); | |
705 __ cmp(G3_scratch, (int)Bytecodes::_fast_agetfield); | |
706 __ br(Assembler::equal, false, Assembler::pn, rewrite); | |
707 __ delayed()->set(Bytecodes::_fast_aaccess_0, G4_scratch); | |
708 | |
709 // if _fgetfield then rewrite to _fast_faccess_0 | |
710 assert(Bytecodes::java_code(Bytecodes::_fast_faccess_0) == Bytecodes::_aload_0, "adjust fast bytecode def"); | |
711 __ cmp(G3_scratch, (int)Bytecodes::_fast_fgetfield); | |
712 __ br(Assembler::equal, false, Assembler::pn, rewrite); | |
713 __ delayed()->set(Bytecodes::_fast_faccess_0, G4_scratch); | |
714 | |
715 // else rewrite to _fast_aload0 | |
716 assert(Bytecodes::java_code(Bytecodes::_fast_aload_0) == Bytecodes::_aload_0, "adjust fast bytecode def"); | |
717 __ set(Bytecodes::_fast_aload_0, G4_scratch); | |
718 | |
719 // rewrite | |
720 // G4_scratch: fast bytecode | |
721 __ bind(rewrite); | |
722 patch_bytecode(Bytecodes::_aload_0, G4_scratch, G3_scratch, false); | |
723 __ bind(done); | |
724 } else { | |
725 aload(0); | |
726 } | |
727 } | |
728 | |
729 | |
730 void TemplateTable::istore() { | |
731 transition(itos, vtos); | |
732 locals_index(G3_scratch); | |
733 __ store_local_int( G3_scratch, Otos_i ); | |
734 } | |
735 | |
736 | |
737 void TemplateTable::lstore() { | |
738 transition(ltos, vtos); | |
739 locals_index(G3_scratch); | |
740 __ store_local_long( G3_scratch, Otos_l ); | |
741 } | |
742 | |
743 | |
744 void TemplateTable::fstore() { | |
745 transition(ftos, vtos); | |
746 locals_index(G3_scratch); | |
747 __ store_local_float( G3_scratch, Ftos_f ); | |
748 } | |
749 | |
750 | |
751 void TemplateTable::dstore() { | |
752 transition(dtos, vtos); | |
753 locals_index(G3_scratch); | |
754 __ store_local_double( G3_scratch, Ftos_d ); | |
755 } | |
756 | |
757 | |
758 void TemplateTable::astore() { | |
759 transition(vtos, vtos); | |
1506 | 760 __ load_ptr(0, Otos_i); |
761 __ inc(Lesp, Interpreter::stackElementSize); | |
0 | 762 __ verify_oop_or_return_address(Otos_i, G3_scratch); |
763 locals_index(G3_scratch); | |
1506 | 764 __ store_local_ptr(G3_scratch, Otos_i); |
0 | 765 } |
766 | |
767 | |
768 void TemplateTable::wide_istore() { | |
769 transition(vtos, vtos); | |
770 __ pop_i(); | |
771 locals_index_wide(G3_scratch); | |
772 __ store_local_int( G3_scratch, Otos_i ); | |
773 } | |
774 | |
775 | |
776 void TemplateTable::wide_lstore() { | |
777 transition(vtos, vtos); | |
778 __ pop_l(); | |
779 locals_index_wide(G3_scratch); | |
780 __ store_local_long( G3_scratch, Otos_l ); | |
781 } | |
782 | |
783 | |
784 void TemplateTable::wide_fstore() { | |
785 transition(vtos, vtos); | |
786 __ pop_f(); | |
787 locals_index_wide(G3_scratch); | |
788 __ store_local_float( G3_scratch, Ftos_f ); | |
789 } | |
790 | |
791 | |
792 void TemplateTable::wide_dstore() { | |
793 transition(vtos, vtos); | |
794 __ pop_d(); | |
795 locals_index_wide(G3_scratch); | |
796 __ store_local_double( G3_scratch, Ftos_d ); | |
797 } | |
798 | |
799 | |
800 void TemplateTable::wide_astore() { | |
801 transition(vtos, vtos); | |
1506 | 802 __ load_ptr(0, Otos_i); |
803 __ inc(Lesp, Interpreter::stackElementSize); | |
0 | 804 __ verify_oop_or_return_address(Otos_i, G3_scratch); |
805 locals_index_wide(G3_scratch); | |
1506 | 806 __ store_local_ptr(G3_scratch, Otos_i); |
0 | 807 } |
808 | |
809 | |
810 void TemplateTable::iastore() { | |
811 transition(itos, vtos); | |
812 __ pop_i(O2); // index | |
813 // Otos_i: val | |
814 // O3: array | |
815 __ index_check(O3, O2, LogBytesPerInt, G3_scratch, O2); | |
816 __ st(Otos_i, O2, arrayOopDesc::base_offset_in_bytes(T_INT)); | |
817 } | |
818 | |
819 | |
820 void TemplateTable::lastore() { | |
821 transition(ltos, vtos); | |
822 __ pop_i(O2); // index | |
823 // Otos_l: val | |
824 // O3: array | |
825 __ index_check(O3, O2, LogBytesPerLong, G3_scratch, O2); | |
826 __ st_long(Otos_l, O2, arrayOopDesc::base_offset_in_bytes(T_LONG)); | |
827 } | |
828 | |
829 | |
830 void TemplateTable::fastore() { | |
831 transition(ftos, vtos); | |
832 __ pop_i(O2); // index | |
833 // Ftos_f: val | |
834 // O3: array | |
835 __ index_check(O3, O2, LogBytesPerInt, G3_scratch, O2); | |
836 __ stf(FloatRegisterImpl::S, Ftos_f, O2, arrayOopDesc::base_offset_in_bytes(T_FLOAT)); | |
837 } | |
838 | |
839 | |
840 void TemplateTable::dastore() { | |
841 transition(dtos, vtos); | |
842 __ pop_i(O2); // index | |
843 // Fos_d: val | |
844 // O3: array | |
845 __ index_check(O3, O2, LogBytesPerLong, G3_scratch, O2); | |
846 __ stf(FloatRegisterImpl::D, Ftos_d, O2, arrayOopDesc::base_offset_in_bytes(T_DOUBLE)); | |
847 } | |
848 | |
849 | |
850 void TemplateTable::aastore() { | |
851 Label store_ok, is_null, done; | |
852 transition(vtos, vtos); | |
853 __ ld_ptr(Lesp, Interpreter::expr_offset_in_bytes(0), Otos_i); | |
854 __ ld(Lesp, Interpreter::expr_offset_in_bytes(1), O2); // get index | |
855 __ ld_ptr(Lesp, Interpreter::expr_offset_in_bytes(2), O3); // get array | |
856 // Otos_i: val | |
857 // O2: index | |
858 // O3: array | |
859 __ verify_oop(Otos_i); | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
860 __ index_check_without_pop(O3, O2, UseCompressedOops ? 2 : LogBytesPerWord, G3_scratch, O1); |
0 | 861 |
862 // do array store check - check for NULL value first | |
863 __ br_null( Otos_i, false, Assembler::pn, is_null ); | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
864 __ delayed()->nop(); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
865 |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
866 __ load_klass(O3, O4); // get array klass |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
867 __ load_klass(Otos_i, O5); // get value klass |
0 | 868 |
869 // do fast instanceof cache test | |
870 | |
871 __ ld_ptr(O4, sizeof(oopDesc) + objArrayKlass::element_klass_offset_in_bytes(), O4); | |
872 | |
873 assert(Otos_i == O0, "just checking"); | |
874 | |
875 // Otos_i: value | |
876 // O1: addr - offset | |
877 // O2: index | |
878 // O3: array | |
879 // O4: array element klass | |
880 // O5: value klass | |
881 | |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
882 // Address element(O1, 0, arrayOopDesc::base_offset_in_bytes(T_OBJECT)); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
883 |
0 | 884 // Generate a fast subtype check. Branch to store_ok if no |
885 // failure. Throw if failure. | |
886 __ gen_subtype_check( O5, O4, G3_scratch, G4_scratch, G1_scratch, store_ok ); | |
887 | |
888 // Not a subtype; so must throw exception | |
889 __ throw_if_not_x( Assembler::never, Interpreter::_throw_ArrayStoreException_entry, G3_scratch ); | |
890 | |
891 // Store is OK. | |
892 __ bind(store_ok); | |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
893 do_oop_store(_masm, O1, noreg, arrayOopDesc::base_offset_in_bytes(T_OBJECT), Otos_i, G3_scratch, _bs->kind(), true); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
894 |
0 | 895 __ ba(false,done); |
1506 | 896 __ delayed()->inc(Lesp, 3* Interpreter::stackElementSize); // adj sp (pops array, index and value) |
0 | 897 |
898 __ bind(is_null); | |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
899 do_oop_store(_masm, O1, noreg, arrayOopDesc::base_offset_in_bytes(T_OBJECT), G0, G4_scratch, _bs->kind(), true); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
900 |
0 | 901 __ profile_null_seen(G3_scratch); |
1506 | 902 __ inc(Lesp, 3* Interpreter::stackElementSize); // adj sp (pops array, index and value) |
0 | 903 __ bind(done); |
904 } | |
905 | |
906 | |
907 void TemplateTable::bastore() { | |
908 transition(itos, vtos); | |
909 __ pop_i(O2); // index | |
910 // Otos_i: val | |
911 // O3: array | |
912 __ index_check(O3, O2, 0, G3_scratch, O2); | |
913 __ stb(Otos_i, O2, arrayOopDesc::base_offset_in_bytes(T_BYTE)); | |
914 } | |
915 | |
916 | |
917 void TemplateTable::castore() { | |
918 transition(itos, vtos); | |
919 __ pop_i(O2); // index | |
920 // Otos_i: val | |
921 // O3: array | |
922 __ index_check(O3, O2, LogBytesPerShort, G3_scratch, O2); | |
923 __ sth(Otos_i, O2, arrayOopDesc::base_offset_in_bytes(T_CHAR)); | |
924 } | |
925 | |
926 | |
927 void TemplateTable::sastore() { | |
928 // %%%%% Factor across platform | |
929 castore(); | |
930 } | |
931 | |
932 | |
933 void TemplateTable::istore(int n) { | |
934 transition(itos, vtos); | |
935 __ st(Otos_i, Llocals, Interpreter::local_offset_in_bytes(n)); | |
936 } | |
937 | |
938 | |
939 void TemplateTable::lstore(int n) { | |
940 transition(ltos, vtos); | |
941 assert(n+1 < Argument::n_register_parameters, "only handle register cases"); | |
942 __ store_unaligned_long(Otos_l, Llocals, Interpreter::local_offset_in_bytes(n+1)); | |
943 | |
944 } | |
945 | |
946 | |
947 void TemplateTable::fstore(int n) { | |
948 transition(ftos, vtos); | |
949 assert(n < Argument::n_register_parameters, "only handle register cases"); | |
950 __ stf(FloatRegisterImpl::S, Ftos_f, Llocals, Interpreter::local_offset_in_bytes(n)); | |
951 } | |
952 | |
953 | |
954 void TemplateTable::dstore(int n) { | |
955 transition(dtos, vtos); | |
956 FloatRegister src = Ftos_d; | |
957 __ store_unaligned_double(src, Llocals, Interpreter::local_offset_in_bytes(n+1)); | |
958 } | |
959 | |
960 | |
961 void TemplateTable::astore(int n) { | |
962 transition(vtos, vtos); | |
1506 | 963 __ load_ptr(0, Otos_i); |
964 __ inc(Lesp, Interpreter::stackElementSize); | |
0 | 965 __ verify_oop_or_return_address(Otos_i, G3_scratch); |
1506 | 966 __ store_local_ptr(n, Otos_i); |
0 | 967 } |
968 | |
969 | |
970 void TemplateTable::pop() { | |
971 transition(vtos, vtos); | |
1506 | 972 __ inc(Lesp, Interpreter::stackElementSize); |
0 | 973 } |
974 | |
975 | |
976 void TemplateTable::pop2() { | |
977 transition(vtos, vtos); | |
1506 | 978 __ inc(Lesp, 2 * Interpreter::stackElementSize); |
0 | 979 } |
980 | |
981 | |
982 void TemplateTable::dup() { | |
983 transition(vtos, vtos); | |
984 // stack: ..., a | |
985 // load a and tag | |
1506 | 986 __ load_ptr(0, Otos_i); |
987 __ push_ptr(Otos_i); | |
0 | 988 // stack: ..., a, a |
989 } | |
990 | |
991 | |
992 void TemplateTable::dup_x1() { | |
993 transition(vtos, vtos); | |
994 // stack: ..., a, b | |
1506 | 995 __ load_ptr( 1, G3_scratch); // get a |
996 __ load_ptr( 0, Otos_l1); // get b | |
997 __ store_ptr(1, Otos_l1); // put b | |
998 __ store_ptr(0, G3_scratch); // put a - like swap | |
999 __ push_ptr(Otos_l1); // push b | |
0 | 1000 // stack: ..., b, a, b |
1001 } | |
1002 | |
1003 | |
1004 void TemplateTable::dup_x2() { | |
1005 transition(vtos, vtos); | |
1006 // stack: ..., a, b, c | |
1007 // get c and push on stack, reuse registers | |
1506 | 1008 __ load_ptr( 0, G3_scratch); // get c |
1009 __ push_ptr(G3_scratch); // push c with tag | |
0 | 1010 // stack: ..., a, b, c, c (c in reg) (Lesp - 4) |
1011 // (stack offsets n+1 now) | |
1506 | 1012 __ load_ptr( 3, Otos_l1); // get a |
1013 __ store_ptr(3, G3_scratch); // put c at 3 | |
0 | 1014 // stack: ..., c, b, c, c (a in reg) |
1506 | 1015 __ load_ptr( 2, G3_scratch); // get b |
1016 __ store_ptr(2, Otos_l1); // put a at 2 | |
0 | 1017 // stack: ..., c, a, c, c (b in reg) |
1506 | 1018 __ store_ptr(1, G3_scratch); // put b at 1 |
0 | 1019 // stack: ..., c, a, b, c |
1020 } | |
1021 | |
1022 | |
1023 void TemplateTable::dup2() { | |
1024 transition(vtos, vtos); | |
1506 | 1025 __ load_ptr(1, G3_scratch); // get a |
1026 __ load_ptr(0, Otos_l1); // get b | |
1027 __ push_ptr(G3_scratch); // push a | |
1028 __ push_ptr(Otos_l1); // push b | |
0 | 1029 // stack: ..., a, b, a, b |
1030 } | |
1031 | |
1032 | |
1033 void TemplateTable::dup2_x1() { | |
1034 transition(vtos, vtos); | |
1035 // stack: ..., a, b, c | |
1506 | 1036 __ load_ptr( 1, Lscratch); // get b |
1037 __ load_ptr( 2, Otos_l1); // get a | |
1038 __ store_ptr(2, Lscratch); // put b at a | |
0 | 1039 // stack: ..., b, b, c |
1506 | 1040 __ load_ptr( 0, G3_scratch); // get c |
1041 __ store_ptr(1, G3_scratch); // put c at b | |
0 | 1042 // stack: ..., b, c, c |
1506 | 1043 __ store_ptr(0, Otos_l1); // put a at c |
0 | 1044 // stack: ..., b, c, a |
1506 | 1045 __ push_ptr(Lscratch); // push b |
1046 __ push_ptr(G3_scratch); // push c | |
0 | 1047 // stack: ..., b, c, a, b, c |
1048 } | |
1049 | |
1050 | |
1051 // The spec says that these types can be a mixture of category 1 (1 word) | |
1052 // types and/or category 2 types (long and doubles) | |
1053 void TemplateTable::dup2_x2() { | |
1054 transition(vtos, vtos); | |
1055 // stack: ..., a, b, c, d | |
1506 | 1056 __ load_ptr( 1, Lscratch); // get c |
1057 __ load_ptr( 3, Otos_l1); // get a | |
1058 __ store_ptr(3, Lscratch); // put c at 3 | |
1059 __ store_ptr(1, Otos_l1); // put a at 1 | |
0 | 1060 // stack: ..., c, b, a, d |
1506 | 1061 __ load_ptr( 2, G3_scratch); // get b |
1062 __ load_ptr( 0, Otos_l1); // get d | |
1063 __ store_ptr(0, G3_scratch); // put b at 0 | |
1064 __ store_ptr(2, Otos_l1); // put d at 2 | |
0 | 1065 // stack: ..., c, d, a, b |
1506 | 1066 __ push_ptr(Lscratch); // push c |
1067 __ push_ptr(Otos_l1); // push d | |
0 | 1068 // stack: ..., c, d, a, b, c, d |
1069 } | |
1070 | |
1071 | |
1072 void TemplateTable::swap() { | |
1073 transition(vtos, vtos); | |
1074 // stack: ..., a, b | |
1506 | 1075 __ load_ptr( 1, G3_scratch); // get a |
1076 __ load_ptr( 0, Otos_l1); // get b | |
1077 __ store_ptr(0, G3_scratch); // put b | |
1078 __ store_ptr(1, Otos_l1); // put a | |
0 | 1079 // stack: ..., b, a |
1080 } | |
1081 | |
1082 | |
1083 void TemplateTable::iop2(Operation op) { | |
1084 transition(itos, itos); | |
1085 __ pop_i(O1); | |
1086 switch (op) { | |
1087 case add: __ add(O1, Otos_i, Otos_i); break; | |
1088 case sub: __ sub(O1, Otos_i, Otos_i); break; | |
1089 // %%%%% Mul may not exist: better to call .mul? | |
1090 case mul: __ smul(O1, Otos_i, Otos_i); break; | |
1506 | 1091 case _and: __ and3(O1, Otos_i, Otos_i); break; |
1092 case _or: __ or3(O1, Otos_i, Otos_i); break; | |
1093 case _xor: __ xor3(O1, Otos_i, Otos_i); break; | |
0 | 1094 case shl: __ sll(O1, Otos_i, Otos_i); break; |
1095 case shr: __ sra(O1, Otos_i, Otos_i); break; | |
1096 case ushr: __ srl(O1, Otos_i, Otos_i); break; | |
1097 default: ShouldNotReachHere(); | |
1098 } | |
1099 } | |
1100 | |
1101 | |
1102 void TemplateTable::lop2(Operation op) { | |
1103 transition(ltos, ltos); | |
1104 __ pop_l(O2); | |
1105 switch (op) { | |
1106 #ifdef _LP64 | |
1506 | 1107 case add: __ add(O2, Otos_l, Otos_l); break; |
1108 case sub: __ sub(O2, Otos_l, Otos_l); break; | |
1109 case _and: __ and3(O2, Otos_l, Otos_l); break; | |
1110 case _or: __ or3(O2, Otos_l, Otos_l); break; | |
1111 case _xor: __ xor3(O2, Otos_l, Otos_l); break; | |
0 | 1112 #else |
1113 case add: __ addcc(O3, Otos_l2, Otos_l2); __ addc(O2, Otos_l1, Otos_l1); break; | |
1114 case sub: __ subcc(O3, Otos_l2, Otos_l2); __ subc(O2, Otos_l1, Otos_l1); break; | |
1506 | 1115 case _and: __ and3(O3, Otos_l2, Otos_l2); __ and3(O2, Otos_l1, Otos_l1); break; |
1116 case _or: __ or3(O3, Otos_l2, Otos_l2); __ or3(O2, Otos_l1, Otos_l1); break; | |
1117 case _xor: __ xor3(O3, Otos_l2, Otos_l2); __ xor3(O2, Otos_l1, Otos_l1); break; | |
0 | 1118 #endif |
1119 default: ShouldNotReachHere(); | |
1120 } | |
1121 } | |
1122 | |
1123 | |
1124 void TemplateTable::idiv() { | |
1125 // %%%%% Later: ForSPARC/V7 call .sdiv library routine, | |
1126 // %%%%% Use ldsw...sdivx on pure V9 ABI. 64 bit safe. | |
1127 | |
1128 transition(itos, itos); | |
1129 __ pop_i(O1); // get 1st op | |
1130 | |
1131 // Y contains upper 32 bits of result, set it to 0 or all ones | |
1132 __ wry(G0); | |
1133 __ mov(~0, G3_scratch); | |
1134 | |
1135 __ tst(O1); | |
1136 Label neg; | |
1137 __ br(Assembler::negative, true, Assembler::pn, neg); | |
1138 __ delayed()->wry(G3_scratch); | |
1139 __ bind(neg); | |
1140 | |
1141 Label ok; | |
1142 __ tst(Otos_i); | |
1143 __ throw_if_not_icc( Assembler::notZero, Interpreter::_throw_ArithmeticException_entry, G3_scratch ); | |
1144 | |
1145 const int min_int = 0x80000000; | |
1146 Label regular; | |
1147 __ cmp(Otos_i, -1); | |
1148 __ br(Assembler::notEqual, false, Assembler::pt, regular); | |
1149 #ifdef _LP64 | |
1150 // Don't put set in delay slot | |
1151 // Set will turn into multiple instructions in 64 bit mode | |
1152 __ delayed()->nop(); | |
1153 __ set(min_int, G4_scratch); | |
1154 #else | |
1155 __ delayed()->set(min_int, G4_scratch); | |
1156 #endif | |
1157 Label done; | |
1158 __ cmp(O1, G4_scratch); | |
1159 __ br(Assembler::equal, true, Assembler::pt, done); | |
1160 __ delayed()->mov(O1, Otos_i); // (mov only executed if branch taken) | |
1161 | |
1162 __ bind(regular); | |
1163 __ sdiv(O1, Otos_i, Otos_i); // note: irem uses O1 after this instruction! | |
1164 __ bind(done); | |
1165 } | |
1166 | |
1167 | |
1168 void TemplateTable::irem() { | |
1169 transition(itos, itos); | |
1170 __ mov(Otos_i, O2); // save divisor | |
1171 idiv(); // %%%% Hack: exploits fact that idiv leaves dividend in O1 | |
1172 __ smul(Otos_i, O2, Otos_i); | |
1173 __ sub(O1, Otos_i, Otos_i); | |
1174 } | |
1175 | |
1176 | |
1177 void TemplateTable::lmul() { | |
1178 transition(ltos, ltos); | |
1179 __ pop_l(O2); | |
1180 #ifdef _LP64 | |
1181 __ mulx(Otos_l, O2, Otos_l); | |
1182 #else | |
1183 __ call_VM_leaf(Lscratch, CAST_FROM_FN_PTR(address, SharedRuntime::lmul)); | |
1184 #endif | |
1185 | |
1186 } | |
1187 | |
1188 | |
1189 void TemplateTable::ldiv() { | |
1190 transition(ltos, ltos); | |
1191 | |
1192 // check for zero | |
1193 __ pop_l(O2); | |
1194 #ifdef _LP64 | |
1195 __ tst(Otos_l); | |
1196 __ throw_if_not_xcc( Assembler::notZero, Interpreter::_throw_ArithmeticException_entry, G3_scratch); | |
1197 __ sdivx(O2, Otos_l, Otos_l); | |
1198 #else | |
1199 __ orcc(Otos_l1, Otos_l2, G0); | |
1200 __ throw_if_not_icc( Assembler::notZero, Interpreter::_throw_ArithmeticException_entry, G3_scratch); | |
1201 __ call_VM_leaf(Lscratch, CAST_FROM_FN_PTR(address, SharedRuntime::ldiv)); | |
1202 #endif | |
1203 } | |
1204 | |
1205 | |
1206 void TemplateTable::lrem() { | |
1207 transition(ltos, ltos); | |
1208 | |
1209 // check for zero | |
1210 __ pop_l(O2); | |
1211 #ifdef _LP64 | |
1212 __ tst(Otos_l); | |
1213 __ throw_if_not_xcc( Assembler::notZero, Interpreter::_throw_ArithmeticException_entry, G3_scratch); | |
1214 __ sdivx(O2, Otos_l, Otos_l2); | |
1215 __ mulx (Otos_l2, Otos_l, Otos_l2); | |
1216 __ sub (O2, Otos_l2, Otos_l); | |
1217 #else | |
1218 __ orcc(Otos_l1, Otos_l2, G0); | |
1219 __ throw_if_not_icc(Assembler::notZero, Interpreter::_throw_ArithmeticException_entry, G3_scratch); | |
1220 __ call_VM_leaf(Lscratch, CAST_FROM_FN_PTR(address, SharedRuntime::lrem)); | |
1221 #endif | |
1222 } | |
1223 | |
1224 | |
1225 void TemplateTable::lshl() { | |
1226 transition(itos, ltos); // %%%% could optimize, fill delay slot or opt for ultra | |
1227 | |
1228 __ pop_l(O2); // shift value in O2, O3 | |
1229 #ifdef _LP64 | |
1230 __ sllx(O2, Otos_i, Otos_l); | |
1231 #else | |
1232 __ lshl(O2, O3, Otos_i, Otos_l1, Otos_l2, O4); | |
1233 #endif | |
1234 } | |
1235 | |
1236 | |
1237 void TemplateTable::lshr() { | |
1238 transition(itos, ltos); // %%%% see lshl comment | |
1239 | |
1240 __ pop_l(O2); // shift value in O2, O3 | |
1241 #ifdef _LP64 | |
1242 __ srax(O2, Otos_i, Otos_l); | |
1243 #else | |
1244 __ lshr(O2, O3, Otos_i, Otos_l1, Otos_l2, O4); | |
1245 #endif | |
1246 } | |
1247 | |
1248 | |
1249 | |
1250 void TemplateTable::lushr() { | |
1251 transition(itos, ltos); // %%%% see lshl comment | |
1252 | |
1253 __ pop_l(O2); // shift value in O2, O3 | |
1254 #ifdef _LP64 | |
1255 __ srlx(O2, Otos_i, Otos_l); | |
1256 #else | |
1257 __ lushr(O2, O3, Otos_i, Otos_l1, Otos_l2, O4); | |
1258 #endif | |
1259 } | |
1260 | |
1261 | |
1262 void TemplateTable::fop2(Operation op) { | |
1263 transition(ftos, ftos); | |
1264 switch (op) { | |
1265 case add: __ pop_f(F4); __ fadd(FloatRegisterImpl::S, F4, Ftos_f, Ftos_f); break; | |
1266 case sub: __ pop_f(F4); __ fsub(FloatRegisterImpl::S, F4, Ftos_f, Ftos_f); break; | |
1267 case mul: __ pop_f(F4); __ fmul(FloatRegisterImpl::S, F4, Ftos_f, Ftos_f); break; | |
1268 case div: __ pop_f(F4); __ fdiv(FloatRegisterImpl::S, F4, Ftos_f, Ftos_f); break; | |
1269 case rem: | |
1270 assert(Ftos_f == F0, "just checking"); | |
1271 #ifdef _LP64 | |
1272 // LP64 calling conventions use F1, F3 for passing 2 floats | |
1273 __ pop_f(F1); | |
1274 __ fmov(FloatRegisterImpl::S, Ftos_f, F3); | |
1275 #else | |
1276 __ pop_i(O0); | |
1277 __ stf(FloatRegisterImpl::S, Ftos_f, __ d_tmp); | |
1278 __ ld( __ d_tmp, O1 ); | |
1279 #endif | |
1280 __ call_VM_leaf(Lscratch, CAST_FROM_FN_PTR(address, SharedRuntime::frem)); | |
1281 assert( Ftos_f == F0, "fix this code" ); | |
1282 break; | |
1283 | |
1284 default: ShouldNotReachHere(); | |
1285 } | |
1286 } | |
1287 | |
1288 | |
1289 void TemplateTable::dop2(Operation op) { | |
1290 transition(dtos, dtos); | |
1291 switch (op) { | |
1292 case add: __ pop_d(F4); __ fadd(FloatRegisterImpl::D, F4, Ftos_d, Ftos_d); break; | |
1293 case sub: __ pop_d(F4); __ fsub(FloatRegisterImpl::D, F4, Ftos_d, Ftos_d); break; | |
1294 case mul: __ pop_d(F4); __ fmul(FloatRegisterImpl::D, F4, Ftos_d, Ftos_d); break; | |
1295 case div: __ pop_d(F4); __ fdiv(FloatRegisterImpl::D, F4, Ftos_d, Ftos_d); break; | |
1296 case rem: | |
1297 #ifdef _LP64 | |
1298 // Pass arguments in D0, D2 | |
1299 __ fmov(FloatRegisterImpl::D, Ftos_f, F2 ); | |
1300 __ pop_d( F0 ); | |
1301 #else | |
1302 // Pass arguments in O0O1, O2O3 | |
1303 __ stf(FloatRegisterImpl::D, Ftos_f, __ d_tmp); | |
1304 __ ldd( __ d_tmp, O2 ); | |
1305 __ pop_d(Ftos_f); | |
1306 __ stf(FloatRegisterImpl::D, Ftos_f, __ d_tmp); | |
1307 __ ldd( __ d_tmp, O0 ); | |
1308 #endif | |
1309 __ call_VM_leaf(Lscratch, CAST_FROM_FN_PTR(address, SharedRuntime::drem)); | |
1310 assert( Ftos_d == F0, "fix this code" ); | |
1311 break; | |
1312 | |
1313 default: ShouldNotReachHere(); | |
1314 } | |
1315 } | |
1316 | |
1317 | |
1318 void TemplateTable::ineg() { | |
1319 transition(itos, itos); | |
1320 __ neg(Otos_i); | |
1321 } | |
1322 | |
1323 | |
1324 void TemplateTable::lneg() { | |
1325 transition(ltos, ltos); | |
1326 #ifdef _LP64 | |
1327 __ sub(G0, Otos_l, Otos_l); | |
1328 #else | |
1329 __ lneg(Otos_l1, Otos_l2); | |
1330 #endif | |
1331 } | |
1332 | |
1333 | |
1334 void TemplateTable::fneg() { | |
1335 transition(ftos, ftos); | |
1336 __ fneg(FloatRegisterImpl::S, Ftos_f); | |
1337 } | |
1338 | |
1339 | |
1340 void TemplateTable::dneg() { | |
1341 transition(dtos, dtos); | |
1342 // v8 has fnegd if source and dest are the same | |
1343 __ fneg(FloatRegisterImpl::D, Ftos_f); | |
1344 } | |
1345 | |
1346 | |
1347 void TemplateTable::iinc() { | |
1348 transition(vtos, vtos); | |
1349 locals_index(G3_scratch); | |
1350 __ ldsb(Lbcp, 2, O2); // load constant | |
1351 __ access_local_int(G3_scratch, Otos_i); | |
1352 __ add(Otos_i, O2, Otos_i); | |
1506 | 1353 __ st(Otos_i, G3_scratch, 0); // access_local_int puts E.A. in G3_scratch |
0 | 1354 } |
1355 | |
1356 | |
1357 void TemplateTable::wide_iinc() { | |
1358 transition(vtos, vtos); | |
1359 locals_index_wide(G3_scratch); | |
1360 __ get_2_byte_integer_at_bcp( 4, O2, O3, InterpreterMacroAssembler::Signed); | |
1361 __ access_local_int(G3_scratch, Otos_i); | |
1362 __ add(Otos_i, O3, Otos_i); | |
1506 | 1363 __ st(Otos_i, G3_scratch, 0); // access_local_int puts E.A. in G3_scratch |
0 | 1364 } |
1365 | |
1366 | |
1367 void TemplateTable::convert() { | |
1368 // %%%%% Factor this first part accross platforms | |
1369 #ifdef ASSERT | |
1370 TosState tos_in = ilgl; | |
1371 TosState tos_out = ilgl; | |
1372 switch (bytecode()) { | |
1373 case Bytecodes::_i2l: // fall through | |
1374 case Bytecodes::_i2f: // fall through | |
1375 case Bytecodes::_i2d: // fall through | |
1376 case Bytecodes::_i2b: // fall through | |
1377 case Bytecodes::_i2c: // fall through | |
1378 case Bytecodes::_i2s: tos_in = itos; break; | |
1379 case Bytecodes::_l2i: // fall through | |
1380 case Bytecodes::_l2f: // fall through | |
1381 case Bytecodes::_l2d: tos_in = ltos; break; | |
1382 case Bytecodes::_f2i: // fall through | |
1383 case Bytecodes::_f2l: // fall through | |
1384 case Bytecodes::_f2d: tos_in = ftos; break; | |
1385 case Bytecodes::_d2i: // fall through | |
1386 case Bytecodes::_d2l: // fall through | |
1387 case Bytecodes::_d2f: tos_in = dtos; break; | |
1388 default : ShouldNotReachHere(); | |
1389 } | |
1390 switch (bytecode()) { | |
1391 case Bytecodes::_l2i: // fall through | |
1392 case Bytecodes::_f2i: // fall through | |
1393 case Bytecodes::_d2i: // fall through | |
1394 case Bytecodes::_i2b: // fall through | |
1395 case Bytecodes::_i2c: // fall through | |
1396 case Bytecodes::_i2s: tos_out = itos; break; | |
1397 case Bytecodes::_i2l: // fall through | |
1398 case Bytecodes::_f2l: // fall through | |
1399 case Bytecodes::_d2l: tos_out = ltos; break; | |
1400 case Bytecodes::_i2f: // fall through | |
1401 case Bytecodes::_l2f: // fall through | |
1402 case Bytecodes::_d2f: tos_out = ftos; break; | |
1403 case Bytecodes::_i2d: // fall through | |
1404 case Bytecodes::_l2d: // fall through | |
1405 case Bytecodes::_f2d: tos_out = dtos; break; | |
1406 default : ShouldNotReachHere(); | |
1407 } | |
1408 transition(tos_in, tos_out); | |
1409 #endif | |
1410 | |
1411 | |
1412 // Conversion | |
1413 Label done; | |
1414 switch (bytecode()) { | |
1415 case Bytecodes::_i2l: | |
1416 #ifdef _LP64 | |
1417 // Sign extend the 32 bits | |
1418 __ sra ( Otos_i, 0, Otos_l ); | |
1419 #else | |
1420 __ addcc(Otos_i, 0, Otos_l2); | |
1421 __ br(Assembler::greaterEqual, true, Assembler::pt, done); | |
1422 __ delayed()->clr(Otos_l1); | |
1423 __ set(~0, Otos_l1); | |
1424 #endif | |
1425 break; | |
1426 | |
1427 case Bytecodes::_i2f: | |
1428 __ st(Otos_i, __ d_tmp ); | |
1429 __ ldf(FloatRegisterImpl::S, __ d_tmp, F0); | |
1430 __ fitof(FloatRegisterImpl::S, F0, Ftos_f); | |
1431 break; | |
1432 | |
1433 case Bytecodes::_i2d: | |
1434 __ st(Otos_i, __ d_tmp); | |
1435 __ ldf(FloatRegisterImpl::S, __ d_tmp, F0); | |
1436 __ fitof(FloatRegisterImpl::D, F0, Ftos_f); | |
1437 break; | |
1438 | |
1439 case Bytecodes::_i2b: | |
1440 __ sll(Otos_i, 24, Otos_i); | |
1441 __ sra(Otos_i, 24, Otos_i); | |
1442 break; | |
1443 | |
1444 case Bytecodes::_i2c: | |
1445 __ sll(Otos_i, 16, Otos_i); | |
1446 __ srl(Otos_i, 16, Otos_i); | |
1447 break; | |
1448 | |
1449 case Bytecodes::_i2s: | |
1450 __ sll(Otos_i, 16, Otos_i); | |
1451 __ sra(Otos_i, 16, Otos_i); | |
1452 break; | |
1453 | |
1454 case Bytecodes::_l2i: | |
1455 #ifndef _LP64 | |
1456 __ mov(Otos_l2, Otos_i); | |
1457 #else | |
1458 // Sign-extend into the high 32 bits | |
1459 __ sra(Otos_l, 0, Otos_i); | |
1460 #endif | |
1461 break; | |
1462 | |
1463 case Bytecodes::_l2f: | |
1464 case Bytecodes::_l2d: | |
1465 __ st_long(Otos_l, __ d_tmp); | |
1466 __ ldf(FloatRegisterImpl::D, __ d_tmp, Ftos_d); | |
1467 | |
1468 if (VM_Version::v9_instructions_work()) { | |
1469 if (bytecode() == Bytecodes::_l2f) { | |
1470 __ fxtof(FloatRegisterImpl::S, Ftos_d, Ftos_f); | |
1471 } else { | |
1472 __ fxtof(FloatRegisterImpl::D, Ftos_d, Ftos_d); | |
1473 } | |
1474 } else { | |
1475 __ call_VM_leaf( | |
1476 Lscratch, | |
1477 bytecode() == Bytecodes::_l2f | |
1478 ? CAST_FROM_FN_PTR(address, SharedRuntime::l2f) | |
1479 : CAST_FROM_FN_PTR(address, SharedRuntime::l2d) | |
1480 ); | |
1481 } | |
1482 break; | |
1483 | |
1484 case Bytecodes::_f2i: { | |
1485 Label isNaN; | |
1486 // result must be 0 if value is NaN; test by comparing value to itself | |
1487 __ fcmp(FloatRegisterImpl::S, Assembler::fcc0, Ftos_f, Ftos_f); | |
1488 // According to the v8 manual, you have to have a non-fp instruction | |
1489 // between fcmp and fb. | |
1490 if (!VM_Version::v9_instructions_work()) { | |
1491 __ nop(); | |
1492 } | |
1493 __ fb(Assembler::f_unordered, true, Assembler::pn, isNaN); | |
1494 __ delayed()->clr(Otos_i); // NaN | |
1495 __ ftoi(FloatRegisterImpl::S, Ftos_f, F30); | |
1496 __ stf(FloatRegisterImpl::S, F30, __ d_tmp); | |
1497 __ ld(__ d_tmp, Otos_i); | |
1498 __ bind(isNaN); | |
1499 } | |
1500 break; | |
1501 | |
1502 case Bytecodes::_f2l: | |
1503 // must uncache tos | |
1504 __ push_f(); | |
1505 #ifdef _LP64 | |
1506 __ pop_f(F1); | |
1507 #else | |
1508 __ pop_i(O0); | |
1509 #endif | |
1510 __ call_VM_leaf(Lscratch, CAST_FROM_FN_PTR(address, SharedRuntime::f2l)); | |
1511 break; | |
1512 | |
1513 case Bytecodes::_f2d: | |
1514 __ ftof( FloatRegisterImpl::S, FloatRegisterImpl::D, Ftos_f, Ftos_f); | |
1515 break; | |
1516 | |
1517 case Bytecodes::_d2i: | |
1518 case Bytecodes::_d2l: | |
1519 // must uncache tos | |
1520 __ push_d(); | |
1521 #ifdef _LP64 | |
1522 // LP64 calling conventions pass first double arg in D0 | |
1523 __ pop_d( Ftos_d ); | |
1524 #else | |
1525 __ pop_i( O0 ); | |
1526 __ pop_i( O1 ); | |
1527 #endif | |
1528 __ call_VM_leaf(Lscratch, | |
1529 bytecode() == Bytecodes::_d2i | |
1530 ? CAST_FROM_FN_PTR(address, SharedRuntime::d2i) | |
1531 : CAST_FROM_FN_PTR(address, SharedRuntime::d2l)); | |
1532 break; | |
1533 | |
1534 case Bytecodes::_d2f: | |
1535 if (VM_Version::v9_instructions_work()) { | |
1536 __ ftof( FloatRegisterImpl::D, FloatRegisterImpl::S, Ftos_d, Ftos_f); | |
1537 } | |
1538 else { | |
1539 // must uncache tos | |
1540 __ push_d(); | |
1541 __ pop_i(O0); | |
1542 __ pop_i(O1); | |
1543 __ call_VM_leaf(Lscratch, CAST_FROM_FN_PTR(address, SharedRuntime::d2f)); | |
1544 } | |
1545 break; | |
1546 | |
1547 default: ShouldNotReachHere(); | |
1548 } | |
1549 __ bind(done); | |
1550 } | |
1551 | |
1552 | |
1553 void TemplateTable::lcmp() { | |
1554 transition(ltos, itos); | |
1555 | |
1556 #ifdef _LP64 | |
1557 __ pop_l(O1); // pop off value 1, value 2 is in O0 | |
1558 __ lcmp( O1, Otos_l, Otos_i ); | |
1559 #else | |
1560 __ pop_l(O2); // cmp O2,3 to O0,1 | |
1561 __ lcmp( O2, O3, Otos_l1, Otos_l2, Otos_i ); | |
1562 #endif | |
1563 } | |
1564 | |
1565 | |
1566 void TemplateTable::float_cmp(bool is_float, int unordered_result) { | |
1567 | |
1568 if (is_float) __ pop_f(F2); | |
1569 else __ pop_d(F2); | |
1570 | |
1571 assert(Ftos_f == F0 && Ftos_d == F0, "alias checking:"); | |
1572 | |
1573 __ float_cmp( is_float, unordered_result, F2, F0, Otos_i ); | |
1574 } | |
1575 | |
1576 void TemplateTable::branch(bool is_jsr, bool is_wide) { | |
1577 // Note: on SPARC, we use InterpreterMacroAssembler::if_cmp also. | |
1578 __ verify_oop(Lmethod); | |
1579 __ verify_thread(); | |
1580 | |
1581 const Register O2_bumped_count = O2; | |
1582 __ profile_taken_branch(G3_scratch, O2_bumped_count); | |
1583 | |
1584 // get (wide) offset to O1_disp | |
1585 const Register O1_disp = O1; | |
1586 if (is_wide) __ get_4_byte_integer_at_bcp( 1, G4_scratch, O1_disp, InterpreterMacroAssembler::set_CC); | |
1587 else __ get_2_byte_integer_at_bcp( 1, G4_scratch, O1_disp, InterpreterMacroAssembler::Signed, InterpreterMacroAssembler::set_CC); | |
1588 | |
1589 // Handle all the JSR stuff here, then exit. | |
1590 // It's much shorter and cleaner than intermingling with the | |
605 | 1591 // non-JSR normal-branch stuff occurring below. |
0 | 1592 if( is_jsr ) { |
1593 // compute return address as bci in Otos_i | |
727 | 1594 __ ld_ptr(Lmethod, methodOopDesc::const_offset(), G3_scratch); |
0 | 1595 __ sub(Lbcp, G3_scratch, G3_scratch); |
1596 __ sub(G3_scratch, in_bytes(constMethodOopDesc::codes_offset()) - (is_wide ? 5 : 3), Otos_i); | |
1597 | |
1598 // Bump Lbcp to target of JSR | |
1599 __ add(Lbcp, O1_disp, Lbcp); | |
1600 // Push returnAddress for "ret" on stack | |
1506 | 1601 __ push_ptr(Otos_i); |
0 | 1602 // And away we go! |
1603 __ dispatch_next(vtos); | |
1604 return; | |
1605 } | |
1606 | |
1607 // Normal (non-jsr) branch handling | |
1608 | |
1609 // Save the current Lbcp | |
1610 const Register O0_cur_bcp = O0; | |
1611 __ mov( Lbcp, O0_cur_bcp ); | |
1612 | |
1783 | 1613 |
0 | 1614 bool increment_invocation_counter_for_backward_branches = UseCompiler && UseLoopCounter; |
1615 if ( increment_invocation_counter_for_backward_branches ) { | |
1616 Label Lforward; | |
1617 // check branch direction | |
1618 __ br( Assembler::positive, false, Assembler::pn, Lforward ); | |
1619 // Bump bytecode pointer by displacement (take the branch) | |
1620 __ delayed()->add( O1_disp, Lbcp, Lbcp ); // add to bc addr | |
1621 | |
1783 | 1622 if (TieredCompilation) { |
1623 Label Lno_mdo, Loverflow; | |
1624 int increment = InvocationCounter::count_increment; | |
1625 int mask = ((1 << Tier0BackedgeNotifyFreqLog) - 1) << InvocationCounter::count_shift; | |
1626 if (ProfileInterpreter) { | |
1627 // If no method data exists, go to profile_continue. | |
1628 __ ld_ptr(Lmethod, methodOopDesc::method_data_offset(), G4_scratch); | |
1629 __ br_null(G4_scratch, false, Assembler::pn, Lno_mdo); | |
1630 __ delayed()->nop(); | |
1631 | |
1632 // Increment backedge counter in the MDO | |
1633 Address mdo_backedge_counter(G4_scratch, in_bytes(methodDataOopDesc::backedge_counter_offset()) + | |
1634 in_bytes(InvocationCounter::counter_offset())); | |
1635 __ increment_mask_and_jump(mdo_backedge_counter, increment, mask, G3_scratch, Lscratch, | |
1636 Assembler::notZero, &Lforward); | |
1637 __ ba(false, Loverflow); | |
1638 __ delayed()->nop(); | |
0 | 1639 } |
1783 | 1640 |
1641 // If there's no MDO, increment counter in methodOop | |
1642 __ bind(Lno_mdo); | |
1643 Address backedge_counter(Lmethod, in_bytes(methodOopDesc::backedge_counter_offset()) + | |
1644 in_bytes(InvocationCounter::counter_offset())); | |
1645 __ increment_mask_and_jump(backedge_counter, increment, mask, G3_scratch, Lscratch, | |
1646 Assembler::notZero, &Lforward); | |
1647 __ bind(Loverflow); | |
1648 | |
1649 // notify point for loop, pass branch bytecode | |
1650 __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::frequency_counter_overflow), O0_cur_bcp); | |
1651 | |
1652 // Was an OSR adapter generated? | |
1653 // O0 = osr nmethod | |
1654 __ br_null(O0, false, Assembler::pn, Lforward); | |
1655 __ delayed()->nop(); | |
1656 | |
1657 // Has the nmethod been invalidated already? | |
1658 __ ld(O0, nmethod::entry_bci_offset(), O2); | |
1659 __ cmp(O2, InvalidOSREntryBci); | |
1660 __ br(Assembler::equal, false, Assembler::pn, Lforward); | |
1661 __ delayed()->nop(); | |
1662 | |
1663 // migrate the interpreter frame off of the stack | |
1664 | |
1665 __ mov(G2_thread, L7); | |
1666 // save nmethod | |
1667 __ mov(O0, L6); | |
1668 __ set_last_Java_frame(SP, noreg); | |
1669 __ call_VM_leaf(noreg, CAST_FROM_FN_PTR(address, SharedRuntime::OSR_migration_begin), L7); | |
1670 __ reset_last_Java_frame(); | |
1671 __ mov(L7, G2_thread); | |
1672 | |
1673 // move OSR nmethod to I1 | |
1674 __ mov(L6, I1); | |
1675 | |
1676 // OSR buffer to I0 | |
1677 __ mov(O0, I0); | |
1678 | |
1679 // remove the interpreter frame | |
1680 __ restore(I5_savedSP, 0, SP); | |
1681 | |
1682 // Jump to the osr code. | |
1683 __ ld_ptr(O1, nmethod::osr_entry_point_offset(), O2); | |
1684 __ jmp(O2, G0); | |
1685 __ delayed()->nop(); | |
1686 | |
0 | 1687 } else { |
1783 | 1688 // Update Backedge branch separately from invocations |
1689 const Register G4_invoke_ctr = G4; | |
1690 __ increment_backedge_counter(G4_invoke_ctr, G1_scratch); | |
1691 if (ProfileInterpreter) { | |
2118
dd031b2226de
4930919: race condition in MDO creation at back branch locations
iveresov
parents:
1972
diff
changeset
|
1692 __ test_invocation_counter_for_mdp(G4_invoke_ctr, G3_scratch, Lforward); |
1783 | 1693 if (UseOnStackReplacement) { |
1694 __ test_backedge_count_for_osr(O2_bumped_count, O0_cur_bcp, G3_scratch); | |
1695 } | |
1696 } else { | |
1697 if (UseOnStackReplacement) { | |
1698 __ test_backedge_count_for_osr(G4_invoke_ctr, O0_cur_bcp, G3_scratch); | |
1699 } | |
0 | 1700 } |
1701 } | |
1702 | |
1703 __ bind(Lforward); | |
1704 } else | |
1705 // Bump bytecode pointer by displacement (take the branch) | |
1706 __ add( O1_disp, Lbcp, Lbcp );// add to bc addr | |
1707 | |
1708 // continue with bytecode @ target | |
1709 // %%%%% Like Intel, could speed things up by moving bytecode fetch to code above, | |
1710 // %%%%% and changing dispatch_next to dispatch_only | |
1711 __ dispatch_next(vtos); | |
1712 } | |
1713 | |
1714 | |
1715 // Note Condition in argument is TemplateTable::Condition | |
1716 // arg scope is within class scope | |
1717 | |
1718 void TemplateTable::if_0cmp(Condition cc) { | |
1719 // no pointers, integer only! | |
1720 transition(itos, vtos); | |
1721 // assume branch is more often taken than not (loops use backward branches) | |
1722 __ cmp( Otos_i, 0); | |
1723 __ if_cmp(ccNot(cc), false); | |
1724 } | |
1725 | |
1726 | |
1727 void TemplateTable::if_icmp(Condition cc) { | |
1728 transition(itos, vtos); | |
1729 __ pop_i(O1); | |
1730 __ cmp(O1, Otos_i); | |
1731 __ if_cmp(ccNot(cc), false); | |
1732 } | |
1733 | |
1734 | |
1735 void TemplateTable::if_nullcmp(Condition cc) { | |
1736 transition(atos, vtos); | |
1737 __ tst(Otos_i); | |
1738 __ if_cmp(ccNot(cc), true); | |
1739 } | |
1740 | |
1741 | |
1742 void TemplateTable::if_acmp(Condition cc) { | |
1743 transition(atos, vtos); | |
1744 __ pop_ptr(O1); | |
1745 __ verify_oop(O1); | |
1746 __ verify_oop(Otos_i); | |
1747 __ cmp(O1, Otos_i); | |
1748 __ if_cmp(ccNot(cc), true); | |
1749 } | |
1750 | |
1751 | |
1752 | |
1753 void TemplateTable::ret() { | |
1754 transition(vtos, vtos); | |
1755 locals_index(G3_scratch); | |
1756 __ access_local_returnAddress(G3_scratch, Otos_i); | |
1757 // Otos_i contains the bci, compute the bcp from that | |
1758 | |
1759 #ifdef _LP64 | |
1760 #ifdef ASSERT | |
1761 // jsr result was labeled as an 'itos' not an 'atos' because we cannot GC | |
1762 // the result. The return address (really a BCI) was stored with an | |
1763 // 'astore' because JVM specs claim it's a pointer-sized thing. Hence in | |
1764 // the 64-bit build the 32-bit BCI is actually in the low bits of a 64-bit | |
1765 // loaded value. | |
1766 { Label zzz ; | |
1767 __ set (65536, G3_scratch) ; | |
1768 __ cmp (Otos_i, G3_scratch) ; | |
1769 __ bp( Assembler::lessEqualUnsigned, false, Assembler::xcc, Assembler::pn, zzz); | |
1770 __ delayed()->nop(); | |
1771 __ stop("BCI is in the wrong register half?"); | |
1772 __ bind (zzz) ; | |
1773 } | |
1774 #endif | |
1775 #endif | |
1776 | |
1777 __ profile_ret(vtos, Otos_i, G4_scratch); | |
1778 | |
727 | 1779 __ ld_ptr(Lmethod, methodOopDesc::const_offset(), G3_scratch); |
0 | 1780 __ add(G3_scratch, Otos_i, G3_scratch); |
1781 __ add(G3_scratch, in_bytes(constMethodOopDesc::codes_offset()), Lbcp); | |
1782 __ dispatch_next(vtos); | |
1783 } | |
1784 | |
1785 | |
1786 void TemplateTable::wide_ret() { | |
1787 transition(vtos, vtos); | |
1788 locals_index_wide(G3_scratch); | |
1789 __ access_local_returnAddress(G3_scratch, Otos_i); | |
1790 // Otos_i contains the bci, compute the bcp from that | |
1791 | |
1792 __ profile_ret(vtos, Otos_i, G4_scratch); | |
1793 | |
727 | 1794 __ ld_ptr(Lmethod, methodOopDesc::const_offset(), G3_scratch); |
0 | 1795 __ add(G3_scratch, Otos_i, G3_scratch); |
1796 __ add(G3_scratch, in_bytes(constMethodOopDesc::codes_offset()), Lbcp); | |
1797 __ dispatch_next(vtos); | |
1798 } | |
1799 | |
1800 | |
1801 void TemplateTable::tableswitch() { | |
1802 transition(itos, vtos); | |
1803 Label default_case, continue_execution; | |
1804 | |
1805 // align bcp | |
1806 __ add(Lbcp, BytesPerInt, O1); | |
1807 __ and3(O1, -BytesPerInt, O1); | |
1808 // load lo, hi | |
1809 __ ld(O1, 1 * BytesPerInt, O2); // Low Byte | |
1810 __ ld(O1, 2 * BytesPerInt, O3); // High Byte | |
1811 #ifdef _LP64 | |
1812 // Sign extend the 32 bits | |
1813 __ sra ( Otos_i, 0, Otos_i ); | |
1814 #endif /* _LP64 */ | |
1815 | |
1816 // check against lo & hi | |
1817 __ cmp( Otos_i, O2); | |
1818 __ br( Assembler::less, false, Assembler::pn, default_case); | |
1819 __ delayed()->cmp( Otos_i, O3 ); | |
1820 __ br( Assembler::greater, false, Assembler::pn, default_case); | |
1821 // lookup dispatch offset | |
1822 __ delayed()->sub(Otos_i, O2, O2); | |
1823 __ profile_switch_case(O2, O3, G3_scratch, G4_scratch); | |
1824 __ sll(O2, LogBytesPerInt, O2); | |
1825 __ add(O2, 3 * BytesPerInt, O2); | |
1826 __ ba(false, continue_execution); | |
1827 __ delayed()->ld(O1, O2, O2); | |
1828 // handle default | |
1829 __ bind(default_case); | |
1830 __ profile_switch_default(O3); | |
1831 __ ld(O1, 0, O2); // get default offset | |
1832 // continue execution | |
1833 __ bind(continue_execution); | |
1834 __ add(Lbcp, O2, Lbcp); | |
1835 __ dispatch_next(vtos); | |
1836 } | |
1837 | |
1838 | |
1839 void TemplateTable::lookupswitch() { | |
1840 transition(itos, itos); | |
1841 __ stop("lookupswitch bytecode should have been rewritten"); | |
1842 } | |
1843 | |
1844 void TemplateTable::fast_linearswitch() { | |
1845 transition(itos, vtos); | |
1846 Label loop_entry, loop, found, continue_execution; | |
1847 // align bcp | |
1848 __ add(Lbcp, BytesPerInt, O1); | |
1849 __ and3(O1, -BytesPerInt, O1); | |
1850 // set counter | |
1851 __ ld(O1, BytesPerInt, O2); | |
1852 __ sll(O2, LogBytesPerInt + 1, O2); // in word-pairs | |
1853 __ add(O1, 2 * BytesPerInt, O3); // set first pair addr | |
1854 __ ba(false, loop_entry); | |
1855 __ delayed()->add(O3, O2, O2); // counter now points past last pair | |
1856 | |
1857 // table search | |
1858 __ bind(loop); | |
1859 __ cmp(O4, Otos_i); | |
1860 __ br(Assembler::equal, true, Assembler::pn, found); | |
1861 __ delayed()->ld(O3, BytesPerInt, O4); // offset -> O4 | |
1862 __ inc(O3, 2 * BytesPerInt); | |
1863 | |
1864 __ bind(loop_entry); | |
1865 __ cmp(O2, O3); | |
1866 __ brx(Assembler::greaterUnsigned, true, Assembler::pt, loop); | |
1867 __ delayed()->ld(O3, 0, O4); | |
1868 | |
1869 // default case | |
1870 __ ld(O1, 0, O4); // get default offset | |
1871 if (ProfileInterpreter) { | |
1872 __ profile_switch_default(O3); | |
1873 __ ba(false, continue_execution); | |
1874 __ delayed()->nop(); | |
1875 } | |
1876 | |
1877 // entry found -> get offset | |
1878 __ bind(found); | |
1879 if (ProfileInterpreter) { | |
1880 __ sub(O3, O1, O3); | |
1881 __ sub(O3, 2*BytesPerInt, O3); | |
1882 __ srl(O3, LogBytesPerInt + 1, O3); // in word-pairs | |
1883 __ profile_switch_case(O3, O1, O2, G3_scratch); | |
1884 | |
1885 __ bind(continue_execution); | |
1886 } | |
1887 __ add(Lbcp, O4, Lbcp); | |
1888 __ dispatch_next(vtos); | |
1889 } | |
1890 | |
1891 | |
1892 void TemplateTable::fast_binaryswitch() { | |
1893 transition(itos, vtos); | |
1894 // Implementation using the following core algorithm: (copied from Intel) | |
1895 // | |
1896 // int binary_search(int key, LookupswitchPair* array, int n) { | |
1897 // // Binary search according to "Methodik des Programmierens" by | |
1898 // // Edsger W. Dijkstra and W.H.J. Feijen, Addison Wesley Germany 1985. | |
1899 // int i = 0; | |
1900 // int j = n; | |
1901 // while (i+1 < j) { | |
1902 // // invariant P: 0 <= i < j <= n and (a[i] <= key < a[j] or Q) | |
1903 // // with Q: for all i: 0 <= i < n: key < a[i] | |
1904 // // where a stands for the array and assuming that the (inexisting) | |
1905 // // element a[n] is infinitely big. | |
1906 // int h = (i + j) >> 1; | |
1907 // // i < h < j | |
1908 // if (key < array[h].fast_match()) { | |
1909 // j = h; | |
1910 // } else { | |
1911 // i = h; | |
1912 // } | |
1913 // } | |
1914 // // R: a[i] <= key < a[i+1] or Q | |
1915 // // (i.e., if key is within array, i is the correct index) | |
1916 // return i; | |
1917 // } | |
1918 | |
1919 // register allocation | |
1920 assert(Otos_i == O0, "alias checking"); | |
1921 const Register Rkey = Otos_i; // already set (tosca) | |
1922 const Register Rarray = O1; | |
1923 const Register Ri = O2; | |
1924 const Register Rj = O3; | |
1925 const Register Rh = O4; | |
1926 const Register Rscratch = O5; | |
1927 | |
1928 const int log_entry_size = 3; | |
1929 const int entry_size = 1 << log_entry_size; | |
1930 | |
1931 Label found; | |
1932 // Find Array start | |
1933 __ add(Lbcp, 3 * BytesPerInt, Rarray); | |
1934 __ and3(Rarray, -BytesPerInt, Rarray); | |
1935 // initialize i & j (in delay slot) | |
1936 __ clr( Ri ); | |
1937 | |
1938 // and start | |
1939 Label entry; | |
1940 __ ba(false, entry); | |
1941 __ delayed()->ld( Rarray, -BytesPerInt, Rj); | |
1942 // (Rj is already in the native byte-ordering.) | |
1943 | |
1944 // binary search loop | |
1945 { Label loop; | |
1946 __ bind( loop ); | |
1947 // int h = (i + j) >> 1; | |
1948 __ sra( Rh, 1, Rh ); | |
1949 // if (key < array[h].fast_match()) { | |
1950 // j = h; | |
1951 // } else { | |
1952 // i = h; | |
1953 // } | |
1954 __ sll( Rh, log_entry_size, Rscratch ); | |
1955 __ ld( Rarray, Rscratch, Rscratch ); | |
1956 // (Rscratch is already in the native byte-ordering.) | |
1957 __ cmp( Rkey, Rscratch ); | |
1958 if ( VM_Version::v9_instructions_work() ) { | |
1959 __ movcc( Assembler::less, false, Assembler::icc, Rh, Rj ); // j = h if (key < array[h].fast_match()) | |
1960 __ movcc( Assembler::greaterEqual, false, Assembler::icc, Rh, Ri ); // i = h if (key >= array[h].fast_match()) | |
1961 } | |
1962 else { | |
1963 Label end_of_if; | |
1964 __ br( Assembler::less, true, Assembler::pt, end_of_if ); | |
1965 __ delayed()->mov( Rh, Rj ); // if (<) Rj = Rh | |
1966 __ mov( Rh, Ri ); // else i = h | |
1967 __ bind(end_of_if); // } | |
1968 } | |
1969 | |
1970 // while (i+1 < j) | |
1971 __ bind( entry ); | |
1972 __ add( Ri, 1, Rscratch ); | |
1973 __ cmp(Rscratch, Rj); | |
1974 __ br( Assembler::less, true, Assembler::pt, loop ); | |
1975 __ delayed()->add( Ri, Rj, Rh ); // start h = i + j >> 1; | |
1976 } | |
1977 | |
1978 // end of binary search, result index is i (must check again!) | |
1979 Label default_case; | |
1980 Label continue_execution; | |
1981 if (ProfileInterpreter) { | |
1982 __ mov( Ri, Rh ); // Save index in i for profiling | |
1983 } | |
1984 __ sll( Ri, log_entry_size, Ri ); | |
1985 __ ld( Rarray, Ri, Rscratch ); | |
1986 // (Rscratch is already in the native byte-ordering.) | |
1987 __ cmp( Rkey, Rscratch ); | |
1988 __ br( Assembler::notEqual, true, Assembler::pn, default_case ); | |
1989 __ delayed()->ld( Rarray, -2 * BytesPerInt, Rj ); // load default offset -> j | |
1990 | |
1991 // entry found -> j = offset | |
1992 __ inc( Ri, BytesPerInt ); | |
1993 __ profile_switch_case(Rh, Rj, Rscratch, Rkey); | |
1994 __ ld( Rarray, Ri, Rj ); | |
1995 // (Rj is already in the native byte-ordering.) | |
1996 | |
1997 if (ProfileInterpreter) { | |
1998 __ ba(false, continue_execution); | |
1999 __ delayed()->nop(); | |
2000 } | |
2001 | |
2002 __ bind(default_case); // fall through (if not profiling) | |
2003 __ profile_switch_default(Ri); | |
2004 | |
2005 __ bind(continue_execution); | |
2006 __ add( Lbcp, Rj, Lbcp ); | |
2007 __ dispatch_next( vtos ); | |
2008 } | |
2009 | |
2010 | |
2011 void TemplateTable::_return(TosState state) { | |
2012 transition(state, state); | |
2013 assert(_desc->calls_vm(), "inconsistent calls_vm information"); | |
2014 | |
2015 if (_desc->bytecode() == Bytecodes::_return_register_finalizer) { | |
2016 assert(state == vtos, "only valid state"); | |
2017 __ mov(G0, G3_scratch); | |
2018 __ access_local_ptr(G3_scratch, Otos_i); | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
2019 __ load_klass(Otos_i, O2); |
0 | 2020 __ set(JVM_ACC_HAS_FINALIZER, G3); |
2021 __ ld(O2, Klass::access_flags_offset_in_bytes() + sizeof(oopDesc), O2); | |
2022 __ andcc(G3, O2, G0); | |
2023 Label skip_register_finalizer; | |
2024 __ br(Assembler::zero, false, Assembler::pn, skip_register_finalizer); | |
2025 __ delayed()->nop(); | |
2026 | |
2027 // Call out to do finalizer registration | |
2028 __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::register_finalizer), Otos_i); | |
2029 | |
2030 __ bind(skip_register_finalizer); | |
2031 } | |
2032 | |
2033 __ remove_activation(state, /* throw_monitor_exception */ true); | |
2034 | |
2035 // The caller's SP was adjusted upon method entry to accomodate | |
2036 // the callee's non-argument locals. Undo that adjustment. | |
2037 __ ret(); // return to caller | |
2038 __ delayed()->restore(I5_savedSP, G0, SP); | |
2039 } | |
2040 | |
2041 | |
2042 // ---------------------------------------------------------------------------- | |
2043 // Volatile variables demand their effects be made known to all CPU's in | |
2044 // order. Store buffers on most chips allow reads & writes to reorder; the | |
2045 // JMM's ReadAfterWrite.java test fails in -Xint mode without some kind of | |
2046 // memory barrier (i.e., it's not sufficient that the interpreter does not | |
2047 // reorder volatile references, the hardware also must not reorder them). | |
2048 // | |
2049 // According to the new Java Memory Model (JMM): | |
2050 // (1) All volatiles are serialized wrt to each other. | |
2051 // ALSO reads & writes act as aquire & release, so: | |
2052 // (2) A read cannot let unrelated NON-volatile memory refs that happen after | |
2053 // the read float up to before the read. It's OK for non-volatile memory refs | |
2054 // that happen before the volatile read to float down below it. | |
2055 // (3) Similar a volatile write cannot let unrelated NON-volatile memory refs | |
2056 // that happen BEFORE the write float down to after the write. It's OK for | |
2057 // non-volatile memory refs that happen after the volatile write to float up | |
2058 // before it. | |
2059 // | |
2060 // We only put in barriers around volatile refs (they are expensive), not | |
2061 // _between_ memory refs (that would require us to track the flavor of the | |
2062 // previous memory refs). Requirements (2) and (3) require some barriers | |
2063 // before volatile stores and after volatile loads. These nearly cover | |
2064 // requirement (1) but miss the volatile-store-volatile-load case. This final | |
2065 // case is placed after volatile-stores although it could just as well go | |
2066 // before volatile-loads. | |
2067 void TemplateTable::volatile_barrier(Assembler::Membar_mask_bits order_constraint) { | |
2068 // Helper function to insert a is-volatile test and memory barrier | |
2069 // All current sparc implementations run in TSO, needing only StoreLoad | |
2070 if ((order_constraint & Assembler::StoreLoad) == 0) return; | |
2071 __ membar( order_constraint ); | |
2072 } | |
2073 | |
2074 // ---------------------------------------------------------------------------- | |
1565 | 2075 void TemplateTable::resolve_cache_and_index(int byte_no, |
2076 Register result, | |
2077 Register Rcache, | |
2078 Register index, | |
2079 size_t index_size) { | |
0 | 2080 // Depends on cpCacheOop layout! |
2081 Label resolved; | |
2082 | |
1565 | 2083 __ get_cache_and_index_at_bcp(Rcache, index, 1, index_size); |
2084 if (byte_no == f1_oop) { | |
2085 // We are resolved if the f1 field contains a non-null object (CallSite, etc.) | |
2086 // This kind of CP cache entry does not need to match the flags byte, because | |
2087 // there is a 1-1 relation between bytecode type and CP entry type. | |
2088 assert_different_registers(result, Rcache); | |
1503 | 2089 __ ld_ptr(Rcache, constantPoolCacheOopDesc::base_offset() + |
1565 | 2090 ConstantPoolCacheEntry::f1_offset(), result); |
2091 __ tst(result); | |
1503 | 2092 __ br(Assembler::notEqual, false, Assembler::pt, resolved); |
2093 __ delayed()->set((int)bytecode(), O1); | |
2094 } else { | |
1565 | 2095 assert(byte_no == f1_byte || byte_no == f2_byte, "byte_no out of range"); |
2096 assert(result == noreg, ""); //else change code for setting result | |
2097 const int shift_count = (1 + byte_no)*BitsPerByte; | |
2098 | |
1503 | 2099 __ ld_ptr(Rcache, constantPoolCacheOopDesc::base_offset() + |
2100 ConstantPoolCacheEntry::indices_offset(), Lbyte_code); | |
2101 | |
2102 __ srl( Lbyte_code, shift_count, Lbyte_code ); | |
2103 __ and3( Lbyte_code, 0xFF, Lbyte_code ); | |
2104 __ cmp( Lbyte_code, (int)bytecode()); | |
2105 __ br( Assembler::equal, false, Assembler::pt, resolved); | |
2106 __ delayed()->set((int)bytecode(), O1); | |
2107 } | |
0 | 2108 |
2109 address entry; | |
2110 switch (bytecode()) { | |
2111 case Bytecodes::_getstatic : // fall through | |
2112 case Bytecodes::_putstatic : // fall through | |
2113 case Bytecodes::_getfield : // fall through | |
2114 case Bytecodes::_putfield : entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_get_put); break; | |
2115 case Bytecodes::_invokevirtual : // fall through | |
2116 case Bytecodes::_invokespecial : // fall through | |
2117 case Bytecodes::_invokestatic : // fall through | |
2118 case Bytecodes::_invokeinterface: entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_invoke); break; | |
1503 | 2119 case Bytecodes::_invokedynamic : entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_invokedynamic); break; |
1602 | 2120 case Bytecodes::_fast_aldc : entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_ldc); break; |
2121 case Bytecodes::_fast_aldc_w : entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_ldc); break; | |
0 | 2122 default : ShouldNotReachHere(); break; |
2123 } | |
2124 // first time invocation - must resolve first | |
2125 __ call_VM(noreg, entry, O1); | |
2126 // Update registers with resolved info | |
1565 | 2127 __ get_cache_and_index_at_bcp(Rcache, index, 1, index_size); |
2128 if (result != noreg) | |
2129 __ ld_ptr(Rcache, constantPoolCacheOopDesc::base_offset() + | |
2130 ConstantPoolCacheEntry::f1_offset(), result); | |
0 | 2131 __ bind(resolved); |
2132 } | |
2133 | |
2134 void TemplateTable::load_invoke_cp_cache_entry(int byte_no, | |
2135 Register Rmethod, | |
2136 Register Ritable_index, | |
2137 Register Rflags, | |
2138 bool is_invokevirtual, | |
1565 | 2139 bool is_invokevfinal, |
2140 bool is_invokedynamic) { | |
0 | 2141 // Uses both G3_scratch and G4_scratch |
2142 Register Rcache = G3_scratch; | |
2143 Register Rscratch = G4_scratch; | |
2144 assert_different_registers(Rcache, Rmethod, Ritable_index); | |
2145 | |
2146 ByteSize cp_base_offset = constantPoolCacheOopDesc::base_offset(); | |
2147 | |
2148 // determine constant pool cache field offsets | |
2149 const int method_offset = in_bytes( | |
2150 cp_base_offset + | |
2151 (is_invokevirtual | |
2152 ? ConstantPoolCacheEntry::f2_offset() | |
2153 : ConstantPoolCacheEntry::f1_offset() | |
2154 ) | |
2155 ); | |
2156 const int flags_offset = in_bytes(cp_base_offset + | |
2157 ConstantPoolCacheEntry::flags_offset()); | |
2158 // access constant pool cache fields | |
2159 const int index_offset = in_bytes(cp_base_offset + | |
2160 ConstantPoolCacheEntry::f2_offset()); | |
2161 | |
2162 if (is_invokevfinal) { | |
2163 __ get_cache_and_index_at_bcp(Rcache, Rscratch, 1); | |
1565 | 2164 __ ld_ptr(Rcache, method_offset, Rmethod); |
2165 } else if (byte_no == f1_oop) { | |
2166 // Resolved f1_oop goes directly into 'method' register. | |
2167 resolve_cache_and_index(byte_no, Rmethod, Rcache, Rscratch, sizeof(u4)); | |
0 | 2168 } else { |
1565 | 2169 resolve_cache_and_index(byte_no, noreg, Rcache, Rscratch, sizeof(u2)); |
2170 __ ld_ptr(Rcache, method_offset, Rmethod); | |
0 | 2171 } |
2172 | |
2173 if (Ritable_index != noreg) { | |
727 | 2174 __ ld_ptr(Rcache, index_offset, Ritable_index); |
0 | 2175 } |
727 | 2176 __ ld_ptr(Rcache, flags_offset, Rflags); |
0 | 2177 } |
2178 | |
2179 // The Rcache register must be set before call | |
2180 void TemplateTable::load_field_cp_cache_entry(Register Robj, | |
2181 Register Rcache, | |
2182 Register index, | |
2183 Register Roffset, | |
2184 Register Rflags, | |
2185 bool is_static) { | |
2186 assert_different_registers(Rcache, Rflags, Roffset); | |
2187 | |
2188 ByteSize cp_base_offset = constantPoolCacheOopDesc::base_offset(); | |
2189 | |
727 | 2190 __ ld_ptr(Rcache, cp_base_offset + ConstantPoolCacheEntry::flags_offset(), Rflags); |
2191 __ ld_ptr(Rcache, cp_base_offset + ConstantPoolCacheEntry::f2_offset(), Roffset); | |
0 | 2192 if (is_static) { |
727 | 2193 __ ld_ptr(Rcache, cp_base_offset + ConstantPoolCacheEntry::f1_offset(), Robj); |
0 | 2194 } |
2195 } | |
2196 | |
2197 // The registers Rcache and index expected to be set before call. | |
2198 // Correct values of the Rcache and index registers are preserved. | |
2199 void TemplateTable::jvmti_post_field_access(Register Rcache, | |
2200 Register index, | |
2201 bool is_static, | |
2202 bool has_tos) { | |
2203 ByteSize cp_base_offset = constantPoolCacheOopDesc::base_offset(); | |
2204 | |
2205 if (JvmtiExport::can_post_field_access()) { | |
2206 // Check to see if a field access watch has been set before we take | |
2207 // the time to call into the VM. | |
2208 Label Label1; | |
2209 assert_different_registers(Rcache, index, G1_scratch); | |
727 | 2210 AddressLiteral get_field_access_count_addr(JvmtiExport::get_field_access_count_addr()); |
0 | 2211 __ load_contents(get_field_access_count_addr, G1_scratch); |
2212 __ tst(G1_scratch); | |
2213 __ br(Assembler::zero, false, Assembler::pt, Label1); | |
2214 __ delayed()->nop(); | |
2215 | |
2216 __ add(Rcache, in_bytes(cp_base_offset), Rcache); | |
2217 | |
2218 if (is_static) { | |
2219 __ clr(Otos_i); | |
2220 } else { | |
2221 if (has_tos) { | |
2222 // save object pointer before call_VM() clobbers it | |
450
b22701a8b88f
6474243: suspicious jvmti code that uses oop unsafely across GC point
coleenp
parents:
356
diff
changeset
|
2223 __ push_ptr(Otos_i); // put object on tos where GC wants it. |
0 | 2224 } else { |
2225 // Load top of stack (do not pop the value off the stack); | |
2226 __ ld_ptr(Lesp, Interpreter::expr_offset_in_bytes(0), Otos_i); | |
2227 } | |
2228 __ verify_oop(Otos_i); | |
2229 } | |
2230 // Otos_i: object pointer or NULL if static | |
2231 // Rcache: cache entry pointer | |
2232 __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::post_field_access), | |
2233 Otos_i, Rcache); | |
2234 if (!is_static && has_tos) { | |
450
b22701a8b88f
6474243: suspicious jvmti code that uses oop unsafely across GC point
coleenp
parents:
356
diff
changeset
|
2235 __ pop_ptr(Otos_i); // restore object pointer |
0 | 2236 __ verify_oop(Otos_i); |
2237 } | |
2238 __ get_cache_and_index_at_bcp(Rcache, index, 1); | |
2239 __ bind(Label1); | |
2240 } | |
2241 } | |
2242 | |
2243 void TemplateTable::getfield_or_static(int byte_no, bool is_static) { | |
2244 transition(vtos, vtos); | |
2245 | |
2246 Register Rcache = G3_scratch; | |
2247 Register index = G4_scratch; | |
2248 Register Rclass = Rcache; | |
2249 Register Roffset= G4_scratch; | |
2250 Register Rflags = G1_scratch; | |
2251 ByteSize cp_base_offset = constantPoolCacheOopDesc::base_offset(); | |
2252 | |
1565 | 2253 resolve_cache_and_index(byte_no, noreg, Rcache, index, sizeof(u2)); |
0 | 2254 jvmti_post_field_access(Rcache, index, is_static, false); |
2255 load_field_cp_cache_entry(Rclass, Rcache, index, Roffset, Rflags, is_static); | |
2256 | |
2257 if (!is_static) { | |
2258 pop_and_check_object(Rclass); | |
2259 } else { | |
2260 __ verify_oop(Rclass); | |
2261 } | |
2262 | |
2263 Label exit; | |
2264 | |
2265 Assembler::Membar_mask_bits membar_bits = | |
2266 Assembler::Membar_mask_bits(Assembler::LoadLoad | Assembler::LoadStore); | |
2267 | |
2268 if (__ membar_has_effect(membar_bits)) { | |
2269 // Get volatile flag | |
2270 __ set((1 << ConstantPoolCacheEntry::volatileField), Lscratch); | |
2271 __ and3(Rflags, Lscratch, Lscratch); | |
2272 } | |
2273 | |
2274 Label checkVolatile; | |
2275 | |
2276 // compute field type | |
2277 Label notByte, notInt, notShort, notChar, notLong, notFloat, notObj; | |
2278 __ srl(Rflags, ConstantPoolCacheEntry::tosBits, Rflags); | |
2279 // Make sure we don't need to mask Rflags for tosBits after the above shift | |
2280 ConstantPoolCacheEntry::verify_tosBits(); | |
2281 | |
2282 // Check atos before itos for getstatic, more likely (in Queens at least) | |
2283 __ cmp(Rflags, atos); | |
2284 __ br(Assembler::notEqual, false, Assembler::pt, notObj); | |
2285 __ delayed() ->cmp(Rflags, itos); | |
2286 | |
2287 // atos | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
2288 __ load_heap_oop(Rclass, Roffset, Otos_i); |
0 | 2289 __ verify_oop(Otos_i); |
2290 __ push(atos); | |
2291 if (!is_static) { | |
2292 patch_bytecode(Bytecodes::_fast_agetfield, G3_scratch, G4_scratch); | |
2293 } | |
2294 __ ba(false, checkVolatile); | |
2295 __ delayed()->tst(Lscratch); | |
2296 | |
2297 __ bind(notObj); | |
2298 | |
2299 // cmp(Rflags, itos); | |
2300 __ br(Assembler::notEqual, false, Assembler::pt, notInt); | |
2301 __ delayed() ->cmp(Rflags, ltos); | |
2302 | |
2303 // itos | |
2304 __ ld(Rclass, Roffset, Otos_i); | |
2305 __ push(itos); | |
2306 if (!is_static) { | |
2307 patch_bytecode(Bytecodes::_fast_igetfield, G3_scratch, G4_scratch); | |
2308 } | |
2309 __ ba(false, checkVolatile); | |
2310 __ delayed()->tst(Lscratch); | |
2311 | |
2312 __ bind(notInt); | |
2313 | |
2314 // cmp(Rflags, ltos); | |
2315 __ br(Assembler::notEqual, false, Assembler::pt, notLong); | |
2316 __ delayed() ->cmp(Rflags, btos); | |
2317 | |
2318 // ltos | |
2319 // load must be atomic | |
2320 __ ld_long(Rclass, Roffset, Otos_l); | |
2321 __ push(ltos); | |
2322 if (!is_static) { | |
2323 patch_bytecode(Bytecodes::_fast_lgetfield, G3_scratch, G4_scratch); | |
2324 } | |
2325 __ ba(false, checkVolatile); | |
2326 __ delayed()->tst(Lscratch); | |
2327 | |
2328 __ bind(notLong); | |
2329 | |
2330 // cmp(Rflags, btos); | |
2331 __ br(Assembler::notEqual, false, Assembler::pt, notByte); | |
2332 __ delayed() ->cmp(Rflags, ctos); | |
2333 | |
2334 // btos | |
2335 __ ldsb(Rclass, Roffset, Otos_i); | |
2336 __ push(itos); | |
2337 if (!is_static) { | |
2338 patch_bytecode(Bytecodes::_fast_bgetfield, G3_scratch, G4_scratch); | |
2339 } | |
2340 __ ba(false, checkVolatile); | |
2341 __ delayed()->tst(Lscratch); | |
2342 | |
2343 __ bind(notByte); | |
2344 | |
2345 // cmp(Rflags, ctos); | |
2346 __ br(Assembler::notEqual, false, Assembler::pt, notChar); | |
2347 __ delayed() ->cmp(Rflags, stos); | |
2348 | |
2349 // ctos | |
2350 __ lduh(Rclass, Roffset, Otos_i); | |
2351 __ push(itos); | |
2352 if (!is_static) { | |
2353 patch_bytecode(Bytecodes::_fast_cgetfield, G3_scratch, G4_scratch); | |
2354 } | |
2355 __ ba(false, checkVolatile); | |
2356 __ delayed()->tst(Lscratch); | |
2357 | |
2358 __ bind(notChar); | |
2359 | |
2360 // cmp(Rflags, stos); | |
2361 __ br(Assembler::notEqual, false, Assembler::pt, notShort); | |
2362 __ delayed() ->cmp(Rflags, ftos); | |
2363 | |
2364 // stos | |
2365 __ ldsh(Rclass, Roffset, Otos_i); | |
2366 __ push(itos); | |
2367 if (!is_static) { | |
2368 patch_bytecode(Bytecodes::_fast_sgetfield, G3_scratch, G4_scratch); | |
2369 } | |
2370 __ ba(false, checkVolatile); | |
2371 __ delayed()->tst(Lscratch); | |
2372 | |
2373 __ bind(notShort); | |
2374 | |
2375 | |
2376 // cmp(Rflags, ftos); | |
2377 __ br(Assembler::notEqual, false, Assembler::pt, notFloat); | |
2378 __ delayed() ->tst(Lscratch); | |
2379 | |
2380 // ftos | |
2381 __ ldf(FloatRegisterImpl::S, Rclass, Roffset, Ftos_f); | |
2382 __ push(ftos); | |
2383 if (!is_static) { | |
2384 patch_bytecode(Bytecodes::_fast_fgetfield, G3_scratch, G4_scratch); | |
2385 } | |
2386 __ ba(false, checkVolatile); | |
2387 __ delayed()->tst(Lscratch); | |
2388 | |
2389 __ bind(notFloat); | |
2390 | |
2391 | |
2392 // dtos | |
2393 __ ldf(FloatRegisterImpl::D, Rclass, Roffset, Ftos_d); | |
2394 __ push(dtos); | |
2395 if (!is_static) { | |
2396 patch_bytecode(Bytecodes::_fast_dgetfield, G3_scratch, G4_scratch); | |
2397 } | |
2398 | |
2399 __ bind(checkVolatile); | |
2400 if (__ membar_has_effect(membar_bits)) { | |
2401 // __ tst(Lscratch); executed in delay slot | |
2402 __ br(Assembler::zero, false, Assembler::pt, exit); | |
2403 __ delayed()->nop(); | |
2404 volatile_barrier(membar_bits); | |
2405 } | |
2406 | |
2407 __ bind(exit); | |
2408 } | |
2409 | |
2410 | |
2411 void TemplateTable::getfield(int byte_no) { | |
2412 getfield_or_static(byte_no, false); | |
2413 } | |
2414 | |
2415 void TemplateTable::getstatic(int byte_no) { | |
2416 getfield_or_static(byte_no, true); | |
2417 } | |
2418 | |
2419 | |
2420 void TemplateTable::fast_accessfield(TosState state) { | |
2421 transition(atos, state); | |
2422 Register Rcache = G3_scratch; | |
2423 Register index = G4_scratch; | |
2424 Register Roffset = G4_scratch; | |
2425 Register Rflags = Rcache; | |
2426 ByteSize cp_base_offset = constantPoolCacheOopDesc::base_offset(); | |
2427 | |
2428 __ get_cache_and_index_at_bcp(Rcache, index, 1); | |
2429 jvmti_post_field_access(Rcache, index, /*is_static*/false, /*has_tos*/true); | |
2430 | |
727 | 2431 __ ld_ptr(Rcache, cp_base_offset + ConstantPoolCacheEntry::f2_offset(), Roffset); |
0 | 2432 |
2433 __ null_check(Otos_i); | |
2434 __ verify_oop(Otos_i); | |
2435 | |
2436 Label exit; | |
2437 | |
2438 Assembler::Membar_mask_bits membar_bits = | |
2439 Assembler::Membar_mask_bits(Assembler::LoadLoad | Assembler::LoadStore); | |
2440 if (__ membar_has_effect(membar_bits)) { | |
2441 // Get volatile flag | |
727 | 2442 __ ld_ptr(Rcache, cp_base_offset + ConstantPoolCacheEntry::f2_offset(), Rflags); |
0 | 2443 __ set((1 << ConstantPoolCacheEntry::volatileField), Lscratch); |
2444 } | |
2445 | |
2446 switch (bytecode()) { | |
2447 case Bytecodes::_fast_bgetfield: | |
2448 __ ldsb(Otos_i, Roffset, Otos_i); | |
2449 break; | |
2450 case Bytecodes::_fast_cgetfield: | |
2451 __ lduh(Otos_i, Roffset, Otos_i); | |
2452 break; | |
2453 case Bytecodes::_fast_sgetfield: | |
2454 __ ldsh(Otos_i, Roffset, Otos_i); | |
2455 break; | |
2456 case Bytecodes::_fast_igetfield: | |
2457 __ ld(Otos_i, Roffset, Otos_i); | |
2458 break; | |
2459 case Bytecodes::_fast_lgetfield: | |
2460 __ ld_long(Otos_i, Roffset, Otos_l); | |
2461 break; | |
2462 case Bytecodes::_fast_fgetfield: | |
2463 __ ldf(FloatRegisterImpl::S, Otos_i, Roffset, Ftos_f); | |
2464 break; | |
2465 case Bytecodes::_fast_dgetfield: | |
2466 __ ldf(FloatRegisterImpl::D, Otos_i, Roffset, Ftos_d); | |
2467 break; | |
2468 case Bytecodes::_fast_agetfield: | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
2469 __ load_heap_oop(Otos_i, Roffset, Otos_i); |
0 | 2470 break; |
2471 default: | |
2472 ShouldNotReachHere(); | |
2473 } | |
2474 | |
2475 if (__ membar_has_effect(membar_bits)) { | |
2476 __ btst(Lscratch, Rflags); | |
2477 __ br(Assembler::zero, false, Assembler::pt, exit); | |
2478 __ delayed()->nop(); | |
2479 volatile_barrier(membar_bits); | |
2480 __ bind(exit); | |
2481 } | |
2482 | |
2483 if (state == atos) { | |
2484 __ verify_oop(Otos_i); // does not blow flags! | |
2485 } | |
2486 } | |
2487 | |
2488 void TemplateTable::jvmti_post_fast_field_mod() { | |
2489 if (JvmtiExport::can_post_field_modification()) { | |
2490 // Check to see if a field modification watch has been set before we take | |
2491 // the time to call into the VM. | |
2492 Label done; | |
727 | 2493 AddressLiteral get_field_modification_count_addr(JvmtiExport::get_field_modification_count_addr()); |
0 | 2494 __ load_contents(get_field_modification_count_addr, G4_scratch); |
2495 __ tst(G4_scratch); | |
2496 __ br(Assembler::zero, false, Assembler::pt, done); | |
2497 __ delayed()->nop(); | |
2498 __ pop_ptr(G4_scratch); // copy the object pointer from tos | |
2499 __ verify_oop(G4_scratch); | |
2500 __ push_ptr(G4_scratch); // put the object pointer back on tos | |
2501 __ get_cache_entry_pointer_at_bcp(G1_scratch, G3_scratch, 1); | |
2502 // Save tos values before call_VM() clobbers them. Since we have | |
2503 // to do it for every data type, we use the saved values as the | |
2504 // jvalue object. | |
2505 switch (bytecode()) { // save tos values before call_VM() clobbers them | |
2506 case Bytecodes::_fast_aputfield: __ push_ptr(Otos_i); break; | |
2507 case Bytecodes::_fast_bputfield: // fall through | |
2508 case Bytecodes::_fast_sputfield: // fall through | |
2509 case Bytecodes::_fast_cputfield: // fall through | |
2510 case Bytecodes::_fast_iputfield: __ push_i(Otos_i); break; | |
2511 case Bytecodes::_fast_dputfield: __ push_d(Ftos_d); break; | |
2512 case Bytecodes::_fast_fputfield: __ push_f(Ftos_f); break; | |
2513 // get words in right order for use as jvalue object | |
2514 case Bytecodes::_fast_lputfield: __ push_l(Otos_l); break; | |
2515 } | |
2516 // setup pointer to jvalue object | |
2517 __ mov(Lesp, G3_scratch); __ inc(G3_scratch, wordSize); | |
2518 // G4_scratch: object pointer | |
2519 // G1_scratch: cache entry pointer | |
2520 // G3_scratch: jvalue object on the stack | |
2521 __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::post_field_modification), G4_scratch, G1_scratch, G3_scratch); | |
2522 switch (bytecode()) { // restore tos values | |
2523 case Bytecodes::_fast_aputfield: __ pop_ptr(Otos_i); break; | |
2524 case Bytecodes::_fast_bputfield: // fall through | |
2525 case Bytecodes::_fast_sputfield: // fall through | |
2526 case Bytecodes::_fast_cputfield: // fall through | |
2527 case Bytecodes::_fast_iputfield: __ pop_i(Otos_i); break; | |
2528 case Bytecodes::_fast_dputfield: __ pop_d(Ftos_d); break; | |
2529 case Bytecodes::_fast_fputfield: __ pop_f(Ftos_f); break; | |
2530 case Bytecodes::_fast_lputfield: __ pop_l(Otos_l); break; | |
2531 } | |
2532 __ bind(done); | |
2533 } | |
2534 } | |
2535 | |
2536 // The registers Rcache and index expected to be set before call. | |
2537 // The function may destroy various registers, just not the Rcache and index registers. | |
2538 void TemplateTable::jvmti_post_field_mod(Register Rcache, Register index, bool is_static) { | |
2539 ByteSize cp_base_offset = constantPoolCacheOopDesc::base_offset(); | |
2540 | |
2541 if (JvmtiExport::can_post_field_modification()) { | |
2542 // Check to see if a field modification watch has been set before we take | |
2543 // the time to call into the VM. | |
2544 Label Label1; | |
2545 assert_different_registers(Rcache, index, G1_scratch); | |
727 | 2546 AddressLiteral get_field_modification_count_addr(JvmtiExport::get_field_modification_count_addr()); |
0 | 2547 __ load_contents(get_field_modification_count_addr, G1_scratch); |
2548 __ tst(G1_scratch); | |
2549 __ br(Assembler::zero, false, Assembler::pt, Label1); | |
2550 __ delayed()->nop(); | |
2551 | |
2552 // The Rcache and index registers have been already set. | |
2553 // This allows to eliminate this call but the Rcache and index | |
2554 // registers must be correspondingly used after this line. | |
2555 __ get_cache_and_index_at_bcp(G1_scratch, G4_scratch, 1); | |
2556 | |
2557 __ add(G1_scratch, in_bytes(cp_base_offset), G3_scratch); | |
2558 if (is_static) { | |
2559 // Life is simple. Null out the object pointer. | |
2560 __ clr(G4_scratch); | |
2561 } else { | |
2562 Register Rflags = G1_scratch; | |
2563 // Life is harder. The stack holds the value on top, followed by the | |
2564 // object. We don't know the size of the value, though; it could be | |
2565 // one or two words depending on its type. As a result, we must find | |
2566 // the type to determine where the object is. | |
2567 | |
2568 Label two_word, valsizeknown; | |
727 | 2569 __ ld_ptr(G1_scratch, cp_base_offset + ConstantPoolCacheEntry::flags_offset(), Rflags); |
0 | 2570 __ mov(Lesp, G4_scratch); |
2571 __ srl(Rflags, ConstantPoolCacheEntry::tosBits, Rflags); | |
2572 // Make sure we don't need to mask Rflags for tosBits after the above shift | |
2573 ConstantPoolCacheEntry::verify_tosBits(); | |
2574 __ cmp(Rflags, ltos); | |
2575 __ br(Assembler::equal, false, Assembler::pt, two_word); | |
2576 __ delayed()->cmp(Rflags, dtos); | |
2577 __ br(Assembler::equal, false, Assembler::pt, two_word); | |
2578 __ delayed()->nop(); | |
2579 __ inc(G4_scratch, Interpreter::expr_offset_in_bytes(1)); | |
2580 __ br(Assembler::always, false, Assembler::pt, valsizeknown); | |
2581 __ delayed()->nop(); | |
2582 __ bind(two_word); | |
2583 | |
2584 __ inc(G4_scratch, Interpreter::expr_offset_in_bytes(2)); | |
2585 | |
2586 __ bind(valsizeknown); | |
2587 // setup object pointer | |
2588 __ ld_ptr(G4_scratch, 0, G4_scratch); | |
2589 __ verify_oop(G4_scratch); | |
2590 } | |
2591 // setup pointer to jvalue object | |
2592 __ mov(Lesp, G1_scratch); __ inc(G1_scratch, wordSize); | |
2593 // G4_scratch: object pointer or NULL if static | |
2594 // G3_scratch: cache entry pointer | |
2595 // G1_scratch: jvalue object on the stack | |
2596 __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::post_field_modification), | |
2597 G4_scratch, G3_scratch, G1_scratch); | |
2598 __ get_cache_and_index_at_bcp(Rcache, index, 1); | |
2599 __ bind(Label1); | |
2600 } | |
2601 } | |
2602 | |
2603 void TemplateTable::pop_and_check_object(Register r) { | |
2604 __ pop_ptr(r); | |
2605 __ null_check(r); // for field access must check obj. | |
2606 __ verify_oop(r); | |
2607 } | |
2608 | |
2609 void TemplateTable::putfield_or_static(int byte_no, bool is_static) { | |
2610 transition(vtos, vtos); | |
2611 Register Rcache = G3_scratch; | |
2612 Register index = G4_scratch; | |
2613 Register Rclass = Rcache; | |
2614 Register Roffset= G4_scratch; | |
2615 Register Rflags = G1_scratch; | |
2616 ByteSize cp_base_offset = constantPoolCacheOopDesc::base_offset(); | |
2617 | |
1565 | 2618 resolve_cache_and_index(byte_no, noreg, Rcache, index, sizeof(u2)); |
0 | 2619 jvmti_post_field_mod(Rcache, index, is_static); |
2620 load_field_cp_cache_entry(Rclass, Rcache, index, Roffset, Rflags, is_static); | |
2621 | |
2622 Assembler::Membar_mask_bits read_bits = | |
2623 Assembler::Membar_mask_bits(Assembler::LoadStore | Assembler::StoreStore); | |
2624 Assembler::Membar_mask_bits write_bits = Assembler::StoreLoad; | |
2625 | |
2626 Label notVolatile, checkVolatile, exit; | |
2627 if (__ membar_has_effect(read_bits) || __ membar_has_effect(write_bits)) { | |
2628 __ set((1 << ConstantPoolCacheEntry::volatileField), Lscratch); | |
2629 __ and3(Rflags, Lscratch, Lscratch); | |
2630 | |
2631 if (__ membar_has_effect(read_bits)) { | |
2632 __ tst(Lscratch); | |
2633 __ br(Assembler::zero, false, Assembler::pt, notVolatile); | |
2634 __ delayed()->nop(); | |
2635 volatile_barrier(read_bits); | |
2636 __ bind(notVolatile); | |
2637 } | |
2638 } | |
2639 | |
2640 __ srl(Rflags, ConstantPoolCacheEntry::tosBits, Rflags); | |
2641 // Make sure we don't need to mask Rflags for tosBits after the above shift | |
2642 ConstantPoolCacheEntry::verify_tosBits(); | |
2643 | |
2644 // compute field type | |
2645 Label notInt, notShort, notChar, notObj, notByte, notLong, notFloat; | |
2646 | |
2647 if (is_static) { | |
2648 // putstatic with object type most likely, check that first | |
2649 __ cmp(Rflags, atos ); | |
2650 __ br(Assembler::notEqual, false, Assembler::pt, notObj); | |
2651 __ delayed() ->cmp(Rflags, itos ); | |
2652 | |
2653 // atos | |
2654 __ pop_ptr(); | |
2655 __ verify_oop(Otos_i); | |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
2656 |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
2657 do_oop_store(_masm, Rclass, Roffset, 0, Otos_i, G1_scratch, _bs->kind(), false); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
2658 |
0 | 2659 __ ba(false, checkVolatile); |
2660 __ delayed()->tst(Lscratch); | |
2661 | |
2662 __ bind(notObj); | |
2663 | |
2664 // cmp(Rflags, itos ); | |
2665 __ br(Assembler::notEqual, false, Assembler::pt, notInt); | |
2666 __ delayed() ->cmp(Rflags, btos ); | |
2667 | |
2668 // itos | |
2669 __ pop_i(); | |
2670 __ st(Otos_i, Rclass, Roffset); | |
2671 __ ba(false, checkVolatile); | |
2672 __ delayed()->tst(Lscratch); | |
2673 | |
2674 __ bind(notInt); | |
2675 | |
2676 } else { | |
2677 // putfield with int type most likely, check that first | |
2678 __ cmp(Rflags, itos ); | |
2679 __ br(Assembler::notEqual, false, Assembler::pt, notInt); | |
2680 __ delayed() ->cmp(Rflags, atos ); | |
2681 | |
2682 // itos | |
2683 __ pop_i(); | |
2684 pop_and_check_object(Rclass); | |
2685 __ st(Otos_i, Rclass, Roffset); | |
2686 patch_bytecode(Bytecodes::_fast_iputfield, G3_scratch, G4_scratch); | |
2687 __ ba(false, checkVolatile); | |
2688 __ delayed()->tst(Lscratch); | |
2689 | |
2690 __ bind(notInt); | |
2691 // cmp(Rflags, atos ); | |
2692 __ br(Assembler::notEqual, false, Assembler::pt, notObj); | |
2693 __ delayed() ->cmp(Rflags, btos ); | |
2694 | |
2695 // atos | |
2696 __ pop_ptr(); | |
2697 pop_and_check_object(Rclass); | |
2698 __ verify_oop(Otos_i); | |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
2699 |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
2700 do_oop_store(_masm, Rclass, Roffset, 0, Otos_i, G1_scratch, _bs->kind(), false); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
2701 |
0 | 2702 patch_bytecode(Bytecodes::_fast_aputfield, G3_scratch, G4_scratch); |
2703 __ ba(false, checkVolatile); | |
2704 __ delayed()->tst(Lscratch); | |
2705 | |
2706 __ bind(notObj); | |
2707 } | |
2708 | |
2709 // cmp(Rflags, btos ); | |
2710 __ br(Assembler::notEqual, false, Assembler::pt, notByte); | |
2711 __ delayed() ->cmp(Rflags, ltos ); | |
2712 | |
2713 // btos | |
2714 __ pop_i(); | |
2715 if (!is_static) pop_and_check_object(Rclass); | |
2716 __ stb(Otos_i, Rclass, Roffset); | |
2717 if (!is_static) { | |
2718 patch_bytecode(Bytecodes::_fast_bputfield, G3_scratch, G4_scratch); | |
2719 } | |
2720 __ ba(false, checkVolatile); | |
2721 __ delayed()->tst(Lscratch); | |
2722 | |
2723 __ bind(notByte); | |
2724 | |
2725 // cmp(Rflags, ltos ); | |
2726 __ br(Assembler::notEqual, false, Assembler::pt, notLong); | |
2727 __ delayed() ->cmp(Rflags, ctos ); | |
2728 | |
2729 // ltos | |
2730 __ pop_l(); | |
2731 if (!is_static) pop_and_check_object(Rclass); | |
2732 __ st_long(Otos_l, Rclass, Roffset); | |
2733 if (!is_static) { | |
2734 patch_bytecode(Bytecodes::_fast_lputfield, G3_scratch, G4_scratch); | |
2735 } | |
2736 __ ba(false, checkVolatile); | |
2737 __ delayed()->tst(Lscratch); | |
2738 | |
2739 __ bind(notLong); | |
2740 | |
2741 // cmp(Rflags, ctos ); | |
2742 __ br(Assembler::notEqual, false, Assembler::pt, notChar); | |
2743 __ delayed() ->cmp(Rflags, stos ); | |
2744 | |
2745 // ctos (char) | |
2746 __ pop_i(); | |
2747 if (!is_static) pop_and_check_object(Rclass); | |
2748 __ sth(Otos_i, Rclass, Roffset); | |
2749 if (!is_static) { | |
2750 patch_bytecode(Bytecodes::_fast_cputfield, G3_scratch, G4_scratch); | |
2751 } | |
2752 __ ba(false, checkVolatile); | |
2753 __ delayed()->tst(Lscratch); | |
2754 | |
2755 __ bind(notChar); | |
2756 // cmp(Rflags, stos ); | |
2757 __ br(Assembler::notEqual, false, Assembler::pt, notShort); | |
2758 __ delayed() ->cmp(Rflags, ftos ); | |
2759 | |
2760 // stos (char) | |
2761 __ pop_i(); | |
2762 if (!is_static) pop_and_check_object(Rclass); | |
2763 __ sth(Otos_i, Rclass, Roffset); | |
2764 if (!is_static) { | |
2765 patch_bytecode(Bytecodes::_fast_sputfield, G3_scratch, G4_scratch); | |
2766 } | |
2767 __ ba(false, checkVolatile); | |
2768 __ delayed()->tst(Lscratch); | |
2769 | |
2770 __ bind(notShort); | |
2771 // cmp(Rflags, ftos ); | |
2772 __ br(Assembler::notZero, false, Assembler::pt, notFloat); | |
2773 __ delayed()->nop(); | |
2774 | |
2775 // ftos | |
2776 __ pop_f(); | |
2777 if (!is_static) pop_and_check_object(Rclass); | |
2778 __ stf(FloatRegisterImpl::S, Ftos_f, Rclass, Roffset); | |
2779 if (!is_static) { | |
2780 patch_bytecode(Bytecodes::_fast_fputfield, G3_scratch, G4_scratch); | |
2781 } | |
2782 __ ba(false, checkVolatile); | |
2783 __ delayed()->tst(Lscratch); | |
2784 | |
2785 __ bind(notFloat); | |
2786 | |
2787 // dtos | |
2788 __ pop_d(); | |
2789 if (!is_static) pop_and_check_object(Rclass); | |
2790 __ stf(FloatRegisterImpl::D, Ftos_d, Rclass, Roffset); | |
2791 if (!is_static) { | |
2792 patch_bytecode(Bytecodes::_fast_dputfield, G3_scratch, G4_scratch); | |
2793 } | |
2794 | |
2795 __ bind(checkVolatile); | |
2796 __ tst(Lscratch); | |
2797 | |
2798 if (__ membar_has_effect(write_bits)) { | |
2799 // __ tst(Lscratch); in delay slot | |
2800 __ br(Assembler::zero, false, Assembler::pt, exit); | |
2801 __ delayed()->nop(); | |
2802 volatile_barrier(Assembler::StoreLoad); | |
2803 __ bind(exit); | |
2804 } | |
2805 } | |
2806 | |
2807 void TemplateTable::fast_storefield(TosState state) { | |
2808 transition(state, vtos); | |
2809 Register Rcache = G3_scratch; | |
2810 Register Rclass = Rcache; | |
2811 Register Roffset= G4_scratch; | |
2812 Register Rflags = G1_scratch; | |
2813 ByteSize cp_base_offset = constantPoolCacheOopDesc::base_offset(); | |
2814 | |
2815 jvmti_post_fast_field_mod(); | |
2816 | |
2817 __ get_cache_and_index_at_bcp(Rcache, G4_scratch, 1); | |
2818 | |
2819 Assembler::Membar_mask_bits read_bits = | |
2820 Assembler::Membar_mask_bits(Assembler::LoadStore | Assembler::StoreStore); | |
2821 Assembler::Membar_mask_bits write_bits = Assembler::StoreLoad; | |
2822 | |
2823 Label notVolatile, checkVolatile, exit; | |
2824 if (__ membar_has_effect(read_bits) || __ membar_has_effect(write_bits)) { | |
727 | 2825 __ ld_ptr(Rcache, cp_base_offset + ConstantPoolCacheEntry::flags_offset(), Rflags); |
0 | 2826 __ set((1 << ConstantPoolCacheEntry::volatileField), Lscratch); |
2827 __ and3(Rflags, Lscratch, Lscratch); | |
2828 if (__ membar_has_effect(read_bits)) { | |
2829 __ tst(Lscratch); | |
2830 __ br(Assembler::zero, false, Assembler::pt, notVolatile); | |
2831 __ delayed()->nop(); | |
2832 volatile_barrier(read_bits); | |
2833 __ bind(notVolatile); | |
2834 } | |
2835 } | |
2836 | |
727 | 2837 __ ld_ptr(Rcache, cp_base_offset + ConstantPoolCacheEntry::f2_offset(), Roffset); |
0 | 2838 pop_and_check_object(Rclass); |
2839 | |
2840 switch (bytecode()) { | |
2841 case Bytecodes::_fast_bputfield: __ stb(Otos_i, Rclass, Roffset); break; | |
2842 case Bytecodes::_fast_cputfield: /* fall through */ | |
2843 case Bytecodes::_fast_sputfield: __ sth(Otos_i, Rclass, Roffset); break; | |
2844 case Bytecodes::_fast_iputfield: __ st(Otos_i, Rclass, Roffset); break; | |
2845 case Bytecodes::_fast_lputfield: __ st_long(Otos_l, Rclass, Roffset); break; | |
2846 case Bytecodes::_fast_fputfield: | |
2847 __ stf(FloatRegisterImpl::S, Ftos_f, Rclass, Roffset); | |
2848 break; | |
2849 case Bytecodes::_fast_dputfield: | |
2850 __ stf(FloatRegisterImpl::D, Ftos_d, Rclass, Roffset); | |
2851 break; | |
2852 case Bytecodes::_fast_aputfield: | |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
2853 do_oop_store(_masm, Rclass, Roffset, 0, Otos_i, G1_scratch, _bs->kind(), false); |
0 | 2854 break; |
2855 default: | |
2856 ShouldNotReachHere(); | |
2857 } | |
2858 | |
2859 if (__ membar_has_effect(write_bits)) { | |
2860 __ tst(Lscratch); | |
2861 __ br(Assembler::zero, false, Assembler::pt, exit); | |
2862 __ delayed()->nop(); | |
2863 volatile_barrier(Assembler::StoreLoad); | |
2864 __ bind(exit); | |
2865 } | |
2866 } | |
2867 | |
2868 | |
2869 void TemplateTable::putfield(int byte_no) { | |
2870 putfield_or_static(byte_no, false); | |
2871 } | |
2872 | |
2873 void TemplateTable::putstatic(int byte_no) { | |
2874 putfield_or_static(byte_no, true); | |
2875 } | |
2876 | |
2877 | |
2878 void TemplateTable::fast_xaccess(TosState state) { | |
2879 transition(vtos, state); | |
2880 Register Rcache = G3_scratch; | |
2881 Register Roffset = G4_scratch; | |
2882 Register Rflags = G4_scratch; | |
2883 Register Rreceiver = Lscratch; | |
2884 | |
1506 | 2885 __ ld_ptr(Llocals, 0, Rreceiver); |
0 | 2886 |
2887 // access constant pool cache (is resolved) | |
2888 __ get_cache_and_index_at_bcp(Rcache, G4_scratch, 2); | |
727 | 2889 __ ld_ptr(Rcache, constantPoolCacheOopDesc::base_offset() + ConstantPoolCacheEntry::f2_offset(), Roffset); |
0 | 2890 __ add(Lbcp, 1, Lbcp); // needed to report exception at the correct bcp |
2891 | |
2892 __ verify_oop(Rreceiver); | |
2893 __ null_check(Rreceiver); | |
2894 if (state == atos) { | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
2895 __ load_heap_oop(Rreceiver, Roffset, Otos_i); |
0 | 2896 } else if (state == itos) { |
2897 __ ld (Rreceiver, Roffset, Otos_i) ; | |
2898 } else if (state == ftos) { | |
2899 __ ldf(FloatRegisterImpl::S, Rreceiver, Roffset, Ftos_f); | |
2900 } else { | |
2901 ShouldNotReachHere(); | |
2902 } | |
2903 | |
2904 Assembler::Membar_mask_bits membar_bits = | |
2905 Assembler::Membar_mask_bits(Assembler::LoadLoad | Assembler::LoadStore); | |
2906 if (__ membar_has_effect(membar_bits)) { | |
2907 | |
2908 // Get is_volatile value in Rflags and check if membar is needed | |
727 | 2909 __ ld_ptr(Rcache, constantPoolCacheOopDesc::base_offset() + ConstantPoolCacheEntry::flags_offset(), Rflags); |
0 | 2910 |
2911 // Test volatile | |
2912 Label notVolatile; | |
2913 __ set((1 << ConstantPoolCacheEntry::volatileField), Lscratch); | |
2914 __ btst(Rflags, Lscratch); | |
2915 __ br(Assembler::zero, false, Assembler::pt, notVolatile); | |
2916 __ delayed()->nop(); | |
2917 volatile_barrier(membar_bits); | |
2918 __ bind(notVolatile); | |
2919 } | |
2920 | |
2921 __ interp_verify_oop(Otos_i, state, __FILE__, __LINE__); | |
2922 __ sub(Lbcp, 1, Lbcp); | |
2923 } | |
2924 | |
2925 //---------------------------------------------------------------------------------------------------- | |
2926 // Calls | |
2927 | |
2928 void TemplateTable::count_calls(Register method, Register temp) { | |
2929 // implemented elsewhere | |
2930 ShouldNotReachHere(); | |
2931 } | |
2932 | |
2933 void TemplateTable::generate_vtable_call(Register Rrecv, Register Rindex, Register Rret) { | |
2934 Register Rtemp = G4_scratch; | |
2935 Register Rcall = Rindex; | |
2936 assert_different_registers(Rcall, G5_method, Gargs, Rret); | |
2937 | |
2938 // get target methodOop & entry point | |
2939 const int base = instanceKlass::vtable_start_offset() * wordSize; | |
2940 if (vtableEntry::size() % 3 == 0) { | |
2941 // scale the vtable index by 12: | |
2942 int one_third = vtableEntry::size() / 3; | |
2943 __ sll(Rindex, exact_log2(one_third * 1 * wordSize), Rtemp); | |
2944 __ sll(Rindex, exact_log2(one_third * 2 * wordSize), Rindex); | |
2945 __ add(Rindex, Rtemp, Rindex); | |
2946 } else { | |
2947 // scale the vtable index by 8: | |
2948 __ sll(Rindex, exact_log2(vtableEntry::size() * wordSize), Rindex); | |
2949 } | |
2950 | |
2951 __ add(Rrecv, Rindex, Rrecv); | |
2952 __ ld_ptr(Rrecv, base + vtableEntry::method_offset_in_bytes(), G5_method); | |
2953 | |
2954 __ call_from_interpreter(Rcall, Gargs, Rret); | |
2955 } | |
2956 | |
2957 void TemplateTable::invokevirtual(int byte_no) { | |
2958 transition(vtos, vtos); | |
1565 | 2959 assert(byte_no == f2_byte, "use this argument"); |
0 | 2960 |
2961 Register Rscratch = G3_scratch; | |
2962 Register Rtemp = G4_scratch; | |
2963 Register Rret = Lscratch; | |
2964 Register Rrecv = G5_method; | |
2965 Label notFinal; | |
2966 | |
1565 | 2967 load_invoke_cp_cache_entry(byte_no, G5_method, noreg, Rret, true, false, false); |
0 | 2968 __ mov(SP, O5_savedSP); // record SP that we wanted the callee to restore |
2969 | |
2970 // Check for vfinal | |
2971 __ set((1 << ConstantPoolCacheEntry::vfinalMethod), G4_scratch); | |
2972 __ btst(Rret, G4_scratch); | |
2973 __ br(Assembler::zero, false, Assembler::pt, notFinal); | |
2974 __ delayed()->and3(Rret, 0xFF, G4_scratch); // gets number of parameters | |
2975 | |
2976 patch_bytecode(Bytecodes::_fast_invokevfinal, Rscratch, Rtemp); | |
2977 | |
2978 invokevfinal_helper(Rscratch, Rret); | |
2979 | |
2980 __ bind(notFinal); | |
2981 | |
2982 __ mov(G5_method, Rscratch); // better scratch register | |
2983 __ load_receiver(G4_scratch, O0); // gets receiverOop | |
2984 // receiver is in O0 | |
2985 __ verify_oop(O0); | |
2986 | |
2987 // get return address | |
727 | 2988 AddressLiteral table(Interpreter::return_3_addrs_by_index_table()); |
2989 __ set(table, Rtemp); | |
0 | 2990 __ srl(Rret, ConstantPoolCacheEntry::tosBits, Rret); // get return type |
2991 // Make sure we don't need to mask Rret for tosBits after the above shift | |
2992 ConstantPoolCacheEntry::verify_tosBits(); | |
2993 __ sll(Rret, LogBytesPerWord, Rret); | |
2994 __ ld_ptr(Rtemp, Rret, Rret); // get return address | |
2995 | |
2996 // get receiver klass | |
2997 __ null_check(O0, 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
|
2998 __ load_klass(O0, Rrecv); |
0 | 2999 __ verify_oop(Rrecv); |
3000 | |
3001 __ profile_virtual_call(Rrecv, O4); | |
3002 | |
3003 generate_vtable_call(Rrecv, Rscratch, Rret); | |
3004 } | |
3005 | |
3006 void TemplateTable::fast_invokevfinal(int byte_no) { | |
3007 transition(vtos, vtos); | |
1565 | 3008 assert(byte_no == f2_byte, "use this argument"); |
0 | 3009 |
3010 load_invoke_cp_cache_entry(byte_no, G5_method, noreg, Lscratch, true, | |
1565 | 3011 /*is_invokevfinal*/true, false); |
0 | 3012 __ mov(SP, O5_savedSP); // record SP that we wanted the callee to restore |
3013 invokevfinal_helper(G3_scratch, Lscratch); | |
3014 } | |
3015 | |
3016 void TemplateTable::invokevfinal_helper(Register Rscratch, Register Rret) { | |
3017 Register Rtemp = G4_scratch; | |
3018 | |
3019 __ verify_oop(G5_method); | |
3020 | |
3021 // Load receiver from stack slot | |
727 | 3022 __ lduh(G5_method, in_bytes(methodOopDesc::size_of_parameters_offset()), G4_scratch); |
0 | 3023 __ load_receiver(G4_scratch, O0); |
3024 | |
3025 // receiver NULL check | |
3026 __ null_check(O0); | |
3027 | |
3028 __ profile_final_call(O4); | |
3029 | |
3030 // get return address | |
727 | 3031 AddressLiteral table(Interpreter::return_3_addrs_by_index_table()); |
3032 __ set(table, Rtemp); | |
0 | 3033 __ srl(Rret, ConstantPoolCacheEntry::tosBits, Rret); // get return type |
3034 // Make sure we don't need to mask Rret for tosBits after the above shift | |
3035 ConstantPoolCacheEntry::verify_tosBits(); | |
3036 __ sll(Rret, LogBytesPerWord, Rret); | |
3037 __ ld_ptr(Rtemp, Rret, Rret); // get return address | |
3038 | |
3039 | |
3040 // do the call | |
3041 __ call_from_interpreter(Rscratch, Gargs, Rret); | |
3042 } | |
3043 | |
3044 void TemplateTable::invokespecial(int byte_no) { | |
3045 transition(vtos, vtos); | |
1565 | 3046 assert(byte_no == f1_byte, "use this argument"); |
0 | 3047 |
3048 Register Rscratch = G3_scratch; | |
3049 Register Rtemp = G4_scratch; | |
3050 Register Rret = Lscratch; | |
3051 | |
1565 | 3052 load_invoke_cp_cache_entry(byte_no, G5_method, noreg, Rret, /*virtual*/ false, false, false); |
0 | 3053 __ mov(SP, O5_savedSP); // record SP that we wanted the callee to restore |
3054 | |
3055 __ verify_oop(G5_method); | |
3056 | |
727 | 3057 __ lduh(G5_method, in_bytes(methodOopDesc::size_of_parameters_offset()), G4_scratch); |
0 | 3058 __ load_receiver(G4_scratch, O0); |
3059 | |
3060 // receiver NULL check | |
3061 __ null_check(O0); | |
3062 | |
3063 __ profile_call(O4); | |
3064 | |
3065 // get return address | |
727 | 3066 AddressLiteral table(Interpreter::return_3_addrs_by_index_table()); |
3067 __ set(table, Rtemp); | |
0 | 3068 __ srl(Rret, ConstantPoolCacheEntry::tosBits, Rret); // get return type |
3069 // Make sure we don't need to mask Rret for tosBits after the above shift | |
3070 ConstantPoolCacheEntry::verify_tosBits(); | |
3071 __ sll(Rret, LogBytesPerWord, Rret); | |
3072 __ ld_ptr(Rtemp, Rret, Rret); // get return address | |
3073 | |
3074 // do the call | |
3075 __ call_from_interpreter(Rscratch, Gargs, Rret); | |
3076 } | |
3077 | |
3078 void TemplateTable::invokestatic(int byte_no) { | |
3079 transition(vtos, vtos); | |
1565 | 3080 assert(byte_no == f1_byte, "use this argument"); |
0 | 3081 |
3082 Register Rscratch = G3_scratch; | |
3083 Register Rtemp = G4_scratch; | |
3084 Register Rret = Lscratch; | |
3085 | |
1565 | 3086 load_invoke_cp_cache_entry(byte_no, G5_method, noreg, Rret, /*virtual*/ false, false, false); |
0 | 3087 __ mov(SP, O5_savedSP); // record SP that we wanted the callee to restore |
3088 | |
3089 __ verify_oop(G5_method); | |
3090 | |
3091 __ profile_call(O4); | |
3092 | |
3093 // get return address | |
727 | 3094 AddressLiteral table(Interpreter::return_3_addrs_by_index_table()); |
3095 __ set(table, Rtemp); | |
0 | 3096 __ srl(Rret, ConstantPoolCacheEntry::tosBits, Rret); // get return type |
3097 // Make sure we don't need to mask Rret for tosBits after the above shift | |
3098 ConstantPoolCacheEntry::verify_tosBits(); | |
3099 __ sll(Rret, LogBytesPerWord, Rret); | |
3100 __ ld_ptr(Rtemp, Rret, Rret); // get return address | |
3101 | |
3102 // do the call | |
3103 __ call_from_interpreter(Rscratch, Gargs, Rret); | |
3104 } | |
3105 | |
3106 | |
3107 void TemplateTable::invokeinterface_object_method(Register RklassOop, | |
3108 Register Rcall, | |
3109 Register Rret, | |
3110 Register Rflags) { | |
3111 Register Rscratch = G4_scratch; | |
3112 Register Rindex = Lscratch; | |
3113 | |
3114 assert_different_registers(Rscratch, Rindex, Rret); | |
3115 | |
3116 Label notFinal; | |
3117 | |
3118 // Check for vfinal | |
3119 __ set((1 << ConstantPoolCacheEntry::vfinalMethod), Rscratch); | |
3120 __ btst(Rflags, Rscratch); | |
3121 __ br(Assembler::zero, false, Assembler::pt, notFinal); | |
3122 __ delayed()->nop(); | |
3123 | |
3124 __ profile_final_call(O4); | |
3125 | |
3126 // do the call - the index (f2) contains the methodOop | |
3127 assert_different_registers(G5_method, Gargs, Rcall); | |
3128 __ mov(Rindex, G5_method); | |
3129 __ call_from_interpreter(Rcall, Gargs, Rret); | |
3130 __ bind(notFinal); | |
3131 | |
3132 __ profile_virtual_call(RklassOop, O4); | |
3133 generate_vtable_call(RklassOop, Rindex, Rret); | |
3134 } | |
3135 | |
3136 | |
3137 void TemplateTable::invokeinterface(int byte_no) { | |
3138 transition(vtos, vtos); | |
1565 | 3139 assert(byte_no == f1_byte, "use this argument"); |
0 | 3140 |
3141 Register Rscratch = G4_scratch; | |
3142 Register Rret = G3_scratch; | |
3143 Register Rindex = Lscratch; | |
3144 Register Rinterface = G1_scratch; | |
3145 Register RklassOop = G5_method; | |
3146 Register Rflags = O1; | |
3147 assert_different_registers(Rscratch, G5_method); | |
3148 | |
1565 | 3149 load_invoke_cp_cache_entry(byte_no, Rinterface, Rindex, Rflags, /*virtual*/ false, false, false); |
0 | 3150 __ mov(SP, O5_savedSP); // record SP that we wanted the callee to restore |
3151 | |
3152 // get receiver | |
3153 __ and3(Rflags, 0xFF, Rscratch); // gets number of parameters | |
3154 __ load_receiver(Rscratch, O0); | |
3155 __ verify_oop(O0); | |
3156 | |
3157 __ mov(Rflags, Rret); | |
3158 | |
3159 // get return address | |
727 | 3160 AddressLiteral table(Interpreter::return_5_addrs_by_index_table()); |
3161 __ set(table, Rscratch); | |
0 | 3162 __ srl(Rret, ConstantPoolCacheEntry::tosBits, Rret); // get return type |
3163 // Make sure we don't need to mask Rret for tosBits after the above shift | |
3164 ConstantPoolCacheEntry::verify_tosBits(); | |
3165 __ sll(Rret, LogBytesPerWord, Rret); | |
3166 __ ld_ptr(Rscratch, Rret, Rret); // get return address | |
3167 | |
3168 // get receiver klass | |
3169 __ null_check(O0, 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
|
3170 __ load_klass(O0, RklassOop); |
0 | 3171 __ verify_oop(RklassOop); |
3172 | |
3173 // Special case of invokeinterface called for virtual method of | |
3174 // java.lang.Object. See cpCacheOop.cpp for details. | |
3175 // This code isn't produced by javac, but could be produced by | |
3176 // another compliant java compiler. | |
3177 Label notMethod; | |
3178 __ set((1 << ConstantPoolCacheEntry::methodInterface), Rscratch); | |
3179 __ btst(Rflags, Rscratch); | |
3180 __ br(Assembler::zero, false, Assembler::pt, notMethod); | |
3181 __ delayed()->nop(); | |
3182 | |
3183 invokeinterface_object_method(RklassOop, Rinterface, Rret, Rflags); | |
3184 | |
3185 __ bind(notMethod); | |
3186 | |
3187 __ profile_virtual_call(RklassOop, O4); | |
3188 | |
3189 // | |
3190 // find entry point to call | |
3191 // | |
3192 | |
3193 // compute start of first itableOffsetEntry (which is at end of vtable) | |
3194 const int base = instanceKlass::vtable_start_offset() * wordSize; | |
3195 Label search; | |
3196 Register Rtemp = Rflags; | |
3197 | |
727 | 3198 __ ld(RklassOop, instanceKlass::vtable_length_offset() * wordSize, Rtemp); |
0 | 3199 if (align_object_offset(1) > 1) { |
3200 __ round_to(Rtemp, align_object_offset(1)); | |
3201 } | |
3202 __ sll(Rtemp, LogBytesPerWord, Rtemp); // Rscratch *= 4; | |
3203 if (Assembler::is_simm13(base)) { | |
3204 __ add(Rtemp, base, Rtemp); | |
3205 } else { | |
3206 __ set(base, Rscratch); | |
3207 __ add(Rscratch, Rtemp, Rtemp); | |
3208 } | |
3209 __ add(RklassOop, Rtemp, Rscratch); | |
3210 | |
3211 __ bind(search); | |
3212 | |
3213 __ ld_ptr(Rscratch, itableOffsetEntry::interface_offset_in_bytes(), Rtemp); | |
3214 { | |
3215 Label ok; | |
3216 | |
3217 // Check that entry is non-null. Null entries are probably a bytecode | |
605 | 3218 // problem. If the interface isn't implemented by the receiver class, |
0 | 3219 // the VM should throw IncompatibleClassChangeError. linkResolver checks |
3220 // this too but that's only if the entry isn't already resolved, so we | |
3221 // need to check again. | |
3222 __ br_notnull( Rtemp, false, Assembler::pt, ok); | |
3223 __ delayed()->nop(); | |
3224 call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_IncompatibleClassChangeError)); | |
3225 __ should_not_reach_here(); | |
3226 __ bind(ok); | |
3227 __ verify_oop(Rtemp); | |
3228 } | |
3229 | |
3230 __ verify_oop(Rinterface); | |
3231 | |
3232 __ cmp(Rinterface, Rtemp); | |
3233 __ brx(Assembler::notEqual, true, Assembler::pn, search); | |
3234 __ delayed()->add(Rscratch, itableOffsetEntry::size() * wordSize, Rscratch); | |
3235 | |
3236 // entry found and Rscratch points to it | |
3237 __ ld(Rscratch, itableOffsetEntry::offset_offset_in_bytes(), Rscratch); | |
3238 | |
3239 assert(itableMethodEntry::method_offset_in_bytes() == 0, "adjust instruction below"); | |
3240 __ sll(Rindex, exact_log2(itableMethodEntry::size() * wordSize), Rindex); // Rindex *= 8; | |
3241 __ add(Rscratch, Rindex, Rscratch); | |
3242 __ ld_ptr(RklassOop, Rscratch, G5_method); | |
3243 | |
3244 // Check for abstract method error. | |
3245 { | |
3246 Label ok; | |
3247 __ tst(G5_method); | |
3248 __ brx(Assembler::notZero, false, Assembler::pt, ok); | |
3249 __ delayed()->nop(); | |
3250 call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_AbstractMethodError)); | |
3251 __ should_not_reach_here(); | |
3252 __ bind(ok); | |
3253 } | |
3254 | |
3255 Register Rcall = Rinterface; | |
3256 assert_different_registers(Rcall, G5_method, Gargs, Rret); | |
3257 | |
3258 __ verify_oop(G5_method); | |
3259 __ call_from_interpreter(Rcall, Gargs, Rret); | |
3260 | |
3261 } | |
3262 | |
3263 | |
726
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
605
diff
changeset
|
3264 void TemplateTable::invokedynamic(int byte_no) { |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
605
diff
changeset
|
3265 transition(vtos, vtos); |
1565 | 3266 assert(byte_no == f1_oop, "use this argument"); |
726
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
605
diff
changeset
|
3267 |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
605
diff
changeset
|
3268 if (!EnableInvokeDynamic) { |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
605
diff
changeset
|
3269 // We should not encounter this bytecode if !EnableInvokeDynamic. |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
605
diff
changeset
|
3270 // The verifier will stop it. However, if we get past the verifier, |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
605
diff
changeset
|
3271 // this will stop the thread in a reasonable way, without crashing the JVM. |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
605
diff
changeset
|
3272 __ call_VM(noreg, CAST_FROM_FN_PTR(address, |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
605
diff
changeset
|
3273 InterpreterRuntime::throw_IncompatibleClassChangeError)); |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
605
diff
changeset
|
3274 // the call_VM checks for exception, so we should never return here. |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
605
diff
changeset
|
3275 __ should_not_reach_here(); |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
605
diff
changeset
|
3276 return; |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
605
diff
changeset
|
3277 } |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
605
diff
changeset
|
3278 |
1503 | 3279 // G5: CallSite object (f1) |
3280 // XX: unused (f2) | |
3281 // XX: flags (unused) | |
3282 | |
3283 Register G5_callsite = G5_method; | |
3284 Register Rscratch = G3_scratch; | |
3285 Register Rtemp = G1_scratch; | |
3286 Register Rret = Lscratch; | |
3287 | |
1565 | 3288 load_invoke_cp_cache_entry(byte_no, G5_callsite, noreg, Rret, |
3289 /*virtual*/ false, /*vfinal*/ false, /*indy*/ true); | |
1503 | 3290 __ mov(SP, O5_savedSP); // record SP that we wanted the callee to restore |
3291 | |
3292 __ verify_oop(G5_callsite); | |
3293 | |
3294 // profile this call | |
3295 __ profile_call(O4); | |
3296 | |
3297 // get return address | |
3298 AddressLiteral table(Interpreter::return_5_addrs_by_index_table()); | |
3299 __ set(table, Rtemp); | |
3300 __ srl(Rret, ConstantPoolCacheEntry::tosBits, Rret); // get return type | |
3301 // Make sure we don't need to mask Rret for tosBits after the above shift | |
3302 ConstantPoolCacheEntry::verify_tosBits(); | |
3303 __ sll(Rret, LogBytesPerWord, Rret); | |
3304 __ ld_ptr(Rtemp, Rret, Rret); // get return address | |
3305 | |
1846 | 3306 __ load_heap_oop(G5_callsite, __ delayed_value(java_dyn_CallSite::target_offset_in_bytes, Rscratch), G3_method_handle); |
1503 | 3307 __ null_check(G3_method_handle); |
3308 | |
3309 // Adjust Rret first so Llast_SP can be same as Rret | |
3310 __ add(Rret, -frame::pc_return_offset, O7); | |
3311 __ add(Lesp, BytesPerWord, Gargs); // setup parameter pointer | |
3312 __ jump_to_method_handle_entry(G3_method_handle, Rtemp, /* emit_delayed_nop */ false); | |
3313 // Record SP so we can remove any stack space allocated by adapter transition | |
3314 __ delayed()->mov(SP, Llast_SP); | |
726
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
605
diff
changeset
|
3315 } |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
605
diff
changeset
|
3316 |
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
605
diff
changeset
|
3317 |
0 | 3318 //---------------------------------------------------------------------------------------------------- |
3319 // Allocation | |
3320 | |
3321 void TemplateTable::_new() { | |
3322 transition(vtos, atos); | |
3323 | |
3324 Label slow_case; | |
3325 Label done; | |
3326 Label initialize_header; | |
3327 Label initialize_object; // including clearing the fields | |
3328 | |
3329 Register RallocatedObject = Otos_i; | |
3330 Register RinstanceKlass = O1; | |
3331 Register Roffset = O3; | |
3332 Register Rscratch = O4; | |
3333 | |
3334 __ get_2_byte_integer_at_bcp(1, Rscratch, Roffset, InterpreterMacroAssembler::Unsigned); | |
3335 __ get_cpool_and_tags(Rscratch, G3_scratch); | |
3336 // make sure the class we're about to instantiate has been resolved | |
1681
126ea7725993
6953477: Increase portability and flexibility of building Hotspot
bobv
parents:
1602
diff
changeset
|
3337 // This is done before loading instanceKlass to be consistent with the order |
126ea7725993
6953477: Increase portability and flexibility of building Hotspot
bobv
parents:
1602
diff
changeset
|
3338 // how Constant Pool is updated (see constantPoolOopDesc::klass_at_put) |
0 | 3339 __ add(G3_scratch, typeArrayOopDesc::header_size(T_BYTE) * wordSize, G3_scratch); |
3340 __ ldub(G3_scratch, Roffset, G3_scratch); | |
3341 __ cmp(G3_scratch, JVM_CONSTANT_Class); | |
3342 __ br(Assembler::notEqual, false, Assembler::pn, slow_case); | |
3343 __ delayed()->sll(Roffset, LogBytesPerWord, Roffset); | |
1681
126ea7725993
6953477: Increase portability and flexibility of building Hotspot
bobv
parents:
1602
diff
changeset
|
3344 // get instanceKlass |
0 | 3345 //__ sll(Roffset, LogBytesPerWord, Roffset); // executed in delay slot |
3346 __ add(Roffset, sizeof(constantPoolOopDesc), Roffset); | |
3347 __ ld_ptr(Rscratch, Roffset, RinstanceKlass); | |
3348 | |
3349 // make sure klass is fully initialized: | |
3350 __ ld(RinstanceKlass, instanceKlass::init_state_offset_in_bytes() + sizeof(oopDesc), G3_scratch); | |
3351 __ cmp(G3_scratch, instanceKlass::fully_initialized); | |
3352 __ br(Assembler::notEqual, false, Assembler::pn, slow_case); | |
3353 __ delayed()->ld(RinstanceKlass, Klass::layout_helper_offset_in_bytes() + sizeof(oopDesc), Roffset); | |
3354 | |
3355 // get instance_size in instanceKlass (already aligned) | |
3356 //__ ld(RinstanceKlass, Klass::layout_helper_offset_in_bytes() + sizeof(oopDesc), Roffset); | |
3357 | |
3358 // make sure klass does not have has_finalizer, or is abstract, or interface or java/lang/Class | |
3359 __ btst(Klass::_lh_instance_slow_path_bit, Roffset); | |
3360 __ br(Assembler::notZero, false, Assembler::pn, slow_case); | |
3361 __ delayed()->nop(); | |
3362 | |
3363 // allocate the instance | |
3364 // 1) Try to allocate in the TLAB | |
3365 // 2) if fail, and the TLAB is not full enough to discard, allocate in the shared Eden | |
3366 // 3) if the above fails (or is not applicable), go to a slow case | |
3367 // (creates a new TLAB, etc.) | |
3368 | |
3369 const bool allow_shared_alloc = | |
3370 Universe::heap()->supports_inline_contig_alloc() && !CMSIncrementalMode; | |
3371 | |
3372 if(UseTLAB) { | |
3373 Register RoldTopValue = RallocatedObject; | |
3374 Register RtopAddr = G3_scratch, RtlabWasteLimitValue = G3_scratch; | |
3375 Register RnewTopValue = G1_scratch; | |
3376 Register RendValue = Rscratch; | |
3377 Register RfreeValue = RnewTopValue; | |
3378 | |
3379 // check if we can allocate in the TLAB | |
3380 __ ld_ptr(G2_thread, in_bytes(JavaThread::tlab_top_offset()), RoldTopValue); // sets up RalocatedObject | |
3381 __ ld_ptr(G2_thread, in_bytes(JavaThread::tlab_end_offset()), RendValue); | |
3382 __ add(RoldTopValue, Roffset, RnewTopValue); | |
3383 | |
3384 // if there is enough space, we do not CAS and do not clear | |
3385 __ cmp(RnewTopValue, RendValue); | |
3386 if(ZeroTLAB) { | |
3387 // the fields have already been cleared | |
3388 __ brx(Assembler::lessEqualUnsigned, true, Assembler::pt, initialize_header); | |
3389 } else { | |
3390 // initialize both the header and fields | |
3391 __ brx(Assembler::lessEqualUnsigned, true, Assembler::pt, initialize_object); | |
3392 } | |
3393 __ delayed()->st_ptr(RnewTopValue, G2_thread, in_bytes(JavaThread::tlab_top_offset())); | |
3394 | |
3395 if (allow_shared_alloc) { | |
2100
b1a2afa37ec4
7003271: Hotspot should track cumulative Java heap bytes allocated on a per-thread basis
phh
parents:
1972
diff
changeset
|
3396 // Check if tlab should be discarded (refill_waste_limit >= free) |
b1a2afa37ec4
7003271: Hotspot should track cumulative Java heap bytes allocated on a per-thread basis
phh
parents:
1972
diff
changeset
|
3397 __ ld_ptr(G2_thread, in_bytes(JavaThread::tlab_refill_waste_limit_offset()), RtlabWasteLimitValue); |
b1a2afa37ec4
7003271: Hotspot should track cumulative Java heap bytes allocated on a per-thread basis
phh
parents:
1972
diff
changeset
|
3398 __ sub(RendValue, RoldTopValue, RfreeValue); |
0 | 3399 #ifdef _LP64 |
2100
b1a2afa37ec4
7003271: Hotspot should track cumulative Java heap bytes allocated on a per-thread basis
phh
parents:
1972
diff
changeset
|
3400 __ srlx(RfreeValue, LogHeapWordSize, RfreeValue); |
0 | 3401 #else |
2100
b1a2afa37ec4
7003271: Hotspot should track cumulative Java heap bytes allocated on a per-thread basis
phh
parents:
1972
diff
changeset
|
3402 __ srl(RfreeValue, LogHeapWordSize, RfreeValue); |
0 | 3403 #endif |
2100
b1a2afa37ec4
7003271: Hotspot should track cumulative Java heap bytes allocated on a per-thread basis
phh
parents:
1972
diff
changeset
|
3404 __ cmp(RtlabWasteLimitValue, RfreeValue); |
b1a2afa37ec4
7003271: Hotspot should track cumulative Java heap bytes allocated on a per-thread basis
phh
parents:
1972
diff
changeset
|
3405 __ brx(Assembler::greaterEqualUnsigned, false, Assembler::pt, slow_case); // tlab waste is small |
b1a2afa37ec4
7003271: Hotspot should track cumulative Java heap bytes allocated on a per-thread basis
phh
parents:
1972
diff
changeset
|
3406 __ delayed()->nop(); |
b1a2afa37ec4
7003271: Hotspot should track cumulative Java heap bytes allocated on a per-thread basis
phh
parents:
1972
diff
changeset
|
3407 |
b1a2afa37ec4
7003271: Hotspot should track cumulative Java heap bytes allocated on a per-thread basis
phh
parents:
1972
diff
changeset
|
3408 // increment waste limit to prevent getting stuck on this slow path |
b1a2afa37ec4
7003271: Hotspot should track cumulative Java heap bytes allocated on a per-thread basis
phh
parents:
1972
diff
changeset
|
3409 __ add(RtlabWasteLimitValue, ThreadLocalAllocBuffer::refill_waste_limit_increment(), RtlabWasteLimitValue); |
b1a2afa37ec4
7003271: Hotspot should track cumulative Java heap bytes allocated on a per-thread basis
phh
parents:
1972
diff
changeset
|
3410 __ st_ptr(RtlabWasteLimitValue, G2_thread, in_bytes(JavaThread::tlab_refill_waste_limit_offset())); |
0 | 3411 } else { |
3412 // No allocation in the shared eden. | |
3413 __ br(Assembler::always, false, Assembler::pt, slow_case); | |
3414 __ delayed()->nop(); | |
3415 } | |
3416 } | |
3417 | |
3418 // Allocation in the shared Eden | |
3419 if (allow_shared_alloc) { | |
3420 Register RoldTopValue = G1_scratch; | |
3421 Register RtopAddr = G3_scratch; | |
3422 Register RnewTopValue = RallocatedObject; | |
3423 Register RendValue = Rscratch; | |
3424 | |
3425 __ set((intptr_t)Universe::heap()->top_addr(), RtopAddr); | |
3426 | |
3427 Label retry; | |
3428 __ bind(retry); | |
3429 __ set((intptr_t)Universe::heap()->end_addr(), RendValue); | |
3430 __ ld_ptr(RendValue, 0, RendValue); | |
3431 __ ld_ptr(RtopAddr, 0, RoldTopValue); | |
3432 __ add(RoldTopValue, Roffset, RnewTopValue); | |
3433 | |
3434 // RnewTopValue contains the top address after the new object | |
3435 // has been allocated. | |
3436 __ cmp(RnewTopValue, RendValue); | |
3437 __ brx(Assembler::greaterUnsigned, false, Assembler::pn, slow_case); | |
3438 __ delayed()->nop(); | |
3439 | |
3440 __ casx_under_lock(RtopAddr, RoldTopValue, RnewTopValue, | |
3441 VM_Version::v9_instructions_work() ? NULL : | |
3442 (address)StubRoutines::Sparc::atomic_memory_operation_lock_addr()); | |
3443 | |
3444 // if someone beat us on the allocation, try again, otherwise continue | |
3445 __ cmp(RoldTopValue, RnewTopValue); | |
3446 __ brx(Assembler::notEqual, false, Assembler::pn, retry); | |
3447 __ delayed()->nop(); | |
2100
b1a2afa37ec4
7003271: Hotspot should track cumulative Java heap bytes allocated on a per-thread basis
phh
parents:
1972
diff
changeset
|
3448 |
b1a2afa37ec4
7003271: Hotspot should track cumulative Java heap bytes allocated on a per-thread basis
phh
parents:
1972
diff
changeset
|
3449 // bump total bytes allocated by this thread |
2127
5577848f5923
7011463: Sparc MacroAssembler::incr_allocated_bytes() needs a RegisterOrConstant argument
phh
parents:
2100
diff
changeset
|
3450 // RoldTopValue and RtopAddr are dead, so can use G1 and G3 |
5577848f5923
7011463: Sparc MacroAssembler::incr_allocated_bytes() needs a RegisterOrConstant argument
phh
parents:
2100
diff
changeset
|
3451 __ incr_allocated_bytes(Roffset, G1_scratch, G3_scratch); |
0 | 3452 } |
3453 | |
3454 if (UseTLAB || Universe::heap()->supports_inline_contig_alloc()) { | |
3455 // clear object fields | |
3456 __ bind(initialize_object); | |
3457 __ deccc(Roffset, sizeof(oopDesc)); | |
3458 __ br(Assembler::zero, false, Assembler::pt, initialize_header); | |
3459 __ delayed()->add(RallocatedObject, sizeof(oopDesc), G3_scratch); | |
3460 | |
3461 // initialize remaining object fields | |
3462 { Label loop; | |
3463 __ subcc(Roffset, wordSize, Roffset); | |
3464 __ bind(loop); | |
3465 //__ subcc(Roffset, wordSize, Roffset); // executed above loop or in delay slot | |
3466 __ st_ptr(G0, G3_scratch, Roffset); | |
3467 __ br(Assembler::notEqual, false, Assembler::pt, loop); | |
3468 __ delayed()->subcc(Roffset, wordSize, Roffset); | |
3469 } | |
3470 __ br(Assembler::always, false, Assembler::pt, initialize_header); | |
3471 __ delayed()->nop(); | |
3472 } | |
3473 | |
3474 // slow case | |
3475 __ bind(slow_case); | |
3476 __ get_2_byte_integer_at_bcp(1, G3_scratch, O2, InterpreterMacroAssembler::Unsigned); | |
3477 __ get_constant_pool(O1); | |
3478 | |
3479 call_VM(Otos_i, CAST_FROM_FN_PTR(address, InterpreterRuntime::_new), O1, O2); | |
3480 | |
3481 __ ba(false, done); | |
3482 __ delayed()->nop(); | |
3483 | |
3484 // Initialize the header: mark, klass | |
3485 __ bind(initialize_header); | |
3486 | |
3487 if (UseBiasedLocking) { | |
3488 __ ld_ptr(RinstanceKlass, Klass::prototype_header_offset_in_bytes() + sizeof(oopDesc), G4_scratch); | |
3489 } else { | |
3490 __ set((intptr_t)markOopDesc::prototype(), G4_scratch); | |
3491 } | |
3492 __ st_ptr(G4_scratch, RallocatedObject, oopDesc::mark_offset_in_bytes()); // mark | |
167
feeb96a45707
6696264: assert("narrow oop can never be zero") for GCBasher & ParNewGC
coleenp
parents:
113
diff
changeset
|
3493 __ store_klass_gap(G0, RallocatedObject); // klass gap if compressed |
feeb96a45707
6696264: assert("narrow oop can never be zero") for GCBasher & ParNewGC
coleenp
parents:
113
diff
changeset
|
3494 __ store_klass(RinstanceKlass, RallocatedObject); // klass (last for cms) |
0 | 3495 |
3496 { | |
3497 SkipIfEqual skip_if( | |
3498 _masm, G4_scratch, &DTraceAllocProbes, Assembler::zero); | |
3499 // Trigger dtrace event | |
3500 __ push(atos); | |
3501 __ call_VM_leaf(noreg, | |
3502 CAST_FROM_FN_PTR(address, SharedRuntime::dtrace_object_alloc), O0); | |
3503 __ pop(atos); | |
3504 } | |
3505 | |
3506 // continue | |
3507 __ bind(done); | |
3508 } | |
3509 | |
3510 | |
3511 | |
3512 void TemplateTable::newarray() { | |
3513 transition(itos, atos); | |
3514 __ ldub(Lbcp, 1, O1); | |
3515 call_VM(Otos_i, CAST_FROM_FN_PTR(address, InterpreterRuntime::newarray), O1, Otos_i); | |
3516 } | |
3517 | |
3518 | |
3519 void TemplateTable::anewarray() { | |
3520 transition(itos, atos); | |
3521 __ get_constant_pool(O1); | |
3522 __ get_2_byte_integer_at_bcp(1, G4_scratch, O2, InterpreterMacroAssembler::Unsigned); | |
3523 call_VM(Otos_i, CAST_FROM_FN_PTR(address, InterpreterRuntime::anewarray), O1, O2, Otos_i); | |
3524 } | |
3525 | |
3526 | |
3527 void TemplateTable::arraylength() { | |
3528 transition(atos, itos); | |
3529 Label ok; | |
3530 __ verify_oop(Otos_i); | |
3531 __ tst(Otos_i); | |
3532 __ throw_if_not_1_x( Assembler::notZero, ok ); | |
3533 __ delayed()->ld(Otos_i, arrayOopDesc::length_offset_in_bytes(), Otos_i); | |
3534 __ throw_if_not_2( Interpreter::_throw_NullPointerException_entry, G3_scratch, ok); | |
3535 } | |
3536 | |
3537 | |
3538 void TemplateTable::checkcast() { | |
3539 transition(atos, atos); | |
3540 Label done, is_null, quicked, cast_ok, resolved; | |
3541 Register Roffset = G1_scratch; | |
3542 Register RobjKlass = O5; | |
3543 Register RspecifiedKlass = O4; | |
3544 | |
3545 // Check for casting a NULL | |
3546 __ br_null(Otos_i, false, Assembler::pn, is_null); | |
3547 __ delayed()->nop(); | |
3548 | |
3549 // Get value klass in RobjKlass | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
3550 __ load_klass(Otos_i, RobjKlass); // get value klass |
0 | 3551 |
3552 // Get constant pool tag | |
3553 __ get_2_byte_integer_at_bcp(1, Lscratch, Roffset, InterpreterMacroAssembler::Unsigned); | |
3554 | |
3555 // See if the checkcast has been quickened | |
3556 __ get_cpool_and_tags(Lscratch, G3_scratch); | |
3557 __ add(G3_scratch, typeArrayOopDesc::header_size(T_BYTE) * wordSize, G3_scratch); | |
3558 __ ldub(G3_scratch, Roffset, G3_scratch); | |
3559 __ cmp(G3_scratch, JVM_CONSTANT_Class); | |
3560 __ br(Assembler::equal, true, Assembler::pt, quicked); | |
3561 __ delayed()->sll(Roffset, LogBytesPerWord, Roffset); | |
3562 | |
3563 __ push_ptr(); // save receiver for result, and for GC | |
3564 call_VM(RspecifiedKlass, CAST_FROM_FN_PTR(address, InterpreterRuntime::quicken_io_cc) ); | |
3565 __ pop_ptr(Otos_i, G3_scratch); // restore receiver | |
3566 | |
3567 __ br(Assembler::always, false, Assembler::pt, resolved); | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
3568 __ delayed()->nop(); |
0 | 3569 |
3570 // Extract target class from constant pool | |
3571 __ bind(quicked); | |
3572 __ add(Roffset, sizeof(constantPoolOopDesc), Roffset); | |
3573 __ ld_ptr(Lscratch, Roffset, RspecifiedKlass); | |
3574 __ bind(resolved); | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
3575 __ load_klass(Otos_i, RobjKlass); // get value klass |
0 | 3576 |
3577 // Generate a fast subtype check. Branch to cast_ok if no | |
3578 // failure. Throw exception if failure. | |
3579 __ gen_subtype_check( RobjKlass, RspecifiedKlass, G3_scratch, G4_scratch, G1_scratch, cast_ok ); | |
3580 | |
3581 // Not a subtype; so must throw exception | |
3582 __ throw_if_not_x( Assembler::never, Interpreter::_throw_ClassCastException_entry, G3_scratch ); | |
3583 | |
3584 __ bind(cast_ok); | |
3585 | |
3586 if (ProfileInterpreter) { | |
3587 __ ba(false, done); | |
3588 __ delayed()->nop(); | |
3589 } | |
3590 __ bind(is_null); | |
3591 __ profile_null_seen(G3_scratch); | |
3592 __ bind(done); | |
3593 } | |
3594 | |
3595 | |
3596 void TemplateTable::instanceof() { | |
3597 Label done, is_null, quicked, resolved; | |
3598 transition(atos, itos); | |
3599 Register Roffset = G1_scratch; | |
3600 Register RobjKlass = O5; | |
3601 Register RspecifiedKlass = O4; | |
3602 | |
3603 // Check for casting a NULL | |
3604 __ br_null(Otos_i, false, Assembler::pt, is_null); | |
3605 __ delayed()->nop(); | |
3606 | |
3607 // Get value klass in RobjKlass | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
3608 __ load_klass(Otos_i, RobjKlass); // get value klass |
0 | 3609 |
3610 // Get constant pool tag | |
3611 __ get_2_byte_integer_at_bcp(1, Lscratch, Roffset, InterpreterMacroAssembler::Unsigned); | |
3612 | |
3613 // See if the checkcast has been quickened | |
3614 __ get_cpool_and_tags(Lscratch, G3_scratch); | |
3615 __ add(G3_scratch, typeArrayOopDesc::header_size(T_BYTE) * wordSize, G3_scratch); | |
3616 __ ldub(G3_scratch, Roffset, G3_scratch); | |
3617 __ cmp(G3_scratch, JVM_CONSTANT_Class); | |
3618 __ br(Assembler::equal, true, Assembler::pt, quicked); | |
3619 __ delayed()->sll(Roffset, LogBytesPerWord, Roffset); | |
3620 | |
3621 __ push_ptr(); // save receiver for result, and for GC | |
3622 call_VM(RspecifiedKlass, CAST_FROM_FN_PTR(address, InterpreterRuntime::quicken_io_cc) ); | |
3623 __ pop_ptr(Otos_i, G3_scratch); // restore receiver | |
3624 | |
3625 __ br(Assembler::always, false, Assembler::pt, resolved); | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
3626 __ delayed()->nop(); |
0 | 3627 |
3628 | |
3629 // Extract target class from constant pool | |
3630 __ bind(quicked); | |
3631 __ add(Roffset, sizeof(constantPoolOopDesc), Roffset); | |
3632 __ get_constant_pool(Lscratch); | |
3633 __ ld_ptr(Lscratch, Roffset, RspecifiedKlass); | |
3634 __ bind(resolved); | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
3635 __ load_klass(Otos_i, RobjKlass); // get value klass |
0 | 3636 |
3637 // Generate a fast subtype check. Branch to cast_ok if no | |
3638 // failure. Return 0 if failure. | |
3639 __ or3(G0, 1, Otos_i); // set result assuming quick tests succeed | |
3640 __ gen_subtype_check( RobjKlass, RspecifiedKlass, G3_scratch, G4_scratch, G1_scratch, done ); | |
3641 // Not a subtype; return 0; | |
3642 __ clr( Otos_i ); | |
3643 | |
3644 if (ProfileInterpreter) { | |
3645 __ ba(false, done); | |
3646 __ delayed()->nop(); | |
3647 } | |
3648 __ bind(is_null); | |
3649 __ profile_null_seen(G3_scratch); | |
3650 __ bind(done); | |
3651 } | |
3652 | |
3653 void TemplateTable::_breakpoint() { | |
3654 | |
3655 // Note: We get here even if we are single stepping.. | |
3656 // jbug inists on setting breakpoints at every bytecode | |
3657 // even if we are in single step mode. | |
3658 | |
3659 transition(vtos, vtos); | |
3660 // get the unpatched byte code | |
3661 __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::get_original_bytecode_at), Lmethod, Lbcp); | |
3662 __ mov(O0, Lbyte_code); | |
3663 | |
3664 // post the breakpoint event | |
3665 __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::_breakpoint), Lmethod, Lbcp); | |
3666 | |
3667 // complete the execution of original bytecode | |
3668 __ dispatch_normal(vtos); | |
3669 } | |
3670 | |
3671 | |
3672 //---------------------------------------------------------------------------------------------------- | |
3673 // Exceptions | |
3674 | |
3675 void TemplateTable::athrow() { | |
3676 transition(atos, vtos); | |
3677 | |
3678 // This works because exception is cached in Otos_i which is same as O0, | |
3679 // which is same as what throw_exception_entry_expects | |
3680 assert(Otos_i == Oexception, "see explanation above"); | |
3681 | |
3682 __ verify_oop(Otos_i); | |
3683 __ null_check(Otos_i); | |
3684 __ throw_if_not_x(Assembler::never, Interpreter::throw_exception_entry(), G3_scratch); | |
3685 } | |
3686 | |
3687 | |
3688 //---------------------------------------------------------------------------------------------------- | |
3689 // Synchronization | |
3690 | |
3691 | |
3692 // See frame_sparc.hpp for monitor block layout. | |
3693 // Monitor elements are dynamically allocated by growing stack as needed. | |
3694 | |
3695 void TemplateTable::monitorenter() { | |
3696 transition(atos, vtos); | |
3697 __ verify_oop(Otos_i); | |
3698 // Try to acquire a lock on the object | |
3699 // Repeat until succeeded (i.e., until | |
3700 // monitorenter returns true). | |
3701 | |
3702 { Label ok; | |
3703 __ tst(Otos_i); | |
3704 __ throw_if_not_1_x( Assembler::notZero, ok); | |
3705 __ delayed()->mov(Otos_i, Lscratch); // save obj | |
3706 __ throw_if_not_2( Interpreter::_throw_NullPointerException_entry, G3_scratch, ok); | |
3707 } | |
3708 | |
3709 assert(O0 == Otos_i, "Be sure where the object to lock is"); | |
3710 | |
3711 // find a free slot in the monitor block | |
3712 | |
3713 | |
3714 // initialize entry pointer | |
3715 __ clr(O1); // points to free slot or NULL | |
3716 | |
3717 { | |
3718 Label entry, loop, exit; | |
3719 __ add( __ top_most_monitor(), O2 ); // last one to check | |
3720 __ ba( false, entry ); | |
3721 __ delayed()->mov( Lmonitors, O3 ); // first one to check | |
3722 | |
3723 | |
3724 __ bind( loop ); | |
3725 | |
3726 __ verify_oop(O4); // verify each monitor's oop | |
3727 __ tst(O4); // is this entry unused? | |
3728 if (VM_Version::v9_instructions_work()) | |
3729 __ movcc( Assembler::zero, false, Assembler::ptr_cc, O3, O1); | |
3730 else { | |
3731 Label L; | |
3732 __ br( Assembler::zero, true, Assembler::pn, L ); | |
3733 __ delayed()->mov(O3, O1); // rememeber this one if match | |
3734 __ bind(L); | |
3735 } | |
3736 | |
3737 __ cmp(O4, O0); // check if current entry is for same object | |
3738 __ brx( Assembler::equal, false, Assembler::pn, exit ); | |
3739 __ delayed()->inc( O3, frame::interpreter_frame_monitor_size() * wordSize ); // check next one | |
3740 | |
3741 __ bind( entry ); | |
3742 | |
3743 __ cmp( O3, O2 ); | |
3744 __ brx( Assembler::lessEqualUnsigned, true, Assembler::pt, loop ); | |
3745 __ delayed()->ld_ptr(O3, BasicObjectLock::obj_offset_in_bytes(), O4); | |
3746 | |
3747 __ bind( exit ); | |
3748 } | |
3749 | |
3750 { Label allocated; | |
3751 | |
3752 // found free slot? | |
3753 __ br_notnull(O1, false, Assembler::pn, allocated); | |
3754 __ delayed()->nop(); | |
3755 | |
3756 __ add_monitor_to_stack( false, O2, O3 ); | |
3757 __ mov(Lmonitors, O1); | |
3758 | |
3759 __ bind(allocated); | |
3760 } | |
3761 | |
3762 // Increment bcp to point to the next bytecode, so exception handling for async. exceptions work correctly. | |
3763 // The object has already been poped from the stack, so the expression stack looks correct. | |
3764 __ inc(Lbcp); | |
3765 | |
3766 __ st_ptr(O0, O1, BasicObjectLock::obj_offset_in_bytes()); // store object | |
3767 __ lock_object(O1, O0); | |
3768 | |
3769 // check if there's enough space on the stack for the monitors after locking | |
3770 __ generate_stack_overflow_check(0); | |
3771 | |
3772 // The bcp has already been incremented. Just need to dispatch to next instruction. | |
3773 __ dispatch_next(vtos); | |
3774 } | |
3775 | |
3776 | |
3777 void TemplateTable::monitorexit() { | |
3778 transition(atos, vtos); | |
3779 __ verify_oop(Otos_i); | |
3780 __ tst(Otos_i); | |
3781 __ throw_if_not_x( Assembler::notZero, Interpreter::_throw_NullPointerException_entry, G3_scratch ); | |
3782 | |
3783 assert(O0 == Otos_i, "just checking"); | |
3784 | |
3785 { Label entry, loop, found; | |
3786 __ add( __ top_most_monitor(), O2 ); // last one to check | |
3787 __ ba(false, entry ); | |
3788 // use Lscratch to hold monitor elem to check, start with most recent monitor, | |
3789 // By using a local it survives the call to the C routine. | |
3790 __ delayed()->mov( Lmonitors, Lscratch ); | |
3791 | |
3792 __ bind( loop ); | |
3793 | |
3794 __ verify_oop(O4); // verify each monitor's oop | |
3795 __ cmp(O4, O0); // check if current entry is for desired object | |
3796 __ brx( Assembler::equal, true, Assembler::pt, found ); | |
3797 __ delayed()->mov(Lscratch, O1); // pass found entry as argument to monitorexit | |
3798 | |
3799 __ inc( Lscratch, frame::interpreter_frame_monitor_size() * wordSize ); // advance to next | |
3800 | |
3801 __ bind( entry ); | |
3802 | |
3803 __ cmp( Lscratch, O2 ); | |
3804 __ brx( Assembler::lessEqualUnsigned, true, Assembler::pt, loop ); | |
3805 __ delayed()->ld_ptr(Lscratch, BasicObjectLock::obj_offset_in_bytes(), O4); | |
3806 | |
3807 call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_illegal_monitor_state_exception)); | |
3808 __ should_not_reach_here(); | |
3809 | |
3810 __ bind(found); | |
3811 } | |
3812 __ unlock_object(O1); | |
3813 } | |
3814 | |
3815 | |
3816 //---------------------------------------------------------------------------------------------------- | |
3817 // Wide instructions | |
3818 | |
3819 void TemplateTable::wide() { | |
3820 transition(vtos, vtos); | |
3821 __ ldub(Lbcp, 1, G3_scratch);// get next bc | |
3822 __ sll(G3_scratch, LogBytesPerWord, G3_scratch); | |
727 | 3823 AddressLiteral ep(Interpreter::_wentry_point); |
3824 __ set(ep, G4_scratch); | |
3825 __ ld_ptr(G4_scratch, G3_scratch, G3_scratch); | |
0 | 3826 __ jmp(G3_scratch, G0); |
3827 __ delayed()->nop(); | |
3828 // Note: the Lbcp increment step is part of the individual wide bytecode implementations | |
3829 } | |
3830 | |
3831 | |
3832 //---------------------------------------------------------------------------------------------------- | |
3833 // Multi arrays | |
3834 | |
3835 void TemplateTable::multianewarray() { | |
3836 transition(vtos, atos); | |
3837 // put ndims * wordSize into Lscratch | |
3838 __ ldub( Lbcp, 3, Lscratch); | |
1506 | 3839 __ sll( Lscratch, Interpreter::logStackElementSize, Lscratch); |
0 | 3840 // Lesp points past last_dim, so set to O1 to first_dim address |
3841 __ add( Lesp, Lscratch, O1); | |
3842 call_VM(Otos_i, CAST_FROM_FN_PTR(address, InterpreterRuntime::multianewarray), O1); | |
3843 __ add( Lesp, Lscratch, Lesp); // pop all dimensions off the stack | |
3844 } | |
3845 #endif /* !CC_INTERP */ |