Mercurial > hg > graal-compiler
annotate src/cpu/sparc/vm/sharedRuntime_sparc.cpp @ 6812:988bf00cc564
7200261: G1: Liveness counting inconsistencies during marking verification
Summary: The clipping code in the routine that sets the bits for a range of cards, in the liveness accounting verification code was incorrect. It set all the bits in the card bitmap from the given starting index which would lead to spurious marking verification failures.
Reviewed-by: brutisso, jwilhelm, jmasa
author | johnc |
---|---|
date | Thu, 27 Sep 2012 15:44:01 -0700 |
parents | 8a02ca5e5576 |
children | 2cb2f30450c7 |
rev | line source |
---|---|
0 | 1 /* |
4873
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2 * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. |
0 | 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * | |
5 * This code is free software; you can redistribute it and/or modify it | |
6 * under the terms of the GNU General Public License version 2 only, as | |
7 * published by the Free Software Foundation. | |
8 * | |
9 * This code is distributed in the hope that it will be useful, but WITHOUT | |
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
12 * version 2 for more details (a copy is included in the LICENSE file that | |
13 * accompanied this code). | |
14 * | |
15 * You should have received a copy of the GNU General Public License version | |
16 * 2 along with this work; if not, write to the Free Software Foundation, | |
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
18 * | |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
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 "asm/assembler.hpp" | |
27 #include "assembler_sparc.inline.hpp" | |
28 #include "code/debugInfoRec.hpp" | |
29 #include "code/icBuffer.hpp" | |
30 #include "code/vtableStubs.hpp" | |
31 #include "interpreter/interpreter.hpp" | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
32 #include "oops/compiledICHolder.hpp" |
1972 | 33 #include "prims/jvmtiRedefineClassesTrace.hpp" |
34 #include "runtime/sharedRuntime.hpp" | |
35 #include "runtime/vframeArray.hpp" | |
36 #include "vmreg_sparc.inline.hpp" | |
37 #ifdef COMPILER1 | |
38 #include "c1/c1_Runtime1.hpp" | |
39 #endif | |
40 #ifdef COMPILER2 | |
41 #include "opto/runtime.hpp" | |
42 #endif | |
43 #ifdef SHARK | |
44 #include "compiler/compileBroker.hpp" | |
45 #include "shark/sharkCompiler.hpp" | |
46 #endif | |
0 | 47 |
48 #define __ masm-> | |
49 | |
50 | |
51 class RegisterSaver { | |
52 | |
53 // Used for saving volatile registers. This is Gregs, Fregs, I/L/O. | |
54 // The Oregs are problematic. In the 32bit build the compiler can | |
55 // have O registers live with 64 bit quantities. A window save will | |
56 // cut the heads off of the registers. We have to do a very extensive | |
57 // stack dance to save and restore these properly. | |
58 | |
59 // Note that the Oregs problem only exists if we block at either a polling | |
60 // page exception a compiled code safepoint that was not originally a call | |
61 // or deoptimize following one of these kinds of safepoints. | |
62 | |
63 // Lots of registers to save. For all builds, a window save will preserve | |
64 // the %i and %l registers. For the 32-bit longs-in-two entries and 64-bit | |
65 // builds a window-save will preserve the %o registers. In the LION build | |
66 // we need to save the 64-bit %o registers which requires we save them | |
67 // before the window-save (as then they become %i registers and get their | |
68 // heads chopped off on interrupt). We have to save some %g registers here | |
69 // as well. | |
70 enum { | |
71 // This frame's save area. Includes extra space for the native call: | |
72 // vararg's layout space and the like. Briefly holds the caller's | |
73 // register save area. | |
74 call_args_area = frame::register_save_words_sp_offset + | |
75 frame::memory_parameter_word_sp_offset*wordSize, | |
76 // Make sure save locations are always 8 byte aligned. | |
77 // can't use round_to because it doesn't produce compile time constant | |
78 start_of_extra_save_area = ((call_args_area + 7) & ~7), | |
79 g1_offset = start_of_extra_save_area, // g-regs needing saving | |
80 g3_offset = g1_offset+8, | |
81 g4_offset = g3_offset+8, | |
82 g5_offset = g4_offset+8, | |
83 o0_offset = g5_offset+8, | |
84 o1_offset = o0_offset+8, | |
85 o2_offset = o1_offset+8, | |
86 o3_offset = o2_offset+8, | |
87 o4_offset = o3_offset+8, | |
88 o5_offset = o4_offset+8, | |
89 start_of_flags_save_area = o5_offset+8, | |
90 ccr_offset = start_of_flags_save_area, | |
91 fsr_offset = ccr_offset + 8, | |
92 d00_offset = fsr_offset+8, // Start of float save area | |
93 register_save_size = d00_offset+8*32 | |
94 }; | |
95 | |
96 | |
97 public: | |
98 | |
99 static int Oexception_offset() { return o0_offset; }; | |
100 static int G3_offset() { return g3_offset; }; | |
101 static int G5_offset() { return g5_offset; }; | |
102 static OopMap* save_live_registers(MacroAssembler* masm, int additional_frame_words, int* total_frame_words); | |
103 static void restore_live_registers(MacroAssembler* masm); | |
104 | |
105 // During deoptimization only the result register need to be restored | |
106 // all the other values have already been extracted. | |
107 | |
108 static void restore_result_registers(MacroAssembler* masm); | |
109 }; | |
110 | |
111 OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, int additional_frame_words, int* total_frame_words) { | |
112 // Record volatile registers as callee-save values in an OopMap so their save locations will be | |
113 // propagated to the caller frame's RegisterMap during StackFrameStream construction (needed for | |
114 // deoptimization; see compiledVFrame::create_stack_value). The caller's I, L and O registers | |
115 // are saved in register windows - I's and L's in the caller's frame and O's in the stub frame | |
116 // (as the stub's I's) when the runtime routine called by the stub creates its frame. | |
117 int i; | |
1007
1ce3281a8e93
6880034: SIGBUS during deoptimisation at a safepoint on 64bit-SPARC
kvn
parents:
1006
diff
changeset
|
118 // Always make the frame size 16 byte aligned. |
0 | 119 int frame_size = round_to(additional_frame_words + register_save_size, 16); |
120 // OopMap frame size is in c2 stack slots (sizeof(jint)) not bytes or words | |
121 int frame_size_in_slots = frame_size / sizeof(jint); | |
122 // CodeBlob frame size is in words. | |
123 *total_frame_words = frame_size / wordSize; | |
124 // OopMap* map = new OopMap(*total_frame_words, 0); | |
125 OopMap* map = new OopMap(frame_size_in_slots, 0); | |
126 | |
127 #if !defined(_LP64) | |
128 | |
129 // Save 64-bit O registers; they will get their heads chopped off on a 'save'. | |
130 __ stx(O0, G2_thread, JavaThread::o_reg_temps_offset_in_bytes()+0*8); | |
131 __ stx(O1, G2_thread, JavaThread::o_reg_temps_offset_in_bytes()+1*8); | |
132 __ stx(O2, G2_thread, JavaThread::o_reg_temps_offset_in_bytes()+2*8); | |
133 __ stx(O3, G2_thread, JavaThread::o_reg_temps_offset_in_bytes()+3*8); | |
134 __ stx(O4, G2_thread, JavaThread::o_reg_temps_offset_in_bytes()+4*8); | |
135 __ stx(O5, G2_thread, JavaThread::o_reg_temps_offset_in_bytes()+5*8); | |
136 #endif /* _LP64 */ | |
137 | |
138 __ save(SP, -frame_size, SP); | |
139 | |
140 #ifndef _LP64 | |
141 // Reload the 64 bit Oregs. Although they are now Iregs we load them | |
142 // to Oregs here to avoid interrupts cutting off their heads | |
143 | |
144 __ ldx(G2_thread, JavaThread::o_reg_temps_offset_in_bytes()+0*8, O0); | |
145 __ ldx(G2_thread, JavaThread::o_reg_temps_offset_in_bytes()+1*8, O1); | |
146 __ ldx(G2_thread, JavaThread::o_reg_temps_offset_in_bytes()+2*8, O2); | |
147 __ ldx(G2_thread, JavaThread::o_reg_temps_offset_in_bytes()+3*8, O3); | |
148 __ ldx(G2_thread, JavaThread::o_reg_temps_offset_in_bytes()+4*8, O4); | |
149 __ ldx(G2_thread, JavaThread::o_reg_temps_offset_in_bytes()+5*8, O5); | |
150 | |
151 __ stx(O0, SP, o0_offset+STACK_BIAS); | |
152 map->set_callee_saved(VMRegImpl::stack2reg((o0_offset + 4)>>2), O0->as_VMReg()); | |
153 | |
154 __ stx(O1, SP, o1_offset+STACK_BIAS); | |
155 | |
156 map->set_callee_saved(VMRegImpl::stack2reg((o1_offset + 4)>>2), O1->as_VMReg()); | |
157 | |
158 __ stx(O2, SP, o2_offset+STACK_BIAS); | |
159 map->set_callee_saved(VMRegImpl::stack2reg((o2_offset + 4)>>2), O2->as_VMReg()); | |
160 | |
161 __ stx(O3, SP, o3_offset+STACK_BIAS); | |
162 map->set_callee_saved(VMRegImpl::stack2reg((o3_offset + 4)>>2), O3->as_VMReg()); | |
163 | |
164 __ stx(O4, SP, o4_offset+STACK_BIAS); | |
165 map->set_callee_saved(VMRegImpl::stack2reg((o4_offset + 4)>>2), O4->as_VMReg()); | |
166 | |
167 __ stx(O5, SP, o5_offset+STACK_BIAS); | |
168 map->set_callee_saved(VMRegImpl::stack2reg((o5_offset + 4)>>2), O5->as_VMReg()); | |
169 #endif /* _LP64 */ | |
170 | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
171 |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
172 #ifdef _LP64 |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
173 int debug_offset = 0; |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
174 #else |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
175 int debug_offset = 4; |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
176 #endif |
0 | 177 // Save the G's |
178 __ stx(G1, SP, g1_offset+STACK_BIAS); | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
179 map->set_callee_saved(VMRegImpl::stack2reg((g1_offset + debug_offset)>>2), G1->as_VMReg()); |
0 | 180 |
181 __ stx(G3, SP, g3_offset+STACK_BIAS); | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
182 map->set_callee_saved(VMRegImpl::stack2reg((g3_offset + debug_offset)>>2), G3->as_VMReg()); |
0 | 183 |
184 __ stx(G4, SP, g4_offset+STACK_BIAS); | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
185 map->set_callee_saved(VMRegImpl::stack2reg((g4_offset + debug_offset)>>2), G4->as_VMReg()); |
0 | 186 |
187 __ stx(G5, SP, g5_offset+STACK_BIAS); | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
188 map->set_callee_saved(VMRegImpl::stack2reg((g5_offset + debug_offset)>>2), G5->as_VMReg()); |
0 | 189 |
190 // This is really a waste but we'll keep things as they were for now | |
191 if (true) { | |
192 #ifndef _LP64 | |
193 map->set_callee_saved(VMRegImpl::stack2reg((o0_offset)>>2), O0->as_VMReg()->next()); | |
194 map->set_callee_saved(VMRegImpl::stack2reg((o1_offset)>>2), O1->as_VMReg()->next()); | |
195 map->set_callee_saved(VMRegImpl::stack2reg((o2_offset)>>2), O2->as_VMReg()->next()); | |
196 map->set_callee_saved(VMRegImpl::stack2reg((o3_offset)>>2), O3->as_VMReg()->next()); | |
197 map->set_callee_saved(VMRegImpl::stack2reg((o4_offset)>>2), O4->as_VMReg()->next()); | |
198 map->set_callee_saved(VMRegImpl::stack2reg((o5_offset)>>2), O5->as_VMReg()->next()); | |
199 map->set_callee_saved(VMRegImpl::stack2reg((g1_offset)>>2), G1->as_VMReg()->next()); | |
200 map->set_callee_saved(VMRegImpl::stack2reg((g3_offset)>>2), G3->as_VMReg()->next()); | |
201 map->set_callee_saved(VMRegImpl::stack2reg((g4_offset)>>2), G4->as_VMReg()->next()); | |
202 map->set_callee_saved(VMRegImpl::stack2reg((g5_offset)>>2), G5->as_VMReg()->next()); | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
203 #endif /* _LP64 */ |
0 | 204 } |
205 | |
206 | |
207 // Save the flags | |
208 __ rdccr( G5 ); | |
209 __ stx(G5, SP, ccr_offset+STACK_BIAS); | |
210 __ stxfsr(SP, fsr_offset+STACK_BIAS); | |
211 | |
1007
1ce3281a8e93
6880034: SIGBUS during deoptimisation at a safepoint on 64bit-SPARC
kvn
parents:
1006
diff
changeset
|
212 // Save all the FP registers: 32 doubles (32 floats correspond to the 2 halves of the first 16 doubles) |
0 | 213 int offset = d00_offset; |
1007
1ce3281a8e93
6880034: SIGBUS during deoptimisation at a safepoint on 64bit-SPARC
kvn
parents:
1006
diff
changeset
|
214 for( int i=0; i<FloatRegisterImpl::number_of_registers; i+=2 ) { |
0 | 215 FloatRegister f = as_FloatRegister(i); |
216 __ stf(FloatRegisterImpl::D, f, SP, offset+STACK_BIAS); | |
1007
1ce3281a8e93
6880034: SIGBUS during deoptimisation at a safepoint on 64bit-SPARC
kvn
parents:
1006
diff
changeset
|
217 // Record as callee saved both halves of double registers (2 float registers). |
0 | 218 map->set_callee_saved(VMRegImpl::stack2reg(offset>>2), f->as_VMReg()); |
1007
1ce3281a8e93
6880034: SIGBUS during deoptimisation at a safepoint on 64bit-SPARC
kvn
parents:
1006
diff
changeset
|
219 map->set_callee_saved(VMRegImpl::stack2reg((offset + sizeof(float))>>2), f->as_VMReg()->next()); |
0 | 220 offset += sizeof(double); |
221 } | |
222 | |
223 // And we're done. | |
224 | |
225 return map; | |
226 } | |
227 | |
228 | |
229 // Pop the current frame and restore all the registers that we | |
230 // saved. | |
231 void RegisterSaver::restore_live_registers(MacroAssembler* masm) { | |
232 | |
233 // Restore all the FP registers | |
1007
1ce3281a8e93
6880034: SIGBUS during deoptimisation at a safepoint on 64bit-SPARC
kvn
parents:
1006
diff
changeset
|
234 for( int i=0; i<FloatRegisterImpl::number_of_registers; i+=2 ) { |
0 | 235 __ ldf(FloatRegisterImpl::D, SP, d00_offset+i*sizeof(float)+STACK_BIAS, as_FloatRegister(i)); |
236 } | |
237 | |
238 __ ldx(SP, ccr_offset+STACK_BIAS, G1); | |
239 __ wrccr (G1) ; | |
240 | |
241 // Restore the G's | |
242 // Note that G2 (AKA GThread) must be saved and restored separately. | |
243 // TODO-FIXME: save and restore some of the other ASRs, viz., %asi and %gsr. | |
244 | |
245 __ ldx(SP, g1_offset+STACK_BIAS, G1); | |
246 __ ldx(SP, g3_offset+STACK_BIAS, G3); | |
247 __ ldx(SP, g4_offset+STACK_BIAS, G4); | |
248 __ ldx(SP, g5_offset+STACK_BIAS, G5); | |
249 | |
250 | |
251 #if !defined(_LP64) | |
252 // Restore the 64-bit O's. | |
253 __ ldx(SP, o0_offset+STACK_BIAS, O0); | |
254 __ ldx(SP, o1_offset+STACK_BIAS, O1); | |
255 __ ldx(SP, o2_offset+STACK_BIAS, O2); | |
256 __ ldx(SP, o3_offset+STACK_BIAS, O3); | |
257 __ ldx(SP, o4_offset+STACK_BIAS, O4); | |
258 __ ldx(SP, o5_offset+STACK_BIAS, O5); | |
259 | |
260 // And temporarily place them in TLS | |
261 | |
262 __ stx(O0, G2_thread, JavaThread::o_reg_temps_offset_in_bytes()+0*8); | |
263 __ stx(O1, G2_thread, JavaThread::o_reg_temps_offset_in_bytes()+1*8); | |
264 __ stx(O2, G2_thread, JavaThread::o_reg_temps_offset_in_bytes()+2*8); | |
265 __ stx(O3, G2_thread, JavaThread::o_reg_temps_offset_in_bytes()+3*8); | |
266 __ stx(O4, G2_thread, JavaThread::o_reg_temps_offset_in_bytes()+4*8); | |
267 __ stx(O5, G2_thread, JavaThread::o_reg_temps_offset_in_bytes()+5*8); | |
268 #endif /* _LP64 */ | |
269 | |
270 // Restore flags | |
271 | |
272 __ ldxfsr(SP, fsr_offset+STACK_BIAS); | |
273 | |
274 __ restore(); | |
275 | |
276 #if !defined(_LP64) | |
277 // Now reload the 64bit Oregs after we've restore the window. | |
278 __ ldx(G2_thread, JavaThread::o_reg_temps_offset_in_bytes()+0*8, O0); | |
279 __ ldx(G2_thread, JavaThread::o_reg_temps_offset_in_bytes()+1*8, O1); | |
280 __ ldx(G2_thread, JavaThread::o_reg_temps_offset_in_bytes()+2*8, O2); | |
281 __ ldx(G2_thread, JavaThread::o_reg_temps_offset_in_bytes()+3*8, O3); | |
282 __ ldx(G2_thread, JavaThread::o_reg_temps_offset_in_bytes()+4*8, O4); | |
283 __ ldx(G2_thread, JavaThread::o_reg_temps_offset_in_bytes()+5*8, O5); | |
284 #endif /* _LP64 */ | |
285 | |
286 } | |
287 | |
288 // Pop the current frame and restore the registers that might be holding | |
289 // a result. | |
290 void RegisterSaver::restore_result_registers(MacroAssembler* masm) { | |
291 | |
292 #if !defined(_LP64) | |
293 // 32bit build returns longs in G1 | |
294 __ ldx(SP, g1_offset+STACK_BIAS, G1); | |
295 | |
296 // Retrieve the 64-bit O's. | |
297 __ ldx(SP, o0_offset+STACK_BIAS, O0); | |
298 __ ldx(SP, o1_offset+STACK_BIAS, O1); | |
299 // and save to TLS | |
300 __ stx(O0, G2_thread, JavaThread::o_reg_temps_offset_in_bytes()+0*8); | |
301 __ stx(O1, G2_thread, JavaThread::o_reg_temps_offset_in_bytes()+1*8); | |
302 #endif /* _LP64 */ | |
303 | |
304 __ ldf(FloatRegisterImpl::D, SP, d00_offset+STACK_BIAS, as_FloatRegister(0)); | |
305 | |
306 __ restore(); | |
307 | |
308 #if !defined(_LP64) | |
309 // Now reload the 64bit Oregs after we've restore the window. | |
310 __ ldx(G2_thread, JavaThread::o_reg_temps_offset_in_bytes()+0*8, O0); | |
311 __ ldx(G2_thread, JavaThread::o_reg_temps_offset_in_bytes()+1*8, O1); | |
312 #endif /* _LP64 */ | |
313 | |
314 } | |
315 | |
316 // The java_calling_convention describes stack locations as ideal slots on | |
317 // a frame with no abi restrictions. Since we must observe abi restrictions | |
318 // (like the placement of the register window) the slots must be biased by | |
319 // the following value. | |
320 static int reg2offset(VMReg r) { | |
321 return (r->reg2stack() + SharedRuntime::out_preserve_stack_slots()) * VMRegImpl::stack_slot_size; | |
322 } | |
323 | |
4873
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
324 static VMRegPair reg64_to_VMRegPair(Register r) { |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
325 VMRegPair ret; |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
326 if (wordSize == 8) { |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
327 ret.set2(r->as_VMReg()); |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
328 } else { |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
329 ret.set_pair(r->successor()->as_VMReg(), r->as_VMReg()); |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
330 } |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
331 return ret; |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
332 } |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
333 |
0 | 334 // --------------------------------------------------------------------------- |
335 // Read the array of BasicTypes from a signature, and compute where the | |
336 // arguments should go. Values in the VMRegPair regs array refer to 4-byte (VMRegImpl::stack_slot_size) | |
337 // quantities. Values less than VMRegImpl::stack0 are registers, those above | |
338 // refer to 4-byte stack slots. All stack slots are based off of the window | |
339 // top. VMRegImpl::stack0 refers to the first slot past the 16-word window, | |
340 // and VMRegImpl::stack0+1 refers to the memory word 4-byes higher. Register | |
341 // values 0-63 (up to RegisterImpl::number_of_registers) are the 64-bit | |
342 // integer registers. Values 64-95 are the (32-bit only) float registers. | |
343 // Each 32-bit quantity is given its own number, so the integer registers | |
344 // (in either 32- or 64-bit builds) use 2 numbers. For example, there is | |
345 // an O0-low and an O0-high. Essentially, all int register numbers are doubled. | |
346 | |
347 // Register results are passed in O0-O5, for outgoing call arguments. To | |
348 // convert to incoming arguments, convert all O's to I's. The regs array | |
349 // refer to the low and hi 32-bit words of 64-bit registers or stack slots. | |
350 // If the regs[].second() field is set to VMRegImpl::Bad(), it means it's unused (a | |
351 // 32-bit value was passed). If both are VMRegImpl::Bad(), it means no value was | |
352 // passed (used as a placeholder for the other half of longs and doubles in | |
353 // the 64-bit build). regs[].second() is either VMRegImpl::Bad() or regs[].second() is | |
354 // regs[].first()+1 (regs[].first() may be misaligned in the C calling convention). | |
355 // Sparc never passes a value in regs[].second() but not regs[].first() (regs[].first() | |
356 // == VMRegImpl::Bad() && regs[].second() != VMRegImpl::Bad()) nor unrelated values in the | |
357 // same VMRegPair. | |
358 | |
359 // Note: the INPUTS in sig_bt are in units of Java argument words, which are | |
360 // either 32-bit or 64-bit depending on the build. The OUTPUTS are in 32-bit | |
361 // units regardless of build. | |
362 | |
363 | |
364 // --------------------------------------------------------------------------- | |
365 // The compiled Java calling convention. The Java convention always passes | |
366 // 64-bit values in adjacent aligned locations (either registers or stack), | |
367 // floats in float registers and doubles in aligned float pairs. Values are | |
368 // packed in the registers. There is no backing varargs store for values in | |
369 // registers. In the 32-bit build, longs are passed in G1 and G4 (cannot be | |
370 // passed in I's, because longs in I's get their heads chopped off at | |
371 // interrupt). | |
372 int SharedRuntime::java_calling_convention(const BasicType *sig_bt, | |
373 VMRegPair *regs, | |
374 int total_args_passed, | |
375 int is_outgoing) { | |
376 assert(F31->as_VMReg()->is_reg(), "overlapping stack/register numbers"); | |
377 | |
378 // Convention is to pack the first 6 int/oop args into the first 6 registers | |
379 // (I0-I5), extras spill to the stack. Then pack the first 8 float args | |
380 // into F0-F7, extras spill to the stack. Then pad all register sets to | |
381 // align. Then put longs and doubles into the same registers as they fit, | |
382 // else spill to the stack. | |
383 const int int_reg_max = SPARC_ARGS_IN_REGS_NUM; | |
384 const int flt_reg_max = 8; | |
385 // | |
386 // Where 32-bit 1-reg longs start being passed | |
387 // In tiered we must pass on stack because c1 can't use a "pair" in a single reg. | |
388 // So make it look like we've filled all the G regs that c2 wants to use. | |
389 Register g_reg = TieredCompilation ? noreg : G1; | |
390 | |
391 // Count int/oop and float args. See how many stack slots we'll need and | |
392 // where the longs & doubles will go. | |
393 int int_reg_cnt = 0; | |
394 int flt_reg_cnt = 0; | |
395 // int stk_reg_pairs = frame::register_save_words*(wordSize>>2); | |
396 // int stk_reg_pairs = SharedRuntime::out_preserve_stack_slots(); | |
397 int stk_reg_pairs = 0; | |
398 for (int i = 0; i < total_args_passed; i++) { | |
399 switch (sig_bt[i]) { | |
400 case T_LONG: // LP64, longs compete with int args | |
401 assert(sig_bt[i+1] == T_VOID, ""); | |
402 #ifdef _LP64 | |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
403 if (int_reg_cnt < int_reg_max) int_reg_cnt++; |
0 | 404 #endif |
405 break; | |
406 case T_OBJECT: | |
407 case T_ARRAY: | |
408 case T_ADDRESS: // Used, e.g., in slow-path locking for the lock's stack address | |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
409 if (int_reg_cnt < int_reg_max) int_reg_cnt++; |
0 | 410 #ifndef _LP64 |
411 else stk_reg_pairs++; | |
412 #endif | |
413 break; | |
414 case T_INT: | |
415 case T_SHORT: | |
416 case T_CHAR: | |
417 case T_BYTE: | |
418 case T_BOOLEAN: | |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
419 if (int_reg_cnt < int_reg_max) int_reg_cnt++; |
0 | 420 else stk_reg_pairs++; |
421 break; | |
422 case T_FLOAT: | |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
423 if (flt_reg_cnt < flt_reg_max) flt_reg_cnt++; |
0 | 424 else stk_reg_pairs++; |
425 break; | |
426 case T_DOUBLE: | |
427 assert(sig_bt[i+1] == T_VOID, ""); | |
428 break; | |
429 case T_VOID: | |
430 break; | |
431 default: | |
432 ShouldNotReachHere(); | |
433 } | |
434 } | |
435 | |
436 // This is where the longs/doubles start on the stack. | |
437 stk_reg_pairs = (stk_reg_pairs+1) & ~1; // Round | |
438 | |
439 int flt_reg_pairs = (flt_reg_cnt+1) & ~1; | |
440 | |
441 // int stk_reg = frame::register_save_words*(wordSize>>2); | |
442 // int stk_reg = SharedRuntime::out_preserve_stack_slots(); | |
443 int stk_reg = 0; | |
444 int int_reg = 0; | |
445 int flt_reg = 0; | |
446 | |
447 // Now do the signature layout | |
448 for (int i = 0; i < total_args_passed; i++) { | |
449 switch (sig_bt[i]) { | |
450 case T_INT: | |
451 case T_SHORT: | |
452 case T_CHAR: | |
453 case T_BYTE: | |
454 case T_BOOLEAN: | |
455 #ifndef _LP64 | |
456 case T_OBJECT: | |
457 case T_ARRAY: | |
458 case T_ADDRESS: // Used, e.g., in slow-path locking for the lock's stack address | |
459 #endif // _LP64 | |
460 if (int_reg < int_reg_max) { | |
461 Register r = is_outgoing ? as_oRegister(int_reg++) : as_iRegister(int_reg++); | |
462 regs[i].set1(r->as_VMReg()); | |
463 } else { | |
464 regs[i].set1(VMRegImpl::stack2reg(stk_reg++)); | |
465 } | |
466 break; | |
467 | |
468 #ifdef _LP64 | |
469 case T_OBJECT: | |
470 case T_ARRAY: | |
471 case T_ADDRESS: // Used, e.g., in slow-path locking for the lock's stack address | |
472 if (int_reg < int_reg_max) { | |
473 Register r = is_outgoing ? as_oRegister(int_reg++) : as_iRegister(int_reg++); | |
474 regs[i].set2(r->as_VMReg()); | |
475 } else { | |
476 regs[i].set2(VMRegImpl::stack2reg(stk_reg_pairs)); | |
477 stk_reg_pairs += 2; | |
478 } | |
479 break; | |
480 #endif // _LP64 | |
481 | |
482 case T_LONG: | |
483 assert(sig_bt[i+1] == T_VOID, "expecting VOID in other half"); | |
484 #ifdef _LP64 | |
485 if (int_reg < int_reg_max) { | |
486 Register r = is_outgoing ? as_oRegister(int_reg++) : as_iRegister(int_reg++); | |
487 regs[i].set2(r->as_VMReg()); | |
488 } else { | |
489 regs[i].set2(VMRegImpl::stack2reg(stk_reg_pairs)); | |
490 stk_reg_pairs += 2; | |
491 } | |
492 #else | |
304 | 493 #ifdef COMPILER2 |
0 | 494 // For 32-bit build, can't pass longs in O-regs because they become |
495 // I-regs and get trashed. Use G-regs instead. G1 and G4 are almost | |
496 // spare and available. This convention isn't used by the Sparc ABI or | |
497 // anywhere else. If we're tiered then we don't use G-regs because c1 | |
304 | 498 // can't deal with them as a "pair". (Tiered makes this code think g's are filled) |
0 | 499 // G0: zero |
500 // G1: 1st Long arg | |
501 // G2: global allocated to TLS | |
502 // G3: used in inline cache check | |
503 // G4: 2nd Long arg | |
504 // G5: used in inline cache check | |
505 // G6: used by OS | |
506 // G7: used by OS | |
507 | |
508 if (g_reg == G1) { | |
509 regs[i].set2(G1->as_VMReg()); // This long arg in G1 | |
510 g_reg = G4; // Where the next arg goes | |
511 } else if (g_reg == G4) { | |
512 regs[i].set2(G4->as_VMReg()); // The 2nd long arg in G4 | |
513 g_reg = noreg; // No more longs in registers | |
514 } else { | |
515 regs[i].set2(VMRegImpl::stack2reg(stk_reg_pairs)); | |
516 stk_reg_pairs += 2; | |
517 } | |
518 #else // COMPILER2 | |
519 regs[i].set2(VMRegImpl::stack2reg(stk_reg_pairs)); | |
520 stk_reg_pairs += 2; | |
521 #endif // COMPILER2 | |
304 | 522 #endif // _LP64 |
0 | 523 break; |
524 | |
525 case T_FLOAT: | |
526 if (flt_reg < flt_reg_max) regs[i].set1(as_FloatRegister(flt_reg++)->as_VMReg()); | |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
527 else regs[i].set1(VMRegImpl::stack2reg(stk_reg++)); |
0 | 528 break; |
529 case T_DOUBLE: | |
530 assert(sig_bt[i+1] == T_VOID, "expecting half"); | |
531 if (flt_reg_pairs + 1 < flt_reg_max) { | |
532 regs[i].set2(as_FloatRegister(flt_reg_pairs)->as_VMReg()); | |
533 flt_reg_pairs += 2; | |
534 } else { | |
535 regs[i].set2(VMRegImpl::stack2reg(stk_reg_pairs)); | |
536 stk_reg_pairs += 2; | |
537 } | |
538 break; | |
539 case T_VOID: regs[i].set_bad(); break; // Halves of longs & doubles | |
540 default: | |
541 ShouldNotReachHere(); | |
542 } | |
543 } | |
544 | |
545 // retun the amount of stack space these arguments will need. | |
546 return stk_reg_pairs; | |
547 | |
548 } | |
549 | |
1006
dcf03e02b020
6879902: CTW failure jdk6_18/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp:845
twisti
parents:
727
diff
changeset
|
550 // Helper class mostly to avoid passing masm everywhere, and handle |
dcf03e02b020
6879902: CTW failure jdk6_18/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp:845
twisti
parents:
727
diff
changeset
|
551 // store displacement overflow logic. |
0 | 552 class AdapterGenerator { |
553 MacroAssembler *masm; | |
554 Register Rdisp; | |
555 void set_Rdisp(Register r) { Rdisp = r; } | |
556 | |
557 void patch_callers_callsite(); | |
558 | |
559 // base+st_off points to top of argument | |
1506 | 560 int arg_offset(const int st_off) { return st_off; } |
0 | 561 int next_arg_offset(const int st_off) { |
1506 | 562 return st_off - Interpreter::stackElementSize; |
1006
dcf03e02b020
6879902: CTW failure jdk6_18/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp:845
twisti
parents:
727
diff
changeset
|
563 } |
dcf03e02b020
6879902: CTW failure jdk6_18/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp:845
twisti
parents:
727
diff
changeset
|
564 |
dcf03e02b020
6879902: CTW failure jdk6_18/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp:845
twisti
parents:
727
diff
changeset
|
565 // Argument slot values may be loaded first into a register because |
dcf03e02b020
6879902: CTW failure jdk6_18/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp:845
twisti
parents:
727
diff
changeset
|
566 // they might not fit into displacement. |
dcf03e02b020
6879902: CTW failure jdk6_18/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp:845
twisti
parents:
727
diff
changeset
|
567 RegisterOrConstant arg_slot(const int st_off); |
dcf03e02b020
6879902: CTW failure jdk6_18/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp:845
twisti
parents:
727
diff
changeset
|
568 RegisterOrConstant next_arg_slot(const int st_off); |
dcf03e02b020
6879902: CTW failure jdk6_18/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp:845
twisti
parents:
727
diff
changeset
|
569 |
0 | 570 // Stores long into offset pointed to by base |
571 void store_c2i_long(Register r, Register base, | |
572 const int st_off, bool is_stack); | |
573 void store_c2i_object(Register r, Register base, | |
574 const int st_off); | |
575 void store_c2i_int(Register r, Register base, | |
576 const int st_off); | |
577 void store_c2i_double(VMReg r_2, | |
578 VMReg r_1, Register base, const int st_off); | |
579 void store_c2i_float(FloatRegister f, Register base, | |
580 const int st_off); | |
581 | |
582 public: | |
583 void gen_c2i_adapter(int total_args_passed, | |
584 // VMReg max_arg, | |
585 int comp_args_on_stack, // VMRegStackSlots | |
586 const BasicType *sig_bt, | |
587 const VMRegPair *regs, | |
588 Label& skip_fixup); | |
589 void gen_i2c_adapter(int total_args_passed, | |
590 // VMReg max_arg, | |
591 int comp_args_on_stack, // VMRegStackSlots | |
592 const BasicType *sig_bt, | |
593 const VMRegPair *regs); | |
594 | |
595 AdapterGenerator(MacroAssembler *_masm) : masm(_masm) {} | |
596 }; | |
597 | |
598 | |
599 // Patch the callers callsite with entry to compiled code if it exists. | |
600 void AdapterGenerator::patch_callers_callsite() { | |
601 Label L; | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
602 __ ld_ptr(G5_method, in_bytes(Method::code_offset()), G3_scratch); |
3839 | 603 __ br_null(G3_scratch, false, Assembler::pt, L); |
0 | 604 // Schedule the branch target address early. |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
605 __ delayed()->ld_ptr(G5_method, in_bytes(Method::interpreter_entry_offset()), G3_scratch); |
0 | 606 // Call into the VM to patch the caller, then jump to compiled callee |
607 __ save_frame(4); // Args in compiled layout; do not blow them | |
608 | |
609 // Must save all the live Gregs the list is: | |
610 // G1: 1st Long arg (32bit build) | |
611 // G2: global allocated to TLS | |
612 // G3: used in inline cache check (scratch) | |
613 // G4: 2nd Long arg (32bit build); | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
614 // G5: used in inline cache check (Method*) |
0 | 615 |
616 // The longs must go to the stack by hand since in the 32 bit build they can be trashed by window ops. | |
617 | |
618 #ifdef _LP64 | |
619 // mov(s,d) | |
620 __ mov(G1, L1); | |
621 __ mov(G4, L4); | |
622 __ mov(G5_method, L5); | |
623 __ mov(G5_method, O0); // VM needs target method | |
624 __ mov(I7, O1); // VM needs caller's callsite | |
625 // Must be a leaf call... | |
626 // can be very far once the blob has been relocated | |
727 | 627 AddressLiteral dest(CAST_FROM_FN_PTR(address, SharedRuntime::fixup_callers_callsite)); |
0 | 628 __ relocate(relocInfo::runtime_call_type); |
727 | 629 __ jumpl_to(dest, O7, O7); |
0 | 630 __ delayed()->mov(G2_thread, L7_thread_cache); |
631 __ mov(L7_thread_cache, G2_thread); | |
632 __ mov(L1, G1); | |
633 __ mov(L4, G4); | |
634 __ mov(L5, G5_method); | |
635 #else | |
636 __ stx(G1, FP, -8 + STACK_BIAS); | |
637 __ stx(G4, FP, -16 + STACK_BIAS); | |
638 __ mov(G5_method, L5); | |
639 __ mov(G5_method, O0); // VM needs target method | |
640 __ mov(I7, O1); // VM needs caller's callsite | |
641 // Must be a leaf call... | |
642 __ call(CAST_FROM_FN_PTR(address, SharedRuntime::fixup_callers_callsite), relocInfo::runtime_call_type); | |
643 __ delayed()->mov(G2_thread, L7_thread_cache); | |
644 __ mov(L7_thread_cache, G2_thread); | |
645 __ ldx(FP, -8 + STACK_BIAS, G1); | |
646 __ ldx(FP, -16 + STACK_BIAS, G4); | |
647 __ mov(L5, G5_method); | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
648 __ ld_ptr(G5_method, in_bytes(Method::interpreter_entry_offset()), G3_scratch); |
0 | 649 #endif /* _LP64 */ |
650 | |
651 __ restore(); // Restore args | |
652 __ bind(L); | |
653 } | |
654 | |
1006
dcf03e02b020
6879902: CTW failure jdk6_18/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp:845
twisti
parents:
727
diff
changeset
|
655 |
dcf03e02b020
6879902: CTW failure jdk6_18/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp:845
twisti
parents:
727
diff
changeset
|
656 RegisterOrConstant AdapterGenerator::arg_slot(const int st_off) { |
dcf03e02b020
6879902: CTW failure jdk6_18/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp:845
twisti
parents:
727
diff
changeset
|
657 RegisterOrConstant roc(arg_offset(st_off)); |
dcf03e02b020
6879902: CTW failure jdk6_18/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp:845
twisti
parents:
727
diff
changeset
|
658 return __ ensure_simm13_or_reg(roc, Rdisp); |
dcf03e02b020
6879902: CTW failure jdk6_18/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp:845
twisti
parents:
727
diff
changeset
|
659 } |
dcf03e02b020
6879902: CTW failure jdk6_18/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp:845
twisti
parents:
727
diff
changeset
|
660 |
dcf03e02b020
6879902: CTW failure jdk6_18/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp:845
twisti
parents:
727
diff
changeset
|
661 RegisterOrConstant AdapterGenerator::next_arg_slot(const int st_off) { |
dcf03e02b020
6879902: CTW failure jdk6_18/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp:845
twisti
parents:
727
diff
changeset
|
662 RegisterOrConstant roc(next_arg_offset(st_off)); |
dcf03e02b020
6879902: CTW failure jdk6_18/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp:845
twisti
parents:
727
diff
changeset
|
663 return __ ensure_simm13_or_reg(roc, Rdisp); |
0 | 664 } |
665 | |
1006
dcf03e02b020
6879902: CTW failure jdk6_18/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp:845
twisti
parents:
727
diff
changeset
|
666 |
0 | 667 // Stores long into offset pointed to by base |
668 void AdapterGenerator::store_c2i_long(Register r, Register base, | |
669 const int st_off, bool is_stack) { | |
670 #ifdef _LP64 | |
671 // In V9, longs are given 2 64-bit slots in the interpreter, but the | |
672 // data is passed in only 1 slot. | |
673 __ stx(r, base, next_arg_slot(st_off)); | |
674 #else | |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
116
diff
changeset
|
675 #ifdef COMPILER2 |
0 | 676 // Misaligned store of 64-bit data |
677 __ stw(r, base, arg_slot(st_off)); // lo bits | |
678 __ srlx(r, 32, r); | |
679 __ stw(r, base, next_arg_slot(st_off)); // hi bits | |
680 #else | |
681 if (is_stack) { | |
682 // Misaligned store of 64-bit data | |
683 __ stw(r, base, arg_slot(st_off)); // lo bits | |
684 __ srlx(r, 32, r); | |
685 __ stw(r, base, next_arg_slot(st_off)); // hi bits | |
686 } else { | |
687 __ stw(r->successor(), base, arg_slot(st_off) ); // lo bits | |
688 __ stw(r , base, next_arg_slot(st_off)); // hi bits | |
689 } | |
690 #endif // COMPILER2 | |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
116
diff
changeset
|
691 #endif // _LP64 |
0 | 692 } |
693 | |
694 void AdapterGenerator::store_c2i_object(Register r, Register base, | |
695 const int st_off) { | |
696 __ st_ptr (r, base, arg_slot(st_off)); | |
697 } | |
698 | |
699 void AdapterGenerator::store_c2i_int(Register r, Register base, | |
700 const int st_off) { | |
701 __ st (r, base, arg_slot(st_off)); | |
702 } | |
703 | |
704 // Stores into offset pointed to by base | |
705 void AdapterGenerator::store_c2i_double(VMReg r_2, | |
706 VMReg r_1, Register base, const int st_off) { | |
707 #ifdef _LP64 | |
708 // In V9, doubles are given 2 64-bit slots in the interpreter, but the | |
709 // data is passed in only 1 slot. | |
710 __ stf(FloatRegisterImpl::D, r_1->as_FloatRegister(), base, next_arg_slot(st_off)); | |
711 #else | |
712 // Need to marshal 64-bit value from misaligned Lesp loads | |
713 __ stf(FloatRegisterImpl::S, r_1->as_FloatRegister(), base, next_arg_slot(st_off)); | |
714 __ stf(FloatRegisterImpl::S, r_2->as_FloatRegister(), base, arg_slot(st_off) ); | |
715 #endif | |
716 } | |
717 | |
718 void AdapterGenerator::store_c2i_float(FloatRegister f, Register base, | |
719 const int st_off) { | |
720 __ stf(FloatRegisterImpl::S, f, base, arg_slot(st_off)); | |
721 } | |
722 | |
723 void AdapterGenerator::gen_c2i_adapter( | |
724 int total_args_passed, | |
725 // VMReg max_arg, | |
726 int comp_args_on_stack, // VMRegStackSlots | |
727 const BasicType *sig_bt, | |
728 const VMRegPair *regs, | |
729 Label& skip_fixup) { | |
730 | |
731 // Before we get into the guts of the C2I adapter, see if we should be here | |
732 // at all. We've come from compiled code and are attempting to jump to the | |
733 // interpreter, which means the caller made a static call to get here | |
734 // (vcalls always get a compiled target if there is one). Check for a | |
735 // compiled target. If there is one, we need to patch the caller's call. | |
736 // However we will run interpreted if we come thru here. The next pass | |
737 // thru the call site will run compiled. If we ran compiled here then | |
738 // we can (theorectically) do endless i2c->c2i->i2c transitions during | |
739 // deopt/uncommon trap cycles. If we always go interpreted here then | |
740 // we can have at most one and don't need to play any tricks to keep | |
741 // from endlessly growing the stack. | |
742 // | |
743 // Actually if we detected that we had an i2c->c2i transition here we | |
744 // ought to be able to reset the world back to the state of the interpreted | |
745 // call and not bother building another interpreter arg area. We don't | |
746 // do that at this point. | |
747 | |
748 patch_callers_callsite(); | |
749 | |
750 __ bind(skip_fixup); | |
751 | |
752 // Since all args are passed on the stack, total_args_passed*wordSize is the | |
753 // space we need. Add in varargs area needed by the interpreter. Round up | |
754 // to stack alignment. | |
1506 | 755 const int arg_size = total_args_passed * Interpreter::stackElementSize; |
0 | 756 const int varargs_area = |
757 (frame::varargs_offset - frame::register_save_words)*wordSize; | |
758 const int extraspace = round_to(arg_size + varargs_area, 2*wordSize); | |
759 | |
760 int bias = STACK_BIAS; | |
761 const int interp_arg_offset = frame::varargs_offset*wordSize + | |
1506 | 762 (total_args_passed-1)*Interpreter::stackElementSize; |
0 | 763 |
764 Register base = SP; | |
765 | |
766 #ifdef _LP64 | |
767 // In the 64bit build because of wider slots and STACKBIAS we can run | |
768 // out of bits in the displacement to do loads and stores. Use g3 as | |
769 // temporary displacement. | |
4114
6729bbc1fcd6
7003454: order constants in constant table by number of references in code
twisti
parents:
3839
diff
changeset
|
770 if (!Assembler::is_simm13(extraspace)) { |
0 | 771 __ set(extraspace, G3_scratch); |
772 __ sub(SP, G3_scratch, SP); | |
773 } else { | |
774 __ sub(SP, extraspace, SP); | |
775 } | |
776 set_Rdisp(G3_scratch); | |
777 #else | |
778 __ sub(SP, extraspace, SP); | |
779 #endif // _LP64 | |
780 | |
781 // First write G1 (if used) to where ever it must go | |
782 for (int i=0; i<total_args_passed; i++) { | |
1506 | 783 const int st_off = interp_arg_offset - (i*Interpreter::stackElementSize) + bias; |
0 | 784 VMReg r_1 = regs[i].first(); |
785 VMReg r_2 = regs[i].second(); | |
786 if (r_1 == G1_scratch->as_VMReg()) { | |
787 if (sig_bt[i] == T_OBJECT || sig_bt[i] == T_ARRAY) { | |
788 store_c2i_object(G1_scratch, base, st_off); | |
789 } else if (sig_bt[i] == T_LONG) { | |
790 assert(!TieredCompilation, "should not use register args for longs"); | |
791 store_c2i_long(G1_scratch, base, st_off, false); | |
792 } else { | |
793 store_c2i_int(G1_scratch, base, st_off); | |
794 } | |
795 } | |
796 } | |
797 | |
798 // Now write the args into the outgoing interpreter space | |
799 for (int i=0; i<total_args_passed; i++) { | |
1506 | 800 const int st_off = interp_arg_offset - (i*Interpreter::stackElementSize) + bias; |
0 | 801 VMReg r_1 = regs[i].first(); |
802 VMReg r_2 = regs[i].second(); | |
803 if (!r_1->is_valid()) { | |
804 assert(!r_2->is_valid(), ""); | |
805 continue; | |
806 } | |
807 // Skip G1 if found as we did it first in order to free it up | |
808 if (r_1 == G1_scratch->as_VMReg()) { | |
809 continue; | |
810 } | |
811 #ifdef ASSERT | |
812 bool G1_forced = false; | |
813 #endif // ASSERT | |
814 if (r_1->is_stack()) { // Pretend stack targets are loaded into G1 | |
815 #ifdef _LP64 | |
816 Register ld_off = Rdisp; | |
817 __ set(reg2offset(r_1) + extraspace + bias, ld_off); | |
818 #else | |
819 int ld_off = reg2offset(r_1) + extraspace + bias; | |
1251
576e77447e3c
6923002: assert(false,"this call site should not be polymorphic")
kvn
parents:
1187
diff
changeset
|
820 #endif // _LP64 |
0 | 821 #ifdef ASSERT |
822 G1_forced = true; | |
823 #endif // ASSERT | |
824 r_1 = G1_scratch->as_VMReg();// as part of the load/store shuffle | |
825 if (!r_2->is_valid()) __ ld (base, ld_off, G1_scratch); | |
826 else __ ldx(base, ld_off, G1_scratch); | |
827 } | |
828 | |
829 if (r_1->is_Register()) { | |
830 Register r = r_1->as_Register()->after_restore(); | |
831 if (sig_bt[i] == T_OBJECT || sig_bt[i] == T_ARRAY) { | |
832 store_c2i_object(r, base, st_off); | |
833 } else if (sig_bt[i] == T_LONG || sig_bt[i] == T_DOUBLE) { | |
1251
576e77447e3c
6923002: assert(false,"this call site should not be polymorphic")
kvn
parents:
1187
diff
changeset
|
834 #ifndef _LP64 |
0 | 835 if (TieredCompilation) { |
836 assert(G1_forced || sig_bt[i] != T_LONG, "should not use register args for longs"); | |
837 } | |
1251
576e77447e3c
6923002: assert(false,"this call site should not be polymorphic")
kvn
parents:
1187
diff
changeset
|
838 #endif // _LP64 |
0 | 839 store_c2i_long(r, base, st_off, r_2->is_stack()); |
840 } else { | |
841 store_c2i_int(r, base, st_off); | |
842 } | |
843 } else { | |
844 assert(r_1->is_FloatRegister(), ""); | |
845 if (sig_bt[i] == T_FLOAT) { | |
846 store_c2i_float(r_1->as_FloatRegister(), base, st_off); | |
847 } else { | |
848 assert(sig_bt[i] == T_DOUBLE, "wrong type"); | |
849 store_c2i_double(r_2, r_1, base, st_off); | |
850 } | |
851 } | |
852 } | |
853 | |
854 #ifdef _LP64 | |
855 // Need to reload G3_scratch, used for temporary displacements. | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
856 __ ld_ptr(G5_method, in_bytes(Method::interpreter_entry_offset()), G3_scratch); |
0 | 857 |
858 // Pass O5_savedSP as an argument to the interpreter. | |
859 // The interpreter will restore SP to this value before returning. | |
860 __ set(extraspace, G1); | |
861 __ add(SP, G1, O5_savedSP); | |
862 #else | |
863 // Pass O5_savedSP as an argument to the interpreter. | |
864 // The interpreter will restore SP to this value before returning. | |
865 __ add(SP, extraspace, O5_savedSP); | |
866 #endif // _LP64 | |
867 | |
868 __ mov((frame::varargs_offset)*wordSize - | |
1506 | 869 1*Interpreter::stackElementSize+bias+BytesPerWord, G1); |
0 | 870 // Jump to the interpreter just as if interpreter was doing it. |
871 __ jmpl(G3_scratch, 0, G0); | |
872 // Setup Lesp for the call. Cannot actually set Lesp as the current Lesp | |
873 // (really L0) is in use by the compiled frame as a generic temp. However, | |
874 // the interpreter does not know where its args are without some kind of | |
875 // arg pointer being passed in. Pass it in Gargs. | |
876 __ delayed()->add(SP, G1, Gargs); | |
877 } | |
878 | |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
879 static void range_check(MacroAssembler* masm, Register pc_reg, Register temp_reg, Register temp2_reg, |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
880 address code_start, address code_end, |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
881 Label& L_ok) { |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
882 Label L_fail; |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
883 __ set(ExternalAddress(code_start), temp_reg); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
884 __ set(pointer_delta(code_end, code_start, 1), temp2_reg); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
885 __ cmp(pc_reg, temp_reg); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
886 __ brx(Assembler::lessEqualUnsigned, false, Assembler::pn, L_fail); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
887 __ delayed()->add(temp_reg, temp2_reg, temp_reg); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
888 __ cmp(pc_reg, temp_reg); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
889 __ cmp_and_brx_short(pc_reg, temp_reg, Assembler::lessUnsigned, Assembler::pt, L_ok); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
890 __ bind(L_fail); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
891 } |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
892 |
0 | 893 void AdapterGenerator::gen_i2c_adapter( |
894 int total_args_passed, | |
895 // VMReg max_arg, | |
896 int comp_args_on_stack, // VMRegStackSlots | |
897 const BasicType *sig_bt, | |
898 const VMRegPair *regs) { | |
899 | |
900 // Generate an I2C adapter: adjust the I-frame to make space for the C-frame | |
901 // layout. Lesp was saved by the calling I-frame and will be restored on | |
902 // return. Meanwhile, outgoing arg space is all owned by the callee | |
903 // C-frame, so we can mangle it at will. After adjusting the frame size, | |
904 // hoist register arguments and repack other args according to the compiled | |
905 // code convention. Finally, end in a jump to the compiled code. The entry | |
906 // point address is the start of the buffer. | |
907 | |
908 // We will only enter here from an interpreted frame and never from after | |
909 // passing thru a c2i. Azul allowed this but we do not. If we lose the | |
910 // race and use a c2i we will remain interpreted for the race loser(s). | |
911 // This removes all sorts of headaches on the x86 side and also eliminates | |
912 // the possibility of having c2i -> i2c -> c2i -> ... endless transitions. | |
913 | |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
914 // More detail: |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
915 // Adapters can be frameless because they do not require the caller |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
916 // to perform additional cleanup work, such as correcting the stack pointer. |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
917 // An i2c adapter is frameless because the *caller* frame, which is interpreted, |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
918 // routinely repairs its own stack pointer (from interpreter_frame_last_sp), |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
919 // even if a callee has modified the stack pointer. |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
920 // A c2i adapter is frameless because the *callee* frame, which is interpreted, |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
921 // routinely repairs its caller's stack pointer (from sender_sp, which is set |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
922 // up via the senderSP register). |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
923 // In other words, if *either* the caller or callee is interpreted, we can |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
924 // get the stack pointer repaired after a call. |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
925 // This is why c2i and i2c adapters cannot be indefinitely composed. |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
926 // In particular, if a c2i adapter were to somehow call an i2c adapter, |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
927 // both caller and callee would be compiled methods, and neither would |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
928 // clean up the stack pointer changes performed by the two adapters. |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
929 // If this happens, control eventually transfers back to the compiled |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
930 // caller, but with an uncorrected stack, causing delayed havoc. |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
931 |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
932 if (VerifyAdapterCalls && |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
933 (Interpreter::code() != NULL || StubRoutines::code1() != NULL)) { |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
934 // So, let's test for cascading c2i/i2c adapters right now. |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
935 // assert(Interpreter::contains($return_addr) || |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
936 // StubRoutines::contains($return_addr), |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
937 // "i2c adapter must return to an interpreter frame"); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
938 __ block_comment("verify_i2c { "); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
939 Label L_ok; |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
940 if (Interpreter::code() != NULL) |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
941 range_check(masm, O7, O0, O1, |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
942 Interpreter::code()->code_start(), Interpreter::code()->code_end(), |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
943 L_ok); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
944 if (StubRoutines::code1() != NULL) |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
945 range_check(masm, O7, O0, O1, |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
946 StubRoutines::code1()->code_begin(), StubRoutines::code1()->code_end(), |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
947 L_ok); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
948 if (StubRoutines::code2() != NULL) |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
949 range_check(masm, O7, O0, O1, |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
950 StubRoutines::code2()->code_begin(), StubRoutines::code2()->code_end(), |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
951 L_ok); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
952 const char* msg = "i2c adapter must return to an interpreter frame"; |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
953 __ block_comment(msg); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
954 __ stop(msg); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
955 __ bind(L_ok); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
956 __ block_comment("} verify_i2ce "); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
957 } |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
958 |
0 | 959 // As you can see from the list of inputs & outputs there are not a lot |
960 // of temp registers to work with: mostly G1, G3 & G4. | |
961 | |
962 // Inputs: | |
963 // G2_thread - TLS | |
964 // G5_method - Method oop | |
710 | 965 // G4 (Gargs) - Pointer to interpreter's args |
966 // O0..O4 - free for scratch | |
967 // O5_savedSP - Caller's saved SP, to be restored if needed | |
0 | 968 // O6 - Current SP! |
969 // O7 - Valid return address | |
710 | 970 // L0-L7, I0-I7 - Caller's temps (no frame pushed yet) |
0 | 971 |
972 // Outputs: | |
973 // G2_thread - TLS | |
974 // G1, G4 - Outgoing long args in 32-bit build | |
975 // O0-O5 - Outgoing args in compiled layout | |
976 // O6 - Adjusted or restored SP | |
977 // O7 - Valid return address | |
1564 | 978 // L0-L7, I0-I7 - Caller's temps (no frame pushed yet) |
0 | 979 // F0-F7 - more outgoing args |
980 | |
981 | |
710 | 982 // Gargs is the incoming argument base, and also an outgoing argument. |
0 | 983 __ sub(Gargs, BytesPerWord, Gargs); |
984 | |
985 // ON ENTRY TO THE CODE WE ARE MAKING, WE HAVE AN INTERPRETED FRAME | |
986 // WITH O7 HOLDING A VALID RETURN PC | |
987 // | |
988 // | | | |
989 // : java stack : | |
990 // | | | |
991 // +--------------+ <--- start of outgoing args | |
992 // | receiver | | | |
993 // : rest of args : |---size is java-arg-words | |
994 // | | | | |
995 // +--------------+ <--- O4_args (misaligned) and Lesp if prior is not C2I | |
996 // | | | | |
997 // : unused : |---Space for max Java stack, plus stack alignment | |
998 // | | | | |
999 // +--------------+ <--- SP + 16*wordsize | |
1000 // | | | |
1001 // : window : | |
1002 // | | | |
1003 // +--------------+ <--- SP | |
1004 | |
1005 // WE REPACK THE STACK. We use the common calling convention layout as | |
1006 // discovered by calling SharedRuntime::calling_convention. We assume it | |
1007 // causes an arbitrary shuffle of memory, which may require some register | |
1008 // temps to do the shuffle. We hope for (and optimize for) the case where | |
1009 // temps are not needed. We may have to resize the stack slightly, in case | |
1010 // we need alignment padding (32-bit interpreter can pass longs & doubles | |
1011 // misaligned, but the compilers expect them aligned). | |
1012 // | |
1013 // | | | |
1014 // : java stack : | |
1015 // | | | |
1016 // +--------------+ <--- start of outgoing args | |
1017 // | pad, align | | | |
1018 // +--------------+ | | |
1019 // | ints, floats | |---Outgoing stack args, packed low. | |
1020 // +--------------+ | First few args in registers. | |
1021 // : doubles : | | |
1022 // | longs | | | |
1023 // +--------------+ <--- SP' + 16*wordsize | |
1024 // | | | |
1025 // : window : | |
1026 // | | | |
1027 // +--------------+ <--- SP' | |
1028 | |
1029 // ON EXIT FROM THE CODE WE ARE MAKING, WE STILL HAVE AN INTERPRETED FRAME | |
1030 // WITH O7 HOLDING A VALID RETURN PC - ITS JUST THAT THE ARGS ARE NOW SETUP | |
1031 // FOR COMPILED CODE AND THE FRAME SLIGHTLY GROWN. | |
1032 | |
1033 // Cut-out for having no stack args. Since up to 6 args are passed | |
1034 // in registers, we will commonly have no stack args. | |
1035 if (comp_args_on_stack > 0) { | |
1036 | |
1037 // Convert VMReg stack slots to words. | |
1038 int comp_words_on_stack = round_to(comp_args_on_stack*VMRegImpl::stack_slot_size, wordSize)>>LogBytesPerWord; | |
1039 // Round up to miminum stack alignment, in wordSize | |
1040 comp_words_on_stack = round_to(comp_words_on_stack, 2); | |
1041 // Now compute the distance from Lesp to SP. This calculation does not | |
1042 // include the space for total_args_passed because Lesp has not yet popped | |
1043 // the arguments. | |
1044 __ sub(SP, (comp_words_on_stack)*wordSize, SP); | |
1045 } | |
1046 | |
1047 // Will jump to the compiled code just as if compiled code was doing it. | |
1048 // Pre-load the register-jump target early, to schedule it better. | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
1049 __ ld_ptr(G5_method, in_bytes(Method::from_compiled_offset()), G3); |
0 | 1050 |
1051 // Now generate the shuffle code. Pick up all register args and move the | |
1052 // rest through G1_scratch. | |
1053 for (int i=0; i<total_args_passed; i++) { | |
1054 if (sig_bt[i] == T_VOID) { | |
1055 // Longs and doubles are passed in native word order, but misaligned | |
1056 // in the 32-bit build. | |
1057 assert(i > 0 && (sig_bt[i-1] == T_LONG || sig_bt[i-1] == T_DOUBLE), "missing half"); | |
1058 continue; | |
1059 } | |
1060 | |
1061 // Pick up 0, 1 or 2 words from Lesp+offset. Assume mis-aligned in the | |
1062 // 32-bit build and aligned in the 64-bit build. Look for the obvious | |
1063 // ldx/lddf optimizations. | |
1064 | |
1065 // Load in argument order going down. | |
1506 | 1066 const int ld_off = (total_args_passed-i)*Interpreter::stackElementSize; |
0 | 1067 set_Rdisp(G1_scratch); |
1068 | |
1069 VMReg r_1 = regs[i].first(); | |
1070 VMReg r_2 = regs[i].second(); | |
1071 if (!r_1->is_valid()) { | |
1072 assert(!r_2->is_valid(), ""); | |
1073 continue; | |
1074 } | |
1075 if (r_1->is_stack()) { // Pretend stack targets are loaded into F8/F9 | |
1076 r_1 = F8->as_VMReg(); // as part of the load/store shuffle | |
1077 if (r_2->is_valid()) r_2 = r_1->next(); | |
1078 } | |
1079 if (r_1->is_Register()) { // Register argument | |
1080 Register r = r_1->as_Register()->after_restore(); | |
1081 if (!r_2->is_valid()) { | |
1082 __ ld(Gargs, arg_slot(ld_off), r); | |
1083 } else { | |
1084 #ifdef _LP64 | |
1085 // In V9, longs are given 2 64-bit slots in the interpreter, but the | |
1086 // data is passed in only 1 slot. | |
1006
dcf03e02b020
6879902: CTW failure jdk6_18/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp:845
twisti
parents:
727
diff
changeset
|
1087 RegisterOrConstant slot = (sig_bt[i] == T_LONG) ? |
0 | 1088 next_arg_slot(ld_off) : arg_slot(ld_off); |
1089 __ ldx(Gargs, slot, r); | |
1090 #else | |
1091 // Need to load a 64-bit value into G1/G4, but G1/G4 is being used in the | |
1092 // stack shuffle. Load the first 2 longs into G1/G4 later. | |
1093 #endif | |
1094 } | |
1095 } else { | |
1096 assert(r_1->is_FloatRegister(), ""); | |
1097 if (!r_2->is_valid()) { | |
1098 __ ldf(FloatRegisterImpl::S, Gargs, arg_slot(ld_off), r_1->as_FloatRegister()); | |
1099 } else { | |
1100 #ifdef _LP64 | |
1101 // In V9, doubles are given 2 64-bit slots in the interpreter, but the | |
1102 // data is passed in only 1 slot. This code also handles longs that | |
1103 // are passed on the stack, but need a stack-to-stack move through a | |
1104 // spare float register. | |
1006
dcf03e02b020
6879902: CTW failure jdk6_18/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp:845
twisti
parents:
727
diff
changeset
|
1105 RegisterOrConstant slot = (sig_bt[i] == T_LONG || sig_bt[i] == T_DOUBLE) ? |
0 | 1106 next_arg_slot(ld_off) : arg_slot(ld_off); |
1107 __ ldf(FloatRegisterImpl::D, Gargs, slot, r_1->as_FloatRegister()); | |
1108 #else | |
1109 // Need to marshal 64-bit value from misaligned Lesp loads | |
1110 __ ldf(FloatRegisterImpl::S, Gargs, next_arg_slot(ld_off), r_1->as_FloatRegister()); | |
1111 __ ldf(FloatRegisterImpl::S, Gargs, arg_slot(ld_off), r_2->as_FloatRegister()); | |
1112 #endif | |
1113 } | |
1114 } | |
1115 // Was the argument really intended to be on the stack, but was loaded | |
1116 // into F8/F9? | |
1117 if (regs[i].first()->is_stack()) { | |
1118 assert(r_1->as_FloatRegister() == F8, "fix this code"); | |
1119 // Convert stack slot to an SP offset | |
1120 int st_off = reg2offset(regs[i].first()) + STACK_BIAS; | |
1121 // Store down the shuffled stack word. Target address _is_ aligned. | |
1006
dcf03e02b020
6879902: CTW failure jdk6_18/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp:845
twisti
parents:
727
diff
changeset
|
1122 RegisterOrConstant slot = __ ensure_simm13_or_reg(st_off, Rdisp); |
dcf03e02b020
6879902: CTW failure jdk6_18/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp:845
twisti
parents:
727
diff
changeset
|
1123 if (!r_2->is_valid()) __ stf(FloatRegisterImpl::S, r_1->as_FloatRegister(), SP, slot); |
dcf03e02b020
6879902: CTW failure jdk6_18/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp:845
twisti
parents:
727
diff
changeset
|
1124 else __ stf(FloatRegisterImpl::D, r_1->as_FloatRegister(), SP, slot); |
0 | 1125 } |
1126 } | |
1127 bool made_space = false; | |
1128 #ifndef _LP64 | |
1129 // May need to pick up a few long args in G1/G4 | |
1130 bool g4_crushed = false; | |
1131 bool g3_crushed = false; | |
1132 for (int i=0; i<total_args_passed; i++) { | |
1133 if (regs[i].first()->is_Register() && regs[i].second()->is_valid()) { | |
1134 // Load in argument order going down | |
1506 | 1135 int ld_off = (total_args_passed-i)*Interpreter::stackElementSize; |
0 | 1136 // Need to marshal 64-bit value from misaligned Lesp loads |
1137 Register r = regs[i].first()->as_Register()->after_restore(); | |
1138 if (r == G1 || r == G4) { | |
1139 assert(!g4_crushed, "ordering problem"); | |
1140 if (r == G4){ | |
1141 g4_crushed = true; | |
1142 __ lduw(Gargs, arg_slot(ld_off) , G3_scratch); // Load lo bits | |
1143 __ ld (Gargs, next_arg_slot(ld_off), r); // Load hi bits | |
1144 } else { | |
1145 // better schedule this way | |
1146 __ ld (Gargs, next_arg_slot(ld_off), r); // Load hi bits | |
1147 __ lduw(Gargs, arg_slot(ld_off) , G3_scratch); // Load lo bits | |
1148 } | |
1149 g3_crushed = true; | |
1150 __ sllx(r, 32, r); | |
1151 __ or3(G3_scratch, r, r); | |
1152 } else { | |
1153 assert(r->is_out(), "longs passed in two O registers"); | |
1154 __ ld (Gargs, arg_slot(ld_off) , r->successor()); // Load lo bits | |
1155 __ ld (Gargs, next_arg_slot(ld_off), r); // Load hi bits | |
1156 } | |
1157 } | |
1158 } | |
1159 #endif | |
1160 | |
1161 // Jump to the compiled code just as if compiled code was doing it. | |
1162 // | |
1163 #ifndef _LP64 | |
1164 if (g3_crushed) { | |
1165 // Rats load was wasted, at least it is in cache... | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
1166 __ ld_ptr(G5_method, Method::from_compiled_offset(), G3); |
0 | 1167 } |
1168 #endif /* _LP64 */ | |
1169 | |
1170 // 6243940 We might end up in handle_wrong_method if | |
1171 // the callee is deoptimized as we race thru here. If that | |
1172 // happens we don't want to take a safepoint because the | |
1173 // caller frame will look interpreted and arguments are now | |
1174 // "compiled" so it is much better to make this transition | |
1175 // invisible to the stack walking code. Unfortunately if | |
1176 // we try and find the callee by normal means a safepoint | |
1177 // is possible. So we stash the desired callee in the thread | |
1178 // and the vm will find there should this case occur. | |
727 | 1179 Address callee_target_addr(G2_thread, JavaThread::callee_target_offset()); |
0 | 1180 __ st_ptr(G5_method, callee_target_addr); |
1181 | |
1182 if (StressNonEntrant) { | |
1183 // Open a big window for deopt failure | |
1184 __ save_frame(0); | |
1185 __ mov(G0, L0); | |
1186 Label loop; | |
1187 __ bind(loop); | |
1188 __ sub(L0, 1, L0); | |
3839 | 1189 __ br_null_short(L0, Assembler::pt, loop); |
0 | 1190 |
1191 __ restore(); | |
1192 } | |
1193 | |
1194 | |
1195 __ jmpl(G3, 0, G0); | |
1196 __ delayed()->nop(); | |
1197 } | |
1198 | |
1199 // --------------------------------------------------------------- | |
1200 AdapterHandlerEntry* SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm, | |
1201 int total_args_passed, | |
1202 // VMReg max_arg, | |
1203 int comp_args_on_stack, // VMRegStackSlots | |
1204 const BasicType *sig_bt, | |
1187
cf0685d550f1
6911204: generated adapters with large signatures can fill up the code cache
never
parents:
1037
diff
changeset
|
1205 const VMRegPair *regs, |
cf0685d550f1
6911204: generated adapters with large signatures can fill up the code cache
never
parents:
1037
diff
changeset
|
1206 AdapterFingerPrint* fingerprint) { |
0 | 1207 address i2c_entry = __ pc(); |
1208 | |
1209 AdapterGenerator agen(masm); | |
1210 | |
1211 agen.gen_i2c_adapter(total_args_passed, comp_args_on_stack, sig_bt, regs); | |
1212 | |
1213 | |
1214 // ------------------------------------------------------------------------- | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
1215 // Generate a C2I adapter. On entry we know G5 holds the Method*. The |
0 | 1216 // args start out packed in the compiled layout. They need to be unpacked |
1217 // into the interpreter layout. This will almost always require some stack | |
1218 // space. We grow the current (compiled) stack, then repack the args. We | |
1219 // finally end in a jump to the generic interpreter entry point. On exit | |
1220 // from the interpreter, the interpreter will restore our SP (lest the | |
1221 // compiled code, which relys solely on SP and not FP, get sick). | |
1222 | |
1223 address c2i_unverified_entry = __ pc(); | |
1224 Label skip_fixup; | |
1225 { | |
1226 #if !defined(_LP64) && defined(COMPILER2) | |
1227 Register R_temp = L0; // another scratch register | |
1228 #else | |
1229 Register R_temp = G1; // another scratch register | |
1230 #endif | |
1231 | |
727 | 1232 AddressLiteral ic_miss(SharedRuntime::get_ic_miss_stub()); |
0 | 1233 |
1234 __ verify_oop(O0); | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
1235 __ load_klass(O0, G3_scratch); |
0 | 1236 |
1237 #if !defined(_LP64) && defined(COMPILER2) | |
1238 __ save(SP, -frame::register_save_words*wordSize, SP); | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
1239 __ ld_ptr(G5_method, CompiledICHolder::holder_klass_offset(), R_temp); |
0 | 1240 __ cmp(G3_scratch, R_temp); |
1241 __ restore(); | |
1242 #else | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
1243 __ ld_ptr(G5_method, CompiledICHolder::holder_klass_offset(), R_temp); |
0 | 1244 __ cmp(G3_scratch, R_temp); |
1245 #endif | |
1246 | |
1247 Label ok, ok2; | |
1248 __ brx(Assembler::equal, false, Assembler::pt, ok); | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
1249 __ delayed()->ld_ptr(G5_method, CompiledICHolder::holder_method_offset(), G5_method); |
727 | 1250 __ jump_to(ic_miss, G3_scratch); |
0 | 1251 __ delayed()->nop(); |
1252 | |
1253 __ bind(ok); | |
1254 // Method might have been compiled since the call site was patched to | |
1255 // interpreted if that is the case treat it as a miss so we can get | |
1256 // the call site corrected. | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
1257 __ ld_ptr(G5_method, in_bytes(Method::code_offset()), G3_scratch); |
0 | 1258 __ bind(ok2); |
3839 | 1259 __ br_null(G3_scratch, false, Assembler::pt, skip_fixup); |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
1260 __ delayed()->ld_ptr(G5_method, in_bytes(Method::interpreter_entry_offset()), G3_scratch); |
727 | 1261 __ jump_to(ic_miss, G3_scratch); |
0 | 1262 __ delayed()->nop(); |
1263 | |
1264 } | |
1265 | |
1266 address c2i_entry = __ pc(); | |
1267 | |
1268 agen.gen_c2i_adapter(total_args_passed, comp_args_on_stack, sig_bt, regs, skip_fixup); | |
1269 | |
1270 __ flush(); | |
1187
cf0685d550f1
6911204: generated adapters with large signatures can fill up the code cache
never
parents:
1037
diff
changeset
|
1271 return AdapterHandlerLibrary::new_entry(fingerprint, i2c_entry, c2i_entry, c2i_unverified_entry); |
0 | 1272 |
1273 } | |
1274 | |
1275 // Helper function for native calling conventions | |
1276 static VMReg int_stk_helper( int i ) { | |
1277 // Bias any stack based VMReg we get by ignoring the window area | |
1278 // but not the register parameter save area. | |
1279 // | |
1280 // This is strange for the following reasons. We'd normally expect | |
1281 // the calling convention to return an VMReg for a stack slot | |
1282 // completely ignoring any abi reserved area. C2 thinks of that | |
1283 // abi area as only out_preserve_stack_slots. This does not include | |
1284 // the area allocated by the C abi to store down integer arguments | |
1285 // because the java calling convention does not use it. So | |
1286 // since c2 assumes that there are only out_preserve_stack_slots | |
1287 // to bias the optoregs (which impacts VMRegs) when actually referencing any actual stack | |
1288 // location the c calling convention must add in this bias amount | |
1289 // to make up for the fact that the out_preserve_stack_slots is | |
1290 // insufficient for C calls. What a mess. I sure hope those 6 | |
1291 // stack words were worth it on every java call! | |
1292 | |
1293 // Another way of cleaning this up would be for out_preserve_stack_slots | |
1294 // to take a parameter to say whether it was C or java calling conventions. | |
1295 // Then things might look a little better (but not much). | |
1296 | |
1297 int mem_parm_offset = i - SPARC_ARGS_IN_REGS_NUM; | |
1298 if( mem_parm_offset < 0 ) { | |
1299 return as_oRegister(i)->as_VMReg(); | |
1300 } else { | |
1301 int actual_offset = (mem_parm_offset + frame::memory_parameter_word_sp_offset) * VMRegImpl::slots_per_word; | |
1302 // Now return a biased offset that will be correct when out_preserve_slots is added back in | |
1303 return VMRegImpl::stack2reg(actual_offset - SharedRuntime::out_preserve_stack_slots()); | |
1304 } | |
1305 } | |
1306 | |
1307 | |
1308 int SharedRuntime::c_calling_convention(const BasicType *sig_bt, | |
1309 VMRegPair *regs, | |
1310 int total_args_passed) { | |
1311 | |
1312 // Return the number of VMReg stack_slots needed for the args. | |
1313 // This value does not include an abi space (like register window | |
1314 // save area). | |
1315 | |
1316 // The native convention is V8 if !LP64 | |
1317 // The LP64 convention is the V9 convention which is slightly more sane. | |
1318 | |
1319 // We return the amount of VMReg stack slots we need to reserve for all | |
1320 // the arguments NOT counting out_preserve_stack_slots. Since we always | |
1321 // have space for storing at least 6 registers to memory we start with that. | |
1322 // See int_stk_helper for a further discussion. | |
1323 int max_stack_slots = (frame::varargs_offset * VMRegImpl::slots_per_word) - SharedRuntime::out_preserve_stack_slots(); | |
1324 | |
1325 #ifdef _LP64 | |
1326 // V9 convention: All things "as-if" on double-wide stack slots. | |
1327 // Hoist any int/ptr/long's in the first 6 to int regs. | |
1328 // Hoist any flt/dbl's in the first 16 dbl regs. | |
1329 int j = 0; // Count of actual args, not HALVES | |
1330 for( int i=0; i<total_args_passed; i++, j++ ) { | |
1331 switch( sig_bt[i] ) { | |
1332 case T_BOOLEAN: | |
1333 case T_BYTE: | |
1334 case T_CHAR: | |
1335 case T_INT: | |
1336 case T_SHORT: | |
1337 regs[i].set1( int_stk_helper( j ) ); break; | |
1338 case T_LONG: | |
1339 assert( sig_bt[i+1] == T_VOID, "expecting half" ); | |
1340 case T_ADDRESS: // raw pointers, like current thread, for VM calls | |
1341 case T_ARRAY: | |
1342 case T_OBJECT: | |
6739
8a02ca5e5576
7195816: NPG: Crash in c1_ValueType - ShouldNotReachHere
roland
parents:
6725
diff
changeset
|
1343 case T_METADATA: |
0 | 1344 regs[i].set2( int_stk_helper( j ) ); |
1345 break; | |
1346 case T_FLOAT: | |
1347 if ( j < 16 ) { | |
1348 // V9ism: floats go in ODD registers | |
1349 regs[i].set1(as_FloatRegister(1 + (j<<1))->as_VMReg()); | |
1350 } else { | |
1351 // V9ism: floats go in ODD stack slot | |
1352 regs[i].set1(VMRegImpl::stack2reg(1 + (j<<1))); | |
1353 } | |
1354 break; | |
1355 case T_DOUBLE: | |
1356 assert( sig_bt[i+1] == T_VOID, "expecting half" ); | |
1357 if ( j < 16 ) { | |
1358 // V9ism: doubles go in EVEN/ODD regs | |
1359 regs[i].set2(as_FloatRegister(j<<1)->as_VMReg()); | |
1360 } else { | |
1361 // V9ism: doubles go in EVEN/ODD stack slots | |
1362 regs[i].set2(VMRegImpl::stack2reg(j<<1)); | |
1363 } | |
1364 break; | |
1365 case T_VOID: regs[i].set_bad(); j--; break; // Do not count HALVES | |
1366 default: | |
1367 ShouldNotReachHere(); | |
1368 } | |
1369 if (regs[i].first()->is_stack()) { | |
1370 int off = regs[i].first()->reg2stack(); | |
1371 if (off > max_stack_slots) max_stack_slots = off; | |
1372 } | |
1373 if (regs[i].second()->is_stack()) { | |
1374 int off = regs[i].second()->reg2stack(); | |
1375 if (off > max_stack_slots) max_stack_slots = off; | |
1376 } | |
1377 } | |
1378 | |
1379 #else // _LP64 | |
1380 // V8 convention: first 6 things in O-regs, rest on stack. | |
1381 // Alignment is willy-nilly. | |
1382 for( int i=0; i<total_args_passed; i++ ) { | |
1383 switch( sig_bt[i] ) { | |
1384 case T_ADDRESS: // raw pointers, like current thread, for VM calls | |
1385 case T_ARRAY: | |
1386 case T_BOOLEAN: | |
1387 case T_BYTE: | |
1388 case T_CHAR: | |
1389 case T_FLOAT: | |
1390 case T_INT: | |
1391 case T_OBJECT: | |
6739
8a02ca5e5576
7195816: NPG: Crash in c1_ValueType - ShouldNotReachHere
roland
parents:
6725
diff
changeset
|
1392 case T_METADATA: |
0 | 1393 case T_SHORT: |
1394 regs[i].set1( int_stk_helper( i ) ); | |
1395 break; | |
1396 case T_DOUBLE: | |
1397 case T_LONG: | |
1398 assert( sig_bt[i+1] == T_VOID, "expecting half" ); | |
1399 regs[i].set_pair( int_stk_helper( i+1 ), int_stk_helper( i ) ); | |
1400 break; | |
1401 case T_VOID: regs[i].set_bad(); break; | |
1402 default: | |
1403 ShouldNotReachHere(); | |
1404 } | |
1405 if (regs[i].first()->is_stack()) { | |
1406 int off = regs[i].first()->reg2stack(); | |
1407 if (off > max_stack_slots) max_stack_slots = off; | |
1408 } | |
1409 if (regs[i].second()->is_stack()) { | |
1410 int off = regs[i].second()->reg2stack(); | |
1411 if (off > max_stack_slots) max_stack_slots = off; | |
1412 } | |
1413 } | |
1414 #endif // _LP64 | |
1415 | |
1416 return round_to(max_stack_slots + 1, 2); | |
1417 | |
1418 } | |
1419 | |
1420 | |
1421 // --------------------------------------------------------------------------- | |
1422 void SharedRuntime::save_native_result(MacroAssembler *masm, BasicType ret_type, int frame_slots) { | |
1423 switch (ret_type) { | |
1424 case T_FLOAT: | |
1425 __ stf(FloatRegisterImpl::S, F0, SP, frame_slots*VMRegImpl::stack_slot_size - 4+STACK_BIAS); | |
1426 break; | |
1427 case T_DOUBLE: | |
1428 __ stf(FloatRegisterImpl::D, F0, SP, frame_slots*VMRegImpl::stack_slot_size - 8+STACK_BIAS); | |
1429 break; | |
1430 } | |
1431 } | |
1432 | |
1433 void SharedRuntime::restore_native_result(MacroAssembler *masm, BasicType ret_type, int frame_slots) { | |
1434 switch (ret_type) { | |
1435 case T_FLOAT: | |
1436 __ ldf(FloatRegisterImpl::S, SP, frame_slots*VMRegImpl::stack_slot_size - 4+STACK_BIAS, F0); | |
1437 break; | |
1438 case T_DOUBLE: | |
1439 __ ldf(FloatRegisterImpl::D, SP, frame_slots*VMRegImpl::stack_slot_size - 8+STACK_BIAS, F0); | |
1440 break; | |
1441 } | |
1442 } | |
1443 | |
1444 // Check and forward and pending exception. Thread is stored in | |
1445 // L7_thread_cache and possibly NOT in G2_thread. Since this is a native call, there | |
1446 // is no exception handler. We merely pop this frame off and throw the | |
1447 // exception in the caller's frame. | |
1448 static void check_forward_pending_exception(MacroAssembler *masm, Register Rex_oop) { | |
1449 Label L; | |
1450 __ br_null(Rex_oop, false, Assembler::pt, L); | |
1451 __ delayed()->mov(L7_thread_cache, G2_thread); // restore in case we have exception | |
1452 // Since this is a native call, we *know* the proper exception handler | |
1453 // without calling into the VM: it's the empty function. Just pop this | |
1454 // frame and then jump to forward_exception_entry; O7 will contain the | |
1455 // native caller's return PC. | |
727 | 1456 AddressLiteral exception_entry(StubRoutines::forward_exception_entry()); |
1457 __ jump_to(exception_entry, G3_scratch); | |
0 | 1458 __ delayed()->restore(); // Pop this frame off. |
1459 __ bind(L); | |
1460 } | |
1461 | |
1462 // A simple move of integer like type | |
1463 static void simple_move32(MacroAssembler* masm, VMRegPair src, VMRegPair dst) { | |
1464 if (src.first()->is_stack()) { | |
1465 if (dst.first()->is_stack()) { | |
1466 // stack to stack | |
1467 __ ld(FP, reg2offset(src.first()) + STACK_BIAS, L5); | |
1468 __ st(L5, SP, reg2offset(dst.first()) + STACK_BIAS); | |
1469 } else { | |
1470 // stack to reg | |
1471 __ ld(FP, reg2offset(src.first()) + STACK_BIAS, dst.first()->as_Register()); | |
1472 } | |
1473 } else if (dst.first()->is_stack()) { | |
1474 // reg to stack | |
1475 __ st(src.first()->as_Register(), SP, reg2offset(dst.first()) + STACK_BIAS); | |
1476 } else { | |
1477 __ mov(src.first()->as_Register(), dst.first()->as_Register()); | |
1478 } | |
1479 } | |
1480 | |
1481 // On 64 bit we will store integer like items to the stack as | |
1482 // 64 bits items (sparc abi) even though java would only store | |
1483 // 32bits for a parameter. On 32bit it will simply be 32 bits | |
1484 // So this routine will do 32->32 on 32bit and 32->64 on 64bit | |
1485 static void move32_64(MacroAssembler* masm, VMRegPair src, VMRegPair dst) { | |
1486 if (src.first()->is_stack()) { | |
1487 if (dst.first()->is_stack()) { | |
1488 // stack to stack | |
1489 __ ld(FP, reg2offset(src.first()) + STACK_BIAS, L5); | |
1490 __ st_ptr(L5, SP, reg2offset(dst.first()) + STACK_BIAS); | |
1491 } else { | |
1492 // stack to reg | |
1493 __ ld(FP, reg2offset(src.first()) + STACK_BIAS, dst.first()->as_Register()); | |
1494 } | |
1495 } else if (dst.first()->is_stack()) { | |
1496 // reg to stack | |
1497 __ st_ptr(src.first()->as_Register(), SP, reg2offset(dst.first()) + STACK_BIAS); | |
1498 } else { | |
1499 __ mov(src.first()->as_Register(), dst.first()->as_Register()); | |
1500 } | |
1501 } | |
1502 | |
1503 | |
4873
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1504 static void move_ptr(MacroAssembler* masm, VMRegPair src, VMRegPair dst) { |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1505 if (src.first()->is_stack()) { |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1506 if (dst.first()->is_stack()) { |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1507 // stack to stack |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1508 __ ld_ptr(FP, reg2offset(src.first()) + STACK_BIAS, L5); |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1509 __ st_ptr(L5, SP, reg2offset(dst.first()) + STACK_BIAS); |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1510 } else { |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1511 // stack to reg |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1512 __ ld_ptr(FP, reg2offset(src.first()) + STACK_BIAS, dst.first()->as_Register()); |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1513 } |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1514 } else if (dst.first()->is_stack()) { |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1515 // reg to stack |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1516 __ st_ptr(src.first()->as_Register(), SP, reg2offset(dst.first()) + STACK_BIAS); |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1517 } else { |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1518 __ mov(src.first()->as_Register(), dst.first()->as_Register()); |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1519 } |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1520 } |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1521 |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1522 |
0 | 1523 // An oop arg. Must pass a handle not the oop itself |
1524 static void object_move(MacroAssembler* masm, | |
1525 OopMap* map, | |
1526 int oop_handle_offset, | |
1527 int framesize_in_slots, | |
1528 VMRegPair src, | |
1529 VMRegPair dst, | |
1530 bool is_receiver, | |
1531 int* receiver_offset) { | |
1532 | |
1533 // must pass a handle. First figure out the location we use as a handle | |
1534 | |
1535 if (src.first()->is_stack()) { | |
1536 // Oop is already on the stack | |
1537 Register rHandle = dst.first()->is_stack() ? L5 : dst.first()->as_Register(); | |
1538 __ add(FP, reg2offset(src.first()) + STACK_BIAS, rHandle); | |
1539 __ ld_ptr(rHandle, 0, L4); | |
1540 #ifdef _LP64 | |
1541 __ movr( Assembler::rc_z, L4, G0, rHandle ); | |
1542 #else | |
1543 __ tst( L4 ); | |
1544 __ movcc( Assembler::zero, false, Assembler::icc, G0, rHandle ); | |
1545 #endif | |
1546 if (dst.first()->is_stack()) { | |
1547 __ st_ptr(rHandle, SP, reg2offset(dst.first()) + STACK_BIAS); | |
1548 } | |
1549 int offset_in_older_frame = src.first()->reg2stack() + SharedRuntime::out_preserve_stack_slots(); | |
1550 if (is_receiver) { | |
1551 *receiver_offset = (offset_in_older_frame + framesize_in_slots) * VMRegImpl::stack_slot_size; | |
1552 } | |
1553 map->set_oop(VMRegImpl::stack2reg(offset_in_older_frame + framesize_in_slots)); | |
1554 } else { | |
1555 // Oop is in an input register pass we must flush it to the stack | |
1556 const Register rOop = src.first()->as_Register(); | |
1557 const Register rHandle = L5; | |
1558 int oop_slot = rOop->input_number() * VMRegImpl::slots_per_word + oop_handle_offset; | |
1559 int offset = oop_slot*VMRegImpl::stack_slot_size; | |
1560 Label skip; | |
1561 __ st_ptr(rOop, SP, offset + STACK_BIAS); | |
1562 if (is_receiver) { | |
1563 *receiver_offset = oop_slot * VMRegImpl::stack_slot_size; | |
1564 } | |
1565 map->set_oop(VMRegImpl::stack2reg(oop_slot)); | |
1566 __ add(SP, offset + STACK_BIAS, rHandle); | |
1567 #ifdef _LP64 | |
1568 __ movr( Assembler::rc_z, rOop, G0, rHandle ); | |
1569 #else | |
1570 __ tst( rOop ); | |
1571 __ movcc( Assembler::zero, false, Assembler::icc, G0, rHandle ); | |
1572 #endif | |
1573 | |
1574 if (dst.first()->is_stack()) { | |
1575 __ st_ptr(rHandle, SP, reg2offset(dst.first()) + STACK_BIAS); | |
1576 } else { | |
1577 __ mov(rHandle, dst.first()->as_Register()); | |
1578 } | |
1579 } | |
1580 } | |
1581 | |
1582 // A float arg may have to do float reg int reg conversion | |
1583 static void float_move(MacroAssembler* masm, VMRegPair src, VMRegPair dst) { | |
1584 assert(!src.second()->is_valid() && !dst.second()->is_valid(), "bad float_move"); | |
1585 | |
1586 if (src.first()->is_stack()) { | |
1587 if (dst.first()->is_stack()) { | |
1588 // stack to stack the easiest of the bunch | |
1589 __ ld(FP, reg2offset(src.first()) + STACK_BIAS, L5); | |
1590 __ st(L5, SP, reg2offset(dst.first()) + STACK_BIAS); | |
1591 } else { | |
1592 // stack to reg | |
1593 if (dst.first()->is_Register()) { | |
1594 __ ld(FP, reg2offset(src.first()) + STACK_BIAS, dst.first()->as_Register()); | |
1595 } else { | |
1596 __ ldf(FloatRegisterImpl::S, FP, reg2offset(src.first()) + STACK_BIAS, dst.first()->as_FloatRegister()); | |
1597 } | |
1598 } | |
1599 } else if (dst.first()->is_stack()) { | |
1600 // reg to stack | |
1601 if (src.first()->is_Register()) { | |
1602 __ st(src.first()->as_Register(), SP, reg2offset(dst.first()) + STACK_BIAS); | |
1603 } else { | |
1604 __ stf(FloatRegisterImpl::S, src.first()->as_FloatRegister(), SP, reg2offset(dst.first()) + STACK_BIAS); | |
1605 } | |
1606 } else { | |
1607 // reg to reg | |
1608 if (src.first()->is_Register()) { | |
1609 if (dst.first()->is_Register()) { | |
1610 // gpr -> gpr | |
1611 __ mov(src.first()->as_Register(), dst.first()->as_Register()); | |
1612 } else { | |
1613 // gpr -> fpr | |
1614 __ st(src.first()->as_Register(), FP, -4 + STACK_BIAS); | |
1615 __ ldf(FloatRegisterImpl::S, FP, -4 + STACK_BIAS, dst.first()->as_FloatRegister()); | |
1616 } | |
1617 } else if (dst.first()->is_Register()) { | |
1618 // fpr -> gpr | |
1619 __ stf(FloatRegisterImpl::S, src.first()->as_FloatRegister(), FP, -4 + STACK_BIAS); | |
1620 __ ld(FP, -4 + STACK_BIAS, dst.first()->as_Register()); | |
1621 } else { | |
1622 // fpr -> fpr | |
1623 // In theory these overlap but the ordering is such that this is likely a nop | |
1624 if ( src.first() != dst.first()) { | |
1625 __ fmov(FloatRegisterImpl::S, src.first()->as_FloatRegister(), dst.first()->as_FloatRegister()); | |
1626 } | |
1627 } | |
1628 } | |
1629 } | |
1630 | |
1631 static void split_long_move(MacroAssembler* masm, VMRegPair src, VMRegPair dst) { | |
1632 VMRegPair src_lo(src.first()); | |
1633 VMRegPair src_hi(src.second()); | |
1634 VMRegPair dst_lo(dst.first()); | |
1635 VMRegPair dst_hi(dst.second()); | |
1636 simple_move32(masm, src_lo, dst_lo); | |
1637 simple_move32(masm, src_hi, dst_hi); | |
1638 } | |
1639 | |
1640 // A long move | |
1641 static void long_move(MacroAssembler* masm, VMRegPair src, VMRegPair dst) { | |
1642 | |
1643 // Do the simple ones here else do two int moves | |
1644 if (src.is_single_phys_reg() ) { | |
1645 if (dst.is_single_phys_reg()) { | |
1646 __ mov(src.first()->as_Register(), dst.first()->as_Register()); | |
1647 } else { | |
1648 // split src into two separate registers | |
1649 // Remember hi means hi address or lsw on sparc | |
1650 // Move msw to lsw | |
1651 if (dst.second()->is_reg()) { | |
1652 // MSW -> MSW | |
1653 __ srax(src.first()->as_Register(), 32, dst.first()->as_Register()); | |
1654 // Now LSW -> LSW | |
1655 // this will only move lo -> lo and ignore hi | |
1656 VMRegPair split(dst.second()); | |
1657 simple_move32(masm, src, split); | |
1658 } else { | |
1659 VMRegPair split(src.first(), L4->as_VMReg()); | |
1660 // MSW -> MSW (lo ie. first word) | |
1661 __ srax(src.first()->as_Register(), 32, L4); | |
1662 split_long_move(masm, split, dst); | |
1663 } | |
1664 } | |
1665 } else if (dst.is_single_phys_reg()) { | |
1666 if (src.is_adjacent_aligned_on_stack(2)) { | |
304 | 1667 __ ldx(FP, reg2offset(src.first()) + STACK_BIAS, dst.first()->as_Register()); |
0 | 1668 } else { |
1669 // dst is a single reg. | |
1670 // Remember lo is low address not msb for stack slots | |
1671 // and lo is the "real" register for registers | |
1672 // src is | |
1673 | |
1674 VMRegPair split; | |
1675 | |
1676 if (src.first()->is_reg()) { | |
1677 // src.lo (msw) is a reg, src.hi is stk/reg | |
1678 // we will move: src.hi (LSW) -> dst.lo, src.lo (MSW) -> src.lo [the MSW is in the LSW of the reg] | |
1679 split.set_pair(dst.first(), src.first()); | |
1680 } else { | |
1681 // msw is stack move to L5 | |
1682 // lsw is stack move to dst.lo (real reg) | |
1683 // we will move: src.hi (LSW) -> dst.lo, src.lo (MSW) -> L5 | |
1684 split.set_pair(dst.first(), L5->as_VMReg()); | |
1685 } | |
1686 | |
1687 // src.lo -> src.lo/L5, src.hi -> dst.lo (the real reg) | |
1688 // msw -> src.lo/L5, lsw -> dst.lo | |
1689 split_long_move(masm, src, split); | |
1690 | |
1691 // So dst now has the low order correct position the | |
1692 // msw half | |
1693 __ sllx(split.first()->as_Register(), 32, L5); | |
1694 | |
1695 const Register d = dst.first()->as_Register(); | |
1696 __ or3(L5, d, d); | |
1697 } | |
1698 } else { | |
1699 // For LP64 we can probably do better. | |
1700 split_long_move(masm, src, dst); | |
1701 } | |
1702 } | |
1703 | |
1704 // A double move | |
1705 static void double_move(MacroAssembler* masm, VMRegPair src, VMRegPair dst) { | |
1706 | |
1707 // The painful thing here is that like long_move a VMRegPair might be | |
1708 // 1: a single physical register | |
1709 // 2: two physical registers (v8) | |
1710 // 3: a physical reg [lo] and a stack slot [hi] (v8) | |
1711 // 4: two stack slots | |
1712 | |
1713 // Since src is always a java calling convention we know that the src pair | |
1714 // is always either all registers or all stack (and aligned?) | |
1715 | |
1716 // in a register [lo] and a stack slot [hi] | |
1717 if (src.first()->is_stack()) { | |
1718 if (dst.first()->is_stack()) { | |
1719 // stack to stack the easiest of the bunch | |
1720 // ought to be a way to do this where if alignment is ok we use ldd/std when possible | |
1721 __ ld(FP, reg2offset(src.first()) + STACK_BIAS, L5); | |
1722 __ ld(FP, reg2offset(src.second()) + STACK_BIAS, L4); | |
1723 __ st(L5, SP, reg2offset(dst.first()) + STACK_BIAS); | |
1724 __ st(L4, SP, reg2offset(dst.second()) + STACK_BIAS); | |
1725 } else { | |
1726 // stack to reg | |
1727 if (dst.second()->is_stack()) { | |
1728 // stack -> reg, stack -> stack | |
1729 __ ld(FP, reg2offset(src.second()) + STACK_BIAS, L4); | |
1730 if (dst.first()->is_Register()) { | |
1731 __ ld(FP, reg2offset(src.first()) + STACK_BIAS, dst.first()->as_Register()); | |
1732 } else { | |
1733 __ ldf(FloatRegisterImpl::S, FP, reg2offset(src.first()) + STACK_BIAS, dst.first()->as_FloatRegister()); | |
1734 } | |
1735 // This was missing. (very rare case) | |
1736 __ st(L4, SP, reg2offset(dst.second()) + STACK_BIAS); | |
1737 } else { | |
1738 // stack -> reg | |
1739 // Eventually optimize for alignment QQQ | |
1740 if (dst.first()->is_Register()) { | |
1741 __ ld(FP, reg2offset(src.first()) + STACK_BIAS, dst.first()->as_Register()); | |
1742 __ ld(FP, reg2offset(src.second()) + STACK_BIAS, dst.second()->as_Register()); | |
1743 } else { | |
1744 __ ldf(FloatRegisterImpl::S, FP, reg2offset(src.first()) + STACK_BIAS, dst.first()->as_FloatRegister()); | |
1745 __ ldf(FloatRegisterImpl::S, FP, reg2offset(src.second()) + STACK_BIAS, dst.second()->as_FloatRegister()); | |
1746 } | |
1747 } | |
1748 } | |
1749 } else if (dst.first()->is_stack()) { | |
1750 // reg to stack | |
1751 if (src.first()->is_Register()) { | |
1752 // Eventually optimize for alignment QQQ | |
1753 __ st(src.first()->as_Register(), SP, reg2offset(dst.first()) + STACK_BIAS); | |
1754 if (src.second()->is_stack()) { | |
1755 __ ld(FP, reg2offset(src.second()) + STACK_BIAS, L4); | |
1756 __ st(L4, SP, reg2offset(dst.second()) + STACK_BIAS); | |
1757 } else { | |
1758 __ st(src.second()->as_Register(), SP, reg2offset(dst.second()) + STACK_BIAS); | |
1759 } | |
1760 } else { | |
1761 // fpr to stack | |
1762 if (src.second()->is_stack()) { | |
1763 ShouldNotReachHere(); | |
1764 } else { | |
1765 // Is the stack aligned? | |
1766 if (reg2offset(dst.first()) & 0x7) { | |
1767 // No do as pairs | |
1768 __ stf(FloatRegisterImpl::S, src.first()->as_FloatRegister(), SP, reg2offset(dst.first()) + STACK_BIAS); | |
1769 __ stf(FloatRegisterImpl::S, src.second()->as_FloatRegister(), SP, reg2offset(dst.second()) + STACK_BIAS); | |
1770 } else { | |
1771 __ stf(FloatRegisterImpl::D, src.first()->as_FloatRegister(), SP, reg2offset(dst.first()) + STACK_BIAS); | |
1772 } | |
1773 } | |
1774 } | |
1775 } else { | |
1776 // reg to reg | |
1777 if (src.first()->is_Register()) { | |
1778 if (dst.first()->is_Register()) { | |
1779 // gpr -> gpr | |
1780 __ mov(src.first()->as_Register(), dst.first()->as_Register()); | |
1781 __ mov(src.second()->as_Register(), dst.second()->as_Register()); | |
1782 } else { | |
1783 // gpr -> fpr | |
1784 // ought to be able to do a single store | |
1785 __ stx(src.first()->as_Register(), FP, -8 + STACK_BIAS); | |
1786 __ stx(src.second()->as_Register(), FP, -4 + STACK_BIAS); | |
1787 // ought to be able to do a single load | |
1788 __ ldf(FloatRegisterImpl::S, FP, -8 + STACK_BIAS, dst.first()->as_FloatRegister()); | |
1789 __ ldf(FloatRegisterImpl::S, FP, -4 + STACK_BIAS, dst.second()->as_FloatRegister()); | |
1790 } | |
1791 } else if (dst.first()->is_Register()) { | |
1792 // fpr -> gpr | |
1793 // ought to be able to do a single store | |
1794 __ stf(FloatRegisterImpl::D, src.first()->as_FloatRegister(), FP, -8 + STACK_BIAS); | |
1795 // ought to be able to do a single load | |
1796 // REMEMBER first() is low address not LSB | |
1797 __ ld(FP, -8 + STACK_BIAS, dst.first()->as_Register()); | |
1798 if (dst.second()->is_Register()) { | |
1799 __ ld(FP, -4 + STACK_BIAS, dst.second()->as_Register()); | |
1800 } else { | |
1801 __ ld(FP, -4 + STACK_BIAS, L4); | |
1802 __ st(L4, SP, reg2offset(dst.second()) + STACK_BIAS); | |
1803 } | |
1804 } else { | |
1805 // fpr -> fpr | |
1806 // In theory these overlap but the ordering is such that this is likely a nop | |
1807 if ( src.first() != dst.first()) { | |
1808 __ fmov(FloatRegisterImpl::D, src.first()->as_FloatRegister(), dst.first()->as_FloatRegister()); | |
1809 } | |
1810 } | |
1811 } | |
1812 } | |
1813 | |
1814 // Creates an inner frame if one hasn't already been created, and | |
1815 // saves a copy of the thread in L7_thread_cache | |
1816 static void create_inner_frame(MacroAssembler* masm, bool* already_created) { | |
1817 if (!*already_created) { | |
1818 __ save_frame(0); | |
1819 // Save thread in L7 (INNER FRAME); it crosses a bunch of VM calls below | |
1820 // Don't use save_thread because it smashes G2 and we merely want to save a | |
1821 // copy | |
1822 __ mov(G2_thread, L7_thread_cache); | |
1823 *already_created = true; | |
1824 } | |
1825 } | |
1826 | |
4873
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1827 |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1828 static void save_or_restore_arguments(MacroAssembler* masm, |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1829 const int stack_slots, |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1830 const int total_in_args, |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1831 const int arg_save_area, |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1832 OopMap* map, |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1833 VMRegPair* in_regs, |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1834 BasicType* in_sig_bt) { |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1835 // if map is non-NULL then the code should store the values, |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1836 // otherwise it should load them. |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1837 if (map != NULL) { |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1838 // Fill in the map |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1839 for (int i = 0; i < total_in_args; i++) { |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1840 if (in_sig_bt[i] == T_ARRAY) { |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1841 if (in_regs[i].first()->is_stack()) { |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1842 int offset_in_older_frame = in_regs[i].first()->reg2stack() + SharedRuntime::out_preserve_stack_slots(); |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1843 map->set_oop(VMRegImpl::stack2reg(offset_in_older_frame + stack_slots)); |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1844 } else if (in_regs[i].first()->is_Register()) { |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1845 map->set_oop(in_regs[i].first()); |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1846 } else { |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1847 ShouldNotReachHere(); |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1848 } |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1849 } |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1850 } |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1851 } |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1852 |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1853 // Save or restore double word values |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1854 int handle_index = 0; |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1855 for (int i = 0; i < total_in_args; i++) { |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1856 int slot = handle_index + arg_save_area; |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1857 int offset = slot * VMRegImpl::stack_slot_size; |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1858 if (in_sig_bt[i] == T_LONG && in_regs[i].first()->is_Register()) { |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1859 const Register reg = in_regs[i].first()->as_Register(); |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1860 if (reg->is_global()) { |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1861 handle_index += 2; |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1862 assert(handle_index <= stack_slots, "overflow"); |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1863 if (map != NULL) { |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1864 __ stx(reg, SP, offset + STACK_BIAS); |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1865 } else { |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1866 __ ldx(SP, offset + STACK_BIAS, reg); |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1867 } |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1868 } |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1869 } else if (in_sig_bt[i] == T_DOUBLE && in_regs[i].first()->is_FloatRegister()) { |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1870 handle_index += 2; |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1871 assert(handle_index <= stack_slots, "overflow"); |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1872 if (map != NULL) { |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1873 __ stf(FloatRegisterImpl::D, in_regs[i].first()->as_FloatRegister(), SP, offset + STACK_BIAS); |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1874 } else { |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1875 __ ldf(FloatRegisterImpl::D, SP, offset + STACK_BIAS, in_regs[i].first()->as_FloatRegister()); |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1876 } |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1877 } |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1878 } |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1879 // Save floats |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1880 for (int i = 0; i < total_in_args; i++) { |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1881 int slot = handle_index + arg_save_area; |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1882 int offset = slot * VMRegImpl::stack_slot_size; |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1883 if (in_sig_bt[i] == T_FLOAT && in_regs[i].first()->is_FloatRegister()) { |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1884 handle_index++; |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1885 assert(handle_index <= stack_slots, "overflow"); |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1886 if (map != NULL) { |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1887 __ stf(FloatRegisterImpl::S, in_regs[i].first()->as_FloatRegister(), SP, offset + STACK_BIAS); |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1888 } else { |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1889 __ ldf(FloatRegisterImpl::S, SP, offset + STACK_BIAS, in_regs[i].first()->as_FloatRegister()); |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1890 } |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1891 } |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1892 } |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1893 |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1894 } |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1895 |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1896 |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1897 // Check GC_locker::needs_gc and enter the runtime if it's true. This |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1898 // keeps a new JNI critical region from starting until a GC has been |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1899 // forced. Save down any oops in registers and describe them in an |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1900 // OopMap. |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1901 static void check_needs_gc_for_critical_native(MacroAssembler* masm, |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1902 const int stack_slots, |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1903 const int total_in_args, |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1904 const int arg_save_area, |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1905 OopMapSet* oop_maps, |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1906 VMRegPair* in_regs, |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1907 BasicType* in_sig_bt) { |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1908 __ block_comment("check GC_locker::needs_gc"); |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1909 Label cont; |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1910 AddressLiteral sync_state(GC_locker::needs_gc_address()); |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1911 __ load_bool_contents(sync_state, G3_scratch); |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1912 __ cmp_zero_and_br(Assembler::equal, G3_scratch, cont); |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1913 __ delayed()->nop(); |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1914 |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1915 // Save down any values that are live in registers and call into the |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1916 // runtime to halt for a GC |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1917 OopMap* map = new OopMap(stack_slots * 2, 0 /* arg_slots*/); |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1918 save_or_restore_arguments(masm, stack_slots, total_in_args, |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1919 arg_save_area, map, in_regs, in_sig_bt); |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1920 |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1921 __ mov(G2_thread, L7_thread_cache); |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1922 |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1923 __ set_last_Java_frame(SP, noreg); |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1924 |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1925 __ block_comment("block_for_jni_critical"); |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1926 __ call(CAST_FROM_FN_PTR(address, SharedRuntime::block_for_jni_critical), relocInfo::runtime_call_type); |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1927 __ delayed()->mov(L7_thread_cache, O0); |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1928 oop_maps->add_gc_map( __ offset(), map); |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1929 |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1930 __ restore_thread(L7_thread_cache); // restore G2_thread |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1931 __ reset_last_Java_frame(); |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1932 |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1933 // Reload all the register arguments |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1934 save_or_restore_arguments(masm, stack_slots, total_in_args, |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1935 arg_save_area, NULL, in_regs, in_sig_bt); |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1936 |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1937 __ bind(cont); |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1938 #ifdef ASSERT |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1939 if (StressCriticalJNINatives) { |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1940 // Stress register saving |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1941 OopMap* map = new OopMap(stack_slots * 2, 0 /* arg_slots*/); |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1942 save_or_restore_arguments(masm, stack_slots, total_in_args, |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1943 arg_save_area, map, in_regs, in_sig_bt); |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1944 // Destroy argument registers |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1945 for (int i = 0; i < total_in_args; i++) { |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1946 if (in_regs[i].first()->is_Register()) { |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1947 const Register reg = in_regs[i].first()->as_Register(); |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1948 if (reg->is_global()) { |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1949 __ mov(G0, reg); |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1950 } |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1951 } else if (in_regs[i].first()->is_FloatRegister()) { |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1952 __ fneg(FloatRegisterImpl::D, in_regs[i].first()->as_FloatRegister(), in_regs[i].first()->as_FloatRegister()); |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1953 } |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1954 } |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1955 |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1956 save_or_restore_arguments(masm, stack_slots, total_in_args, |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1957 arg_save_area, NULL, in_regs, in_sig_bt); |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1958 } |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1959 #endif |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1960 } |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1961 |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1962 // Unpack an array argument into a pointer to the body and the length |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1963 // if the array is non-null, otherwise pass 0 for both. |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1964 static void unpack_array_argument(MacroAssembler* masm, VMRegPair reg, BasicType in_elem_type, VMRegPair body_arg, VMRegPair length_arg) { |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1965 // Pass the length, ptr pair |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1966 Label is_null, done; |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1967 if (reg.first()->is_stack()) { |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1968 VMRegPair tmp = reg64_to_VMRegPair(L2); |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1969 // Load the arg up from the stack |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1970 move_ptr(masm, reg, tmp); |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1971 reg = tmp; |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1972 } |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1973 __ cmp(reg.first()->as_Register(), G0); |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1974 __ brx(Assembler::equal, false, Assembler::pt, is_null); |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1975 __ delayed()->add(reg.first()->as_Register(), arrayOopDesc::base_offset_in_bytes(in_elem_type), L4); |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1976 move_ptr(masm, reg64_to_VMRegPair(L4), body_arg); |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1977 __ ld(reg.first()->as_Register(), arrayOopDesc::length_offset_in_bytes(), L4); |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1978 move32_64(masm, reg64_to_VMRegPair(L4), length_arg); |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1979 __ ba_short(done); |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1980 __ bind(is_null); |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1981 // Pass zeros |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1982 move_ptr(masm, reg64_to_VMRegPair(G0), body_arg); |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1983 move32_64(masm, reg64_to_VMRegPair(G0), length_arg); |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1984 __ bind(done); |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1985 } |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
1986 |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
1987 static void verify_oop_args(MacroAssembler* masm, |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
1988 int total_args_passed, |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
1989 const BasicType* sig_bt, |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
1990 const VMRegPair* regs) { |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
1991 Register temp_reg = G5_method; // not part of any compiled calling seq |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
1992 if (VerifyOops) { |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
1993 for (int i = 0; i < total_args_passed; i++) { |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
1994 if (sig_bt[i] == T_OBJECT || |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
1995 sig_bt[i] == T_ARRAY) { |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
1996 VMReg r = regs[i].first(); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
1997 assert(r->is_valid(), "bad oop arg"); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
1998 if (r->is_stack()) { |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
1999 RegisterOrConstant ld_off = reg2offset(r) + STACK_BIAS; |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
2000 ld_off = __ ensure_simm13_or_reg(ld_off, temp_reg); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
2001 __ ld_ptr(SP, ld_off, temp_reg); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
2002 __ verify_oop(temp_reg); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
2003 } else { |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
2004 __ verify_oop(r->as_Register()); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
2005 } |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
2006 } |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
2007 } |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
2008 } |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
2009 } |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
2010 |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
2011 static void gen_special_dispatch(MacroAssembler* masm, |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
2012 int total_args_passed, |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
2013 int comp_args_on_stack, |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
2014 vmIntrinsics::ID special_dispatch, |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
2015 const BasicType* sig_bt, |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
2016 const VMRegPair* regs) { |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
2017 verify_oop_args(masm, total_args_passed, sig_bt, regs); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
2018 |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
2019 // Now write the args into the outgoing interpreter space |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
2020 bool has_receiver = false; |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
2021 Register receiver_reg = noreg; |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
2022 int member_arg_pos = -1; |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
2023 Register member_reg = noreg; |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
2024 int ref_kind = MethodHandles::signature_polymorphic_intrinsic_ref_kind(special_dispatch); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
2025 if (ref_kind != 0) { |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
2026 member_arg_pos = total_args_passed - 1; // trailing MemberName argument |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
2027 member_reg = G5_method; // known to be free at this point |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
2028 has_receiver = MethodHandles::ref_kind_has_receiver(ref_kind); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
2029 } else if (special_dispatch == vmIntrinsics::_invokeBasic) { |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
2030 has_receiver = true; |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
2031 } else { |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
2032 fatal(err_msg("special_dispatch=%d", special_dispatch)); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
2033 } |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
2034 |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
2035 if (member_reg != noreg) { |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
2036 // Load the member_arg into register, if necessary. |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
2037 assert(member_arg_pos >= 0 && member_arg_pos < total_args_passed, "oob"); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
2038 assert(sig_bt[member_arg_pos] == T_OBJECT, "dispatch argument must be an object"); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
2039 VMReg r = regs[member_arg_pos].first(); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
2040 assert(r->is_valid(), "bad member arg"); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
2041 if (r->is_stack()) { |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
2042 RegisterOrConstant ld_off = reg2offset(r) + STACK_BIAS; |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
2043 ld_off = __ ensure_simm13_or_reg(ld_off, member_reg); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
2044 __ ld_ptr(SP, ld_off, member_reg); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
2045 } else { |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
2046 // no data motion is needed |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
2047 member_reg = r->as_Register(); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
2048 } |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
2049 } |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
2050 |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
2051 if (has_receiver) { |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
2052 // Make sure the receiver is loaded into a register. |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
2053 assert(total_args_passed > 0, "oob"); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
2054 assert(sig_bt[0] == T_OBJECT, "receiver argument must be an object"); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
2055 VMReg r = regs[0].first(); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
2056 assert(r->is_valid(), "bad receiver arg"); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
2057 if (r->is_stack()) { |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
2058 // Porting note: This assumes that compiled calling conventions always |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
2059 // pass the receiver oop in a register. If this is not true on some |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
2060 // platform, pick a temp and load the receiver from stack. |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
2061 assert(false, "receiver always in a register"); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
2062 receiver_reg = G3_scratch; // known to be free at this point |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
2063 RegisterOrConstant ld_off = reg2offset(r) + STACK_BIAS; |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
2064 ld_off = __ ensure_simm13_or_reg(ld_off, member_reg); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
2065 __ ld_ptr(SP, ld_off, receiver_reg); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
2066 } else { |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
2067 // no data motion is needed |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
2068 receiver_reg = r->as_Register(); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
2069 } |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
2070 } |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
2071 |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
2072 // Figure out which address we are really jumping to: |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
2073 MethodHandles::generate_method_handle_dispatch(masm, special_dispatch, |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
2074 receiver_reg, member_reg, /*for_compiler_entry:*/ true); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
2075 } |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
2076 |
0 | 2077 // --------------------------------------------------------------------------- |
2078 // Generate a native wrapper for a given method. The method takes arguments | |
2079 // in the Java compiled code convention, marshals them to the native | |
2080 // convention (handlizes oops, etc), transitions to native, makes the call, | |
2081 // returns to java state (possibly blocking), unhandlizes any result and | |
2082 // returns. | |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
2083 // |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
2084 // Critical native functions are a shorthand for the use of |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
2085 // GetPrimtiveArrayCritical and disallow the use of any other JNI |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
2086 // functions. The wrapper is expected to unpack the arguments before |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
2087 // passing them to the callee and perform checks before and after the |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
2088 // native call to ensure that they GC_locker |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
2089 // lock_critical/unlock_critical semantics are followed. Some other |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
2090 // parts of JNI setup are skipped like the tear down of the JNI handle |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
2091 // block and the check for pending exceptions it's impossible for them |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
2092 // to be thrown. |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
2093 // |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
2094 // They are roughly structured like this: |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
2095 // if (GC_locker::needs_gc()) |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
2096 // SharedRuntime::block_for_jni_critical(); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
2097 // tranistion to thread_in_native |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
2098 // unpack arrray arguments and call native entry point |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
2099 // check for safepoint in progress |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
2100 // check if any thread suspend flags are set |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
2101 // call into JVM and possible unlock the JNI critical |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
2102 // if a GC was suppressed while in the critical native. |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
2103 // transition back to thread_in_Java |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
2104 // return to caller |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
2105 // |
0 | 2106 nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler* masm, |
2107 methodHandle method, | |
2405
3d58a4983660
7022998: JSR 292 recursive method handle calls inline themselves infinitely
twisti
parents:
2177
diff
changeset
|
2108 int compile_id, |
0 | 2109 int total_in_args, |
2110 int comp_args_on_stack, // in VMRegStackSlots | |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
2111 BasicType* in_sig_bt, |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
2112 VMRegPair* in_regs, |
0 | 2113 BasicType ret_type) { |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
2114 if (method->is_method_handle_intrinsic()) { |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
2115 vmIntrinsics::ID iid = method->intrinsic_id(); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
2116 intptr_t start = (intptr_t)__ pc(); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
2117 int vep_offset = ((intptr_t)__ pc()) - start; |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
2118 gen_special_dispatch(masm, |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
2119 total_in_args, |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
2120 comp_args_on_stack, |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
2121 method->intrinsic_id(), |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
2122 in_sig_bt, |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
2123 in_regs); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
2124 int frame_complete = ((intptr_t)__ pc()) - start; // not complete, period |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
2125 __ flush(); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
2126 int stack_slots = SharedRuntime::out_preserve_stack_slots(); // no out slots at all, actually |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
2127 return nmethod::new_native_nmethod(method, |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
2128 compile_id, |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
2129 masm->code(), |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
2130 vep_offset, |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
2131 frame_complete, |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
2132 stack_slots / VMRegImpl::slots_per_word, |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
2133 in_ByteSize(-1), |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
2134 in_ByteSize(-1), |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
2135 (OopMapSet*)NULL); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
5923
diff
changeset
|
2136 } |
4873
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2137 bool is_critical_native = true; |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2138 address native_func = method->critical_native_function(); |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2139 if (native_func == NULL) { |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2140 native_func = method->native_function(); |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2141 is_critical_native = false; |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2142 } |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2143 assert(native_func != NULL, "must have function"); |
0 | 2144 |
2145 // Native nmethod wrappers never take possesion of the oop arguments. | |
2146 // So the caller will gc the arguments. The only thing we need an | |
2147 // oopMap for is if the call is static | |
2148 // | |
2149 // An OopMap for lock (and class if static), and one for the VM call itself | |
2150 OopMapSet *oop_maps = new OopMapSet(); | |
2151 intptr_t start = (intptr_t)__ pc(); | |
2152 | |
2153 // First thing make an ic check to see if we should even be here | |
2154 { | |
2155 Label L; | |
2156 const Register temp_reg = G3_scratch; | |
727 | 2157 AddressLiteral ic_miss(SharedRuntime::get_ic_miss_stub()); |
0 | 2158 __ verify_oop(O0); |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
2159 __ load_klass(O0, temp_reg); |
3839 | 2160 __ cmp_and_brx_short(temp_reg, G5_inline_cache_reg, Assembler::equal, Assembler::pt, L); |
0 | 2161 |
727 | 2162 __ jump_to(ic_miss, temp_reg); |
0 | 2163 __ delayed()->nop(); |
2164 __ align(CodeEntryAlignment); | |
2165 __ bind(L); | |
2166 } | |
2167 | |
2168 int vep_offset = ((intptr_t)__ pc()) - start; | |
2169 | |
2170 #ifdef COMPILER1 | |
2171 if (InlineObjectHash && method->intrinsic_id() == vmIntrinsics::_hashCode) { | |
2172 // Object.hashCode can pull the hashCode from the header word | |
2173 // instead of doing a full VM transition once it's been computed. | |
2174 // Since hashCode is usually polymorphic at call sites we can't do | |
2175 // this optimization at the call site without a lot of work. | |
2176 Label slowCase; | |
2177 Register receiver = O0; | |
2178 Register result = O0; | |
2179 Register header = G3_scratch; | |
2180 Register hash = G3_scratch; // overwrite header value with hash value | |
2181 Register mask = G1; // to get hash field from header | |
2182 | |
2183 // Read the header and build a mask to get its hash field. Give up if the object is not unlocked. | |
2184 // We depend on hash_mask being at most 32 bits and avoid the use of | |
2185 // hash_mask_in_place because it could be larger than 32 bits in a 64-bit | |
2186 // vm: see markOop.hpp. | |
2187 __ ld_ptr(receiver, oopDesc::mark_offset_in_bytes(), header); | |
2188 __ sethi(markOopDesc::hash_mask, mask); | |
2189 __ btst(markOopDesc::unlocked_value, header); | |
2190 __ br(Assembler::zero, false, Assembler::pn, slowCase); | |
2191 if (UseBiasedLocking) { | |
2192 // Check if biased and fall through to runtime if so | |
2193 __ delayed()->nop(); | |
2194 __ btst(markOopDesc::biased_lock_bit_in_place, header); | |
2195 __ br(Assembler::notZero, false, Assembler::pn, slowCase); | |
2196 } | |
2197 __ delayed()->or3(mask, markOopDesc::hash_mask & 0x3ff, mask); | |
2198 | |
2199 // Check for a valid (non-zero) hash code and get its value. | |
2200 #ifdef _LP64 | |
2201 __ srlx(header, markOopDesc::hash_shift, hash); | |
2202 #else | |
2203 __ srl(header, markOopDesc::hash_shift, hash); | |
2204 #endif | |
2205 __ andcc(hash, mask, hash); | |
2206 __ br(Assembler::equal, false, Assembler::pn, slowCase); | |
2207 __ delayed()->nop(); | |
2208 | |
2209 // leaf return. | |
2210 __ retl(); | |
2211 __ delayed()->mov(hash, result); | |
2212 __ bind(slowCase); | |
2213 } | |
2214 #endif // COMPILER1 | |
2215 | |
2216 | |
2217 // We have received a description of where all the java arg are located | |
2218 // on entry to the wrapper. We need to convert these args to where | |
2219 // the jni function will expect them. To figure out where they go | |
2220 // we convert the java signature to a C signature by inserting | |
2221 // the hidden arguments as arg[0] and possibly arg[1] (static method) | |
2222 | |
4873
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2223 int total_c_args = total_in_args; |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2224 int total_save_slots = 6 * VMRegImpl::slots_per_word; |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2225 if (!is_critical_native) { |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2226 total_c_args += 1; |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2227 if (method->is_static()) { |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2228 total_c_args++; |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2229 } |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2230 } else { |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2231 for (int i = 0; i < total_in_args; i++) { |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2232 if (in_sig_bt[i] == T_ARRAY) { |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2233 // These have to be saved and restored across the safepoint |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2234 total_c_args++; |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2235 } |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2236 } |
0 | 2237 } |
2238 | |
2239 BasicType* out_sig_bt = NEW_RESOURCE_ARRAY(BasicType, total_c_args); | |
4873
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2240 VMRegPair* out_regs = NEW_RESOURCE_ARRAY(VMRegPair, total_c_args); |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2241 BasicType* in_elem_bt = NULL; |
0 | 2242 |
2243 int argc = 0; | |
4873
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2244 if (!is_critical_native) { |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2245 out_sig_bt[argc++] = T_ADDRESS; |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2246 if (method->is_static()) { |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2247 out_sig_bt[argc++] = T_OBJECT; |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2248 } |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2249 |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2250 for (int i = 0; i < total_in_args ; i++ ) { |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2251 out_sig_bt[argc++] = in_sig_bt[i]; |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2252 } |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2253 } else { |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2254 Thread* THREAD = Thread::current(); |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2255 in_elem_bt = NEW_RESOURCE_ARRAY(BasicType, total_in_args); |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2256 SignatureStream ss(method->signature()); |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2257 for (int i = 0; i < total_in_args ; i++ ) { |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2258 if (in_sig_bt[i] == T_ARRAY) { |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2259 // Arrays are passed as int, elem* pair |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2260 out_sig_bt[argc++] = T_INT; |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2261 out_sig_bt[argc++] = T_ADDRESS; |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2262 Symbol* atype = ss.as_symbol(CHECK_NULL); |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2263 const char* at = atype->as_C_string(); |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2264 if (strlen(at) == 2) { |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2265 assert(at[0] == '[', "must be"); |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2266 switch (at[1]) { |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2267 case 'B': in_elem_bt[i] = T_BYTE; break; |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2268 case 'C': in_elem_bt[i] = T_CHAR; break; |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2269 case 'D': in_elem_bt[i] = T_DOUBLE; break; |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2270 case 'F': in_elem_bt[i] = T_FLOAT; break; |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2271 case 'I': in_elem_bt[i] = T_INT; break; |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2272 case 'J': in_elem_bt[i] = T_LONG; break; |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2273 case 'S': in_elem_bt[i] = T_SHORT; break; |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2274 case 'Z': in_elem_bt[i] = T_BOOLEAN; break; |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2275 default: ShouldNotReachHere(); |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2276 } |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2277 } |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2278 } else { |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2279 out_sig_bt[argc++] = in_sig_bt[i]; |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2280 in_elem_bt[i] = T_VOID; |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2281 } |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2282 if (in_sig_bt[i] != T_VOID) { |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2283 assert(in_sig_bt[i] == ss.type(), "must match"); |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2284 ss.next(); |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2285 } |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2286 } |
0 | 2287 } |
2288 | |
2289 // Now figure out where the args must be stored and how much stack space | |
2290 // they require (neglecting out_preserve_stack_slots but space for storing | |
2291 // the 1st six register arguments). It's weird see int_stk_helper. | |
2292 // | |
2293 int out_arg_slots; | |
2294 out_arg_slots = c_calling_convention(out_sig_bt, out_regs, total_c_args); | |
2295 | |
4873
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2296 if (is_critical_native) { |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2297 // Critical natives may have to call out so they need a save area |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2298 // for register arguments. |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2299 int double_slots = 0; |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2300 int single_slots = 0; |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2301 for ( int i = 0; i < total_in_args; i++) { |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2302 if (in_regs[i].first()->is_Register()) { |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2303 const Register reg = in_regs[i].first()->as_Register(); |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2304 switch (in_sig_bt[i]) { |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2305 case T_ARRAY: |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2306 case T_BOOLEAN: |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2307 case T_BYTE: |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2308 case T_SHORT: |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2309 case T_CHAR: |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2310 case T_INT: assert(reg->is_in(), "don't need to save these"); break; |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2311 case T_LONG: if (reg->is_global()) double_slots++; break; |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2312 default: ShouldNotReachHere(); |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2313 } |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2314 } else if (in_regs[i].first()->is_FloatRegister()) { |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2315 switch (in_sig_bt[i]) { |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2316 case T_FLOAT: single_slots++; break; |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2317 case T_DOUBLE: double_slots++; break; |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2318 default: ShouldNotReachHere(); |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2319 } |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2320 } |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2321 } |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2322 total_save_slots = double_slots * 2 + single_slots; |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2323 } |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2324 |
0 | 2325 // Compute framesize for the wrapper. We need to handlize all oops in |
2326 // registers. We must create space for them here that is disjoint from | |
2327 // the windowed save area because we have no control over when we might | |
2328 // flush the window again and overwrite values that gc has since modified. | |
2329 // (The live window race) | |
2330 // | |
2331 // We always just allocate 6 word for storing down these object. This allow | |
2332 // us to simply record the base and use the Ireg number to decide which | |
2333 // slot to use. (Note that the reg number is the inbound number not the | |
2334 // outbound number). | |
2335 // We must shuffle args to match the native convention, and include var-args space. | |
2336 | |
2337 // Calculate the total number of stack slots we will need. | |
2338 | |
2339 // First count the abi requirement plus all of the outgoing args | |
2340 int stack_slots = SharedRuntime::out_preserve_stack_slots() + out_arg_slots; | |
2341 | |
2342 // Now the space for the inbound oop handle area | |
2343 | |
4873
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2344 int oop_handle_offset = round_to(stack_slots, 2); |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2345 stack_slots += total_save_slots; |
0 | 2346 |
2347 // Now any space we need for handlizing a klass if static method | |
2348 | |
2349 int klass_slot_offset = 0; | |
2350 int klass_offset = -1; | |
2351 int lock_slot_offset = 0; | |
2352 bool is_static = false; | |
2353 | |
2354 if (method->is_static()) { | |
2355 klass_slot_offset = stack_slots; | |
2356 stack_slots += VMRegImpl::slots_per_word; | |
2357 klass_offset = klass_slot_offset * VMRegImpl::stack_slot_size; | |
2358 is_static = true; | |
2359 } | |
2360 | |
2361 // Plus a lock if needed | |
2362 | |
2363 if (method->is_synchronized()) { | |
2364 lock_slot_offset = stack_slots; | |
2365 stack_slots += VMRegImpl::slots_per_word; | |
2366 } | |
2367 | |
2368 // Now a place to save return value or as a temporary for any gpr -> fpr moves | |
2369 stack_slots += 2; | |
2370 | |
2371 // Ok The space we have allocated will look like: | |
2372 // | |
2373 // | |
2374 // FP-> | | | |
2375 // |---------------------| | |
2376 // | 2 slots for moves | | |
2377 // |---------------------| | |
2378 // | lock box (if sync) | | |
2379 // |---------------------| <- lock_slot_offset | |
2380 // | klass (if static) | | |
2381 // |---------------------| <- klass_slot_offset | |
2382 // | oopHandle area | | |
2383 // |---------------------| <- oop_handle_offset | |
2384 // | outbound memory | | |
2385 // | based arguments | | |
2386 // | | | |
2387 // |---------------------| | |
2388 // | vararg area | | |
2389 // |---------------------| | |
2390 // | | | |
2391 // SP-> | out_preserved_slots | | |
2392 // | |
2393 // | |
2394 | |
2395 | |
2396 // Now compute actual number of stack words we need rounding to make | |
2397 // stack properly aligned. | |
2398 stack_slots = round_to(stack_slots, 2 * VMRegImpl::slots_per_word); | |
2399 | |
2400 int stack_size = stack_slots * VMRegImpl::stack_slot_size; | |
2401 | |
2402 // Generate stack overflow check before creating frame | |
2403 __ generate_stack_overflow_check(stack_size); | |
2404 | |
2405 // Generate a new frame for the wrapper. | |
2406 __ save(SP, -stack_size, SP); | |
2407 | |
2408 int frame_complete = ((intptr_t)__ pc()) - start; | |
2409 | |
2410 __ verify_thread(); | |
2411 | |
4873
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2412 if (is_critical_native) { |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2413 check_needs_gc_for_critical_native(masm, stack_slots, total_in_args, |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2414 oop_handle_offset, oop_maps, in_regs, in_sig_bt); |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2415 } |
0 | 2416 |
2417 // | |
2418 // We immediately shuffle the arguments so that any vm call we have to | |
2419 // make from here on out (sync slow path, jvmti, etc.) we will have | |
2420 // captured the oops from our caller and have a valid oopMap for | |
2421 // them. | |
2422 | |
2423 // ----------------- | |
2424 // The Grand Shuffle | |
2425 // | |
2426 // Natives require 1 or 2 extra arguments over the normal ones: the JNIEnv* | |
2427 // (derived from JavaThread* which is in L7_thread_cache) and, if static, | |
2428 // the class mirror instead of a receiver. This pretty much guarantees that | |
2429 // register layout will not match. We ignore these extra arguments during | |
2430 // the shuffle. The shuffle is described by the two calling convention | |
2431 // vectors we have in our possession. We simply walk the java vector to | |
2432 // get the source locations and the c vector to get the destinations. | |
2433 // Because we have a new window and the argument registers are completely | |
2434 // disjoint ( I0 -> O1, I1 -> O2, ...) we have nothing to worry about | |
2435 // here. | |
2436 | |
2437 // This is a trick. We double the stack slots so we can claim | |
2438 // the oops in the caller's frame. Since we are sure to have | |
2439 // more args than the caller doubling is enough to make | |
2440 // sure we can capture all the incoming oop args from the | |
2441 // caller. | |
2442 // | |
2443 OopMap* map = new OopMap(stack_slots * 2, 0 /* arg_slots*/); | |
2444 // Record sp-based slot for receiver on stack for non-static methods | |
2445 int receiver_offset = -1; | |
2446 | |
2447 // We move the arguments backward because the floating point registers | |
2448 // destination will always be to a register with a greater or equal register | |
2449 // number or the stack. | |
2450 | |
2451 #ifdef ASSERT | |
2452 bool reg_destroyed[RegisterImpl::number_of_registers]; | |
2453 bool freg_destroyed[FloatRegisterImpl::number_of_registers]; | |
2454 for ( int r = 0 ; r < RegisterImpl::number_of_registers ; r++ ) { | |
2455 reg_destroyed[r] = false; | |
2456 } | |
2457 for ( int f = 0 ; f < FloatRegisterImpl::number_of_registers ; f++ ) { | |
2458 freg_destroyed[f] = false; | |
2459 } | |
2460 | |
2461 #endif /* ASSERT */ | |
2462 | |
4873
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2463 for ( int i = total_in_args - 1, c_arg = total_c_args - 1; i >= 0 ; i--, c_arg-- ) { |
0 | 2464 |
2465 #ifdef ASSERT | |
2466 if (in_regs[i].first()->is_Register()) { | |
2467 assert(!reg_destroyed[in_regs[i].first()->as_Register()->encoding()], "ack!"); | |
2468 } else if (in_regs[i].first()->is_FloatRegister()) { | |
2469 assert(!freg_destroyed[in_regs[i].first()->as_FloatRegister()->encoding(FloatRegisterImpl::S)], "ack!"); | |
2470 } | |
2471 if (out_regs[c_arg].first()->is_Register()) { | |
2472 reg_destroyed[out_regs[c_arg].first()->as_Register()->encoding()] = true; | |
2473 } else if (out_regs[c_arg].first()->is_FloatRegister()) { | |
2474 freg_destroyed[out_regs[c_arg].first()->as_FloatRegister()->encoding(FloatRegisterImpl::S)] = true; | |
2475 } | |
2476 #endif /* ASSERT */ | |
2477 | |
2478 switch (in_sig_bt[i]) { | |
2479 case T_ARRAY: | |
4873
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2480 if (is_critical_native) { |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2481 unpack_array_argument(masm, in_regs[i], in_elem_bt[i], out_regs[c_arg], out_regs[c_arg - 1]); |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2482 c_arg--; |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2483 break; |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2484 } |
0 | 2485 case T_OBJECT: |
4873
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2486 assert(!is_critical_native, "no oop arguments"); |
0 | 2487 object_move(masm, map, oop_handle_offset, stack_slots, in_regs[i], out_regs[c_arg], |
2488 ((i == 0) && (!is_static)), | |
2489 &receiver_offset); | |
2490 break; | |
2491 case T_VOID: | |
2492 break; | |
2493 | |
2494 case T_FLOAT: | |
2495 float_move(masm, in_regs[i], out_regs[c_arg]); | |
4873
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2496 break; |
0 | 2497 |
2498 case T_DOUBLE: | |
2499 assert( i + 1 < total_in_args && | |
2500 in_sig_bt[i + 1] == T_VOID && | |
2501 out_sig_bt[c_arg+1] == T_VOID, "bad arg list"); | |
2502 double_move(masm, in_regs[i], out_regs[c_arg]); | |
2503 break; | |
2504 | |
2505 case T_LONG : | |
2506 long_move(masm, in_regs[i], out_regs[c_arg]); | |
2507 break; | |
2508 | |
2509 case T_ADDRESS: assert(false, "found T_ADDRESS in java args"); | |
2510 | |
2511 default: | |
2512 move32_64(masm, in_regs[i], out_regs[c_arg]); | |
2513 } | |
2514 } | |
2515 | |
2516 // Pre-load a static method's oop into O1. Used both by locking code and | |
2517 // the normal JNI call code. | |
4873
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2518 if (method->is_static() && !is_critical_native) { |
0 | 2519 __ set_oop_constant(JNIHandles::make_local(Klass::cast(method->method_holder())->java_mirror()), O1); |
2520 | |
2521 // Now handlize the static class mirror in O1. It's known not-null. | |
2522 __ st_ptr(O1, SP, klass_offset + STACK_BIAS); | |
2523 map->set_oop(VMRegImpl::stack2reg(klass_slot_offset)); | |
2524 __ add(SP, klass_offset + STACK_BIAS, O1); | |
2525 } | |
2526 | |
2527 | |
2528 const Register L6_handle = L6; | |
2529 | |
2530 if (method->is_synchronized()) { | |
4873
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2531 assert(!is_critical_native, "unhandled"); |
0 | 2532 __ mov(O1, L6_handle); |
2533 } | |
2534 | |
2535 // We have all of the arguments setup at this point. We MUST NOT touch any Oregs | |
2536 // except O6/O7. So if we must call out we must push a new frame. We immediately | |
2537 // push a new frame and flush the windows. | |
2538 #ifdef _LP64 | |
2539 intptr_t thepc = (intptr_t) __ pc(); | |
2540 { | |
2541 address here = __ pc(); | |
2542 // Call the next instruction | |
2543 __ call(here + 8, relocInfo::none); | |
2544 __ delayed()->nop(); | |
2545 } | |
2546 #else | |
2547 intptr_t thepc = __ load_pc_address(O7, 0); | |
2548 #endif /* _LP64 */ | |
2549 | |
2550 // We use the same pc/oopMap repeatedly when we call out | |
2551 oop_maps->add_gc_map(thepc - start, map); | |
2552 | |
2553 // O7 now has the pc loaded that we will use when we finally call to native. | |
2554 | |
2555 // Save thread in L7; it crosses a bunch of VM calls below | |
2556 // Don't use save_thread because it smashes G2 and we merely | |
2557 // want to save a copy | |
2558 __ mov(G2_thread, L7_thread_cache); | |
2559 | |
2560 | |
2561 // If we create an inner frame once is plenty | |
2562 // when we create it we must also save G2_thread | |
2563 bool inner_frame_created = false; | |
2564 | |
2565 // dtrace method entry support | |
2566 { | |
2567 SkipIfEqual skip_if( | |
2568 masm, G3_scratch, &DTraceMethodProbes, Assembler::zero); | |
2569 // create inner frame | |
2570 __ save_frame(0); | |
2571 __ mov(G2_thread, L7_thread_cache); | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
2572 __ set_metadata_constant(method(), O1); |
0 | 2573 __ call_VM_leaf(L7_thread_cache, |
2574 CAST_FROM_FN_PTR(address, SharedRuntime::dtrace_method_entry), | |
2575 G2_thread, O1); | |
2576 __ restore(); | |
2577 } | |
2578 | |
610
70998f2e05ef
6805864: 4/3 Problem with jvmti->redefineClasses: some methods don't get redefined
dcubed
parents:
362
diff
changeset
|
2579 // RedefineClasses() tracing support for obsolete method entry |
70998f2e05ef
6805864: 4/3 Problem with jvmti->redefineClasses: some methods don't get redefined
dcubed
parents:
362
diff
changeset
|
2580 if (RC_TRACE_IN_RANGE(0x00001000, 0x00002000)) { |
70998f2e05ef
6805864: 4/3 Problem with jvmti->redefineClasses: some methods don't get redefined
dcubed
parents:
362
diff
changeset
|
2581 // create inner frame |
70998f2e05ef
6805864: 4/3 Problem with jvmti->redefineClasses: some methods don't get redefined
dcubed
parents:
362
diff
changeset
|
2582 __ save_frame(0); |
70998f2e05ef
6805864: 4/3 Problem with jvmti->redefineClasses: some methods don't get redefined
dcubed
parents:
362
diff
changeset
|
2583 __ mov(G2_thread, L7_thread_cache); |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
2584 __ set_metadata_constant(method(), O1); |
610
70998f2e05ef
6805864: 4/3 Problem with jvmti->redefineClasses: some methods don't get redefined
dcubed
parents:
362
diff
changeset
|
2585 __ call_VM_leaf(L7_thread_cache, |
70998f2e05ef
6805864: 4/3 Problem with jvmti->redefineClasses: some methods don't get redefined
dcubed
parents:
362
diff
changeset
|
2586 CAST_FROM_FN_PTR(address, SharedRuntime::rc_trace_method_entry), |
70998f2e05ef
6805864: 4/3 Problem with jvmti->redefineClasses: some methods don't get redefined
dcubed
parents:
362
diff
changeset
|
2587 G2_thread, O1); |
70998f2e05ef
6805864: 4/3 Problem with jvmti->redefineClasses: some methods don't get redefined
dcubed
parents:
362
diff
changeset
|
2588 __ restore(); |
70998f2e05ef
6805864: 4/3 Problem with jvmti->redefineClasses: some methods don't get redefined
dcubed
parents:
362
diff
changeset
|
2589 } |
70998f2e05ef
6805864: 4/3 Problem with jvmti->redefineClasses: some methods don't get redefined
dcubed
parents:
362
diff
changeset
|
2590 |
0 | 2591 // We are in the jni frame unless saved_frame is true in which case |
2592 // we are in one frame deeper (the "inner" frame). If we are in the | |
2593 // "inner" frames the args are in the Iregs and if the jni frame then | |
2594 // they are in the Oregs. | |
2595 // If we ever need to go to the VM (for locking, jvmti) then | |
2596 // we will always be in the "inner" frame. | |
2597 | |
2598 // Lock a synchronized method | |
2599 int lock_offset = -1; // Set if locked | |
2600 if (method->is_synchronized()) { | |
2601 Register Roop = O1; | |
2602 const Register L3_box = L3; | |
2603 | |
2604 create_inner_frame(masm, &inner_frame_created); | |
2605 | |
2606 __ ld_ptr(I1, 0, O1); | |
2607 Label done; | |
2608 | |
2609 lock_offset = (lock_slot_offset * VMRegImpl::stack_slot_size); | |
2610 __ add(FP, lock_offset+STACK_BIAS, L3_box); | |
2611 #ifdef ASSERT | |
2612 if (UseBiasedLocking) { | |
2613 // making the box point to itself will make it clear it went unused | |
2614 // but also be obviously invalid | |
2615 __ st_ptr(L3_box, L3_box, 0); | |
2616 } | |
2617 #endif // ASSERT | |
2618 // | |
2619 // Compiler_lock_object (Roop, Rmark, Rbox, Rscratch) -- kills Rmark, Rbox, Rscratch | |
2620 // | |
2621 __ compiler_lock_object(Roop, L1, L3_box, L2); | |
2622 __ br(Assembler::equal, false, Assembler::pt, done); | |
2623 __ delayed() -> add(FP, lock_offset+STACK_BIAS, L3_box); | |
2624 | |
2625 | |
2626 // None of the above fast optimizations worked so we have to get into the | |
2627 // slow case of monitor enter. Inline a special case of call_VM that | |
2628 // disallows any pending_exception. | |
2629 __ mov(Roop, O0); // Need oop in O0 | |
2630 __ mov(L3_box, O1); | |
2631 | |
2632 // Record last_Java_sp, in case the VM code releases the JVM lock. | |
2633 | |
2634 __ set_last_Java_frame(FP, I7); | |
2635 | |
2636 // do the call | |
2637 __ call(CAST_FROM_FN_PTR(address, SharedRuntime::complete_monitor_locking_C), relocInfo::runtime_call_type); | |
2638 __ delayed()->mov(L7_thread_cache, O2); | |
2639 | |
2640 __ restore_thread(L7_thread_cache); // restore G2_thread | |
2641 __ reset_last_Java_frame(); | |
2642 | |
2643 #ifdef ASSERT | |
2644 { Label L; | |
2645 __ ld_ptr(G2_thread, in_bytes(Thread::pending_exception_offset()), O0); | |
3839 | 2646 __ br_null_short(O0, Assembler::pt, L); |
0 | 2647 __ stop("no pending exception allowed on exit from IR::monitorenter"); |
2648 __ bind(L); | |
2649 } | |
2650 #endif | |
2651 __ bind(done); | |
2652 } | |
2653 | |
2654 | |
2655 // Finally just about ready to make the JNI call | |
2656 | |
2657 __ flush_windows(); | |
2658 if (inner_frame_created) { | |
2659 __ restore(); | |
2660 } else { | |
2661 // Store only what we need from this frame | |
2662 // QQQ I think that non-v9 (like we care) we don't need these saves | |
2663 // either as the flush traps and the current window goes too. | |
2664 __ st_ptr(FP, SP, FP->sp_offset_in_saved_window()*wordSize + STACK_BIAS); | |
2665 __ st_ptr(I7, SP, I7->sp_offset_in_saved_window()*wordSize + STACK_BIAS); | |
2666 } | |
2667 | |
2668 // get JNIEnv* which is first argument to native | |
4873
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2669 if (!is_critical_native) { |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2670 __ add(G2_thread, in_bytes(JavaThread::jni_environment_offset()), O0); |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2671 } |
0 | 2672 |
2673 // Use that pc we placed in O7 a while back as the current frame anchor | |
2674 __ set_last_Java_frame(SP, O7); | |
2675 | |
4873
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2676 // We flushed the windows ages ago now mark them as flushed before transitioning. |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2677 __ set(JavaFrameAnchor::flushed, G3_scratch); |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2678 __ st(G3_scratch, G2_thread, JavaThread::frame_anchor_offset() + JavaFrameAnchor::flags_offset()); |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2679 |
0 | 2680 // Transition from _thread_in_Java to _thread_in_native. |
2681 __ set(_thread_in_native, G3_scratch); | |
2682 | |
2683 #ifdef _LP64 | |
4873
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2684 AddressLiteral dest(native_func); |
0 | 2685 __ relocate(relocInfo::runtime_call_type); |
727 | 2686 __ jumpl_to(dest, O7, O7); |
0 | 2687 #else |
4873
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2688 __ call(native_func, relocInfo::runtime_call_type); |
0 | 2689 #endif |
4873
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2690 __ delayed()->st(G3_scratch, G2_thread, JavaThread::thread_state_offset()); |
0 | 2691 |
2692 __ restore_thread(L7_thread_cache); // restore G2_thread | |
2693 | |
2694 // Unpack native results. For int-types, we do any needed sign-extension | |
2695 // and move things into I0. The return value there will survive any VM | |
2696 // calls for blocking or unlocking. An FP or OOP result (handle) is done | |
2697 // specially in the slow-path code. | |
2698 switch (ret_type) { | |
2699 case T_VOID: break; // Nothing to do! | |
2700 case T_FLOAT: break; // Got it where we want it (unless slow-path) | |
2701 case T_DOUBLE: break; // Got it where we want it (unless slow-path) | |
2702 // In 64 bits build result is in O0, in O0, O1 in 32bit build | |
2703 case T_LONG: | |
2704 #ifndef _LP64 | |
2705 __ mov(O1, I1); | |
2706 #endif | |
2707 // Fall thru | |
2708 case T_OBJECT: // Really a handle | |
2709 case T_ARRAY: | |
2710 case T_INT: | |
2711 __ mov(O0, I0); | |
2712 break; | |
2713 case T_BOOLEAN: __ subcc(G0, O0, G0); __ addc(G0, 0, I0); break; // !0 => true; 0 => false | |
2714 case T_BYTE : __ sll(O0, 24, O0); __ sra(O0, 24, I0); break; | |
2715 case T_CHAR : __ sll(O0, 16, O0); __ srl(O0, 16, I0); break; // cannot use and3, 0xFFFF too big as immediate value! | |
2716 case T_SHORT : __ sll(O0, 16, O0); __ sra(O0, 16, I0); break; | |
2717 break; // Cannot de-handlize until after reclaiming jvm_lock | |
2718 default: | |
2719 ShouldNotReachHere(); | |
2720 } | |
2721 | |
4873
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2722 Label after_transition; |
0 | 2723 // must we block? |
2724 | |
2725 // Block, if necessary, before resuming in _thread_in_Java state. | |
2726 // In order for GC to work, don't clear the last_Java_sp until after blocking. | |
2727 { Label no_block; | |
727 | 2728 AddressLiteral sync_state(SafepointSynchronize::address_of_state()); |
0 | 2729 |
2730 // Switch thread to "native transition" state before reading the synchronization state. | |
2731 // This additional state is necessary because reading and testing the synchronization | |
2732 // state is not atomic w.r.t. GC, as this scenario demonstrates: | |
2733 // Java thread A, in _thread_in_native state, loads _not_synchronized and is preempted. | |
2734 // VM thread changes sync state to synchronizing and suspends threads for GC. | |
2735 // Thread A is resumed to finish this native method, but doesn't block here since it | |
2736 // didn't see any synchronization is progress, and escapes. | |
2737 __ set(_thread_in_native_trans, G3_scratch); | |
727 | 2738 __ st(G3_scratch, G2_thread, JavaThread::thread_state_offset()); |
0 | 2739 if(os::is_MP()) { |
2740 if (UseMembar) { | |
2741 // Force this write out before the read below | |
2742 __ membar(Assembler::StoreLoad); | |
2743 } else { | |
2744 // Write serialization page so VM thread can do a pseudo remote membar. | |
2745 // We use the current thread pointer to calculate a thread specific | |
2746 // offset to write to within the page. This minimizes bus traffic | |
2747 // due to cache line collision. | |
2748 __ serialize_memory(G2_thread, G1_scratch, G3_scratch); | |
2749 } | |
2750 } | |
2751 __ load_contents(sync_state, G3_scratch); | |
2752 __ cmp(G3_scratch, SafepointSynchronize::_not_synchronized); | |
2753 | |
2754 Label L; | |
727 | 2755 Address suspend_state(G2_thread, JavaThread::suspend_flags_offset()); |
0 | 2756 __ br(Assembler::notEqual, false, Assembler::pn, L); |
727 | 2757 __ delayed()->ld(suspend_state, G3_scratch); |
3839 | 2758 __ cmp_and_br_short(G3_scratch, 0, Assembler::equal, Assembler::pt, no_block); |
0 | 2759 __ bind(L); |
2760 | |
2761 // Block. Save any potential method result value before the operation and | |
2762 // use a leaf call to leave the last_Java_frame setup undisturbed. Doing this | |
2763 // lets us share the oopMap we used when we went native rather the create | |
2764 // a distinct one for this pc | |
2765 // | |
2766 save_native_result(masm, ret_type, stack_slots); | |
4873
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2767 if (!is_critical_native) { |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2768 __ call_VM_leaf(L7_thread_cache, |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2769 CAST_FROM_FN_PTR(address, JavaThread::check_special_condition_for_native_trans), |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2770 G2_thread); |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2771 } else { |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2772 __ call_VM_leaf(L7_thread_cache, |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2773 CAST_FROM_FN_PTR(address, JavaThread::check_special_condition_for_native_trans_and_transition), |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2774 G2_thread); |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2775 } |
0 | 2776 |
2777 // Restore any method result value | |
2778 restore_native_result(masm, ret_type, stack_slots); | |
4873
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2779 |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2780 if (is_critical_native) { |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2781 // The call above performed the transition to thread_in_Java so |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2782 // skip the transition logic below. |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2783 __ ba(after_transition); |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2784 __ delayed()->nop(); |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2785 } |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2786 |
0 | 2787 __ bind(no_block); |
2788 } | |
2789 | |
2790 // thread state is thread_in_native_trans. Any safepoint blocking has already | |
2791 // happened so we can now change state to _thread_in_Java. | |
2792 __ set(_thread_in_Java, G3_scratch); | |
727 | 2793 __ st(G3_scratch, G2_thread, JavaThread::thread_state_offset()); |
4873
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2794 __ bind(after_transition); |
0 | 2795 |
2796 Label no_reguard; | |
727 | 2797 __ ld(G2_thread, JavaThread::stack_guard_state_offset(), G3_scratch); |
3839 | 2798 __ cmp_and_br_short(G3_scratch, JavaThread::stack_guard_yellow_disabled, Assembler::notEqual, Assembler::pt, no_reguard); |
0 | 2799 |
2800 save_native_result(masm, ret_type, stack_slots); | |
2801 __ call(CAST_FROM_FN_PTR(address, SharedRuntime::reguard_yellow_pages)); | |
2802 __ delayed()->nop(); | |
2803 | |
2804 __ restore_thread(L7_thread_cache); // restore G2_thread | |
2805 restore_native_result(masm, ret_type, stack_slots); | |
2806 | |
2807 __ bind(no_reguard); | |
2808 | |
2809 // Handle possible exception (will unlock if necessary) | |
2810 | |
2811 // native result if any is live in freg or I0 (and I1 if long and 32bit vm) | |
2812 | |
2813 // Unlock | |
2814 if (method->is_synchronized()) { | |
2815 Label done; | |
2816 Register I2_ex_oop = I2; | |
2817 const Register L3_box = L3; | |
2818 // Get locked oop from the handle we passed to jni | |
2819 __ ld_ptr(L6_handle, 0, L4); | |
2820 __ add(SP, lock_offset+STACK_BIAS, L3_box); | |
2821 // Must save pending exception around the slow-path VM call. Since it's a | |
2822 // leaf call, the pending exception (if any) can be kept in a register. | |
2823 __ ld_ptr(G2_thread, in_bytes(Thread::pending_exception_offset()), I2_ex_oop); | |
2824 // Now unlock | |
2825 // (Roop, Rmark, Rbox, Rscratch) | |
2826 __ compiler_unlock_object(L4, L1, L3_box, L2); | |
2827 __ br(Assembler::equal, false, Assembler::pt, done); | |
2828 __ delayed()-> add(SP, lock_offset+STACK_BIAS, L3_box); | |
2829 | |
2830 // save and restore any potential method result value around the unlocking | |
2831 // operation. Will save in I0 (or stack for FP returns). | |
2832 save_native_result(masm, ret_type, stack_slots); | |
2833 | |
2834 // Must clear pending-exception before re-entering the VM. Since this is | |
2835 // a leaf call, pending-exception-oop can be safely kept in a register. | |
2836 __ st_ptr(G0, G2_thread, in_bytes(Thread::pending_exception_offset())); | |
2837 | |
2838 // slow case of monitor enter. Inline a special case of call_VM that | |
2839 // disallows any pending_exception. | |
2840 __ mov(L3_box, O1); | |
2841 | |
2842 __ call(CAST_FROM_FN_PTR(address, SharedRuntime::complete_monitor_unlocking_C), relocInfo::runtime_call_type); | |
2843 __ delayed()->mov(L4, O0); // Need oop in O0 | |
2844 | |
2845 __ restore_thread(L7_thread_cache); // restore G2_thread | |
2846 | |
2847 #ifdef ASSERT | |
2848 { Label L; | |
2849 __ ld_ptr(G2_thread, in_bytes(Thread::pending_exception_offset()), O0); | |
3839 | 2850 __ br_null_short(O0, Assembler::pt, L); |
0 | 2851 __ stop("no pending exception allowed on exit from IR::monitorexit"); |
2852 __ bind(L); | |
2853 } | |
2854 #endif | |
2855 restore_native_result(masm, ret_type, stack_slots); | |
2856 // check_forward_pending_exception jump to forward_exception if any pending | |
2857 // exception is set. The forward_exception routine expects to see the | |
2858 // exception in pending_exception and not in a register. Kind of clumsy, | |
2859 // since all folks who branch to forward_exception must have tested | |
2860 // pending_exception first and hence have it in a register already. | |
2861 __ st_ptr(I2_ex_oop, G2_thread, in_bytes(Thread::pending_exception_offset())); | |
2862 __ bind(done); | |
2863 } | |
2864 | |
2865 // Tell dtrace about this method exit | |
2866 { | |
2867 SkipIfEqual skip_if( | |
2868 masm, G3_scratch, &DTraceMethodProbes, Assembler::zero); | |
2869 save_native_result(masm, ret_type, stack_slots); | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
2870 __ set_metadata_constant(method(), O1); |
0 | 2871 __ call_VM_leaf(L7_thread_cache, |
2872 CAST_FROM_FN_PTR(address, SharedRuntime::dtrace_method_exit), | |
2873 G2_thread, O1); | |
2874 restore_native_result(masm, ret_type, stack_slots); | |
2875 } | |
2876 | |
2877 // Clear "last Java frame" SP and PC. | |
2878 __ verify_thread(); // G2_thread must be correct | |
2879 __ reset_last_Java_frame(); | |
2880 | |
2881 // Unpack oop result | |
2882 if (ret_type == T_OBJECT || ret_type == T_ARRAY) { | |
2883 Label L; | |
2884 __ addcc(G0, I0, G0); | |
2885 __ brx(Assembler::notZero, true, Assembler::pt, L); | |
2886 __ delayed()->ld_ptr(I0, 0, I0); | |
2887 __ mov(G0, I0); | |
2888 __ bind(L); | |
2889 __ verify_oop(I0); | |
2890 } | |
2891 | |
4873
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2892 if (!is_critical_native) { |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2893 // reset handle block |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2894 __ ld_ptr(G2_thread, in_bytes(JavaThread::active_handles_offset()), L5); |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2895 __ st_ptr(G0, L5, JNIHandleBlock::top_offset_in_bytes()); |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2896 |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2897 __ ld_ptr(G2_thread, in_bytes(Thread::pending_exception_offset()), G3_scratch); |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2898 check_forward_pending_exception(masm, G3_scratch); |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2899 } |
0 | 2900 |
2901 | |
2902 // Return | |
2903 | |
2904 #ifndef _LP64 | |
2905 if (ret_type == T_LONG) { | |
2906 | |
2907 // Must leave proper result in O0,O1 and G1 (c2/tiered only) | |
2908 __ sllx(I0, 32, G1); // Shift bits into high G1 | |
2909 __ srl (I1, 0, I1); // Zero extend O1 (harmless?) | |
2910 __ or3 (I1, G1, G1); // OR 64 bits into G1 | |
2911 } | |
2912 #endif | |
2913 | |
2914 __ ret(); | |
2915 __ delayed()->restore(); | |
2916 | |
2917 __ flush(); | |
2918 | |
2919 nmethod *nm = nmethod::new_native_nmethod(method, | |
2405
3d58a4983660
7022998: JSR 292 recursive method handle calls inline themselves infinitely
twisti
parents:
2177
diff
changeset
|
2920 compile_id, |
0 | 2921 masm->code(), |
2922 vep_offset, | |
2923 frame_complete, | |
2924 stack_slots / VMRegImpl::slots_per_word, | |
2925 (is_static ? in_ByteSize(klass_offset) : in_ByteSize(receiver_offset)), | |
2926 in_ByteSize(lock_offset), | |
2927 oop_maps); | |
4873
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2928 |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2929 if (is_critical_native) { |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2930 nm->set_lazy_critical_native(true); |
0382d2b469b2
7013347: allow crypto functions to be called inline to enhance performance
never
parents:
4114
diff
changeset
|
2931 } |
0 | 2932 return nm; |
2933 | |
2934 } | |
2935 | |
116
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
2936 #ifdef HAVE_DTRACE_H |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
2937 // --------------------------------------------------------------------------- |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
2938 // Generate a dtrace nmethod for a given signature. The method takes arguments |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
2939 // in the Java compiled code convention, marshals them to the native |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
2940 // abi and then leaves nops at the position you would expect to call a native |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
2941 // function. When the probe is enabled the nops are replaced with a trap |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
2942 // instruction that dtrace inserts and the trace will cause a notification |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
2943 // to dtrace. |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
2944 // |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
2945 // The probes are only able to take primitive types and java/lang/String as |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
2946 // arguments. No other java types are allowed. Strings are converted to utf8 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
2947 // strings so that from dtrace point of view java strings are converted to C |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
2948 // strings. There is an arbitrary fixed limit on the total space that a method |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
2949 // can use for converting the strings. (256 chars per string in the signature). |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
2950 // So any java string larger then this is truncated. |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
2951 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
2952 static int fp_offset[ConcreteRegisterImpl::number_of_registers] = { 0 }; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
2953 static bool offsets_initialized = false; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
2954 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
2955 nmethod *SharedRuntime::generate_dtrace_nmethod( |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
2956 MacroAssembler *masm, methodHandle method) { |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
2957 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
2958 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
2959 // generate_dtrace_nmethod is guarded by a mutex so we are sure to |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
2960 // be single threaded in this method. |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
2961 assert(AdapterHandlerLibrary_lock->owned_by_self(), "must be"); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
2962 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
2963 // Fill in the signature array, for the calling-convention call. |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
2964 int total_args_passed = method->size_of_parameters(); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
2965 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
2966 BasicType* in_sig_bt = NEW_RESOURCE_ARRAY(BasicType, total_args_passed); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
2967 VMRegPair *in_regs = NEW_RESOURCE_ARRAY(VMRegPair, total_args_passed); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
2968 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
2969 // The signature we are going to use for the trap that dtrace will see |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
2970 // java/lang/String is converted. We drop "this" and any other object |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
2971 // is converted to NULL. (A one-slot java/lang/Long object reference |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
2972 // is converted to a two-slot long, which is why we double the allocation). |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
2973 BasicType* out_sig_bt = NEW_RESOURCE_ARRAY(BasicType, total_args_passed * 2); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
2974 VMRegPair* out_regs = NEW_RESOURCE_ARRAY(VMRegPair, total_args_passed * 2); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
2975 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
2976 int i=0; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
2977 int total_strings = 0; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
2978 int first_arg_to_pass = 0; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
2979 int total_c_args = 0; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
2980 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
2981 // Skip the receiver as dtrace doesn't want to see it |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
2982 if( !method->is_static() ) { |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
2983 in_sig_bt[i++] = T_OBJECT; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
2984 first_arg_to_pass = 1; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
2985 } |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
2986 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
2987 SignatureStream ss(method->signature()); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
2988 for ( ; !ss.at_return_type(); ss.next()) { |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
2989 BasicType bt = ss.type(); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
2990 in_sig_bt[i++] = bt; // Collect remaining bits of signature |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
2991 out_sig_bt[total_c_args++] = bt; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
2992 if( bt == T_OBJECT) { |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1972
diff
changeset
|
2993 Symbol* s = ss.as_symbol_or_null(); |
116
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
2994 if (s == vmSymbols::java_lang_String()) { |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
2995 total_strings++; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
2996 out_sig_bt[total_c_args-1] = T_ADDRESS; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
2997 } else if (s == vmSymbols::java_lang_Boolean() || |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
2998 s == vmSymbols::java_lang_Byte()) { |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
2999 out_sig_bt[total_c_args-1] = T_BYTE; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3000 } else if (s == vmSymbols::java_lang_Character() || |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3001 s == vmSymbols::java_lang_Short()) { |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3002 out_sig_bt[total_c_args-1] = T_SHORT; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3003 } else if (s == vmSymbols::java_lang_Integer() || |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3004 s == vmSymbols::java_lang_Float()) { |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3005 out_sig_bt[total_c_args-1] = T_INT; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3006 } else if (s == vmSymbols::java_lang_Long() || |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3007 s == vmSymbols::java_lang_Double()) { |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3008 out_sig_bt[total_c_args-1] = T_LONG; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3009 out_sig_bt[total_c_args++] = T_VOID; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3010 } |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3011 } else if ( bt == T_LONG || bt == T_DOUBLE ) { |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3012 in_sig_bt[i++] = T_VOID; // Longs & doubles take 2 Java slots |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3013 // We convert double to long |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3014 out_sig_bt[total_c_args-1] = T_LONG; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3015 out_sig_bt[total_c_args++] = T_VOID; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3016 } else if ( bt == T_FLOAT) { |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3017 // We convert float to int |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3018 out_sig_bt[total_c_args-1] = T_INT; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3019 } |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3020 } |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3021 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3022 assert(i==total_args_passed, "validly parsed signature"); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3023 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3024 // Now get the compiled-Java layout as input arguments |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3025 int comp_args_on_stack; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3026 comp_args_on_stack = SharedRuntime::java_calling_convention( |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3027 in_sig_bt, in_regs, total_args_passed, false); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3028 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3029 // We have received a description of where all the java arg are located |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3030 // on entry to the wrapper. We need to convert these args to where |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3031 // the a native (non-jni) function would expect them. To figure out |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3032 // where they go we convert the java signature to a C signature and remove |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3033 // T_VOID for any long/double we might have received. |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3034 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3035 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3036 // Now figure out where the args must be stored and how much stack space |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3037 // they require (neglecting out_preserve_stack_slots but space for storing |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3038 // the 1st six register arguments). It's weird see int_stk_helper. |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3039 // |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3040 int out_arg_slots; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3041 out_arg_slots = c_calling_convention(out_sig_bt, out_regs, total_c_args); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3042 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3043 // Calculate the total number of stack slots we will need. |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3044 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3045 // First count the abi requirement plus all of the outgoing args |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3046 int stack_slots = SharedRuntime::out_preserve_stack_slots() + out_arg_slots; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3047 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3048 // Plus a temp for possible converion of float/double/long register args |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3049 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3050 int conversion_temp = stack_slots; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3051 stack_slots += 2; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3052 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3053 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3054 // Now space for the string(s) we must convert |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3055 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3056 int string_locs = stack_slots; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3057 stack_slots += total_strings * |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3058 (max_dtrace_string_size / VMRegImpl::stack_slot_size); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3059 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3060 // Ok The space we have allocated will look like: |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3061 // |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3062 // |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3063 // FP-> | | |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3064 // |---------------------| |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3065 // | string[n] | |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3066 // |---------------------| <- string_locs[n] |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3067 // | string[n-1] | |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3068 // |---------------------| <- string_locs[n-1] |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3069 // | ... | |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3070 // | ... | |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3071 // |---------------------| <- string_locs[1] |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3072 // | string[0] | |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3073 // |---------------------| <- string_locs[0] |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3074 // | temp | |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3075 // |---------------------| <- conversion_temp |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3076 // | outbound memory | |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3077 // | based arguments | |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3078 // | | |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3079 // |---------------------| |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3080 // | | |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3081 // SP-> | out_preserved_slots | |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3082 // |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3083 // |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3084 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3085 // Now compute actual number of stack words we need rounding to make |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3086 // stack properly aligned. |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3087 stack_slots = round_to(stack_slots, 4 * VMRegImpl::slots_per_word); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3088 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3089 int stack_size = stack_slots * VMRegImpl::stack_slot_size; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3090 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3091 intptr_t start = (intptr_t)__ pc(); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3092 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3093 // First thing make an ic check to see if we should even be here |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3094 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3095 { |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3096 Label L; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3097 const Register temp_reg = G3_scratch; |
727 | 3098 AddressLiteral ic_miss(SharedRuntime::get_ic_miss_stub()); |
116
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3099 __ verify_oop(O0); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3100 __ ld_ptr(O0, oopDesc::klass_offset_in_bytes(), temp_reg); |
3839 | 3101 __ cmp_and_brx_short(temp_reg, G5_inline_cache_reg, Assembler::equal, Assembler::pt, L); |
116
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3102 |
727 | 3103 __ jump_to(ic_miss, temp_reg); |
116
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3104 __ delayed()->nop(); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3105 __ align(CodeEntryAlignment); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3106 __ bind(L); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3107 } |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3108 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3109 int vep_offset = ((intptr_t)__ pc()) - start; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3110 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3111 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3112 // The instruction at the verified entry point must be 5 bytes or longer |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3113 // because it can be patched on the fly by make_non_entrant. The stack bang |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3114 // instruction fits that requirement. |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3115 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3116 // Generate stack overflow check before creating frame |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3117 __ generate_stack_overflow_check(stack_size); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3118 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3119 assert(((intptr_t)__ pc() - start - vep_offset) >= 5, |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3120 "valid size for make_non_entrant"); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3121 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3122 // Generate a new frame for the wrapper. |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3123 __ save(SP, -stack_size, SP); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3124 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3125 // Frame is now completed as far a size and linkage. |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3126 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3127 int frame_complete = ((intptr_t)__ pc()) - start; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3128 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3129 #ifdef ASSERT |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3130 bool reg_destroyed[RegisterImpl::number_of_registers]; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3131 bool freg_destroyed[FloatRegisterImpl::number_of_registers]; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3132 for ( int r = 0 ; r < RegisterImpl::number_of_registers ; r++ ) { |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3133 reg_destroyed[r] = false; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3134 } |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3135 for ( int f = 0 ; f < FloatRegisterImpl::number_of_registers ; f++ ) { |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3136 freg_destroyed[f] = false; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3137 } |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3138 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3139 #endif /* ASSERT */ |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3140 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3141 VMRegPair zero; |
176
6b648fefb395
6705523: Fix for 6695506 will violate spec when used in JDK6
kamg
parents:
116
diff
changeset
|
3142 const Register g0 = G0; // without this we get a compiler warning (why??) |
6b648fefb395
6705523: Fix for 6695506 will violate spec when used in JDK6
kamg
parents:
116
diff
changeset
|
3143 zero.set2(g0->as_VMReg()); |
116
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3144 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3145 int c_arg, j_arg; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3146 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3147 Register conversion_off = noreg; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3148 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3149 for (j_arg = first_arg_to_pass, c_arg = 0 ; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3150 j_arg < total_args_passed ; j_arg++, c_arg++ ) { |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3151 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3152 VMRegPair src = in_regs[j_arg]; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3153 VMRegPair dst = out_regs[c_arg]; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3154 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3155 #ifdef ASSERT |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3156 if (src.first()->is_Register()) { |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3157 assert(!reg_destroyed[src.first()->as_Register()->encoding()], "ack!"); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3158 } else if (src.first()->is_FloatRegister()) { |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3159 assert(!freg_destroyed[src.first()->as_FloatRegister()->encoding( |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3160 FloatRegisterImpl::S)], "ack!"); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3161 } |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3162 if (dst.first()->is_Register()) { |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3163 reg_destroyed[dst.first()->as_Register()->encoding()] = true; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3164 } else if (dst.first()->is_FloatRegister()) { |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3165 freg_destroyed[dst.first()->as_FloatRegister()->encoding( |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3166 FloatRegisterImpl::S)] = true; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3167 } |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3168 #endif /* ASSERT */ |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3169 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3170 switch (in_sig_bt[j_arg]) { |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3171 case T_ARRAY: |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3172 case T_OBJECT: |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3173 { |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3174 if (out_sig_bt[c_arg] == T_BYTE || out_sig_bt[c_arg] == T_SHORT || |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3175 out_sig_bt[c_arg] == T_INT || out_sig_bt[c_arg] == T_LONG) { |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3176 // need to unbox a one-slot value |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3177 Register in_reg = L0; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3178 Register tmp = L2; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3179 if ( src.first()->is_reg() ) { |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3180 in_reg = src.first()->as_Register(); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3181 } else { |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3182 assert(Assembler::is_simm13(reg2offset(src.first()) + STACK_BIAS), |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3183 "must be"); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3184 __ ld_ptr(FP, reg2offset(src.first()) + STACK_BIAS, in_reg); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3185 } |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3186 // If the final destination is an acceptable register |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3187 if ( dst.first()->is_reg() ) { |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3188 if ( dst.is_single_phys_reg() || out_sig_bt[c_arg] != T_LONG ) { |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3189 tmp = dst.first()->as_Register(); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3190 } |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3191 } |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3192 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3193 Label skipUnbox; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3194 if ( wordSize == 4 && out_sig_bt[c_arg] == T_LONG ) { |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3195 __ mov(G0, tmp->successor()); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3196 } |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3197 __ br_null(in_reg, true, Assembler::pn, skipUnbox); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3198 __ delayed()->mov(G0, tmp); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3199 |
165
437d03ea40b1
6703888: Compressed Oops: use the 32-bits gap after klass in a object
kvn
parents:
116
diff
changeset
|
3200 BasicType bt = out_sig_bt[c_arg]; |
437d03ea40b1
6703888: Compressed Oops: use the 32-bits gap after klass in a object
kvn
parents:
116
diff
changeset
|
3201 int box_offset = java_lang_boxing_object::value_offset_in_bytes(bt); |
437d03ea40b1
6703888: Compressed Oops: use the 32-bits gap after klass in a object
kvn
parents:
116
diff
changeset
|
3202 switch (bt) { |
116
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3203 case T_BYTE: |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3204 __ ldub(in_reg, box_offset, tmp); break; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3205 case T_SHORT: |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3206 __ lduh(in_reg, box_offset, tmp); break; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3207 case T_INT: |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3208 __ ld(in_reg, box_offset, tmp); break; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3209 case T_LONG: |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3210 __ ld_long(in_reg, box_offset, tmp); break; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3211 default: ShouldNotReachHere(); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3212 } |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3213 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3214 __ bind(skipUnbox); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3215 // If tmp wasn't final destination copy to final destination |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3216 if (tmp == L2) { |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3217 VMRegPair tmp_as_VM = reg64_to_VMRegPair(L2); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3218 if (out_sig_bt[c_arg] == T_LONG) { |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3219 long_move(masm, tmp_as_VM, dst); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3220 } else { |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3221 move32_64(masm, tmp_as_VM, out_regs[c_arg]); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3222 } |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3223 } |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3224 if (out_sig_bt[c_arg] == T_LONG) { |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3225 assert(out_sig_bt[c_arg+1] == T_VOID, "must be"); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3226 ++c_arg; // move over the T_VOID to keep the loop indices in sync |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3227 } |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3228 } else if (out_sig_bt[c_arg] == T_ADDRESS) { |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3229 Register s = |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3230 src.first()->is_reg() ? src.first()->as_Register() : L2; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3231 Register d = |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3232 dst.first()->is_reg() ? dst.first()->as_Register() : L2; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3233 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3234 // We store the oop now so that the conversion pass can reach |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3235 // while in the inner frame. This will be the only store if |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3236 // the oop is NULL. |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3237 if (s != L2) { |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3238 // src is register |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3239 if (d != L2) { |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3240 // dst is register |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3241 __ mov(s, d); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3242 } else { |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3243 assert(Assembler::is_simm13(reg2offset(dst.first()) + |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3244 STACK_BIAS), "must be"); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3245 __ st_ptr(s, SP, reg2offset(dst.first()) + STACK_BIAS); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3246 } |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3247 } else { |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3248 // src not a register |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3249 assert(Assembler::is_simm13(reg2offset(src.first()) + |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3250 STACK_BIAS), "must be"); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3251 __ ld_ptr(FP, reg2offset(src.first()) + STACK_BIAS, d); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3252 if (d == L2) { |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3253 assert(Assembler::is_simm13(reg2offset(dst.first()) + |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3254 STACK_BIAS), "must be"); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3255 __ st_ptr(d, SP, reg2offset(dst.first()) + STACK_BIAS); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3256 } |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3257 } |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3258 } else if (out_sig_bt[c_arg] != T_VOID) { |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3259 // Convert the arg to NULL |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3260 if (dst.first()->is_reg()) { |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3261 __ mov(G0, dst.first()->as_Register()); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3262 } else { |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3263 assert(Assembler::is_simm13(reg2offset(dst.first()) + |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3264 STACK_BIAS), "must be"); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3265 __ st_ptr(G0, SP, reg2offset(dst.first()) + STACK_BIAS); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3266 } |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3267 } |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3268 } |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3269 break; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3270 case T_VOID: |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3271 break; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3272 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3273 case T_FLOAT: |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3274 if (src.first()->is_stack()) { |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3275 // Stack to stack/reg is simple |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3276 move32_64(masm, src, dst); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3277 } else { |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3278 if (dst.first()->is_reg()) { |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3279 // freg -> reg |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3280 int off = |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3281 STACK_BIAS + conversion_temp * VMRegImpl::stack_slot_size; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3282 Register d = dst.first()->as_Register(); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3283 if (Assembler::is_simm13(off)) { |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3284 __ stf(FloatRegisterImpl::S, src.first()->as_FloatRegister(), |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3285 SP, off); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3286 __ ld(SP, off, d); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3287 } else { |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3288 if (conversion_off == noreg) { |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3289 __ set(off, L6); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3290 conversion_off = L6; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3291 } |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3292 __ stf(FloatRegisterImpl::S, src.first()->as_FloatRegister(), |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3293 SP, conversion_off); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3294 __ ld(SP, conversion_off , d); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3295 } |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3296 } else { |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3297 // freg -> mem |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3298 int off = STACK_BIAS + reg2offset(dst.first()); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3299 if (Assembler::is_simm13(off)) { |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3300 __ stf(FloatRegisterImpl::S, src.first()->as_FloatRegister(), |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3301 SP, off); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3302 } else { |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3303 if (conversion_off == noreg) { |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3304 __ set(off, L6); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3305 conversion_off = L6; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3306 } |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3307 __ stf(FloatRegisterImpl::S, src.first()->as_FloatRegister(), |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3308 SP, conversion_off); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3309 } |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3310 } |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3311 } |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3312 break; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3313 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3314 case T_DOUBLE: |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3315 assert( j_arg + 1 < total_args_passed && |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3316 in_sig_bt[j_arg + 1] == T_VOID && |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3317 out_sig_bt[c_arg+1] == T_VOID, "bad arg list"); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3318 if (src.first()->is_stack()) { |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3319 // Stack to stack/reg is simple |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3320 long_move(masm, src, dst); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3321 } else { |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3322 Register d = dst.first()->is_reg() ? dst.first()->as_Register() : L2; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3323 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3324 // Destination could be an odd reg on 32bit in which case |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3325 // we can't load direct to the destination. |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3326 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3327 if (!d->is_even() && wordSize == 4) { |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3328 d = L2; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3329 } |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3330 int off = STACK_BIAS + conversion_temp * VMRegImpl::stack_slot_size; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3331 if (Assembler::is_simm13(off)) { |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3332 __ stf(FloatRegisterImpl::D, src.first()->as_FloatRegister(), |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3333 SP, off); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3334 __ ld_long(SP, off, d); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3335 } else { |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3336 if (conversion_off == noreg) { |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3337 __ set(off, L6); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3338 conversion_off = L6; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3339 } |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3340 __ stf(FloatRegisterImpl::D, src.first()->as_FloatRegister(), |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3341 SP, conversion_off); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3342 __ ld_long(SP, conversion_off, d); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3343 } |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3344 if (d == L2) { |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3345 long_move(masm, reg64_to_VMRegPair(L2), dst); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3346 } |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3347 } |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3348 break; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3349 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3350 case T_LONG : |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3351 // 32bit can't do a split move of something like g1 -> O0, O1 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3352 // so use a memory temp |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3353 if (src.is_single_phys_reg() && wordSize == 4) { |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3354 Register tmp = L2; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3355 if (dst.first()->is_reg() && |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3356 (wordSize == 8 || dst.first()->as_Register()->is_even())) { |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3357 tmp = dst.first()->as_Register(); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3358 } |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3359 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3360 int off = STACK_BIAS + conversion_temp * VMRegImpl::stack_slot_size; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3361 if (Assembler::is_simm13(off)) { |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3362 __ stx(src.first()->as_Register(), SP, off); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3363 __ ld_long(SP, off, tmp); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3364 } else { |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3365 if (conversion_off == noreg) { |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3366 __ set(off, L6); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3367 conversion_off = L6; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3368 } |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3369 __ stx(src.first()->as_Register(), SP, conversion_off); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3370 __ ld_long(SP, conversion_off, tmp); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3371 } |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3372 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3373 if (tmp == L2) { |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3374 long_move(masm, reg64_to_VMRegPair(L2), dst); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3375 } |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3376 } else { |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3377 long_move(masm, src, dst); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3378 } |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3379 break; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3380 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3381 case T_ADDRESS: assert(false, "found T_ADDRESS in java args"); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3382 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3383 default: |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3384 move32_64(masm, src, dst); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3385 } |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3386 } |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3387 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3388 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3389 // If we have any strings we must store any register based arg to the stack |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3390 // This includes any still live xmm registers too. |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3391 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3392 if (total_strings > 0 ) { |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3393 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3394 // protect all the arg registers |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3395 __ save_frame(0); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3396 __ mov(G2_thread, L7_thread_cache); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3397 const Register L2_string_off = L2; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3398 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3399 // Get first string offset |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3400 __ set(string_locs * VMRegImpl::stack_slot_size, L2_string_off); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3401 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3402 for (c_arg = 0 ; c_arg < total_c_args ; c_arg++ ) { |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3403 if (out_sig_bt[c_arg] == T_ADDRESS) { |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3404 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3405 VMRegPair dst = out_regs[c_arg]; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3406 const Register d = dst.first()->is_reg() ? |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3407 dst.first()->as_Register()->after_save() : noreg; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3408 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3409 // It's a string the oop and it was already copied to the out arg |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3410 // position |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3411 if (d != noreg) { |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3412 __ mov(d, O0); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3413 } else { |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3414 assert(Assembler::is_simm13(reg2offset(dst.first()) + STACK_BIAS), |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3415 "must be"); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3416 __ ld_ptr(FP, reg2offset(dst.first()) + STACK_BIAS, O0); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3417 } |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3418 Label skip; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3419 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3420 __ br_null(O0, false, Assembler::pn, skip); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3421 __ delayed()->add(FP, L2_string_off, O1); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3422 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3423 if (d != noreg) { |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3424 __ mov(O1, d); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3425 } else { |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3426 assert(Assembler::is_simm13(reg2offset(dst.first()) + STACK_BIAS), |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3427 "must be"); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3428 __ st_ptr(O1, FP, reg2offset(dst.first()) + STACK_BIAS); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3429 } |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3430 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3431 __ call(CAST_FROM_FN_PTR(address, SharedRuntime::get_utf), |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3432 relocInfo::runtime_call_type); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3433 __ delayed()->add(L2_string_off, max_dtrace_string_size, L2_string_off); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3434 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3435 __ bind(skip); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3436 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3437 } |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3438 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3439 } |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3440 __ mov(L7_thread_cache, G2_thread); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3441 __ restore(); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3442 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3443 } |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3444 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3445 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3446 // Ok now we are done. Need to place the nop that dtrace wants in order to |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3447 // patch in the trap |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3448 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3449 int patch_offset = ((intptr_t)__ pc()) - start; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3450 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3451 __ nop(); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3452 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3453 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3454 // Return |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3455 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3456 __ ret(); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3457 __ delayed()->restore(); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3458 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3459 __ flush(); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3460 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3461 nmethod *nm = nmethod::new_dtrace_nmethod( |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3462 method, masm->code(), vep_offset, patch_offset, frame_complete, |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3463 stack_slots / VMRegImpl::slots_per_word); |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3464 return nm; |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3465 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3466 } |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3467 |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3468 #endif // HAVE_DTRACE_H |
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
113
diff
changeset
|
3469 |
0 | 3470 // this function returns the adjust size (in number of words) to a c2i adapter |
3471 // activation for use during deoptimization | |
3472 int Deoptimization::last_frame_adjust(int callee_parameters, int callee_locals) { | |
3473 assert(callee_locals >= callee_parameters, | |
3474 "test and remove; got more parms than locals"); | |
3475 if (callee_locals < callee_parameters) | |
3476 return 0; // No adjustment for negative locals | |
1506 | 3477 int diff = (callee_locals - callee_parameters) * Interpreter::stackElementWords; |
0 | 3478 return round_to(diff, WordsPerLong); |
3479 } | |
3480 | |
3481 // "Top of Stack" slots that may be unused by the calling convention but must | |
3482 // otherwise be preserved. | |
3483 // On Intel these are not necessary and the value can be zero. | |
3484 // On Sparc this describes the words reserved for storing a register window | |
3485 // when an interrupt occurs. | |
3486 uint SharedRuntime::out_preserve_stack_slots() { | |
3487 return frame::register_save_words * VMRegImpl::slots_per_word; | |
3488 } | |
3489 | |
3490 static void gen_new_frame(MacroAssembler* masm, bool deopt) { | |
3491 // | |
3492 // Common out the new frame generation for deopt and uncommon trap | |
3493 // | |
3494 Register G3pcs = G3_scratch; // Array of new pcs (input) | |
3495 Register Oreturn0 = O0; | |
3496 Register Oreturn1 = O1; | |
3497 Register O2UnrollBlock = O2; | |
3498 Register O3array = O3; // Array of frame sizes (input) | |
3499 Register O4array_size = O4; // number of frames (input) | |
3500 Register O7frame_size = O7; // number of frames (input) | |
3501 | |
3502 __ ld_ptr(O3array, 0, O7frame_size); | |
3503 __ sub(G0, O7frame_size, O7frame_size); | |
3504 __ save(SP, O7frame_size, SP); | |
3505 __ ld_ptr(G3pcs, 0, I7); // load frame's new pc | |
3506 | |
3507 #ifdef ASSERT | |
3508 // make sure that the frames are aligned properly | |
3509 #ifndef _LP64 | |
3510 __ btst(wordSize*2-1, SP); | |
5923 | 3511 __ breakpoint_trap(Assembler::notZero, Assembler::ptr_cc); |
0 | 3512 #endif |
3513 #endif | |
3514 | |
3515 // Deopt needs to pass some extra live values from frame to frame | |
3516 | |
3517 if (deopt) { | |
3518 __ mov(Oreturn0->after_save(), Oreturn0); | |
3519 __ mov(Oreturn1->after_save(), Oreturn1); | |
3520 } | |
3521 | |
3522 __ mov(O4array_size->after_save(), O4array_size); | |
3523 __ sub(O4array_size, 1, O4array_size); | |
3524 __ mov(O3array->after_save(), O3array); | |
3525 __ mov(O2UnrollBlock->after_save(), O2UnrollBlock); | |
3526 __ add(G3pcs, wordSize, G3pcs); // point to next pc value | |
3527 | |
3528 #ifdef ASSERT | |
3529 // trash registers to show a clear pattern in backtraces | |
3530 __ set(0xDEAD0000, I0); | |
3531 __ add(I0, 2, I1); | |
3532 __ add(I0, 4, I2); | |
3533 __ add(I0, 6, I3); | |
3534 __ add(I0, 8, I4); | |
3535 // Don't touch I5 could have valuable savedSP | |
3536 __ set(0xDEADBEEF, L0); | |
3537 __ mov(L0, L1); | |
3538 __ mov(L0, L2); | |
3539 __ mov(L0, L3); | |
3540 __ mov(L0, L4); | |
3541 __ mov(L0, L5); | |
3542 | |
3543 // trash the return value as there is nothing to return yet | |
3544 __ set(0xDEAD0001, O7); | |
3545 #endif | |
3546 | |
3547 __ mov(SP, O5_savedSP); | |
3548 } | |
3549 | |
3550 | |
3551 static void make_new_frames(MacroAssembler* masm, bool deopt) { | |
3552 // | |
3553 // loop through the UnrollBlock info and create new frames | |
3554 // | |
3555 Register G3pcs = G3_scratch; | |
3556 Register Oreturn0 = O0; | |
3557 Register Oreturn1 = O1; | |
3558 Register O2UnrollBlock = O2; | |
3559 Register O3array = O3; | |
3560 Register O4array_size = O4; | |
3561 Label loop; | |
3562 | |
3563 // Before we make new frames, check to see if stack is available. | |
3564 // Do this after the caller's return address is on top of stack | |
3565 if (UseStackBanging) { | |
3566 // Get total frame size for interpreted frames | |
727 | 3567 __ ld(O2UnrollBlock, Deoptimization::UnrollBlock::total_frame_sizes_offset_in_bytes(), O4); |
0 | 3568 __ bang_stack_size(O4, O3, G3_scratch); |
3569 } | |
3570 | |
727 | 3571 __ ld(O2UnrollBlock, Deoptimization::UnrollBlock::number_of_frames_offset_in_bytes(), O4array_size); |
3572 __ ld_ptr(O2UnrollBlock, Deoptimization::UnrollBlock::frame_pcs_offset_in_bytes(), G3pcs); | |
3573 __ ld_ptr(O2UnrollBlock, Deoptimization::UnrollBlock::frame_sizes_offset_in_bytes(), O3array); | |
0 | 3574 |
3575 // Adjust old interpreter frame to make space for new frame's extra java locals | |
3576 // | |
3577 // We capture the original sp for the transition frame only because it is needed in | |
3578 // order to properly calculate interpreter_sp_adjustment. Even though in real life | |
3579 // every interpreter frame captures a savedSP it is only needed at the transition | |
3580 // (fortunately). If we had to have it correct everywhere then we would need to | |
3581 // be told the sp_adjustment for each frame we create. If the frame size array | |
3582 // were to have twice the frame count entries then we could have pairs [sp_adjustment, frame_size] | |
3583 // for each frame we create and keep up the illusion every where. | |
3584 // | |
3585 | |
727 | 3586 __ ld(O2UnrollBlock, Deoptimization::UnrollBlock::caller_adjustment_offset_in_bytes(), O7); |
0 | 3587 __ mov(SP, O5_savedSP); // remember initial sender's original sp before adjustment |
3588 __ sub(SP, O7, SP); | |
3589 | |
3590 #ifdef ASSERT | |
3591 // make sure that there is at least one entry in the array | |
3592 __ tst(O4array_size); | |
5923 | 3593 __ breakpoint_trap(Assembler::zero, Assembler::icc); |
0 | 3594 #endif |
3595 | |
3596 // Now push the new interpreter frames | |
3597 __ bind(loop); | |
3598 | |
3599 // allocate a new frame, filling the registers | |
3600 | |
3601 gen_new_frame(masm, deopt); // allocate an interpreter frame | |
3602 | |
3839 | 3603 __ cmp_zero_and_br(Assembler::notZero, O4array_size, loop); |
0 | 3604 __ delayed()->add(O3array, wordSize, O3array); |
3605 __ ld_ptr(G3pcs, 0, O7); // load final frame new pc | |
3606 | |
3607 } | |
3608 | |
3609 //------------------------------generate_deopt_blob---------------------------- | |
3610 // Ought to generate an ideal graph & compile, but here's some SPARC ASM | |
3611 // instead. | |
3612 void SharedRuntime::generate_deopt_blob() { | |
3613 // allocate space for the code | |
3614 ResourceMark rm; | |
3615 // setup code generation tools | |
3616 int pad = VerifyThread ? 512 : 0;// Extra slop space for more verify code | |
4957
931e5f39e365
7147064: assert(allocates2(pc)) failed: not in CodeBuffer memory: 0xffffffff778d9d60 <= 0xffffffff778da69c
kvn
parents:
4873
diff
changeset
|
3617 if (UseStackBanging) { |
931e5f39e365
7147064: assert(allocates2(pc)) failed: not in CodeBuffer memory: 0xffffffff778d9d60 <= 0xffffffff778da69c
kvn
parents:
4873
diff
changeset
|
3618 pad += StackShadowPages*16 + 32; |
931e5f39e365
7147064: assert(allocates2(pc)) failed: not in CodeBuffer memory: 0xffffffff778d9d60 <= 0xffffffff778da69c
kvn
parents:
4873
diff
changeset
|
3619 } |
0 | 3620 #ifdef _LP64 |
3621 CodeBuffer buffer("deopt_blob", 2100+pad, 512); | |
3622 #else | |
3623 // Measured 8/7/03 at 1212 in 32bit debug build (no VerifyThread) | |
3624 // Measured 8/7/03 at 1396 in 32bit debug build (VerifyThread) | |
3625 CodeBuffer buffer("deopt_blob", 1600+pad, 512); | |
3626 #endif /* _LP64 */ | |
3627 MacroAssembler* masm = new MacroAssembler(&buffer); | |
3628 FloatRegister Freturn0 = F0; | |
3629 Register Greturn1 = G1; | |
3630 Register Oreturn0 = O0; | |
3631 Register Oreturn1 = O1; | |
3632 Register O2UnrollBlock = O2; | |
1037 | 3633 Register L0deopt_mode = L0; |
3634 Register G4deopt_mode = G4_scratch; | |
0 | 3635 int frame_size_words; |
727 | 3636 Address saved_Freturn0_addr(FP, -sizeof(double) + STACK_BIAS); |
0 | 3637 #if !defined(_LP64) && defined(COMPILER2) |
727 | 3638 Address saved_Greturn1_addr(FP, -sizeof(double) -sizeof(jlong) + STACK_BIAS); |
0 | 3639 #endif |
3640 Label cont; | |
3641 | |
3642 OopMapSet *oop_maps = new OopMapSet(); | |
3643 | |
3644 // | |
3645 // This is the entry point for code which is returning to a de-optimized | |
3646 // frame. | |
3647 // The steps taken by this frame are as follows: | |
3648 // - push a dummy "register_save" and save the return values (O0, O1, F0/F1, G1) | |
3649 // and all potentially live registers (at a pollpoint many registers can be live). | |
3650 // | |
3651 // - call the C routine: Deoptimization::fetch_unroll_info (this function | |
3652 // returns information about the number and size of interpreter frames | |
3653 // which are equivalent to the frame which is being deoptimized) | |
3654 // - deallocate the unpack frame, restoring only results values. Other | |
3655 // volatile registers will now be captured in the vframeArray as needed. | |
3656 // - deallocate the deoptimization frame | |
3657 // - in a loop using the information returned in the previous step | |
3658 // push new interpreter frames (take care to propagate the return | |
3659 // values through each new frame pushed) | |
3660 // - create a dummy "unpack_frame" and save the return values (O0, O1, F0) | |
3661 // - call the C routine: Deoptimization::unpack_frames (this function | |
3662 // lays out values on the interpreter frame which was just created) | |
3663 // - deallocate the dummy unpack_frame | |
3664 // - ensure that all the return values are correctly set and then do | |
3665 // a return to the interpreter entry point | |
3666 // | |
3667 // Refer to the following methods for more information: | |
3668 // - Deoptimization::fetch_unroll_info | |
3669 // - Deoptimization::unpack_frames | |
3670 | |
3671 OopMap* map = NULL; | |
3672 | |
3673 int start = __ offset(); | |
3674 | |
3675 // restore G2, the trampoline destroyed it | |
3676 __ get_thread(); | |
3677 | |
3678 // On entry we have been called by the deoptimized nmethod with a call that | |
3679 // replaced the original call (or safepoint polling location) so the deoptimizing | |
3680 // pc is now in O7. Return values are still in the expected places | |
3681 | |
3682 map = RegisterSaver::save_live_registers(masm, 0, &frame_size_words); | |
3839 | 3683 __ ba(cont); |
1037 | 3684 __ delayed()->mov(Deoptimization::Unpack_deopt, L0deopt_mode); |
0 | 3685 |
3686 int exception_offset = __ offset() - start; | |
3687 | |
3688 // restore G2, the trampoline destroyed it | |
3689 __ get_thread(); | |
3690 | |
3691 // On entry we have been jumped to by the exception handler (or exception_blob | |
3692 // for server). O0 contains the exception oop and O7 contains the original | |
3693 // exception pc. So if we push a frame here it will look to the | |
3694 // stack walking code (fetch_unroll_info) just like a normal call so | |
3695 // state will be extracted normally. | |
3696 | |
3697 // save exception oop in JavaThread and fall through into the | |
3698 // exception_in_tls case since they are handled in same way except | |
3699 // for where the pending exception is kept. | |
727 | 3700 __ st_ptr(Oexception, G2_thread, JavaThread::exception_oop_offset()); |
0 | 3701 |
3702 // | |
3703 // Vanilla deoptimization with an exception pending in exception_oop | |
3704 // | |
3705 int exception_in_tls_offset = __ offset() - start; | |
3706 | |
3707 // No need to update oop_map as each call to save_live_registers will produce identical oopmap | |
3708 (void) RegisterSaver::save_live_registers(masm, 0, &frame_size_words); | |
3709 | |
3710 // Restore G2_thread | |
3711 __ get_thread(); | |
3712 | |
3713 #ifdef ASSERT | |
3714 { | |
3715 // verify that there is really an exception oop in exception_oop | |
3716 Label has_exception; | |
727 | 3717 __ ld_ptr(G2_thread, JavaThread::exception_oop_offset(), Oexception); |
3839 | 3718 __ br_notnull_short(Oexception, Assembler::pt, has_exception); |
0 | 3719 __ stop("no exception in thread"); |
3720 __ bind(has_exception); | |
3721 | |
3722 // verify that there is no pending exception | |
3723 Label no_pending_exception; | |
727 | 3724 Address exception_addr(G2_thread, Thread::pending_exception_offset()); |
0 | 3725 __ ld_ptr(exception_addr, Oexception); |
3839 | 3726 __ br_null_short(Oexception, Assembler::pt, no_pending_exception); |
0 | 3727 __ stop("must not have pending exception here"); |
3728 __ bind(no_pending_exception); | |
3729 } | |
3730 #endif | |
3731 | |
3839 | 3732 __ ba(cont); |
1037 | 3733 __ delayed()->mov(Deoptimization::Unpack_exception, L0deopt_mode);; |
0 | 3734 |
3735 // | |
3736 // Reexecute entry, similar to c2 uncommon trap | |
3737 // | |
3738 int reexecute_offset = __ offset() - start; | |
3739 | |
3740 // No need to update oop_map as each call to save_live_registers will produce identical oopmap | |
3741 (void) RegisterSaver::save_live_registers(masm, 0, &frame_size_words); | |
3742 | |
1037 | 3743 __ mov(Deoptimization::Unpack_reexecute, L0deopt_mode); |
0 | 3744 |
3745 __ bind(cont); | |
3746 | |
3747 __ set_last_Java_frame(SP, noreg); | |
3748 | |
3749 // do the call by hand so we can get the oopmap | |
3750 | |
3751 __ mov(G2_thread, L7_thread_cache); | |
3752 __ call(CAST_FROM_FN_PTR(address, Deoptimization::fetch_unroll_info), relocInfo::runtime_call_type); | |
3753 __ delayed()->mov(G2_thread, O0); | |
3754 | |
3755 // Set an oopmap for the call site this describes all our saved volatile registers | |
3756 | |
3757 oop_maps->add_gc_map( __ offset()-start, map); | |
3758 | |
3759 __ mov(L7_thread_cache, G2_thread); | |
3760 | |
3761 __ reset_last_Java_frame(); | |
3762 | |
3763 // NOTE: we know that only O0/O1 will be reloaded by restore_result_registers | |
3764 // so this move will survive | |
3765 | |
1037 | 3766 __ mov(L0deopt_mode, G4deopt_mode); |
0 | 3767 |
3768 __ mov(O0, O2UnrollBlock->after_save()); | |
3769 | |
3770 RegisterSaver::restore_result_registers(masm); | |
3771 | |
3772 Label noException; | |
3839 | 3773 __ cmp_and_br_short(G4deopt_mode, Deoptimization::Unpack_exception, Assembler::notEqual, Assembler::pt, noException); |
0 | 3774 |
3775 // Move the pending exception from exception_oop to Oexception so | |
3776 // the pending exception will be picked up the interpreter. | |
3777 __ ld_ptr(G2_thread, in_bytes(JavaThread::exception_oop_offset()), Oexception); | |
3778 __ st_ptr(G0, G2_thread, in_bytes(JavaThread::exception_oop_offset())); | |
3779 __ bind(noException); | |
3780 | |
3781 // deallocate the deoptimization frame taking care to preserve the return values | |
3782 __ mov(Oreturn0, Oreturn0->after_save()); | |
3783 __ mov(Oreturn1, Oreturn1->after_save()); | |
3784 __ mov(O2UnrollBlock, O2UnrollBlock->after_save()); | |
3785 __ restore(); | |
3786 | |
3787 // Allocate new interpreter frame(s) and possible c2i adapter frame | |
3788 | |
3789 make_new_frames(masm, true); | |
3790 | |
3791 // push a dummy "unpack_frame" taking care of float return values and | |
3792 // call Deoptimization::unpack_frames to have the unpacker layout | |
3793 // information in the interpreter frames just created and then return | |
3794 // to the interpreter entry point | |
3795 __ save(SP, -frame_size_words*wordSize, SP); | |
3796 __ stf(FloatRegisterImpl::D, Freturn0, saved_Freturn0_addr); | |
3797 #if !defined(_LP64) | |
3798 #if defined(COMPILER2) | |
1783 | 3799 // 32-bit 1-register longs return longs in G1 |
3800 __ stx(Greturn1, saved_Greturn1_addr); | |
0 | 3801 #endif |
3802 __ set_last_Java_frame(SP, noreg); | |
1037 | 3803 __ call_VM_leaf(L7_thread_cache, CAST_FROM_FN_PTR(address, Deoptimization::unpack_frames), G2_thread, G4deopt_mode); |
0 | 3804 #else |
3805 // LP64 uses g4 in set_last_Java_frame | |
1037 | 3806 __ mov(G4deopt_mode, O1); |
0 | 3807 __ set_last_Java_frame(SP, G0); |
3808 __ call_VM_leaf(L7_thread_cache, CAST_FROM_FN_PTR(address, Deoptimization::unpack_frames), G2_thread, O1); | |
3809 #endif | |
3810 __ reset_last_Java_frame(); | |
3811 __ ldf(FloatRegisterImpl::D, saved_Freturn0_addr, Freturn0); | |
3812 | |
3813 #if !defined(_LP64) && defined(COMPILER2) | |
3814 // In 32 bit, C2 returns longs in G1 so restore the saved G1 into | |
1783 | 3815 // I0/I1 if the return value is long. |
3816 Label not_long; | |
3839 | 3817 __ cmp_and_br_short(O0,T_LONG, Assembler::notEqual, Assembler::pt, not_long); |
1783 | 3818 __ ldd(saved_Greturn1_addr,I0); |
3819 __ bind(not_long); | |
0 | 3820 #endif |
3821 __ ret(); | |
3822 __ delayed()->restore(); | |
3823 | |
3824 masm->flush(); | |
3825 _deopt_blob = DeoptimizationBlob::create(&buffer, oop_maps, 0, exception_offset, reexecute_offset, frame_size_words); | |
3826 _deopt_blob->set_unpack_with_exception_in_tls_offset(exception_in_tls_offset); | |
3827 } | |
3828 | |
3829 #ifdef COMPILER2 | |
3830 | |
3831 //------------------------------generate_uncommon_trap_blob-------------------- | |
3832 // Ought to generate an ideal graph & compile, but here's some SPARC ASM | |
3833 // instead. | |
3834 void SharedRuntime::generate_uncommon_trap_blob() { | |
3835 // allocate space for the code | |
3836 ResourceMark rm; | |
3837 // setup code generation tools | |
3838 int pad = VerifyThread ? 512 : 0; | |
4957
931e5f39e365
7147064: assert(allocates2(pc)) failed: not in CodeBuffer memory: 0xffffffff778d9d60 <= 0xffffffff778da69c
kvn
parents:
4873
diff
changeset
|
3839 if (UseStackBanging) { |
931e5f39e365
7147064: assert(allocates2(pc)) failed: not in CodeBuffer memory: 0xffffffff778d9d60 <= 0xffffffff778da69c
kvn
parents:
4873
diff
changeset
|
3840 pad += StackShadowPages*16 + 32; |
931e5f39e365
7147064: assert(allocates2(pc)) failed: not in CodeBuffer memory: 0xffffffff778d9d60 <= 0xffffffff778da69c
kvn
parents:
4873
diff
changeset
|
3841 } |
0 | 3842 #ifdef _LP64 |
3843 CodeBuffer buffer("uncommon_trap_blob", 2700+pad, 512); | |
3844 #else | |
3845 // Measured 8/7/03 at 660 in 32bit debug build (no VerifyThread) | |
3846 // Measured 8/7/03 at 1028 in 32bit debug build (VerifyThread) | |
3847 CodeBuffer buffer("uncommon_trap_blob", 2000+pad, 512); | |
3848 #endif | |
3849 MacroAssembler* masm = new MacroAssembler(&buffer); | |
3850 Register O2UnrollBlock = O2; | |
3851 Register O2klass_index = O2; | |
3852 | |
3853 // | |
3854 // This is the entry point for all traps the compiler takes when it thinks | |
3855 // it cannot handle further execution of compilation code. The frame is | |
3856 // deoptimized in these cases and converted into interpreter frames for | |
3857 // execution | |
3858 // The steps taken by this frame are as follows: | |
3859 // - push a fake "unpack_frame" | |
3860 // - call the C routine Deoptimization::uncommon_trap (this function | |
3861 // packs the current compiled frame into vframe arrays and returns | |
3862 // information about the number and size of interpreter frames which | |
3863 // are equivalent to the frame which is being deoptimized) | |
3864 // - deallocate the "unpack_frame" | |
3865 // - deallocate the deoptimization frame | |
3866 // - in a loop using the information returned in the previous step | |
3867 // push interpreter frames; | |
3868 // - create a dummy "unpack_frame" | |
3869 // - call the C routine: Deoptimization::unpack_frames (this function | |
3870 // lays out values on the interpreter frame which was just created) | |
3871 // - deallocate the dummy unpack_frame | |
3872 // - return to the interpreter entry point | |
3873 // | |
3874 // Refer to the following methods for more information: | |
3875 // - Deoptimization::uncommon_trap | |
3876 // - Deoptimization::unpack_frame | |
3877 | |
3878 // the unloaded class index is in O0 (first parameter to this blob) | |
3879 | |
3880 // push a dummy "unpack_frame" | |
3881 // and call Deoptimization::uncommon_trap to pack the compiled frame into | |
3882 // vframe array and return the UnrollBlock information | |
3883 __ save_frame(0); | |
3884 __ set_last_Java_frame(SP, noreg); | |
3885 __ mov(I0, O2klass_index); | |
3886 __ call_VM_leaf(L7_thread_cache, CAST_FROM_FN_PTR(address, Deoptimization::uncommon_trap), G2_thread, O2klass_index); | |
3887 __ reset_last_Java_frame(); | |
3888 __ mov(O0, O2UnrollBlock->after_save()); | |
3889 __ restore(); | |
3890 | |
3891 // deallocate the deoptimized frame taking care to preserve the return values | |
3892 __ mov(O2UnrollBlock, O2UnrollBlock->after_save()); | |
3893 __ restore(); | |
3894 | |
3895 // Allocate new interpreter frame(s) and possible c2i adapter frame | |
3896 | |
3897 make_new_frames(masm, false); | |
3898 | |
3899 // push a dummy "unpack_frame" taking care of float return values and | |
3900 // call Deoptimization::unpack_frames to have the unpacker layout | |
3901 // information in the interpreter frames just created and then return | |
3902 // to the interpreter entry point | |
3903 __ save_frame(0); | |
3904 __ set_last_Java_frame(SP, noreg); | |
3905 __ mov(Deoptimization::Unpack_uncommon_trap, O3); // indicate it is the uncommon trap case | |
3906 __ call_VM_leaf(L7_thread_cache, CAST_FROM_FN_PTR(address, Deoptimization::unpack_frames), G2_thread, O3); | |
3907 __ reset_last_Java_frame(); | |
3908 __ ret(); | |
3909 __ delayed()->restore(); | |
3910 | |
3911 masm->flush(); | |
3912 _uncommon_trap_blob = UncommonTrapBlob::create(&buffer, NULL, __ total_frame_size_in_bytes(0)/wordSize); | |
3913 } | |
3914 | |
3915 #endif // COMPILER2 | |
3916 | |
3917 //------------------------------generate_handler_blob------------------- | |
3918 // | |
3919 // Generate a special Compile2Runtime blob that saves all registers, and sets | |
3920 // up an OopMap. | |
3921 // | |
3922 // This blob is jumped to (via a breakpoint and the signal handler) from a | |
3923 // safepoint in compiled code. On entry to this blob, O7 contains the | |
3924 // address in the original nmethod at which we should resume normal execution. | |
3925 // Thus, this blob looks like a subroutine which must preserve lots of | |
3926 // registers and return normally. Note that O7 is never register-allocated, | |
3927 // so it is guaranteed to be free here. | |
3928 // | |
3929 | |
3930 // The hardest part of what this blob must do is to save the 64-bit %o | |
3931 // registers in the 32-bit build. A simple 'save' turn the %o's to %i's and | |
3932 // an interrupt will chop off their heads. Making space in the caller's frame | |
3933 // first will let us save the 64-bit %o's before save'ing, but we cannot hand | |
3934 // the adjusted FP off to the GC stack-crawler: this will modify the caller's | |
3935 // SP and mess up HIS OopMaps. So we first adjust the caller's SP, then save | |
3936 // the 64-bit %o's, then do a save, then fixup the caller's SP (our FP). | |
3937 // Tricky, tricky, tricky... | |
3938 | |
3753
cba7b5c2d53f
7045514: SPARC assembly code for JSR 292 ricochet frames
never
parents:
2405
diff
changeset
|
3939 SafepointBlob* SharedRuntime::generate_handler_blob(address call_ptr, bool cause_return) { |
0 | 3940 assert (StubRoutines::forward_exception_entry() != NULL, "must be generated before"); |
3941 | |
3942 // allocate space for the code | |
3943 ResourceMark rm; | |
3944 // setup code generation tools | |
3945 // Measured 8/7/03 at 896 in 32bit debug build (no VerifyThread) | |
3946 // Measured 8/7/03 at 1080 in 32bit debug build (VerifyThread) | |
3947 // even larger with TraceJumps | |
3948 int pad = TraceJumps ? 512 : 0; | |
3949 CodeBuffer buffer("handler_blob", 1600 + pad, 512); | |
3950 MacroAssembler* masm = new MacroAssembler(&buffer); | |
3951 int frame_size_words; | |
3952 OopMapSet *oop_maps = new OopMapSet(); | |
3953 OopMap* map = NULL; | |
3954 | |
3955 int start = __ offset(); | |
3956 | |
3957 // If this causes a return before the processing, then do a "restore" | |
3958 if (cause_return) { | |
3959 __ restore(); | |
3960 } else { | |
3961 // Make it look like we were called via the poll | |
3962 // so that frame constructor always sees a valid return address | |
3963 __ ld_ptr(G2_thread, in_bytes(JavaThread::saved_exception_pc_offset()), O7); | |
3964 __ sub(O7, frame::pc_return_offset, O7); | |
3965 } | |
3966 | |
3967 map = RegisterSaver::save_live_registers(masm, 0, &frame_size_words); | |
3968 | |
3969 // setup last_Java_sp (blows G4) | |
3970 __ set_last_Java_frame(SP, noreg); | |
3971 | |
3972 // call into the runtime to handle illegal instructions exception | |
3973 // Do not use call_VM_leaf, because we need to make a GC map at this call site. | |
3974 __ mov(G2_thread, O0); | |
3975 __ save_thread(L7_thread_cache); | |
3976 __ call(call_ptr); | |
3977 __ delayed()->nop(); | |
3978 | |
3979 // Set an oopmap for the call site. | |
3980 // We need this not only for callee-saved registers, but also for volatile | |
3981 // registers that the compiler might be keeping live across a safepoint. | |
3982 | |
3983 oop_maps->add_gc_map( __ offset() - start, map); | |
3984 | |
3985 __ restore_thread(L7_thread_cache); | |
3986 // clear last_Java_sp | |
3987 __ reset_last_Java_frame(); | |
3988 | |
3989 // Check for exceptions | |
3990 Label pending; | |
3991 | |
3992 __ ld_ptr(G2_thread, in_bytes(Thread::pending_exception_offset()), O1); | |
3839 | 3993 __ br_notnull_short(O1, Assembler::pn, pending); |
0 | 3994 |
3995 RegisterSaver::restore_live_registers(masm); | |
3996 | |
3997 // We are back the the original state on entry and ready to go. | |
3998 | |
3999 __ retl(); | |
4000 __ delayed()->nop(); | |
4001 | |
4002 // Pending exception after the safepoint | |
4003 | |
4004 __ bind(pending); | |
4005 | |
4006 RegisterSaver::restore_live_registers(masm); | |
4007 | |
4008 // We are back the the original state on entry. | |
4009 | |
4010 // Tail-call forward_exception_entry, with the issuing PC in O7, | |
4011 // so it looks like the original nmethod called forward_exception_entry. | |
4012 __ set((intptr_t)StubRoutines::forward_exception_entry(), O0); | |
4013 __ JMP(O0, 0); | |
4014 __ delayed()->nop(); | |
4015 | |
4016 // ------------- | |
4017 // make sure all code is generated | |
4018 masm->flush(); | |
4019 | |
4020 // return exception blob | |
4021 return SafepointBlob::create(&buffer, oop_maps, frame_size_words); | |
4022 } | |
4023 | |
4024 // | |
4025 // generate_resolve_blob - call resolution (static/virtual/opt-virtual/ic-miss | |
4026 // | |
4027 // Generate a stub that calls into vm to find out the proper destination | |
4028 // of a java call. All the argument registers are live at this point | |
4029 // but since this is generic code we don't know what they are and the caller | |
4030 // must do any gc of the args. | |
4031 // | |
3753
cba7b5c2d53f
7045514: SPARC assembly code for JSR 292 ricochet frames
never
parents:
2405
diff
changeset
|
4032 RuntimeStub* SharedRuntime::generate_resolve_blob(address destination, const char* name) { |
0 | 4033 assert (StubRoutines::forward_exception_entry() != NULL, "must be generated before"); |
4034 | |
4035 // allocate space for the code | |
4036 ResourceMark rm; | |
4037 // setup code generation tools | |
4038 // Measured 8/7/03 at 896 in 32bit debug build (no VerifyThread) | |
4039 // Measured 8/7/03 at 1080 in 32bit debug build (VerifyThread) | |
4040 // even larger with TraceJumps | |
4041 int pad = TraceJumps ? 512 : 0; | |
4042 CodeBuffer buffer(name, 1600 + pad, 512); | |
4043 MacroAssembler* masm = new MacroAssembler(&buffer); | |
4044 int frame_size_words; | |
4045 OopMapSet *oop_maps = new OopMapSet(); | |
4046 OopMap* map = NULL; | |
4047 | |
4048 int start = __ offset(); | |
4049 | |
4050 map = RegisterSaver::save_live_registers(masm, 0, &frame_size_words); | |
4051 | |
4052 int frame_complete = __ offset(); | |
4053 | |
4054 // setup last_Java_sp (blows G4) | |
4055 __ set_last_Java_frame(SP, noreg); | |
4056 | |
4057 // call into the runtime to handle illegal instructions exception | |
4058 // Do not use call_VM_leaf, because we need to make a GC map at this call site. | |
4059 __ mov(G2_thread, O0); | |
4060 __ save_thread(L7_thread_cache); | |
4061 __ call(destination, relocInfo::runtime_call_type); | |
4062 __ delayed()->nop(); | |
4063 | |
4064 // O0 contains the address we are going to jump to assuming no exception got installed | |
4065 | |
4066 // Set an oopmap for the call site. | |
4067 // We need this not only for callee-saved registers, but also for volatile | |
4068 // registers that the compiler might be keeping live across a safepoint. | |
4069 | |
4070 oop_maps->add_gc_map( __ offset() - start, map); | |
4071 | |
4072 __ restore_thread(L7_thread_cache); | |
4073 // clear last_Java_sp | |
4074 __ reset_last_Java_frame(); | |
4075 | |
4076 // Check for exceptions | |
4077 Label pending; | |
4078 | |
4079 __ ld_ptr(G2_thread, in_bytes(Thread::pending_exception_offset()), O1); | |
3839 | 4080 __ br_notnull_short(O1, Assembler::pn, pending); |
0 | 4081 |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
4082 // get the returned Method* |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
4083 |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
4084 __ get_vm_result_2(G5_method); |
0 | 4085 __ stx(G5_method, SP, RegisterSaver::G5_offset()+STACK_BIAS); |
4086 | |
4087 // O0 is where we want to jump, overwrite G3 which is saved and scratch | |
4088 | |
4089 __ stx(O0, SP, RegisterSaver::G3_offset()+STACK_BIAS); | |
4090 | |
4091 RegisterSaver::restore_live_registers(masm); | |
4092 | |
4093 // We are back the the original state on entry and ready to go. | |
4094 | |
4095 __ JMP(G3, 0); | |
4096 __ delayed()->nop(); | |
4097 | |
4098 // Pending exception after the safepoint | |
4099 | |
4100 __ bind(pending); | |
4101 | |
4102 RegisterSaver::restore_live_registers(masm); | |
4103 | |
4104 // We are back the the original state on entry. | |
4105 | |
4106 // Tail-call forward_exception_entry, with the issuing PC in O7, | |
4107 // so it looks like the original nmethod called forward_exception_entry. | |
4108 __ set((intptr_t)StubRoutines::forward_exception_entry(), O0); | |
4109 __ JMP(O0, 0); | |
4110 __ delayed()->nop(); | |
4111 | |
4112 // ------------- | |
4113 // make sure all code is generated | |
4114 masm->flush(); | |
4115 | |
4116 // return the blob | |
4117 // frame_size_words or bytes?? | |
4118 return RuntimeStub::new_runtime_stub(name, &buffer, frame_complete, frame_size_words, oop_maps, true); | |
4119 } |